summaryrefslogtreecommitdiff
path: root/src/compute.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/compute.c')
-rw-r--r--src/compute.c116
1 files changed, 116 insertions, 0 deletions
diff --git a/src/compute.c b/src/compute.c
new file mode 100644
index 0000000..272d6f8
--- /dev/null
+++ b/src/compute.c
@@ -0,0 +1,116 @@
+#include "compute.h"
+
+#include "fft.h"
+#include <math.h>
+
+#define MIN_SAMPLES 256
+#define MAX_SAMPLES 2048
+
+//#define MAX(a,b) (a>b?a:b)
+//#define MIN(a,b) (a<b?a:b)
+
+//static inline float todB_a(const float *x);
+void compute_spectrum(float *data, int width, float output[PSHalf]);
+
+
+float compute_level(const float *data, size_t nsamples, int rate) {
+
+ size_t i;
+ float input[MAX_SAMPLES], pwrspec[PSHalf];
+ float value;
+ int f, min_f_index, max_f_index;
+
+ if (nsamples >= 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<MIN_SAMPLES;i++) {
+ if ( (i/nsamples)%2==1 )
+ input[i]=data[i]; // First channel only
+ else
+ input[i]=data[nsamples-i-1];
+ }
+ nsamples=MIN_SAMPLES;
+ } else {
+ for (i=0;i<nsamples;i++) {
+ input[i]=data[i]; // First channel only
+ }
+ }
+
+ compute_spectrum(input, nsamples, pwrspec);
+
+ // Compute the mean power for 200Hz to 2000Hz band
+ min_f_index=((float)PSHalf)*200.f/(((float)rate)/2.f);
+ max_f_index=((float)PSHalf)*2000.f/(((float)rate)/2.f);
+
+ value=0.f;
+ for (f=min_f_index;f<=max_f_index;f++) {
+ value+=pwrspec[f];
+ }
+ // Mean value
+ value=value/(max_f_index-min_f_index+1);
+
+ return value;
+}
+/*
+static inline float todB_a(const float *x){
+ return (float)((*(int32_t *)x)&0x7fffffff) * 7.17711438e-7f -764.6161886f;
+}
+*/
+// Adapted from Audacity
+void compute_spectrum(float *data, int width, float output[PSHalf]) {
+
+ int i, start, windows;
+ float temp;
+ float in[PSNumS];
+ float out[PSHalf];
+ float processed[PSHalf]={0.0f};
+
+ start = 0;
+ windows = 0;
+ while (start + PSNumS <= width) {
+ // Windowing : Hanning
+ for (i=0; i<PSNumS; i++)
+ in[i] = data[start+i] *(0.50-0.50*cos(2*M_PI*i/(PSNumS-1)));
+
+ // Returns only the real part of the result
+ PowerSpectrum(in, out);
+
+ for (i=0; i<PSHalf; i++)
+ processed[i] += out[i];
+
+ start += PSHalf;
+ windows++;
+ }
+ // Convert to decibels
+ // But do it safely; -Inf is nobody's friend
+ for (i = 0; i < PSHalf; i++){
+ temp=(processed[i] / PSNumS / windows);
+ if (temp > 0.0)
+ output[i] = 10*log10(temp);
+ else
+ output[i] = 0;
+ }
+}
+
+void audio2hsv_1(float audio_level, float *light_h, float *light_s, float *light_v) {
+ static float hue=0;
+
+ float level_norm=(50.f+audio_level)/30.f;
+
+ if (level_norm<0.f) level_norm=0.f;
+ if (level_norm>1.f) level_norm=1.f;
+ hue=(hue+0.0002f);
+ if (hue>1.f) hue-=1.f;
+
+ printf("%+3.1f %+1.3f\n", audio_level, level_norm);
+
+ // Dummy code
+ *light_h=hue;
+ *light_s=1.f;
+ *light_v=level_norm;
+}
+