inline void impulse2freq(int id, float *imp, unsigned int length, fftw_real *out) { fftw_real impulse_time[MAX_FFT_LENGTH]; #ifdef FFTW3 fft_plan tmp_plan; #endif unsigned int i, fftl = 128; while (fftl < length+SEG_LENGTH) { fftl *= 2; } fft_length[id] = fftl; #ifdef FFTW3 plan_rc[id] = fftwf_plan_r2r_1d(fftl, real_in, comp_out, FFTW_R2HC, FFTW_MEASURE); plan_cr[id] = fftwf_plan_r2r_1d(fftl, comp_in, real_out, FFTW_HC2R, FFTW_MEASURE); tmp_plan = fftwf_plan_r2r_1d(fftl, impulse_time, out, FFTW_R2HC, FFTW_MEASURE); #else plan_rc[id] = rfftw_create_plan(fftl, FFTW_REAL_TO_COMPLEX, FFTW_ESTIMATE); plan_cr[id] = rfftw_create_plan(fftl, FFTW_COMPLEX_TO_REAL, FFTW_ESTIMATE); #endif for (i=0; i<length; i++) { impulse_time[i] = imp[i]; } for (; i<fftl; i++) { impulse_time[i] = 0.0f; } #ifdef FFTW3 fftwf_execute(tmp_plan); fftwf_destroy_plan(tmp_plan); #else rfftw_one(plan_rc[id], impulse_time, out); #endif }
FFT::FFT(int nsamples_){ nsamples=nsamples_; if (nsamples%2!=0) { nsamples+=1; printf("WARNING: Odd sample size on FFT::FFT() (%d)",nsamples); }; smp=new REALTYPE[nsamples];for (int i=0;i<nsamples;i++) smp[i]=0.0; freq=new REALTYPE[nsamples/2+1];for (int i=0;i<nsamples/2+1;i++) freq[i]=0.0; window.data=new REALTYPE[nsamples];for (int i=0;i<nsamples;i++) window.data[i]=0.707; window.type=W_RECTANGULAR; #ifdef KISSFFT datar=new kiss_fft_scalar[nsamples+2]; for (int i=0;i<nsamples+2;i++) datar[i]=0.0; datac=new kiss_fft_cpx[nsamples/2+2]; for (int i=0;i<nsamples/2+2;i++) datac[i].r=datac[i].i=0.0; plankfft = kiss_fftr_alloc(nsamples,0,0,0); plankifft = kiss_fftr_alloc(nsamples,1,0,0); #else data=new REALTYPE[nsamples];for (int i=0;i<nsamples;i++) data[i]=0.0; planfftw=fftwf_plan_r2r_1d(nsamples,data,data,FFTW_R2HC,FFTW_ESTIMATE); planifftw=fftwf_plan_r2r_1d(nsamples,data,data,FFTW_HC2R,FFTW_ESTIMATE); #endif rand_seed=start_rand_seed; start_rand_seed+=161103; };
bool PitchTracker::setParameters(int priority, int policy, int sampleRate, int buffersize) { assert(buffersize <= FFT_SIZE); if (error) { return false; } m_sampleRate = fixed_sampleRate / DOWNSAMPLE; resamp.setup(sampleRate, m_sampleRate, 1, 16); // 16 == least quality if (m_buffersize != buffersize) { m_buffersize = buffersize; m_fftSize = m_buffersize + (m_buffersize+1) / 2; fftwf_destroy_plan(m_fftwPlanFFT); fftwf_destroy_plan(m_fftwPlanIFFT); m_fftwPlanFFT = fftwf_plan_r2r_1d( m_fftSize, m_fftwBufferTime, m_fftwBufferFreq, FFTW_R2HC, FFTW_ESTIMATE); m_fftwPlanIFFT = fftwf_plan_r2r_1d( m_fftSize, m_fftwBufferFreq, m_fftwBufferTime, FFTW_HC2R, FFTW_ESTIMATE); } if (!m_fftwPlanFFT || !m_fftwPlanIFFT) { error = true; return false; } if (!m_pthr) { start_thread(priority, policy); } return !error; }
/** init() Initalises the parameters of a class instance. This must be called before use @param n_ The size of the data windows to be processed @param k_ The number of outputs wanted (autocorr size = n_ + k_). Set k_ = 0, to get default n_/2 @param rate_ The sampling rate of the incoming signal to process @param threshold_ The ratio of highest peak to the first peak allowed to be chosen */ void MyTransforms::init(int n_, int k_, double rate_, /*float threshold_, */bool equalLoudness_, int numHarmonics_) { const int myFFTMode = FFTW_ESTIMATE; //const int myFFTMode = FFTW_MEASURE; //const int myFFTMode = FFTW_PATIENT; uninit(); if(k_ == 0) k_ = (n_ + 1) / 2; n = n_; k = k_; size = n + k; rate = rate_; //_threshold = threshold_; equalLoudness = equalLoudness_; numHarmonics = numHarmonics_; dataTemp = (float*)fftwf_malloc(sizeof(float) * n); dataTime = (float*)fftwf_malloc(sizeof(float) * n); dataFFT = (float*)fftwf_malloc(sizeof(float) * n); autocorrTime = (float*)fftwf_malloc(sizeof(float) * size); autocorrFFT = (float*)fftwf_malloc(sizeof(float) * size); //storeFFT = (float*)fftwf_malloc(sizeof(float) * size); //equalLoudnessTable = (float*)fftwf_malloc(sizeof(float) * n); hanningCoeff = (float*)fftwf_malloc(sizeof(float) * n); planAutocorrTime2FFT = fftwf_plan_r2r_1d(size, autocorrTime, autocorrFFT, FFTW_R2HC, myFFTMode); planAutocorrFFT2Time = fftwf_plan_r2r_1d(size, autocorrFFT, autocorrTime, FFTW_HC2R, myFFTMode); planDataTime2FFT = fftwf_plan_r2r_1d(n, dataTime, dataFFT, FFTW_R2HC, myFFTMode); planDataFFT2Time = fftwf_plan_r2r_1d(n, dataFFT, dataTime, FFTW_HC2R, myFFTMode); //??? harmonicsAmpLeft = (float*)fftwf_malloc(numHarmonics * sizeof(float)); harmonicsPhaseLeft = (float*)fftwf_malloc(numHarmonics * sizeof(float)); harmonicsAmpCenter = (float*)fftwf_malloc(numHarmonics * sizeof(float)); harmonicsPhaseCenter = (float*)fftwf_malloc(numHarmonics * sizeof(float)); harmonicsAmpRight = (float*)fftwf_malloc(numHarmonics * sizeof(float)); harmonicsPhaseRight = (float*)fftwf_malloc(numHarmonics * sizeof(float)); //storeFFTAmp1 = (float*)malloc(n/2 * sizeof(float)); //storeFFTAmp2 = (float*)malloc(n/2 * sizeof(float)); freqPerBin = rate / double(size); //buildEqualLoudnessTable(50.0); //init hanningCoeff. The hanning windowing function hanningScalar = 0; for(int j=0; j<n; j++) { hanningCoeff[j] = (1.0 - cos(double(j+1) / double(n+1) * twoPI)) / 2.0; hanningScalar += hanningCoeff[j]; } hanningScalar /= 2; //to normalise the FFT coefficients we divide by the sum of the hanning window / 2 fastSmooth = new fast_smooth(n/8); //printf("fast_smooth size = %d\n", n/8); beenInit = true; }
DCT::DCT(int n, unsigned flags) { sqrt2 = sqrt(2.0f); this->n = n; cd = 1.0f/(n*2)*sqrt2/2.0f; tmpf = MyAlloc<float>::alc(n); tmpi = MyAlloc<float>::alc(n); pf = fftwf_plan_r2r_1d(n,tmpf,tmpf,FFTW_REDFT10,flags); pi = fftwf_plan_r2r_1d(n,tmpi,tmpi,FFTW_REDFT01,flags); check(pf,"can not initialize pf in DCT(int n, unsigned flags) "); check(pi,"can not initialize pi in DCT(int n, unsigned flags) "); }
FFTwrapper::FFTwrapper(int fftsize_){ fftsize=fftsize_; tmpfftdata1=new fftw_real[fftsize]; tmpfftdata2=new fftw_real[fftsize]; #ifdef FFTW_VERSION_2 planfftw=rfftw_create_plan(fftsize,FFTW_REAL_TO_COMPLEX,FFTW_ESTIMATE|FFTW_IN_PLACE); planfftw_inv=rfftw_create_plan(fftsize,FFTW_COMPLEX_TO_REAL,FFTW_ESTIMATE|FFTW_IN_PLACE); #else planfftw=fftwf_plan_r2r_1d(fftsize,tmpfftdata1,tmpfftdata1,FFTW_R2HC,FFTW_ESTIMATE); planfftw_inv=fftwf_plan_r2r_1d(fftsize,tmpfftdata2,tmpfftdata2,FFTW_HC2R,FFTW_ESTIMATE); #endif };
// TODO make this run automatically from the pipeline extern "C" void init_globals() { filter_filepath = new Field<char, -1, 0, VariableStorage>(); audio = new Field<float, -1, 0, VariableStorage>(); audio_length = new Field<int>(); segment_offset = new Field<int>(); fft = new Field<float, fft_size>(); clipped = new Field<float, dim>(); float dummy_seg_size[seg_size]; float dummy_fft_size[fft_size]; fft_plan = (fftwf_plan*)malloc(sizeof(fftwf_plan)); ifft_plan = (fftwf_plan*)malloc(sizeof(fftwf_plan)); *fft_plan = fftwf_plan_r2r_1d(fft_size, dummy_seg_size, dummy_seg_size, FFTW_R2HC, FFTW_ESTIMATE); *ifft_plan = fftwf_plan_r2r_1d(fft_size, dummy_fft_size, dummy_fft_size, FFTW_HC2R, FFTW_ESTIMATE); }
int padsynth_init(void) { global.padsynth_table_size = -1; global.padsynth_outfreqs = NULL; global.padsynth_outsamples = NULL; global.padsynth_fft_plan = NULL; global.padsynth_ifft_plan = NULL; /* allocate input FFT buffer */ global.padsynth_inbuf = (float *)fftwf_malloc(WAVETABLE_POINTS * sizeof(float)); if (!global.padsynth_inbuf) { return 0; } /* create input FFTW plan */ #ifdef FFTW_VERSION_2 global.padsynth_fft_plan = (void *)rfftw_create_plan(WAVETABLE_POINTS, FFTW_REAL_TO_COMPLEX, FFTW_ESTIMATE); #else global.padsynth_fft_plan = (void *)fftwf_plan_r2r_1d(WAVETABLE_POINTS, global.padsynth_inbuf, global.padsynth_inbuf, FFTW_R2HC, FFTW_ESTIMATE); #endif if (!global.padsynth_fft_plan) { padsynth_fini(); return 0; } return 1; }
FFTX_FN_PREFIX void fftx_init(struct FFTAnalysis *ft, uint32_t window_size, double rate, double fps) { ft->rate = rate; ft->window_size = window_size; ft->data_size = window_size / 2; ft->hann_window = NULL; ft->rboff = 0; ft->smps = 0; ft->step = 0; ft->sps = (fps > 0) ? ceil(rate / fps) : 0; ft->freq_per_bin = ft->rate / ft->data_size / 2.f; ft->phasediff_step = M_PI / ft->data_size; ft->phasediff_bin = 0; ft->ringbuf = (float *) malloc(window_size * sizeof(float)); ft->fft_in = (float *) fftwf_malloc(sizeof(float) * window_size); ft->fft_out = (float *) fftwf_malloc(sizeof(float) * window_size); ft->power = (float *) malloc(ft->data_size * sizeof(float)); ft->phase = (float *) malloc(ft->data_size * sizeof(float)); ft->phase_h = (float *) malloc(ft->data_size * sizeof(float)); fftx_reset(ft); ft->fftplan = fftwf_plan_r2r_1d(window_size, ft->fft_in, ft->fft_out, FFTW_R2HC, FFTW_MEASURE); }
void ofxFftw::setup(int signalSize, fftWindowType windowType) { ofxFft::setup(signalSize, windowType); // more info on setting up a forward r2r fft here: // http://www.fftw.org/fftw3_doc/Real_002dto_002dReal-Transforms.html fftIn = (float*) fftwf_malloc(sizeof(float) * signalSize); fftOut = (float*) fftwf_malloc(sizeof(float) * signalSize); fftPlan = fftwf_plan_r2r_1d(signalSize, fftIn, fftOut, FFTW_R2HC, FFTW_DESTROY_INPUT | FFTW_MEASURE); // the difference between setting up an r2r ifft and fft // is using the flag/kind FFTW_HC2R instead of FFTW_R2HC: // http://www.fftw.org/fftw3_doc/Real_002dto_002dReal-Transform-Kinds.html ifftIn = (float*) fftwf_malloc(sizeof(float) * signalSize); ifftOut = (float*) fftwf_malloc(sizeof(float) * signalSize); ifftPlan = fftwf_plan_r2r_1d(signalSize, ifftIn, ifftOut, FFTW_HC2R, FFTW_DESTROY_INPUT | FFTW_MEASURE); }
void MyMFCC::myUpdate(MarControlPtr sender) { static const double fh = 0.5; static const double fl = 0; mrs_natural filterCount = inObservations_; //mrs_natural filterCount = getControl("mrs_natural/coefficients")->to<mrs_natural>(); //mrs_natural windowSize = 2 * (inObservations_ - 1); //mrs_real sampleRate = israte_ * windowSize; if (filterCount < 1 ) //|| windowSize < 1) { // skip unnecessary updates m_filterCount = filterCount; //m_win = windowSize; //m_sr = sampleRate; return; } //cout << "*** MyMFCC: sampleRate = " << sampleRate << endl; /* if (filterCount != m_filterCount || windowSize != m_win || sampleRate != m_sr) { initMelFilters(filterCount, windowSize, sampleRate, fl, fh); } */ if (filterCount != m_filterCount) { fftwf_free(m_dctIn); fftwf_free(m_dctOut); fftwf_destroy_plan(m_plan); m_dctIn = fftwf_alloc_real(filterCount); m_dctOut = fftwf_alloc_real(filterCount); m_plan = fftwf_plan_r2r_1d(filterCount, m_dctIn, m_dctOut, FFTW_REDFT10, FFTW_ESTIMATE); } /* if ( windowSize != m_win ) { m_buf.allocate( inObservations_ ); } */ setControl("mrs_natural/onObservations", filterCount); setControl("mrs_natural/onSamples", inSamples_); m_filterCount = filterCount; //m_win = windowSize; //m_sr = sampleRate; }
int srslte_dft_replan_r(srslte_dft_plan_t *plan, const int new_dft_points) { int sign = (plan->dir == SRSLTE_DFT_FORWARD) ? FFTW_R2HC : FFTW_HC2R; if (plan->p) { fftwf_destroy_plan(plan->p); plan->p = NULL; } plan->p = fftwf_plan_r2r_1d(new_dft_points, plan->in, plan->out, sign, FFTW_TYPE); if (!plan->p) { return -1; } plan->size = new_dft_points; return 0; }
static rfftw_info *rfftw_getplan(int n,int fwd) { rfftw_info *info; int logn = ilog2(n); if (logn < MINFFT || logn > MAXFFT) return (0); info = (fwd?rfftw_fwd:rfftw_bwd)+(logn-MINFFT); if (!info->plan) { info->in = (float*) fftwf_malloc(sizeof(float) * n); info->out = (float*) fftwf_malloc(sizeof(float) * n); info->plan = fftwf_plan_r2r_1d(n, info->in, info->out, fwd?FFTW_R2HC:FFTW_HC2R, FFTW_MEASURE); } return info; }
int dft_plan_r2r(const int dft_points, dft_dir_t dir, dft_plan_t *plan) { int sign; sign = (dir == FORWARD) ? FFTW_R2HC : FFTW_HC2R; allocate(plan,sizeof(float),sizeof(float), dft_points); plan->p = fftwf_plan_r2r_1d(dft_points, plan->in, plan->out, sign, 0U); if (!plan->p) { return -1; } plan->size = dft_points; plan->mode = REAL_2_REAL; return 0; }
/** * Do all necessary initializations * @param settings Pointer to the global settings */ void TaskCoreFFTW::prepare(swspect_settings_t* settings) { /* get settings and prepare buffers */ this->cfg = settings; this->windowfct = (fftw_real*)memalign(128, sizeof(fftw_real)*cfg->fft_points); this->unpacked_re = (fftw_real*)memalign(128, sizeof(fftw_real)*cfg->fft_points); this->fft_result_reim = new fftw_real*[cfg->num_sources]; this->fft_accu_reim = new fftw_real*[cfg->num_sources]; this->num_ffts_accumulated = 0; this->num_spectra_calculated = 0; for (int s=0; s<cfg->num_sources; s++) { this->fft_result_reim[s] = (fftw_real*)memalign(128, sizeof(fftw_real)*cfg->fft_points); // 4*fft_points*2 if c2c dft this->fft_accu_reim[s] = (fftw_real*)memalign(128, sizeof(fftw_real)*cfg->fft_points); } this->fft_result_reim_conj = (fftw_real*)memalign(128, sizeof(fftw_real)*cfg->fft_points); // 4*fft_points*2 if c2c dft this->spectrum_scalevector = (fftw_real*)memalign(128, sizeof(fftw_real)*cfg->fft_points); this->processing_stage = STAGE_NONE; this->total_runtime = 0.0; this->total_ffts = 0; reset_spectrum(); /* windowing function */ for (int i=0; i<(cfg->fft_points); i++) { fftw_real w = sin(fftw_real(i) * M_PI/(cfg->fft_points - 1.0)); windowfct[i] = w*w; } /* FFT setup */ // fftwPlan = fftw_create_plan(cfg->fft_points, FFTW_REAL_TO_COMPLEX, FFTW_ESTIMATE); // IPP_FFT_DIV_INV_BY_N, ippAlgHintFast fftwPlans = new fftwf_plan[cfg->num_sources]; for (int s=0; s<cfg->num_sources; s++) { fftwPlans[s] = fftwf_plan_r2r_1d(cfg->fft_points, this->unpacked_re, this->fft_result_reim[s], FFTW_R2HC, FFTW_ESTIMATE); } /* prepare fixed scale/normalization factor */ vecSet(fftw_real(1.0/cfg->integrated_ffts), spectrum_scalevector, cfg->fft_points); /* init mutexeds and start the worker thread */ terminate_worker = false; pthread_mutex_init(&mmutex, NULL); pthread_mutex_lock(&mmutex); pthread_create(&wthread, NULL, taskcorefft_worker, (void*)this); return; }
int srslte_dft_plan_r(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_dir_t dir) { allocate(plan,sizeof(float),sizeof(float), dft_points); int sign = (dir == SRSLTE_DFT_FORWARD) ? FFTW_R2HC : FFTW_HC2R; plan->p = fftwf_plan_r2r_1d(dft_points, plan->in, plan->out, sign, 0U); if (!plan->p) { return -1; } plan->size = dft_points; plan->mode = SRSLTE_REAL; plan->dir = dir; plan->forward = (dir==SRSLTE_DFT_FORWARD)?true:false; plan->mirror = false; plan->db = false; plan->norm = false; plan->dc = false; return 0; }
PowerSpectrum( int windowSize ): m_windowSize(windowSize) { m_inBuffer = fftwf_alloc_real(windowSize); m_outBuffer = fftwf_alloc_real(windowSize); m_plan = fftwf_plan_r2r_1d(windowSize, m_inBuffer, m_outBuffer, FFTW_R2HC, FFTW_ESTIMATE); double pi = Segmenter::pi(); m_window = new float[windowSize]; float sumWindow = 0.f; for (int idx=0; idx < windowSize; ++idx) { // hamming window: m_window[idx] = 0.54 - 0.46 * std::cos(2 * pi * idx / (windowSize-1) ); sumWindow += m_window[idx]; } m_outputScale = 2.f / sumWindow; m_outputScale *= m_outputScale; // square, because we'll be multiplying power instead of raw spectrum m_output.resize(windowSize / 2 + 1); }
MirageAudio* mirageaudio_initialize(gint rate, gint seconds, gint winsize) { MirageAudio *ma; gint i; ma = g_new0(MirageAudio, 1); ma->rate = rate; ma->seconds = seconds; ma->hops = rate*seconds/winsize; ma->out = malloc(ma->hops*((winsize/2)+1)*sizeof(float)); // FFTW ma->winsize = winsize; ma->fftwsize = 2 * ma->winsize; ma->fftw = (float*)fftwf_malloc(ma->fftwsize * sizeof(float)); ma->fftwplan = fftwf_plan_r2r_1d((2*ma->winsize), ma->fftw, ma->fftw, FFTW_R2HC, FFTW_ESTIMATE | FFTW_DESTROY_INPUT); // Hann Window ma->window = malloc(ma->winsize*sizeof(float)); for (i = 0; i < ma->winsize; i++) { ma->window[i] = (float)(0.5 * (1.0 - cos((2.0*M_PI *(double)i)/(double)(ma->winsize-1)))); } // Samplingrate converter int error; ma->src_state = src_new(SRC_ZERO_ORDER_HOLD, 1, &error); ma->src_data.data_out = malloc(SRC_BUFFERLENGTH*sizeof(float)); ma->src_data.output_frames = SRC_BUFFERLENGTH; // cancel decoding mutex ma->decoding_mutex = g_mutex_new(); return ma; }
int main(int argc, char*argv[]) { #ifdef HAVE_FFTW3_H unsigned int n = 32; // transform size unsigned int d = 4; // number of elements to print each line int dopt; while ((dopt = getopt(argc,argv,"uhn:")) != EOF) { switch (dopt) { case 'u': case 'h': usage(); return 0; case 'n': n = atoi(optarg); break; default: exit(1); } } // validate input if ( n < 2 ) { fprintf(stderr,"error: input transform size must be at least 2\n"); exit(1); } // create and initialize data arrays float x[n]; float y[n]; unsigned int i; for (i=0; i<n; i++) x[i] = cosf(2*M_PI*i/((float)n)) * expf(-4.0f*i*i/((float)n*n)); // create fftw plans fftwf_plan plan[8]; plan[0] = fftwf_plan_r2r_1d(n, x, y, FFTW_REDFT00, FFTW_ESTIMATE); plan[1] = fftwf_plan_r2r_1d(n, x, y, FFTW_REDFT10, FFTW_ESTIMATE); plan[2] = fftwf_plan_r2r_1d(n, x, y, FFTW_REDFT01, FFTW_ESTIMATE); plan[3] = fftwf_plan_r2r_1d(n, x, y, FFTW_REDFT11, FFTW_ESTIMATE); plan[4] = fftwf_plan_r2r_1d(n, x, y, FFTW_RODFT00, FFTW_ESTIMATE); plan[5] = fftwf_plan_r2r_1d(n, x, y, FFTW_RODFT10, FFTW_ESTIMATE); plan[6] = fftwf_plan_r2r_1d(n, x, y, FFTW_RODFT01, FFTW_ESTIMATE); plan[7] = fftwf_plan_r2r_1d(n, x, y, FFTW_RODFT11, FFTW_ESTIMATE); char plan_name[][8] = {"REDFT00", "REDFT10", "REDFT01", "REDFT11", "RODFT00", "RODFT10", "RODFT01", "RODFT11"}; unsigned int j; printf("// %u-point real even/odd dft data\n", n); printf("float fftdata_r2r_n%u[] = {\n ", n); for (j=0; j<n; j++) { //printf(" %16.10f%s\n", y[j], j==(n-1) ? "};" : ","); printf("%16.8e", x[j]); if ( j==n-1 ) printf(" "); else if ( ((j+1)%d)==0 ) printf(",\n "); else printf(", "); } printf("};\n\n"); // execute plans and print for (i=0; i<8; i++) { fftwf_execute(plan[i]); printf("\n"); printf("// %s\n", plan_name[i]); printf("float fftdata_r2r_%s_n%u[] = {\n ", plan_name[i], n); for (j=0; j<n; j++) { //printf(" %16.10f%s\n", y[j], j==(n-1) ? "};" : ","); printf("%16.8e", y[j]); if ( j==n-1 ) printf(" "); else if ( ((j+1)%d)==0 ) printf(",\n "); else printf(", "); } printf("};\n\n"); } // destroy plans for (i=0; i<8; i++) fftwf_destroy_plan(plan[i]); #else printf("please install fftw and try again\n"); #endif return 0; }
/** Initialize the convolver. * It also sets the filter to be a Dirac. Thus, if no filter is specified * the audio data are not affected. However, quite some computational * load for nothing... * * You should use create() instead of directly using this constructor. * @throw std::bad_alloc if not enough memory could be allocated * @throw std::runtime_error if sizeof(float) != 4 **/ Convolver::Convolver(const nframes_t nframes, const crossfade_t crossfade_type) throw (std::bad_alloc, std::runtime_error) : _frame_size(nframes), _partition_size(nframes + nframes), _crossfade_type( crossfade_type), _no_of_partitions_to_process(0), _old_weighting_factor( 0) { // make sure that SIMD instructions can be used properly if (sizeof(float) != 4) { throw(std::runtime_error("sizeof(float) on your computer is not 4! " " The convolution can not take place properly.")); } _signal.clear(); _waiting_queue.clear(); // allocate memory and initialize to 0 _fft_buffer.resize(_partition_size, 0.0f); _ifft_buffer.resize(_partition_size, 0.0f); // create first partition //_filter_coefficients.resize(_partition_size, 0.0f); _zeros.resize(_partition_size, 0.0f); _output_buffer.resize(_frame_size, 0.0f); // create fades if required if (_crossfade_type != none) { // init memory _fade_in.resize(_frame_size, 0.0f); _fade_out.resize(_frame_size, 0.0f); // this is the ifft normalization factor (fftw3 does not normalize) const float norm = 1.0f / _partition_size; // raised cosine fade if (_crossfade_type == raised_cosine) { // create fades for (unsigned int n = 0u; n < _frame_size; n++) { _fade_in[n] = norm * (0.5f + 0.5f * cos( static_cast<float>(_frame_size - n) / _frame_size * pi_float)); _fade_out[n] = norm * (0.5f + 0.5f * cos( static_cast<float>(n) / _frame_size * pi_float)); } // for } // if // linear fade else if (_crossfade_type == linear) { // create fades for (unsigned int n = 0u; n < _frame_size; n++) { _fade_in[n] = norm * (static_cast<float>(n) / _frame_size); _fade_out[n] = norm * (static_cast<float>(_frame_size - n) / _frame_size); } // for } // else if } // if // create fft plans for halfcomplex data format _fft_plan = fftwf_plan_r2r_1d(_partition_size, &_fft_buffer[0], &_fft_buffer[0], FFTW_R2HC, FFTW_PATIENT); _ifft_plan = fftwf_plan_r2r_1d(_partition_size, &_ifft_buffer[0], &_ifft_buffer[0], FFTW_HC2R, FFTW_PATIENT); // calculate transfer function of a dirac std::copy(_zeros.begin(), _zeros.end(), _fft_buffer.begin()); _fft_buffer[0] = 1.0f; _fft(); // store dirac _neutral_filter = _fft_buffer; // clear _fft_buffer std::copy(_zeros.begin(), _zeros.end(), _fft_buffer.begin()); // set dirac as default filter set_neutral_filter(); }
/** This is an autarc function to precalculate the frequency * domain filter partitions that a \b Convolver needs. It does * not require an instantiation of a \b Convolver. However, it is * not very efficient since an FFT plan is created with every call. * @param container place to store the partitions. * @param filter impulse response of the filter * @param filter_size size of the impulse response * @param partition_size size of the partitions (this is the * partition size that the outside world sees, internally it is twice as long) */ void Convolver::prepare_impulse_response(data_t& container, const float *filter, const unsigned int filter_size, const unsigned int partition_size) { // find out how many complete partitions we have unsigned int no_of_partitions = filter_size / partition_size; // if there is even one more if (filter_size % partition_size) no_of_partitions++; // empty container container.clear(); // allocate memory container.resize(2 * no_of_partitions * partition_size, 0.0f); // define temporary buffers data_t fft_buffer; data_t zeros; // allocate memory and initialize to 0 fft_buffer.resize(2 * partition_size, 0.0f); zeros.resize(2 * partition_size, 0.0f); // create fft plans for halfcomplex data format fftwf_plan fft_plan = fftwf_plan_r2r_1d(2 * partition_size, &fft_buffer[0], &fft_buffer[0], FFTW_R2HC, FFTW_ESTIMATE); // convert filter partitionwise to frequency domain /////// process complete partitions ////////////// for (unsigned int partition = 0u; partition < no_of_partitions - 1; partition++) { std::copy(filter + partition * partition_size, filter + (partition + 1) * partition_size, fft_buffer.begin()); // zero pad std::copy(zeros.begin(), zeros.begin() + partition_size, fft_buffer.begin() + partition_size); // fft fftwf_execute(fft_plan); sort_coefficients(fft_buffer, 2 * partition_size); // add the partition to the filter std::copy(fft_buffer.begin(), fft_buffer.begin() + 2 * partition_size, container.begin() + 2 * partition * partition_size); } ////// end process complete partitions //// process potentially incomplete last partition //////////// // zeros std::copy(zeros.begin(), zeros.end(), fft_buffer.begin()); // add filter coefficients std::copy(filter + (no_of_partitions - 1) * partition_size, filter + filter_size, fft_buffer.begin()); // fft fftwf_execute(fft_plan); sort_coefficients(fft_buffer, 2 * partition_size); // add the partition to the filter std::copy(fft_buffer.begin(), fft_buffer.end(), container.begin() + 2 * (no_of_partitions - 1) * partition_size); ///// end process potentially incomplete partition //////// // clean up fftwf_destroy_plan(fft_plan); }
/** * Instantiates the plugin. */ static LV2_Handle instantiate(const LV2_Descriptor *descriptor, double rate, const char *bundle_path, const LV2_Feature *const *features) { //Actual struct declaration Nrepel *self = (Nrepel *)calloc(1, sizeof(Nrepel)); //Retrieve the URID map callback, and needed URIDs for (int i = 0; features[i]; ++i) { if (!strcmp(features[i]->URI, LV2_URID__map)) { self->map = (LV2_URID_Map *)features[i]->data; } } if (!self->map) { //bail out: host does not support urid:map free(self); return NULL; } //For lv2 state (noise profile saving) self->atom_Vector = self->map->map(self->map->handle, LV2_ATOM__Vector); self->atom_Int = self->map->map(self->map->handle, LV2_ATOM__Int); self->atom_Float = self->map->map(self->map->handle, LV2_ATOM__Float); self->prop_fftsize = self->map->map(self->map->handle, NREPEL_URI "#fftsize"); self->prop_nwindow = self->map->map(self->map->handle, NREPEL_URI "#nwindow"); self->prop_FFTp2 = self->map->map(self->map->handle, NREPEL_URI "#FFTp2"); //Sampling related self->samp_rate = (float)rate; //FFT related self->fft_size = FFT_SIZE; self->fft_size_2 = self->fft_size / 2; self->input_fft_buffer = (float *)calloc(self->fft_size, sizeof(float)); self->output_fft_buffer = (float *)calloc(self->fft_size, sizeof(float)); self->forward = fftwf_plan_r2r_1d(self->fft_size, self->input_fft_buffer, self->output_fft_buffer, FFTW_R2HC, FFTW_ESTIMATE); self->backward = fftwf_plan_r2r_1d(self->fft_size, self->output_fft_buffer, self->input_fft_buffer, FFTW_HC2R, FFTW_ESTIMATE); //STFT window related self->window_option_input = INPUT_WINDOW; self->window_option_output = OUTPUT_WINDOW; self->input_window = (float *)calloc(self->fft_size, sizeof(float)); self->output_window = (float *)calloc(self->fft_size, sizeof(float)); //buffers for OLA self->in_fifo = (float *)calloc(self->fft_size, sizeof(float)); self->out_fifo = (float *)calloc(self->fft_size, sizeof(float)); self->output_accum = (float *)calloc(self->fft_size * 2, sizeof(float)); self->overlap_factor = OVERLAP_FACTOR; self->hop = self->fft_size / self->overlap_factor; self->input_latency = self->fft_size - self->hop; self->read_ptr = self->input_latency; //the initial position because we are that many samples ahead //soft bypass self->tau = (1.f - expf(-2.f * M_PI * 25.f * 64.f / self->samp_rate)); self->wet_dry = 0.f; //Arrays for getting bins info self->fft_p2 = (float *)calloc((self->fft_size_2 + 1), sizeof(float)); self->fft_magnitude = (float *)calloc((self->fft_size_2 + 1), sizeof(float)); self->fft_phase = (float *)calloc((self->fft_size_2 + 1), sizeof(float)); //noise threshold related self->noise_thresholds_p2 = (float *)calloc((self->fft_size_2 + 1), sizeof(float)); self->noise_thresholds_scaled = (float *)calloc((self->fft_size_2 + 1), sizeof(float)); self->noise_window_count = 0.f; self->noise_thresholds_availables = false; //noise adaptive estimation related self->auto_thresholds = (float *)calloc((self->fft_size_2 + 1), sizeof(float)); self->prev_noise_thresholds = (float *)calloc((self->fft_size_2 + 1), sizeof(float)); self->s_pow_spec = (float *)calloc((self->fft_size_2 + 1), sizeof(float)); self->prev_s_pow_spec = (float *)calloc((self->fft_size_2 + 1), sizeof(float)); self->p_min = (float *)calloc((self->fft_size_2 + 1), sizeof(float)); self->prev_p_min = (float *)calloc((self->fft_size_2 + 1), sizeof(float)); self->speech_p_p = (float *)calloc((self->fft_size_2 + 1), sizeof(float)); self->prev_speech_p_p = (float *)calloc((self->fft_size_2 + 1), sizeof(float)); //smoothing related self->smoothed_spectrum = (float *)calloc((self->fft_size_2 + 1), sizeof(float)); self->smoothed_spectrum_prev = (float *)calloc((self->fft_size_2 + 1), sizeof(float)); //transient preservation self->transient_preserv_prev = (float *)calloc((self->fft_size_2 + 1), sizeof(float)); self->tp_window_count = 0.f; self->tp_r_mean = 0.f; self->transient_present = false; //masking related self->bark_z = (float *)calloc((self->fft_size_2 + 1), sizeof(float)); self->absolute_thresholds = (float *)calloc((self->fft_size_2 + 1), sizeof(float)); self->unity_gain_bark_spectrum = (float *)calloc(N_BARK_BANDS, sizeof(float)); self->spreaded_unity_gain_bark_spectrum = (float *)calloc(N_BARK_BANDS, sizeof(float)); self->spl_reference_values = (float *)calloc((self->fft_size_2 + 1), sizeof(float)); self->alpha_masking = (float *)calloc((self->fft_size_2 + 1), sizeof(float)); self->beta_masking = (float *)calloc((self->fft_size_2 + 1), sizeof(float)); self->SSF = (float *)calloc((N_BARK_BANDS * N_BARK_BANDS), sizeof(float)); self->input_fft_buffer_at = (float *)calloc(self->fft_size, sizeof(float)); self->output_fft_buffer_at = (float *)calloc(self->fft_size, sizeof(float)); self->forward_at = fftwf_plan_r2r_1d(self->fft_size, self->input_fft_buffer_at, self->output_fft_buffer_at, FFTW_R2HC, FFTW_ESTIMATE); //reduction gains related self->Gk = (float *)calloc((self->fft_size), sizeof(float)); //whitening related self->residual_max_spectrum = (float *)calloc((self->fft_size), sizeof(float)); self->max_decay_rate = expf(-1000.f / (((WHITENING_DECAY_RATE)*self->samp_rate) / self->hop)); self->whitening_window_count = 0.f; //final ensemble related self->residual_spectrum = (float *)calloc((self->fft_size), sizeof(float)); self->denoised_spectrum = (float *)calloc((self->fft_size), sizeof(float)); self->final_spectrum = (float *)calloc((self->fft_size), sizeof(float)); //Window combination initialization (pre processing window post processing window) fft_pre_and_post_window(self->input_window, self->output_window, self->fft_size, self->window_option_input, self->window_option_output, &self->overlap_scale_factor); //Set initial gain as unity for the positive part initialize_array(self->Gk, 1.f, self->fft_size); //Compute adaptive initial thresholds compute_auto_thresholds(self->auto_thresholds, self->fft_size, self->fft_size_2, self->samp_rate); //MASKING initializations compute_bark_mapping(self->bark_z, self->fft_size_2, self->samp_rate); compute_absolute_thresholds(self->absolute_thresholds, self->fft_size_2, self->samp_rate); spl_reference(self->spl_reference_values, self->fft_size_2, self->samp_rate, self->input_fft_buffer_at, self->output_fft_buffer_at, &self->forward_at); compute_SSF(self->SSF); //Initializing unity gain values for offset normalization initialize_array(self->unity_gain_bark_spectrum, 1.f, N_BARK_BANDS); //Convolve unitary energy bark spectrum with SSF convolve_with_SSF(self->SSF, self->unity_gain_bark_spectrum, self->spreaded_unity_gain_bark_spectrum); initialize_array(self->alpha_masking, 1.f, self->fft_size_2 + 1); initialize_array(self->beta_masking, 0.f, self->fft_size_2 + 1); return (LV2_Handle)self; }
static LADSPA_Handle instantiateMbeq( const LADSPA_Descriptor *descriptor, unsigned long s_rate) { Mbeq *plugin_data = (Mbeq *)malloc(sizeof(Mbeq)); int *bin_base = NULL; float *bin_delta = NULL; fftw_real *comp = NULL; float *db_table = NULL; long fifo_pos; LADSPA_Data *in_fifo = NULL; LADSPA_Data *out_accum = NULL; LADSPA_Data *out_fifo = NULL; fftw_real *real = NULL; float *window = NULL; #line 52 "mbeq_1197.xml" int i, bin; float last_bin, next_bin; float db; float hz_per_bin = (float)s_rate / (float)FFT_LENGTH; in_fifo = calloc(FFT_LENGTH, sizeof(LADSPA_Data)); out_fifo = calloc(FFT_LENGTH, sizeof(LADSPA_Data)); out_accum = calloc(FFT_LENGTH * 2, sizeof(LADSPA_Data)); real = calloc(FFT_LENGTH, sizeof(fftw_real)); comp = calloc(FFT_LENGTH, sizeof(fftw_real)); window = calloc(FFT_LENGTH, sizeof(float)); bin_base = calloc(FFT_LENGTH/2, sizeof(int)); bin_delta = calloc(FFT_LENGTH/2, sizeof(float)); fifo_pos = 0; #ifdef FFTW3 plan_rc = fftwf_plan_r2r_1d(FFT_LENGTH, real, comp, FFTW_R2HC, FFTW_MEASURE); plan_cr = fftwf_plan_r2r_1d(FFT_LENGTH, comp, real, FFTW_HC2R, FFTW_MEASURE); #else plan_rc = rfftw_create_plan(FFT_LENGTH, FFTW_REAL_TO_COMPLEX, FFTW_ESTIMATE); plan_cr = rfftw_create_plan(FFT_LENGTH, FFTW_COMPLEX_TO_REAL, FFTW_ESTIMATE); #endif // Create raised cosine window table for (i=0; i < FFT_LENGTH; i++) { window[i] = -0.5f*cos(2.0f*M_PI*(double)i/(double)FFT_LENGTH)+0.5f; } // Create db->coeffiecnt lookup table db_table = malloc(1000 * sizeof(float)); for (i=0; i < 1000; i++) { db = ((float)i/10) - 70; db_table[i] = pow(10.0f, db/20.0f); } // Create FFT bin -> band + delta tables bin = 0; while (bin <= bands[0]/hz_per_bin) { bin_base[bin] = 0; bin_delta[bin++] = 0.0f; } for (i = 1; 1 < BANDS-1 && bin < (FFT_LENGTH/2)-1 && bands[i+1] < s_rate/2; i++) { last_bin = bin; next_bin = (bands[i+1])/hz_per_bin; while (bin <= next_bin) { bin_base[bin] = i; bin_delta[bin] = (float)(bin - last_bin) / (float)(next_bin - last_bin); bin++; } } for (; bin < (FFT_LENGTH/2); bin++) { bin_base[bin] = BANDS-1; bin_delta[bin] = 0.0f; } plugin_data->bin_base = bin_base; plugin_data->bin_delta = bin_delta; plugin_data->comp = comp; plugin_data->db_table = db_table; plugin_data->fifo_pos = fifo_pos; plugin_data->in_fifo = in_fifo; plugin_data->out_accum = out_accum; plugin_data->out_fifo = out_fifo; plugin_data->real = real; plugin_data->window = window; return (LADSPA_Handle)plugin_data; }
/* * PADsynth-ize a WhySynth wavetable. */ int padsynth_render(y_sample_t *sample) { int N, i, fc0, nh, plimit_low, plimit_high, rndlim_low, rndlim_high; float bw, stretch, bwscale, damping; float f, max, samplerate, bw0_Hz, relf; float *inbuf = global.padsynth_inbuf; float *outfreqs, *smp; /* handle the special case where the sample key limit is 256 -- these * don't get rendered because they're usually just sine waves, and are * played at very high frequency */ if (sample->max_key == 256) { sample->data = (signed short *)malloc((WAVETABLE_POINTS + 8) * sizeof(signed short)); if (!sample->data) return 0; sample->data += 4; /* guard points */ memcpy(sample->data - 4, sample->source - 4, (WAVETABLE_POINTS + 8) * sizeof(signed short)); /* including guard points */ sample->length = WAVETABLE_POINTS; sample->period = (float)WAVETABLE_POINTS; return 1; } /* calculate the output table size */ i = lrintf((float)global.sample_rate * 2.5f); /* at least 2.5 seconds long -FIX- this should be configurable */ N = WAVETABLE_POINTS * 2; while (N < i) { if (N * 5 / 4 >= i) { N = N * 5 / 4; break; } if (N * 3 / 2 >= i) { N = N * 3 / 2; break; } N <<= 1; } /* check temporary memory and IFFT plan, allocate if needed */ if (global.padsynth_table_size != N) { padsynth_free_temp(); if (global.padsynth_ifft_plan) { #ifdef FFTW_VERSION_2 rfftw_destroy_plan(global.padsynth_ifft_plan); #else fftwf_destroy_plan(global.padsynth_ifft_plan); #endif global.padsynth_ifft_plan = NULL; } global.padsynth_table_size = N; } if (!global.padsynth_outfreqs) global.padsynth_outfreqs = (float *)fftwf_malloc(N * sizeof(float)); if (!global.padsynth_outsamples) global.padsynth_outsamples = (float *)fftwf_malloc(N * sizeof(float)); if (!global.padsynth_outfreqs || !global.padsynth_outsamples) return 0; outfreqs = global.padsynth_outfreqs; smp = global.padsynth_outsamples; if (!global.padsynth_ifft_plan) global.padsynth_ifft_plan = #ifdef FFTW_VERSION_2 (void *)rfftw_create_plan(N, FFTW_COMPLEX_TO_REAL, FFTW_ESTIMATE); #else (void *)fftwf_plan_r2r_1d(N, global.padsynth_outfreqs, global.padsynth_outsamples, FFTW_HC2R, FFTW_ESTIMATE); #endif if (!global.padsynth_ifft_plan) return 0; /* allocate sample memory */ sample->data = (signed short *)malloc((N + 8) * sizeof(signed short)); if (!sample->data) return 0; sample->data += 4; /* guard points */ sample->length = N; /* condition parameters */ bw = (sample->param1 ? (float)(sample->param1 * 2) : 1.0f); /* partial width: 1, or 2 to 100 cents by 2 */ stretch = (float)(sample->param2 - 10) / 10.0f; stretch *= stretch * stretch / 10.0f; /* partial stretch: -10% to +10% */ switch (sample->param3) { default: case 0: bwscale = 1.0f; break; /* width scale: 10% to 250% */ case 2: bwscale = 0.5f; break; case 4: bwscale = 0.25f; break; case 6: bwscale = 0.1f; break; case 8: bwscale = 1.5f; break; case 10: bwscale = 2.0f; break; case 12: bwscale = 2.5f; break; case 14: bwscale = 0.75f; break; } damping = (float)sample->param4 / 20.0f; damping = damping * damping * -6.0f * logf(10.0f) / 20.0f; /* damping: 0 to -6dB per partial */ /* obtain spectrum of input wavetable */ YDB_MESSAGE(YDB_SAMPLE, " padsynth_render: analyzing input table\n"); for (i = 0; i < WAVETABLE_POINTS; i++) inbuf[i] = (float)sample->source[i] / 32768.0f; #ifdef FFTW_VERSION_2 rfftw_one((rfftw_plan)global.padsynth_fft_plan, inbuf, inbuf); #else fftwf_execute((const fftwf_plan)global.padsynth_fft_plan); /* transform inbuf in-place */ #endif max = 0.0f; if (damping > -1e-3f) { /* no damping */ for (i = 1; i < WAVETABLE_POINTS / 2; i++) { inbuf[i] = sqrtf(inbuf[i] * inbuf[i] + inbuf[WAVETABLE_POINTS - i] * inbuf[WAVETABLE_POINTS - i]); if (fabsf(inbuf[i]) > max) max = fabsf(inbuf[i]); } if (fabsf(inbuf[WAVETABLE_POINTS / 2]) > max) max = fabsf(inbuf[WAVETABLE_POINTS / 2]); } else { /* damping */ for (i = 1; i < WAVETABLE_POINTS / 2; i++) { inbuf[i] = sqrtf(inbuf[i] * inbuf[i] + inbuf[WAVETABLE_POINTS - i] * inbuf[WAVETABLE_POINTS - i]) * expf((float)i * damping); if (fabsf(inbuf[i]) > max) max = fabsf(inbuf[i]); } inbuf[WAVETABLE_POINTS / 2] = 0.0f; /* lazy */ } if (max < 1e-5f) max = 1e-5f; for (i = 1; i <= WAVETABLE_POINTS / 2; i++) inbuf[i] /= max; /* create new frequency profile */ YDB_MESSAGE(YDB_SAMPLE, " padsynth_render: creating frequency profile\n"); memset(outfreqs, 0, N * sizeof(float)); /* render the fundamental at 4 semitones below the key limit */ f = 440.0f * y_pitch[sample->max_key - 4]; /* Find a nominal samplerate close to the real samplerate such that the * input partials fall exactly at integer output partials. This ensures * that especially the lower partials are not out of tune. Example: * N = 131072 * global.samplerate = 44100 * f = 261.625565 * fi = f / global.samplerate = 0.00593255 * fc0 = int(fi * N) = int(777.592) = 778 * so we find a new 'samplerate' that will result in fi * N being exactly 778: * samplerate = f * N / fc = 44076.8 */ fc0 = lrintf(f / (float)global.sample_rate * (float)N); sample->period = (float)N / (float)fc0; /* frames per period */ samplerate = f * sample->period; /* YDB_MESSAGE(YDB_SAMPLE, " padsynth_render: size = %d, f = %f, fc0 = %d, period = %f\n", N, f, fc0, sample->period); */ bw0_Hz = (powf(2.0f, bw / 1200.0f) - 1.0f) * f; /* Find the limits of the harmonics to be used in the output table. These * are 20Hz and Nyquist, corrected for the nominal-to-actual sample rate * difference, with the latter also corrected for the 4-semitone shift in * the fundamental frequency. * lower partial limit: * (20Hz * samplerate / global.sample_rate) / samplerate * N * 4-semitone shift: * (2 ^ -12) ^ 4 * upper partial limit: * ((global.sample_rate / 2) * samplerate / global.sample_rate) / samplerate * N / shift */ plimit_low = lrintf(20.0f / (float)global.sample_rate * (float)N); /* plimit_high = lrintf(20000.0f / (float)global.sample_rate * (float)N / 1.25992f); */ plimit_high = lrintf((float)N / 2 / 1.25992f); /* YDB_MESSAGE(YDB_SAMPLE, " padsynth_render: nominal rate = %f, plimit low = %d, plimit high = %d\n", samplerate, plimit_low, plimit_high); */ rndlim_low = N / 2; rndlim_high = 0; for (nh = 1; nh <= WAVETABLE_POINTS / 2; nh++) { int fc, contributed; float bw_Hz; /* bandwidth of the current harmonic measured in Hz */ float bwi; float fi; float plimit_amp; if (inbuf[nh] < 1e-5f) continue; relf = relF(nh, stretch); if (relf < 1e-10f) continue; bw_Hz = bw0_Hz * powf(relf, bwscale); bwi = bw_Hz / (2.0f * samplerate); fi = f * relf / samplerate; fc = lrintf(fi * (float)N); /* printf("...... kl = %d, nh = %d, fn = %f, fc = %d, bwi*N = %f\n", sample->max_key, nh, f * relf, fc, bwi * (float)N); */ /* set plimit_amp such that we don't calculate harmonics -100dB or more * below the profile peak for this harmonic */ plimit_amp = profile(0.0f, bwi) * 1e-5f / inbuf[nh]; /* printf("...... (nh = %d, fc = %d, prof(0) = %e, plimit_amp = %e, amp = %e)\n", nh, fc, profile(0.0f, bwi), plimit_amp, inbuf[nh]); */ /* scan profile and add partial's contribution to outfreqs */ contributed = 0; for (i = (fc < plimit_high ? fc : plimit_high); i >= plimit_low; i--) { float hprofile = profile(((float)i / (float)N) - fi, bwi); if (hprofile < plimit_amp) { /* printf("...... (i = %d, profile = %e)\n", i, hprofile); */ break; } outfreqs[i] += hprofile * inbuf[nh]; contributed = 1; } if (contributed && rndlim_low > i + 1) rndlim_low = i + 1; contributed = 0; for (i = (fc + 1 > plimit_low ? fc + 1 : plimit_low); i <= plimit_high; i++) { float hprofile = profile(((float)i / (float)N) - fi, bwi); if (hprofile < plimit_amp) { /* printf("...... (i = %d, profile = %e)\n", i, hprofile); */ break; } outfreqs[i] += hprofile * inbuf[nh]; contributed = 1; } if (contributed && rndlim_high < i - 1) rndlim_high = i - 1; }; if (rndlim_low > rndlim_high) { /* somehow, outfreqs is still empty */ YDB_MESSAGE(YDB_SAMPLE, " padsynth_render WARNING: empty output table (key limit = %d)\n", sample->max_key); rndlim_low = rndlim_high = fc0; outfreqs[fc0] = 1.0f; } /* randomize the phases */ /* YDB_MESSAGE(YDB_SAMPLE, " padsynth_render: randomizing phases (%d to %d, kl=%d)\n", rndlim_low, rndlim_high, sample->max_key); */ YDB_MESSAGE(YDB_SAMPLE, " padsynth_render: randomizing phases\n"); if (rndlim_high >= N / 2) rndlim_high = N / 2 - 1; for (i = rndlim_low; i < rndlim_high; i++) { float phase = RND() * 2.0f * M_PI_F; outfreqs[N - i] = outfreqs[i] * cosf(phase); outfreqs[i] = outfreqs[i] * sinf(phase); }; /* inverse FFT back to time domain */ YDB_MESSAGE(YDB_SAMPLE, " padsynth_render: performing inverse FFT\n"); #ifdef FFTW_VERSION_2 rfftw_one((rfftw_plan)global.padsynth_ifft_plan, outfreqs, smp); #else /* remember restrictions on FFTW3 'guru' execute: buffers must be the same * sizes, same in-place-ness or out-of-place-ness, and same alignment as * when plan was created. */ fftwf_execute_r2r((const fftwf_plan)global.padsynth_ifft_plan, outfreqs, smp); #endif /* normalize and convert output data */ YDB_MESSAGE(YDB_SAMPLE, " padsynth_render: normalizing output\n"); max = 0.0f; for (i = 0; i < N; i++) if (fabsf(smp[i]) > max) max = fabsf(smp[i]); if (max < 1e-5f) max = 1e-5f; max = 32767.0f / max; for (i = 0; i < N; i++) sample->data[i] = lrintf(smp[i] * max); /* copy guard points */ for (i = -4; i < 0; i++) sample->data[i] = sample->data[i + N]; for (i = 0; i < 4; i++) sample->data[N + i] = sample->data[i]; YDB_MESSAGE(YDB_SAMPLE, " padsynth_render: done\n"); return 1; }
void lib_object_update(obj_t *obj) { assert( obj != NULL ); clutter_circle_set_angle_stop( CLUTTER_CIRCLE(obj->circle_volume), (uint) (obj->audio->volume * 360.0f) ); clutter_circle_set_angle_stop( CLUTTER_CIRCLE(obj->circle_position), (uint) (obj->audio->position * 360.0f) ); if ( ! (obj->flags & OBJ_FL_HIDE_BARGRAPH) ) { /* bar graph */ if ( obj->audio->input != NULL && obj->audio->input->data != NULL ) { static float v, *tmp; static int n, i; n = obj->audio->input->size; /* allocate memory * reajust if we got big sound. */ if ( bargraph_datasize != n ) { tmp = realloc(bargraph_data, sizeof(float) * n); if ( tmp == NULL ) return; bargraph_data = tmp; bargraph_datasize = n; } /* execute fast fourier plan */ if ( obj->fftpl == NULL ) { obj->fftpl = fftwf_plan_r2r_1d(n, obj->audio->input->data, bargraph_data, FFTW_R2HC, FFTW_FORWARD | FFTW_PRESERVE_INPUT ); } fftwf_execute(obj->fftpl); /* and ajust bargraph ! */ for ( i = 0; i < n && i < BAR_COUNT; i++ ) { v = sqrtf(bargraph_data[i] * bargraph_data[i]) * 30; if ( v > 50 ) v = 50; clutter_circle_set_width(CLUTTER_CIRCLE(obj->bars[i]), v); } } } }