📄 taudiofilterconvolver.cpp.svn-base
字号:
/* * Copyright (c) 2005,2006 Milan Cutka * based on jack_convolve by Florian Schmidt * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */#include "stdafx.h"#include "TaudioFilterConvolver.h"#include "fftsg.h"#include "ffdebug.h"#include "resample/resample2.h"TaudioFilterConvolver::TaudioFilterConvolver(IffdshowBase *Ideci,Tfilters *Iparent):TaudioFilter(Ideci,Iparent){}//==================== TaudioFilterConvolver::Tconvolver::fft_response_t ========================void TaudioFilterConvolver::Tconvolver::fft_response_t::init(const TwavReader<float> &response,const TconvolverSettings *cfg,unsigned int chunk_length,float normalization_factor,Tfftforward &fft_plan_forward,unsigned int procchannel){ float levelAdjust=cfg->levelAdjustAuto?response.getAdjust():db2value((float)cfg->levelAdjustDB,10); // create new response struct length=response[0].size(); // make channel_data array big enough to hold pointers for all channels size_t number_of_response_channels=procchannel!=INT32_MAX?1:response.size(); channel_data.resize(number_of_response_channels); // how many chunks do we need for this response? number_of_chunks = (unsigned int)ceil((response[0].size())/(float)(chunk_length)); // allocate per channel data buffer) // no need for double size, as we use r2c/c2r for (unsigned int index2 = 0; index2 < number_of_response_channels; ++index2) channel_data[index2].resize( (chunk_length + 1) * number_of_chunks); // for each channel std::vector<float> fft_real(2*chunk_length); std::vector<complex> fft_complex(chunk_length+1); for (unsigned int index2 = 0; index2 < number_of_response_channels; ++index2) { unsigned int respchannel=procchannel!=INT32_MAX?std::min(response.nchannels-1,procchannel):index2; // for each chunk for (unsigned int index3 = 0; index3 < number_of_chunks; ++index3) { // copy original chunk to fft_real for (unsigned int index4 = 0; index4 < chunk_length; ++index4) { if (index4 + index3 * chunk_length < length) fft_real[index4] = response[respchannel][index4+index3*chunk_length]*levelAdjust; else fft_real[index4] = 0; // and zero pad the second half of the chunk at the same time fft_real[index4+chunk_length] = 0; } // do the fft fft_plan_forward.execute(&fft_real[0],&fft_complex[0]); // copy fft output to our private chunk store :) for (unsigned int index4 = 0; index4 < chunk_length + 1; ++index4) channel_data[index2][index4+index3 * (chunk_length + 1)]= complex(fft_complex[index4].real() / normalization_factor, fft_complex[index4].imag() / normalization_factor); } }}static unsigned int getNextPower2(unsigned int l){ int num=1<<(av_log2(l)+2); return num;}//============================== TaudioFilterConvolver::Tconvolver ==============================TaudioFilterConvolver::Tconvolver::Tconvolver(const TsampleFormat &infmt,const TwavReader<float> &response,const TconvolverSettings *cfg,unsigned int procchannel): chunk_length(getNextPower2((unsigned int)response[0].size())), number_of_responses(1), fft_plan_forward(2*getNextPower2((unsigned int)response[0].size())), fft_plan_backward(2*getNextPower2((unsigned int)response[0].size())), fft_real(2*getNextPower2((unsigned int)response[0].size())), fft_complex(getNextPower2((unsigned int)response[0].size())+1), fft_responses(1), input_chunk_ringbuffers(1){ number_of_response_channels=procchannel!=INT32_MAX?1:response.nchannels; normalization_factor=sqrt(chunk_length * 2.0f); // -------------- chunk, pad, fft and store the responses // allocate array of response pointers // process input responses to padded, chunked, fft'ed internal representation //for (unsigned int index=0;index<number_of_responses;++index) fft_responses[0].init(response,cfg,chunk_length,normalization_factor,fft_plan_forward,procchannel); // ------------- setup ringbuffers for storing FFT'ed input.. // the chunks are size chunk_length + 1 thus // we need number_of_chunks * (chunk_length + 1) // frames // one for each response for (unsigned int index = 0; index < number_of_responses; ++index) { input_chunk_ringbuffers[index].resize(fft_responses[index].number_of_chunks * (chunk_length + 1)); // zero out for (unsigned int index2 = 0; index2 < (chunk_length + 1) * fft_responses[index].number_of_chunks; ++index2) input_chunk_ringbuffers[index][index2]=0; } // allocate input_chunk_ringbuffer_index arrays input_chunk_ringbuffer_indexes.resize(number_of_responses); // zero out for (unsigned int index = 0; index < number_of_responses; ++index) input_chunk_ringbuffer_indexes[index] = 0; // ---------------- setup overlap buffers // these need only be chunk_length sized overlap_buffers.resize(number_of_response_channels); for (unsigned int index = 0; index < number_of_response_channels; ++index) { overlap_buffers[index].resize(chunk_length); // zero out for (unsigned int index2 = 0; index2 < chunk_length; ++index2) overlap_buffers[index][index2] = 0; } if (procchannel!=INT32_MAX) { in_channels=out_channels=infmt.nchannels; in_channel[0]=out_channel[0]=procchannel; } else { in_channels=infmt.nchannels; for (unsigned int i=0;i<number_of_response_channels;i++) in_channel[i]=number_of_response_channels%in_channels; out_channels=number_of_response_channels; for (unsigned int i=0;i<number_of_response_channels;i++) out_channel[i]=i; } }int TaudioFilterConvolver::Tconvolver::process(const float * const in_data,float *out_data,size_t numsamples,const TconvolverSettings *cfg){ float mixingStrength=cfg->mixingStrength/100.0f,mixingStrengthInv=1.0f-mixingStrength; int samplesPtr=0; for (;samplesPtr<int(numsamples-chunk_length);samplesPtr+=chunk_length) { for (unsigned int index = 0; index < number_of_responses; ++index) { // copy input chunk into fft_real for (unsigned int index2 = 0; index2 < chunk_length; ++index2) { fft_real[index2] = in_data[in_channel[0]+in_channels*(index2+samplesPtr)];//in_data[index][index2]; // and pad at the same time fft_real[index2+chunk_length] = 0; } // do the fft fft_plan_forward.execute(&fft_real[0],&fft_complex[0]); // copy output into input_chunks ringbuffers for (unsigned int index2 = 0; index2 < chunk_length + 1; ++index2) input_chunk_ringbuffers[index][index2 + input_chunk_ringbuffer_indexes[index]]=complex(fft_complex[index2].real() / normalization_factor, fft_complex[index2].imag() / normalization_factor); } // do the complex multiplications for all response input channels for (unsigned int index = 0; index < number_of_response_channels; ++index) { // zero our the reverse fft input buffer for (unsigned int index2 = 0; index2 < chunk_length + 1; ++index2) fft_complex[index2]=0; // for all responses (of this output channel) for (unsigned int index2 = 0; index2 < number_of_responses; ++index2) { // for all chunks for (unsigned int index3 = 0; index3 < fft_responses[index2].number_of_chunks; ++index3) { // we go backward in time (from current chunk in input_chunnks_ringbuffers[] to oldest) int tmp_rb_chunk_index = input_chunk_ringbuffer_indexes[index2] - (index3 * (chunk_length + 1)) + ((chunk_length + 1) * fft_responses[index2].number_of_chunks); // constraint to the actual data length ("%") tmp_rb_chunk_index %= (chunk_length + 1) * fft_responses[index2].number_of_chunks; complex_mul(&input_chunk_ringbuffers[index2][tmp_rb_chunk_index], &fft_responses[index2].channel_data[index][index3 * (chunk_length + 1)], &fft_complex[0], chunk_length + 1); } // chunks } // responses // reverse fft the results fft_plan_backward.execute(&fft_complex[0],&fft_real[0]); // copy to out_buffers, save overlap and add previous overlap
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -