📄 taudiofilterconvolver.cpp
字号:
if (cfg->mixingStrength==100)
for (unsigned int index2 = 0; index2 < chunk_length; ++index2)
{
float out=fft_real[index2] / normalization_factor + overlap_buffers[index][index2];
out_data[out_channel[index]+out_channels*(index2+samplesPtr)] = out;
overlap_buffers[index][index2] = fft_real[index2 + chunk_length] / normalization_factor;
}
else
for (unsigned int index2 = 0; index2 < chunk_length; ++index2)
{
float out=fft_real[index2] / normalization_factor + overlap_buffers[index][index2];
out_data[out_channel[index]+out_channels*(index2+samplesPtr)] = mix(in_data[in_channel[index]+in_channels*(index2+samplesPtr)],out,mixingStrength,mixingStrengthInv);
overlap_buffers[index][index2] = fft_real[index2 + chunk_length] / normalization_factor;
}
}
// advance input_chunk_ringbuffer_indexes
for (unsigned int index = 0; index < number_of_responses; ++index)
{
input_chunk_ringbuffer_indexes[index] += chunk_length + 1;
input_chunk_ringbuffer_indexes[index] %= fft_responses[index].number_of_chunks * (chunk_length + 1);
}
}
return samplesPtr;
}
//==================================== TaudioFilterConvolver ====================================
void TaudioFilterConvolver::Tconvolver::Tfftforward::execute(const Tin *in,Tout *out)
{
for (int i=0;i<length/2;i++)
out[i]=complex(in[2*i+0],in[2*i+1]);
rdft(length,1,(float*)out,&ip[0],&w[0]);
out[length/2]=complex(out[0].imag(),0);
out[0].imag()=0.0f;
}
void TaudioFilterConvolver::Tconvolver::Tfftbackward::execute(const Tin *in,Tout *out)
{
for (int i=0;i<length/2;i++)
{
out[2*i+0]=in[i].real();
out[2*i+1]=in[i].imag();
}
out[1]=in[length/2].real();
rdft(length,-1,(float*)out,&ip[0],&w[0]);
for (int i=0;i<length;i++)
out[i]*=2;
}
void TaudioFilterConvolver::done(void)
{
buffer.clear();
convolvers.clear();
}
bool TaudioFilterConvolver::is(const TsampleFormat &fmt,const TfilterSettingsAudio *cfg0)
{
const TconvolverSettings *cfg=(const TconvolverSettings*)cfg0;
return super::is(fmt,cfg)/* && (cfg->mappingMode!=0 || !TwavReader<float>(cfg->file,true).empty())*/;
}
bool TaudioFilterConvolver::getOutputFmt(TsampleFormat &fmt,const TfilterSettingsAudio *cfg0)
{
if (super::getOutputFmt(fmt,cfg0))
{
const TconvolverSettings *cfg=(const TconvolverSettings*)cfg0;
if (cfg->mappingMode==0)
{
TwavReader<float> impulse(cfg->file,true);
if (fmt.nchannels==1 && !(fmt.nchannels==impulse.nchannels || impulse.nchannels==1))
fmt.setChannels(impulse.nchannels);
}
return true;
}
else
return false;
}
void TaudioFilterConvolver::resampleImpulse(TwavReader<float> &impulse,int dstfreq)
{
size_t lenout=impulse[0].size()*dstfreq/impulse.freq;
std::vector<float> buffOut(lenout*2);
for (unsigned int i=0;i<impulse.nchannels;i++)
{
TreSampleContext<float> resampler(1,dstfreq,impulse.freq,int(16*2.2),10,1,1.0,0);
std::vector<float> bufIn(impulse[i]);bufIn.resize(bufIn.size()*2,impulse[i].back());
int ret=resampler.audio_resample(&buffOut[0],&bufIn[0],(int)bufIn.size());
impulse[i]=buffOut;impulse[i].resize(lenout);
}
impulse.freq=dstfreq;
}
HRESULT TaudioFilterConvolver::process(TfilterQueue::iterator it,TsampleFormat &fmt,void *samples0,size_t numsamples,const TfilterSettingsAudio *cfg0)
{
const TconvolverSettings *cfg=(const TconvolverSettings*)cfg0;
if (is(fmt,cfg) && cfg->mixingStrength)
{
if (!cfg->equal(oldcfg))
{
oldcfg=*cfg;
done();
if (cfg->mappingMode==0)
{
TwavReader<float> impulse(cfg->file);
if (!impulse.empty())
{
if (impulse.freq!=fmt.freq)
resampleImpulse(impulse,fmt.freq);
if (fmt.nchannels==1)
{
convolvers.push_back(Tconvolver(fmt,impulse,cfg));
outchannels=convolvers[0].number_of_response_channels;
}
else if (fmt.nchannels==impulse.nchannels || impulse.nchannels==1)
{
for (unsigned int i=0;i<fmt.nchannels;i++)
convolvers.push_back(Tconvolver(fmt,impulse,cfg,i));
outchannels=fmt.nchannels;
}
}
}
else
{
size_t oldsize=0;
TwavReader<float> *impulses[6];memset(impulses,0,sizeof(impulses));
for (unsigned int i=0;i<fmt.nchannels;i++)
{
const char_t *file=NULL;
if (fmt.speakers[i]&SPEAKER_FRONT_LEFT)
file=cfg->fileL;
else if (fmt.speakers[i]&SPEAKER_FRONT_RIGHT)
file=cfg->fileR;
else if (fmt.speakers[i]&SPEAKER_FRONT_CENTER)
file=cfg->fileC;
else if (fmt.speakers[i]&SPEAKER_LOW_FREQUENCY)
file=cfg->fileLFE;
else if (fmt.speakers[i]&(SPEAKER_BACK_LEFT|SPEAKER_BACK_CENTER))
file=cfg->fileSL;
else if (fmt.speakers[i]&SPEAKER_BACK_RIGHT)
file=cfg->fileSR;
if (file)
{
impulses[i]=new TwavReader<float>(file);
if (!impulses[i]->empty() && (impulses[i]->nchannels!=1 || (oldsize && impulses[i]->at(0).size()!=oldsize)))
goto endManual;
if (!impulses[i]->empty())
{
if (impulses[i]->freq!=fmt.freq)
resampleImpulse(*impulses[i],fmt.freq);
oldsize=impulses[i]->at(0).size();
}
}
}
if (oldsize)
{
for (unsigned int i=0;i<fmt.nchannels;i++)
convolvers.push_back(Tconvolver(fmt,(!impulses[i] || impulses[i]->empty())?TwavReader<float>(fmt.freq,1,oldsize,0.0f):*impulses[i],cfg,i));
outchannels=fmt.nchannels;
}
endManual:
for (unsigned int i=0;i<fmt.nchannels;i++)
if (impulses[i])
delete impulses[i];
}
}
if (!convolvers.empty())
{
float *samples=(float*)init(cfg,fmt,samples0,numsamples);
unsigned int inBlockAlign=fmt.blockAlign();
buffer.append(samples,numsamples*inBlockAlign);
const float * const in_data=(const float* const)&*buffer.begin();
numsamples=buffer.size()/inBlockAlign;
fmt.setChannels(outchannels);
float *out_data=(float*)alloc_buffer(fmt,numsamples,buf);
int samplesProcessed=0;
for (Tconvolvers::iterator convolver=convolvers.begin();convolver!=convolvers.end();convolver++)
samplesProcessed=convolver->process(in_data,out_data,numsamples,cfg);
buffer.erase(buffer.begin(),buffer.begin()+samplesProcessed*inBlockAlign);
numsamples=samplesProcessed;
samples0=out_data;
}
}
return parent->deliverSamples(++it,fmt,samples0,numsamples);
}
void TaudioFilterConvolver::onSeek(void)
{
buffer.clear();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -