/* Instru2Light - Illumine un instrument de musique en temps réel Copyright (C) 2012-2013 Ludovic Pouzenc <lpouzenc@gmail.com> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "compute.h" #include "fft.h" #include <math.h> #define MIN_SAMPLES 256 #define MAX_SAMPLES 2048 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 : %zu >= %i\n", nsamples, MAX_SAMPLES); nsamples=MAX_SAMPLES; } if (nsamples < MIN_SAMPLES) { printf("WARN : nsamples < MIN_SAMPLES : %zu >= %i\n", nsamples, MIN_SAMPLES); return -120.f; } /* 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; } /* This function was adapted from Audacity 1.3.13 (orignally in C++ and with more genericity and functionnality) Original Author : Dominic Mazzoni Licenced under GPL 2.0 */ 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; static float value_decay[8]={0.f}; static int decay_idx=0; int i; float level_norm, temp; // Testé avec micro externe sur lud-msi //[-38dB;0dB] -> [0.0;1.0] level_norm=(38.f+audio_level)/38.f; if (level_norm<0.0f) level_norm=0.f; //if (level_norm<0.1f) level_norm=0.f; //FIXME : ici cache misere pour le tremblement sur plancher bruit if (level_norm>1.f) level_norm=1.f; if (decay_idx>=8) decay_idx=0; value_decay[decay_idx++]=level_norm; 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; temp=hue+level_norm/3.f; *light_h=temp-(int)temp; // Fractionnal part *light_s=1.f; // *light_v=level_norm; temp=0.f; for(i=0;i<8;i++) temp+=value_decay[i]; temp/=8.f; *light_v=temp; }