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

📄 taudiofiltervolume.cpp.svn-base

📁 ffshow源码
💻 SVN-BASE
字号:
/* * Copyright (c) 2003-2006 Milan Cutka * * Volume normalizing code from mplayer by pl <p_l@gmx.fr>, *  sources: some ideas from volnorm plugin for xmms * * 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 "TaudioFilterVolume.h"#include "IffdshowBase.h"#include "IffdshowDecAudio.h"const unsigned int TaudioFilterVolume::NSAMPLES=128;// If summing all the mem[].len is lower than MIN_SAMPLE_SIZE bytes, then we// choose to ignore the computed value as it's not significant enough// FIXME: should depend on the frequency of the data (0.5s maybe)const unsigned int TaudioFilterVolume::MIN_SAMPLE_SIZE=32000;const float TaudioFilterVolume::MUL_INIT=1.0f;const float TaudioFilterVolume::MUL_MIN=0.1f;//const float TaudioFilterVolume::MUL_MAX=5.0f;//const int TaudioFilterVolume::MIN_S16=-32768;//const int TaudioFilterVolume::MAX_S16= 32767;const float TaudioFilterVolume::MID_S16=/*MAX_S16**/0.25f;const float TaudioFilterVolume::SIL_S16=/*MAX_S16**/0.001f;template<class sample_t> void TaudioFilterVolume::volume(sample_t* const samples,size_t numsamples,const TsampleFormat &fmt,const TvolumeSettings *cfg){ if (cfg->is)  if (!cfg->normalize)   {    if (isVol)     {      typedef void (*TprocessVol)(sample_t * const samples,size_t numsamples,const int *volumes);      static const TprocessVol processVol[7]=       {        NULL,        &Tmultiply<1>::processVol,        &Tmultiply<2>::processVol,        &Tmultiply<3>::processVol,        &Tmultiply<4>::processVol,        &Tmultiply<5>::processVol,        &Tmultiply<6>::processVol       };      processVol[fmt.nchannels](samples,numsamples,volumes);     }    }  else   {    if (!mem)     {      mem=new Tmem[NSAMPLES];      for (int i=0;i<NSAMPLES;i++)        {        mem[i].len=0;        mem[i].avg=0;       }     }      size_t len=numsamples*fmt.nchannels;    // Evaluate current samples average level    float curavg=0.0f;    for (size_t i=0;i<len;i++)     {      float tmp=float(samples[i]);      curavg+=tmp*tmp;     }    curavg=sqrtf(curavg/float(len));    // Evaluate an adequate 'mul' coefficient based on previous state, current samples level, etc    float avg=0.0f;    size_t totallen=0;    for (unsigned int i=0;i<NSAMPLES;i++)     {      avg+=mem[i].avg*(float)mem[i].len;      totallen+=mem[i].len;     }    if (totallen>MIN_SAMPLE_SIZE)      {      avg/=(float)totallen;      if (avg>=TsampleFormatInfo<sample_t>::max()*SIL_S16)        mul=limit((float)(TsampleFormatInfo<sample_t>::max()*MID_S16)/avg,MUL_MIN,cfg->normalizeMax/100.0f);     }    // Scale & clamp the samples    typedef void (*TprocessMul)(sample_t * const samples,size_t numsamples,const int *volumes,float mul);    static const TprocessMul processMul[7]=     {      NULL,      &Tmultiply<1>::processMul,      &Tmultiply<2>::processMul,      &Tmultiply<3>::processMul,      &Tmultiply<4>::processMul,      &Tmultiply<5>::processMul,      &Tmultiply<6>::processMul     };    processMul[fmt.nchannels](samples,numsamples,volumes,mul);     // Evaluation of newavg (not 100% accurate because of values clamping)    float newavg=mul*curavg;    // Stores computed values for future smoothing    mem[idx].len=len;    mem[idx].avg=newavg;    idx=(idx+1)%NSAMPLES;   } if (numsamples>0 && deci->getParam2(IDFF_showCurrentVolume) && deci->getCfgDlgHwnd())  {   int64_t sum[6];memset(sum,0,sizeof(sum));   for (size_t i=0;i<numsamples*fmt.nchannels;)    for (unsigned int ch=0;ch<fmt.nchannels;ch++,i++)     sum[ch]+=int64_t((int64_t)65536*ff_abs(samples[i]));   CAutoLock lock(&csVolumes);     for (unsigned int i=0;i<fmt.nchannels;i++)    storedvolumes.volumes[i]=int((sum[i]/numsamples)/int64_t(TsampleFormatInfo<sample_t>::max()));   storedvolumes.have=true;   }  }TaudioFilterVolume::TaudioFilterVolume(IffdshowBase *Ideci,Tfilters *Iparent):TaudioFilter(Ideci,Iparent){ mem=NULL; mul=MUL_INIT; idx=0; oldfmt.freq=0; oldcfg.vol=-100; storedvolumes.have=false;}TaudioFilterVolume::~TaudioFilterVolume(){ if (mem) delete []mem;}bool TaudioFilterVolume::is(const TsampleFormat &fmt,const TfilterSettingsAudio *cfg){ return !!cfg->is;}HRESULT TaudioFilterVolume::process(TfilterQueue::iterator it,TsampleFormat &fmt,void *samples,size_t numsamples,const TfilterSettingsAudio *cfg0){ const TvolumeSettings *cfg=(const TvolumeSettings*)cfg0; if (oldfmt!=fmt || !cfg->equal(oldcfg))  {   oldfmt=fmt;oldcfg=*cfg;   if (mem) delete []mem;mem=NULL;   isVol=false;   static const int speakers[]={SPEAKER_FRONT_LEFT,SPEAKER_FRONT_RIGHT,SPEAKER_FRONT_CENTER,SPEAKER_BACK_LEFT|SPEAKER_BACK_CENTER,SPEAKER_BACK_RIGHT,SPEAKER_LOW_FREQUENCY};   static const int TvolumeSettings::*cfgvols[]={&TvolumeSettings::volL,&TvolumeSettings::volR,&TvolumeSettings::volC,&TvolumeSettings::volSL,&TvolumeSettings::volSR,&TvolumeSettings::volLFE};   static const int TvolumeSettings::*cfgmutes[]={&TvolumeSettings::volLmute,&TvolumeSettings::volRmute,&TvolumeSettings::volCmute,&TvolumeSettings::volSLmute,&TvolumeSettings::volSRmute,&TvolumeSettings::volLFEmute};   unsigned int solo=0;   for (unsigned int i=0;i<countof(speakers);i++)    if (cfg->*cfgmutes[i]==2)     {      solo=speakers[i];      break;     }   for (unsigned int i=0;i<fmt.nchannels;i++)    {     int v=100;     for (int ii=0;i<countof(speakers);ii++)      if (fmt.speakers[i]&speakers[ii])       {        v=cfg->*cfgmutes[ii]!=1 && (solo==0 || (fmt.speakers[i]&solo))?cfg->*cfgvols[ii]:0;        break;       }      volumes[i]=v*cfg->vol/39;      if (volumes[i]!=256) isVol=true;    }  } if (is(fmt,cfg))   samples=init(cfg,fmt,samples,numsamples); if (numsamples>0)  {   switch (fmt.sf)    {     case TsampleFormat::SF_PCM16  :volume((int16_t*)samples,numsamples,fmt,cfg);break;     case TsampleFormat::SF_PCM32  :volume((int32_t*)samples,numsamples,fmt,cfg);break;     case TsampleFormat::SF_FLOAT32:volume((float*)  samples,numsamples,fmt,cfg);break;    }  } return (it!=NULL)?parent->deliverSamples(++it,fmt,samples,numsamples):S_OK;}void TaudioFilterVolume::onSeek(void){ if (mem)  {   mul=MUL_INIT;   delete []mem;mem=NULL;  }}HRESULT TaudioFilterVolume::queryInterface(const IID &iid,void **ptr) const{ if (iid==IID_IaudioFilterVolume) {*ptr=(IaudioFilterVolume*)this;return S_OK;} else return E_NOINTERFACE;}STDMETHODIMP TaudioFilterVolume::getVolumeData(unsigned int *nchannels,int channels[],int vol[]){ if (!storedvolumes.have) return E_UNEXPECTED; if (!nchannels || !channels || !vol)  return E_POINTER; CAutoLock lock(&csVolumes); *nchannels=oldfmt.nchannels; memcpy(channels,oldfmt.speakers,oldfmt.nchannels*sizeof(int)); memcpy(vol,storedvolumes.volumes,oldfmt.nchannels*sizeof(int)); return S_OK;}STDMETHODIMP_(int) TaudioFilterVolume::getCurrentNormalization(void){ return int(mul*100);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -