/* * Copyright (C) 2007 John Gibson * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as * published by the Free Software Foundation. * * 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. */ // derived from RTcmix SPECTACLE2.cpp, (C) John Gibson 2005. #include "Spectacle-dsp.h" #include #include //#define DEBUG //#define PRINT_DELTIMES //#define PRINT_DELTIME_CHANGES #if defined(PRINT_DELTIME_CHANGES) && !defined(PRINT_DELTIMES) #define PRINT_DELTIMES #endif const float kMaxDelayTime = 20.0f; #ifdef ANTI_DENORM const float kAntiDenormConstant = 1e-18f; #endif // ---------------------------------------------------------------- Spectacle_dsp -- Spectacle_dsp::Spectacle_dsp() : _maxdelsamps(0L), _maxdeltime(0.0f), _eqconst(0.0f), _deltimeconst(0.0f), _feedbackconst(0.0f), _delay_minfreq(-FLT_MAX), _delay_maxfreq(-FLT_MAX), _eqtable(NULL), _deltimetable(NULL), _feedbacktable(NULL), _delay_bin_groups(NULL), _delay_binmap_table(NULL), _delay_table_size(0) { #ifdef ANTI_DENORM _antidenorm_offset = kAntiDenormConstant; #endif } // --------------------------------------------------------------- ~Spectacle_dsp -- Spectacle_dsp::~Spectacle_dsp() { // NB: we don't own the EQ, delay time, and feedback tables. for (int i = 0; i < _half_fftlen; i++) { if (_real_delay[i]) delete _real_delay[i]; if (_imag_delay[i]) delete _imag_delay[i]; } delete [] _delay_bin_groups; } // --------------------------------------------------------------------- init -- // Invoke base init, and perform any initialization specific to this subclass. // Return 0 if okay, -1 if not. int Spectacle_dsp::init(int fftlen, int windowlen, int overlap, float srate, float maxdeltime) { if (SpectacleBase::init(fftlen, windowlen, overlap, srate) != 0) return -1; // Compute maximum delay lag and create delay lines for FFT real and // imaginary values. Remember that these delays function at the decimation // rate, not at the audio rate, so the memory footprint is not as large // as you would expect -- about 44100 samples per second at fftlen=1024, // overlap=2 and SR=44100. _maxdeltime = maxdeltime; _maxdelsamps = long(maxdeltime * get_srate() / float(_decimation) + 0.5); for (int i = 0; i < _half_fftlen; i++) { Odelay *delay = new Odelay(_maxdelsamps); if (delay == NULL) goto bad_alloc; _real_delay[i] = delay; delay = new Odelay(_maxdelsamps); if (delay == NULL) goto bad_alloc; _imag_delay[i] = delay; } _delay_bin_groups = new int [_half_fftlen]; set_delay_freqrange(0.0f, 0.0f); return 0; bad_alloc: //error("%s: Not enough memory for delay lines.", instname()); return -1; } // -------------------------------------------------------------------- clear -- void Spectacle_dsp::clear() { for (int i = 0; i < _half_fftlen; i++) { _real_delay[i]->clear(); _imag_delay[i]->clear(); } SpectacleBase::clear(); } // ---------------------------------------------------------------- set_srate -- void Spectacle_dsp::set_srate(float srate) { if (_delay_maxfreq == _nyquist) _delay_maxfreq = 0.0f; SpectacleBase::set_srate(srate); if (_delay_maxfreq == 0.0f) // nyquist might have changed _delay_maxfreq = _nyquist; set_maxdeltime(_maxdeltime); update_bin_groups(_delay_bin_groups, _delay_binmap_table, _delay_minfreq, _delay_maxfreq, _delay_table_size); } // ----------------------------------------------------------- set_maxdeltime -- // Reset delay lines to accommodate a maximum delay of