📄 mixer.h.svn-base
字号:
/* Mixer Mixer and gain control class. Smooth gain control based on ac3 time window, so delayed samples are also required for operation. Usage. Create instance of a mixer, set input and output modes, set matrix directly or call calc_matrix() function, then call mix() function. 'level' - desired output level. It is guaranteed that Samples will not exceed it. 'clev', 'slev', 'lfelev' are params for matrix calculation calc_matrix(). 'master', 'gain', 'dynrng' are used in gain control and matrix-independent. 'normalize' flag controls gain control behavior. True means one-pass normalization. So at at the beginning mixing use 'gain' = 'master'. When overflow occur gain is decreased and so on. When 'normalize' = false then after overflow gain begins to increase bit by bit until it reaches 'master' again or other overflow occur. 'auto_gain' - automatic gain control. It will automatically lower gain level on overload and restore it back then. 'voice_control' - (only when stereo input) enables voice control when stereo input. Amplifies in-phase signal and route it to center speaker if present. Only when auto_matrix = true. 'expand_stereo' - (only when stereo input) enables surround control when stereo input. Amplifies out-of-phase signal and route it to surround speakers if present. Only when auto_matrix = true. calc_matrix() - calc mixing matrix complied with ac3 standart (not normalized) normalize() - normalizes matrix so no overflow at output if no overflow at input. reset() - reset time window, reset to 'master' to 'gain' and 'dynrng' to 1.0.*/#ifndef MIXER_H#define MIXER_H#include "TsampleFormat.h"#include "TmixerSettings.h"#include "TaudioFilter.h"#include "IffdshowDecAudio.h"class TmixerMatrix{private: static const double LEVEL_PLUS6DB,LEVEL_PLUS3DB,LEVEL_3DB,LEVEL_45DB,LEVEL_6DB; // channel numbers // used as index in arrays enum { CH_L =0, // Left channel CH_R =1, // Right channel CH_C =2, // Center channel CH_LFE =3, // LFE channel CH_SL =4, // Surround left channel CH_SR =5, // Surround right channel CH_NONE =6, // indicates that channel is not used in channel order CH_M =2, // Mono channel = center channel CH_S =4 // Surround channel for x/1 modes };protected: static const int NCHANNELS=6; // mixing matrix 6-to-6 channels TsampleFormat calc_matrix(const TsampleFormat &insf,const TmixerSettings *cfg);public: typedef double mixer_matrix_t[NCHANNELS][NCHANNELS]; mixer_matrix_t matrix; TmixerMatrix(void);};template<class sample_t,class div_t,div_t div,div_t div2> class Mixer :public TmixerMatrix{private: typedef typename TsampleFormatInfo<sample_t>::helper_t helper_t; typedef helper_t mixer_matrix_t[NCHANNELS][NCHANNELS]; mixer_matrix_t matrix; unsigned int rows,cols; template<unsigned int colsT,unsigned int rowsT> static void mix(size_t nsamples,const sample_t *insamples,sample_t *outsamples,const mixer_matrix_t &matrix) { for (unsigned int nsample=0;nsample<nsamples;insamples+=rowsT,outsamples+=colsT,nsample++) for (unsigned int i=0;i<colsT;i++) { helper_t sum=0; for (unsigned int j=0;j<rowsT;j++) sum+=(insamples[j]*matrix[j][i])/helper_t(div/div2); outsamples[i]=TsampleFormatInfo<sample_t>::limit(sum); } } typedef void (*TmixFn)(size_t nsamples,const sample_t *insamples,sample_t *outsamples,const mixer_matrix_t &matrix); TmixFn mixFn; TsampleFormat calc_matrix(const TsampleFormat &insf,const TmixerSettings *cfg,const TmixerMatrix::mixer_matrix_t* *matrixPtr) { TsampleFormat outsf=TmixerMatrix::calc_matrix(insf,cfg); *matrixPtr=&this->TmixerMatrix::matrix; static const int mspeakers[]={SPEAKER_FRONT_LEFT,SPEAKER_FRONT_RIGHT,SPEAKER_FRONT_CENTER,SPEAKER_LOW_FREQUENCY,SPEAKER_BACK_LEFT|SPEAKER_BACK_CENTER,SPEAKER_BACK_RIGHT}; rows=0; int inmask=insf.makeChannelMask(),outmask=outsf.makeChannelMask(); for (int i=0;i<NCHANNELS;i++) if (inmask&mspeakers[i]) { cols=0; for (int j=0;j<NCHANNELS;j++) if (outmask&mspeakers[j]) { matrix[rows][cols]=helper_t(TmixerMatrix::matrix[i][j]*div/div2); cols++; } rows++; } static const TmixFn mixFns[6][6]= { mix<1,1>,mix<1,2>,mix<1,3>,mix<1,4>,mix<1,5>,mix<1,6>, mix<2,1>,mix<2,2>,mix<2,3>,mix<2,4>,mix<2,5>,mix<2,6>, mix<3,1>,mix<3,2>,mix<3,3>,mix<3,4>,mix<3,5>,mix<3,6>, mix<4,1>,mix<4,2>,mix<4,3>,mix<4,4>,mix<4,5>,mix<4,6>, mix<5,1>,mix<5,2>,mix<5,3>,mix<5,4>,mix<5,5>,mix<5,6>, mix<6,1>,mix<6,2>,mix<6,3>,mix<6,4>,mix<6,5>,mix<6,6>, }; mixFn=mixFns[cols-1][rows-1]; return outsf; } unsigned int oldnchannels,oldchannelmask;int oldsf; TmixerSettings oldcfg; Tbuffer buf; TsampleFormat outfmt;public: IffdshowDecAudio *deciA; Mixer(void) { oldnchannels=0;oldchannelmask=0xffffffff;oldsf=TsampleFormat::SF_NULL; oldcfg.out=-1; } void process(TsampleFormat &fmt,sample_t* &samples1,size_t &numsamples,const TmixerSettings *cfg,const TmixerMatrix::mixer_matrix_t* *matrixPtr) { if (oldnchannels!=fmt.nchannels || oldchannelmask!=fmt.channelmask || oldsf!=fmt.sf || !cfg->equal(oldcfg)) { oldnchannels=fmt.nchannels;oldchannelmask=fmt.channelmask;oldsf=fmt.sf;oldcfg=*cfg; outfmt=calc_matrix(fmt,cfg,matrixPtr); } TsampleFormat fmt2=fmt; fmt2.setChannels(outfmt.nchannels,outfmt.channelmask); sample_t *samples2=(sample_t*)TaudioFilter::alloc_buffer(fmt2,numsamples,buf); mixFn(numsamples,samples1,samples2,matrix); fmt=fmt2; samples1=samples2; }};#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -