From 593e1cbe3470f409c19a7f06f5d10c6f5677361a Mon Sep 17 00:00:00 2001 From: Ludovic Pouzenc Date: Sat, 16 Jun 2012 21:16:46 +0000 Subject: Bon, calcul du niveau sonore dans la plage 200 à 2000Hz en reprennant les choses calmement. Il n'est pas impossible que les valeurs soient bonnes :P MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: file:///var/svn/2012-violon-leds/trunk@19 6be1fa4d-33ac-4c33-becc-79fcb3794bb6 --- tests/test6/Makefile | 30 +++++++ tests/test6/compil.sh | 2 - tests/test6/compute.c | 138 +++++++++++++++++++++++++++++ tests/test6/compute.h | 11 +++ tests/test6/fft.c | 241 ++++++++++++++++++++++++++++++++++++++++++++++++++ tests/test6/fft.h | 19 ++++ tests/test6/test.raw | 1 + tests/test6/test6.c | 19 +++- 8 files changed, 456 insertions(+), 5 deletions(-) create mode 100644 tests/test6/Makefile delete mode 100755 tests/test6/compil.sh create mode 100644 tests/test6/compute.c create mode 100644 tests/test6/compute.h create mode 100644 tests/test6/fft.c create mode 100644 tests/test6/fft.h create mode 120000 tests/test6/test.raw diff --git a/tests/test6/Makefile b/tests/test6/Makefile new file mode 100644 index 0000000..560ff03 --- /dev/null +++ b/tests/test6/Makefile @@ -0,0 +1,30 @@ +CC=gcc +CFLAGS=-W -Wall -Werror -Wno-error=unused-parameter -g +LDFLAGS=-Werror -g +EXEC=test6 + +#CFLAGS+=$(shell pkg-config --cflags gtk+-2.0 gthread-2.0 libpulse) +#LDFLAGS+=$(shell pkg-config --libs gtk+-2.0 gthread-2.0 libpulse) +LDFLAGS+=-lm + +SRC= $(wildcard *.c) +OBJ= $(SRC:.c=.o) + +all: $(EXEC) + +$(EXEC): $(OBJ) + $(CC) -o $@ $^ $(LDFLAGS) + +#main.o: hello.h + +%.o: %.c + $(CC) -o $@ -c $< $(CFLAGS) + +.PHONY: clean mrproper + +clean: + rm *.o + +mrproper: clean + rm $(EXEC) + diff --git a/tests/test6/compil.sh b/tests/test6/compil.sh deleted file mode 100755 index 2e49576..0000000 --- a/tests/test6/compil.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -xe -gcc -Wall -g -o test6 test6.c -lm diff --git a/tests/test6/compute.c b/tests/test6/compute.c new file mode 100644 index 0000000..017416b --- /dev/null +++ b/tests/test6/compute.c @@ -0,0 +1,138 @@ +#include "compute.h" + +#include "fft.h" +#include + +#define MIN_SAMPLES 256 +#define MAX_SAMPLES 2048 + +//#define MAX(a,b) (a>b?a:b) +//#define MIN(a,b) (a= MAX_SAMPLES) { + printf("WARN : nsamples >= MAX_SAMPLES : %i >= %i\n", nsamples, MAX_SAMPLES); + nsamples=MAX_SAMPLES; + } + if (nsamples < MIN_SAMPLES) { + printf("WARN : nsamples < MIN_SAMPLES : %i >= %i\n", nsamples, MIN_SAMPLES); + // Replicate with symmetry the sound to obtain an input buffer of the minimal len + for (i=0;i 0.0) + output[i] = 10*log10(temp); + else + output[i] = 0; + } +} + +void audio2hsv_1(int audio_level, int *light_h, int *light_s, int *light_v) { + // Dummy code + *light_h=-audio_level; + *light_s=audio_level; + *light_v=65535; +} + + +void hsv2rgb(int h, int s, int v, int *r, int *g, int *b) { + /* + * Purpose: + * Convert HSV values to RGB values + * All values are in the range [0..65535] + */ + float F, M, N, K; + int I; + + if ( s == 0 ) { + /* + * Achromatic case, set level of grey + */ + *r = v; + *g = v; + *b = v; + } else { + I = (int) h/(65535/6); /* should be in the range 0..5 */ + F = h - I; /* fractional part */ + + M = v * (1 - s); + N = v * (1 - s * F); + K = v * (1 - s * (1 - F)); + + if (I == 0) { *r = v; *g = K; *b = M; } + if (I == 1) { *r = N; *g = v; *b = M; } + if (I == 2) { *r = M; *g = v; *b = K; } + if (I == 3) { *r = M; *g = N; *b = v; } + if (I == 4) { *r = K; *g = M; *b = v; } + if (I == 5) { *r = v; *g = M; *b = N; } + } +} diff --git a/tests/test6/compute.h b/tests/test6/compute.h new file mode 100644 index 0000000..d663ba5 --- /dev/null +++ b/tests/test6/compute.h @@ -0,0 +1,11 @@ +#ifndef COMPUTE_H +#define COMPUTE_H +#include // for size_t +#include // for printf + +float compute_level(const float *data, size_t nsamples, int rate); +void audio2hsv_1(int audio_level, int *light_h, int *light_s, int *light_v); +void hsv2rgb(int h, int s, int v, int *r, int *g, int *b); + +#endif + diff --git a/tests/test6/fft.c b/tests/test6/fft.c new file mode 100644 index 0000000..dd91d14 --- /dev/null +++ b/tests/test6/fft.c @@ -0,0 +1,241 @@ +#include "fft.h" +#include +#include + +/* Everything here comes from Audacity 1.3.13 + (orignally in C++ and with more genericity and functionnality) + Original Author : Dominic Mazzoni + Licenced under GPL 2.0 (see LICENCE) +*/ + +#define MaxFastBits 16 + +int *gFFTBitTable[MaxFastBits]={NULL}; + +void InitFFT(); +int NumberOfBitsNeeded(int PowerOfTwo); +inline int FastReverseBits(int i, int NumBits); +int ReverseBits(int index, int NumBits); + + +void FFT(int NumSamples, + int InverseTransform, + float *RealIn, float *ImagIn, float *RealOut, float *ImagOut) +{ + int NumBits; /* Number of bits needed to store indices */ + int i, j, k, n; + int BlockSize, BlockEnd; + + double angle_numerator = 2.0 * M_PI; + double tr, ti; /* temp real, temp imaginary */ +/* + if (!IsPowerOfTwo(NumSamples)) { + fprintf(stderr, "%d is not a power of two\n", NumSamples); + exit(1); + } +*/ + if (!gFFTBitTable[0]) + InitFFT(); + + if (!InverseTransform) + angle_numerator = -angle_numerator; + + NumBits = NumberOfBitsNeeded(NumSamples); + + /* + ** Do simultaneous data copy and bit-reversal ordering into outputs... + */ + for (i = 0; i < NumSamples; i++) { + j = FastReverseBits(i, NumBits); + RealOut[j] = RealIn[i]; + ImagOut[j] = (ImagIn == NULL) ? 0.0 : ImagIn[i]; + } + + /* + ** Do the FFT itself... + */ + + BlockEnd = 1; + for (BlockSize = 2; BlockSize <= NumSamples; BlockSize <<= 1) { + + double delta_angle = angle_numerator / (double) BlockSize; + + double sm2 = sin(-2 * delta_angle); + double sm1 = sin(-delta_angle); + double cm2 = cos(-2 * delta_angle); + double cm1 = cos(-delta_angle); + double w = 2 * cm1; + double ar0, ar1, ar2, ai0, ai1, ai2; + + for (i = 0; i < NumSamples; i += BlockSize) { + ar2 = cm2; + ar1 = cm1; + + ai2 = sm2; + ai1 = sm1; + + for (j = i, n = 0; n < BlockEnd; j++, n++) { + ar0 = w * ar1 - ar2; + ar2 = ar1; + ar1 = ar0; + + ai0 = w * ai1 - ai2; + ai2 = ai1; + ai1 = ai0; + + k = j + BlockEnd; + tr = ar0 * RealOut[k] - ai0 * ImagOut[k]; + ti = ar0 * ImagOut[k] + ai0 * RealOut[k]; + + RealOut[k] = RealOut[j] - tr; + ImagOut[k] = ImagOut[j] - ti; + + RealOut[j] += tr; + ImagOut[j] += ti; + } + } + BlockEnd = BlockSize; + } + + /* + ** Need to normalize if inverse transform... + */ + + if (InverseTransform) { + float denom = (float) NumSamples; + + for (i = 0; i < NumSamples; i++) { + RealOut[i] /= denom; + ImagOut[i] /= denom; + } + } +} + +void InitFFT() { + int len=2; + int b, i; + for (b=0; b>= 1; + } + + return rev; +} + + +/* + * PowerSpectrum + * + * This function computes the same as RealFFT, above, but + * adds the squares of the real and imaginary part of each + * coefficient, extracting the power and throwing away the + * phase. + * + * For speed, it does not call RealFFT, but duplicates some + * of its code. + */ + +void PowerSpectrum(float In[PSNumS], float Out[PSHalf]) { + int i; + + float theta = M_PI / PSHalf; + + float tmpReal[PSHalf]; + float tmpImag[PSHalf]; + float RealOut[PSHalf]; + float ImagOut[PSHalf]; + + for (i=0; i #include +#include "compute.h" + typedef void (*cb_processdata_t)(int n, float *); @@ -60,10 +62,12 @@ void parse_testfile(cb_processdata_t cb) { FILE *fh=fopen("./test.raw", "r"); if (fh==NULL) return; - n=128; + //n=128; + n=512; while ( (n=fread(f, sizeof(float), n, fh)) > 0 ) { cb(n,f); - n=128+256*(rand()%7); + //n=128+256*(rand()%7); + n=512; } fclose(fh); } @@ -81,10 +85,19 @@ void process_mean_max(int n, float *f) { printf("%+.3f %+.3f %4i\n", mean, max, n); } +void process_level(int n, float *f) { + int rate=24000; + float level; + + level=compute_level(f, n, rate); + printf("%+.3f %4i\n", level, n); +} + int main() { //test_todb_a(); //dump_testfile(); - parse_testfile(process_mean_max); + //parse_testfile(process_mean_max); + parse_testfile(process_level); return 0; } -- cgit v1.2.3