HRTFKernel::HRTFKernel(AudioChannel* channel, size_t fftSize, float sampleRate, bool bassBoost) : m_frameDelay(0) , m_sampleRate(sampleRate) { ASSERT(channel); // Determine the leading delay (average group delay) for the response. m_frameDelay = extractAverageGroupDelay(channel, fftSize / 2); float* impulseResponse = channel->data(); size_t responseLength = channel->length(); if (bassBoost) { // Run through some post-processing to boost the bass a little -- the HRTF's seem to be a little bass-deficient. // FIXME: this post-processing should have already been applied to the HRTF file resources. Once the files are put into this form, // then this code path can be removed along with the bassBoost parameter. Biquad filter; filter.setLowShelfParams(700.0 / nyquist(), 6.0); // boost 6dB at 700Hz filter.process(impulseResponse, impulseResponse, responseLength); } // We need to truncate to fit into 1/2 the FFT size (with zero padding) in order to do proper convolution. size_t truncatedResponseLength = min(responseLength, fftSize / 2); // truncate if necessary to max impulse response length allowed by FFT // Quick fade-out (apply window) at truncation point unsigned numberOfFadeOutFrames = static_cast<unsigned>(sampleRate / 4410); // 10 sample-frames @44.1KHz sample-rate ASSERT(numberOfFadeOutFrames < truncatedResponseLength); if (numberOfFadeOutFrames < truncatedResponseLength) { for (unsigned i = truncatedResponseLength - numberOfFadeOutFrames; i < truncatedResponseLength; ++i) { float x = 1.0f - static_cast<float>(i - (truncatedResponseLength - numberOfFadeOutFrames)) / numberOfFadeOutFrames; impulseResponse[i] *= x; } } m_fftFrame = adoptPtr(new FFTFrame(fftSize)); m_fftFrame->doPaddedFFT(impulseResponse, truncatedResponseLength); }