⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 taudiofilterconvolver.cpp

📁 从FFMPEG转换而来的H264解码程序,VC下编译..
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
 * 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 + -