📄 taudiofilter.cpp
字号:
if (c_loop)
fc_3dnow(inbuf,samples,(unsigned int)c_loop);
}
#endif
else if (fc_sse && Tconfig::cpu_flags&FF_CPU_SSE) //TODO fix?
{
c_miss=count&3;
c_loop=count-c_miss;
if (c_loop)
fc_sse(inbuf,samples,(unsigned int)c_loop);
}
else
{
c_miss=count;
c_loop=0;
}
for (size_t i=0;i<c_miss;i++)
samples[i+c_loop]=TsampleFormatInfo<Tout>::limit(inbuf[i+c_loop]*TsampleFormatInfo<Tout>::max());
return samples;
}
};
//---------------------------- int16 -> float ----------------------------
#ifndef WIN64
extern "C" void convert_16_float_3dnow(const int16_t*inbuf,float *samples,unsigned int c_loop);
#else
#define convert_16_float_3dnow NULL
#endif
static void convert_16_float_sse(const int16_t*inbuf,float *samples,unsigned int c_loop)
{
int eax=0;
int edx=c_loop;
const unsigned char *esi=(const unsigned char*)inbuf;
edx<<=1;// Number of input bytes.
const __m128 divisor_float_16=_mm_set_ps1(0.000030517578125f);
__m128 xmm7=divisor_float_16;
for (unsigned char *edi=(unsigned char*)samples;eax!=edx;eax+=8)
{
__m64 mm0,mm1;
movq (mm1, esi+eax); //; d c | b a
punpcklwd (mm0, mm1 ); //; b x | a x
punpckhwd (mm1, mm1 ); //; d d | c c
psrad (mm0, 16 ); //; sign extend
psrad (mm1, 16 ); //; sign extend
__m128 xmm0,xmm1;
cvtpi2ps (xmm0, mm0 ); //; - b | - a -> float
cvtpi2ps (xmm1, mm1 ); //; - d | - c -> float
movlhps (xmm0, xmm1); //; xd xc || xb xa
mulps (xmm0, xmm7); //; *=1/MAX_SHORT
movups (edi+(eax+8)*2-16, xmm0); //; store xd | xc | xb | xa
}
_mm_empty();
}
#ifdef __SSE2__
static void convert_16_float_sse2(const int16_t*inbuf,float *samples,unsigned int c_loop)
{
int eax=0;
int edx=c_loop;
const unsigned char *esi=(const unsigned char*)inbuf;
edx<<= 1; // Number of input bytes.
__m128 xmm7=_mm_set_ps1(0.000030517578125f);
for (unsigned char *edi=(unsigned char*)samples;eax!=edx;eax+=16)
{
__m128i xmm0,xmm1;
movdqu (xmm1, esi+eax); // h g | f e | d c | b a
punpcklwd (xmm0, xmm1); // d x | c x | b x | a x
punpckhwd (xmm1, xmm1); // h h | g g | f f | e e
psrad (xmm0, 16 ); // sign extend
psrad (xmm1, 16 ); // sign extend
__m128 xmm2,xmm3;
cvtdq2ps (xmm2, xmm0); // - d | - c | - b | - a -> float
cvtdq2ps (xmm3, xmm1); // - h | - g | - f | - e -> float
mulps (xmm2, xmm7); // *=1/MAX_SHORT
mulps (xmm3, xmm7); // *=1/MAX_SHORT
movaps (edi+(eax+16)*2-32, xmm2); // store xd | xc | xb | xa
movaps (edi+(eax+16)*2-16, xmm3); // store xh | xg | xf | xe
}
}
#else
#define convert_16_float_sse2 NULL
#endif
//---------------------------- int32 -> float ----------------------------
#ifndef WIN64
extern "C" void convert_32_float_3dnow(const int32_t*inbuf,float *samples,unsigned int c_loop);
#else
#define convert_32_float_3dnow NULL
#endif
static void convert_32_float_sse(const int32_t*inbuf,float *samples,unsigned int c_loop)
{
int eax=0;
int edx= c_loop;
const unsigned char *esi=(const unsigned char*)inbuf;
edx<<=2;// in input bytes (*4)
const __m128 divisor_float_32=_mm_set_ps1(4.656612875245796924105750827168e-10f);
__m128 xmm7=divisor_float_32;
for (unsigned char *edi=(unsigned char*)samples;eax!=edx;eax+= 16)
{
__m64 mm0,mm1;
movq (mm0, esi+eax); // b b | a a
movq (mm1, esi+eax+8); // d d | c c
__m128 xmm0,xmm1;
cvtpi2ps (xmm0, mm0); // b b | a a -> float
cvtpi2ps (xmm1, mm1); // d d | c c -> float
movlhps (xmm0, xmm1); // xd xc || xb xa
mulps (xmm0, xmm7); // *=1/MAX_INT
movups (edi+eax-16+16, xmm0); // store xd | xc | xb | xa
}
_mm_empty();
}
#ifdef __SSE2__
static void convert_32_float_sse2(const int32_t*inbuf,float *samples,unsigned int c_loop)
{
int eax=0; // count
int edx= c_loop;
const unsigned char *esi=(const unsigned char*)inbuf;
edx<<= 2; // in input bytes (*4)
__m128 xmm7=_mm_set_ps1(4.656612875245796924105750827168e-10f);
for (unsigned char *edi=(unsigned char*)samples;eax!= edx;eax+=32)
{
__m128i xmm0,xmm1;
movdqu (xmm0, esi+eax); // dd | cc | bb | aa
movdqu (xmm1, esi+eax+16); // hh | gg | ff | ee
__m128 xmm2,xmm3;
cvtdq2ps (xmm2, xmm0); // xd | xc | xb | xa
cvtdq2ps (xmm3, xmm1); // xh | xg | xf | xe
mulps (xmm2, xmm7); // *=1/MAX_INT
mulps (xmm3, xmm7); // *=1/MAX_INT
movaps (edi+eax+32-32, xmm2); // store xd | xc | xb | xa
movaps (edi+eax+32-16, xmm3); // store xh | xg | xf | xe
}
}
#else
#define convert_32_float_sse2 NULL
#endif
template<class Tin> struct TconvertToFloat
{
typedef void (*TconvertToFloatFc)(const Tin*inbuf,float *samples,unsigned int c_loop);
static float* convert(const Tin *samples,float *outbuf,size_t count,TconvertToFloatFc fc_3dnow,TconvertToFloatFc fc_sse,TconvertToFloatFc fc_sse2)
{
static const float divisor=1.0f/-TsampleFormatInfo<Tin>::min();
size_t c_miss,c_loop;
if (fc_sse2 && Tconfig::cpu_flags&FF_CPU_SSE2)
{
while (((intptr_t)outbuf&15) && count)
{
*outbuf++=divisor*(float)*samples++;
count-=1;
}
c_miss=count&7;
c_loop=count-c_miss;
if (c_loop)
fc_sse2(samples,outbuf,(unsigned int)c_loop);
}
#ifndef WIN64
else if (fc_3dnow && Tconfig::cpu_flags&FF_CPU_3DNOW)
{
c_miss=count&3;
c_loop=count-c_miss;
if (c_loop)
fc_3dnow(samples,outbuf,(unsigned int)c_loop);
}
#endif
else if (fc_sse && Tconfig::cpu_flags&FF_CPU_SSE)
{
c_miss=count&3;
c_loop=count-c_miss;
if (c_loop)
fc_sse(samples,outbuf,(unsigned int)c_loop);
}
else
{
c_miss=count;
c_loop=0;
}
for (size_t i=0;i<c_miss;i++)
outbuf[i+c_loop]=(float)samples[i+c_loop]*divisor;
return outbuf;
}
};
void* TaudioFilter::convertTo(const TsampleFormat &sfIn,const void *bufIn,size_t numsamples,const TsampleFormat &sfOut,size_t samplestoalloc)
{
if (sfIn.sf==sfOut.sf || numsamples==0) return (void*)bufIn;
void *bufOut=alloc_buffer(sfOut,samplestoalloc?samplestoalloc:numsamples);
const size_t count=sfIn.nchannels*numsamples;
switch (sfIn.sf)
{
case TsampleFormat::SF_FLOAT32:
{
int dithering=deci->getParam2(IDFF_dithering),noiseshaping=deci->getParam2(IDFF_noiseShaping); //TODO don't read this always
if (dithering || noiseshaping)
{
if (!dither || oldnoiseshaping!=noiseshaping || oldsfout!=sfOut.sf)
{
oldnoiseshaping=noiseshaping;oldsfout=sfOut.sf;
if (dither) delete dither;
dither=new Tdither(sfOut.bitsPerSample(),noiseshaping);
}
switch (sfOut.sf)
{
case TsampleFormat::SF_PCM16:return dither->process((const float*)bufIn,(int16_t*)bufOut,sfOut.nchannels,numsamples,dithering);
case TsampleFormat::SF_PCM24:return dither->process((const float*)bufIn,(int24_t*)bufOut,sfOut.nchannels,numsamples,dithering);
case TsampleFormat::SF_PCM32:return dither->process((const float*)bufIn,(int32_t*)bufOut,sfOut.nchannels,numsamples,dithering);
}
}
else
switch (sfOut.sf)
{
case TsampleFormat::SF_PCM16:return TconvertFromFloat<int16_t>::convert((const float*)bufIn,(int16_t*)bufOut,count,convert_float_16_3dnow,convert_float_16_sse,convert_float_16_sse2);
case TsampleFormat::SF_PCM24:return TconvertFromFloat<int24_t>::convert((const float*)bufIn,(int24_t*)bufOut,count,NULL,NULL,NULL);
case TsampleFormat::SF_PCM32:return TconvertFromFloat<int32_t>::convert((const float*)bufIn,(int32_t*)bufOut,count,convert_float_32_3dnow,convert_float_32_sse,convert_float_32_sse2);
}
break;
}
case TsampleFormat::SF_PCM16:
switch (sfOut.sf)
{
case TsampleFormat::SF_PCM24:return convert((const int16_t*)bufIn,(int24_t*)bufOut,count);
case TsampleFormat::SF_PCM32:return convert((const int16_t*)bufIn,(int32_t*)bufOut,count);
case TsampleFormat::SF_FLOAT32:return TconvertToFloat<int16_t>::convert((const int16_t*)bufIn,(float*)bufOut,count,convert_16_float_3dnow,convert_16_float_sse,convert_16_float_sse2);
}
break;
case TsampleFormat::SF_PCM24:
switch (sfOut.sf)
{
case TsampleFormat::SF_PCM16:return convert((const int24_t*)bufIn,(int16_t*)bufOut,count);
case TsampleFormat::SF_PCM32:return convert((const int24_t*)bufIn,(int32_t*)bufOut,count);
case TsampleFormat::SF_FLOAT32:return TconvertToFloat<int24_t>::convert((const int24_t*)bufIn,(float*)bufOut,count,NULL,NULL,NULL);
}
break;
case TsampleFormat::SF_PCM32:
switch (sfOut.sf)
{
case TsampleFormat::SF_PCM16:return convert((const int32_t*)bufIn,(int16_t*)bufOut,count);
case TsampleFormat::SF_PCM24:return convert((const int32_t*)bufIn,(int24_t*)bufOut,count);
case TsampleFormat::SF_FLOAT32:return TconvertToFloat<int32_t>::convert((const int32_t*)bufIn,(float*)bufOut,count,convert_32_float_3dnow,convert_32_float_sse,convert_32_float_sse2);
}
break;
}
return bufOut;
}
void* TaudioFilter::init(const TfilterSettingsAudio *cfg,TsampleFormat &sf,const void *bufIn,size_t numsamples,size_t samplestoalloc)
{
bool honourPreferred=true;
int supSF=getSupportedFormats(cfg,&honourPreferred);
int honouredSF=honourPreferred?(parent->preferredsfs|TsampleFormat::SF_PCM24):TsampleFormat::SF_ALL;
if (supSF&honouredSF)
supSF&=honouredSF;
if (sf.sf&supSF)
return (void*)bufIn;
TsampleFormat sfIn=sf;
sf.sf=TsampleFormat::sf_bestMatch(sf.sf,supSF);
return convertTo(sfIn,bufIn,numsamples,sf,samplestoalloc);
}
bool TaudioFilter::is(const TsampleFormat &fmt,const TfilterSettingsAudio *cfg)
{
return cfg->is && cfg->show;
}
bool TaudioFilter::getOutputFmt(TsampleFormat &sf,const TfilterSettingsAudio *cfg)
{
if (!is(sf,cfg)) return false;
bool honourPreferred=true;
int supSF=getSupportedFormats(cfg,&honourPreferred);
int honouredSF=honourPreferred?(parent->preferredsfs|TsampleFormat::SF_PCM24):TsampleFormat::SF_ALL;
if (supSF&honouredSF)
supSF&=honouredSF;
if ((sf.sf&supSF)==0)
sf.sf=TsampleFormat::sf_bestMatch(sf.sf,supSF);
return true;
}
HRESULT TaudioFilter::flush(TfilterQueue::iterator it,TsampleFormat &fmt,const TfilterSettingsAudio *cfg0)
{
return parent->deliverSamples(++it,fmt,NULL,0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -