|
本帖最后由 zasflower 于 2023-4-13 23:36 编辑
最近在优化DSD解码的代码的cpu性能,突然想到了为什么DSD的声音不一样了。实际上你把CD转成DSD64,然后再用DSD低通滤波器重新滤波再转成CD,声音也是不一样的。
数学原理就是这样,DSD-PCM PCM-DSD转换不是无损的。这和ape转flac或者flac转wav不一样。实际上采用什么滤波器和滤波器截止频率选取在那个点声音都会不一样。
代码是这样子:
//dsf DSD file(SACD)
public function decodeDsfDSD(dsdBytes:ByteArray,sampleEventOutBytes:ByteArray):void
{
var byte:uint ;
var dataLeft:Number;
var dataRight:Number;
var readInt:uint;
var indexL:int=0;
var indexR:int =0;
if(dsdBytes.position==60){
dsdBytes.position = 92;
}
for (var i:int = 0; i < 8192; ) {
for(var mny:int=0;mny<512;mny++){
dataLeft = 0;
for(var m:int=0;m<2;m++){
readInt = dsdBytes.readUnsignedInt();
byte = readInt >> 24 & 0xFF;
lpfdataL = lpfdataL+ cacheAlpha*((( byte ) & 0x01)*2-1 - lpfdataL );
lpfdata2L = lpfdata2L+ cacheAlpha*(lpfdataL - lpfdata2L );
dataLeft += lpfdata2L;
lpfdataL = lpfdataL+ cacheAlpha*((( byte >> 1 ) & 0x01)*2-1 - lpfdataL );
lpfdata2L = lpfdata2L+ cacheAlpha*(lpfdataL - lpfdata2L );
dataLeft += lpfdata2L;
lpfdataL = lpfdataL+ cacheAlpha*((( byte >> 2 ) & 0x01)*2-1 - lpfdataL );
lpfdata2L = lpfdata2L+ cacheAlpha*(lpfdataL - lpfdata2L );
dataLeft += lpfdata2L;
lpfdataL = lpfdataL+ cacheAlpha*((( byte >> 3 ) & 0x01)*2-1 - lpfdataL );
lpfdata2L = lpfdata2L+ cacheAlpha*(lpfdataL - lpfdata2L );
dataLeft += lpfdata2L;
lpfdataL = lpfdataL+ cacheAlpha*((( byte >> 4 ) & 0x01)*2-1 - lpfdataL );
lpfdata2L = lpfdata2L+ cacheAlpha*(lpfdataL - lpfdata2L );
dataLeft += lpfdata2L;
lpfdataL = lpfdataL+ cacheAlpha*((( byte >> 5 ) & 0x01)*2-1 - lpfdataL );
lpfdata2L = lpfdata2L+ cacheAlpha*(lpfdataL - lpfdata2L );
dataLeft += lpfdata2L;
lpfdataL = lpfdataL+ cacheAlpha*((( byte >> 6 ) & 0x01)*2-1 - lpfdataL );
lpfdata2L = lpfdata2L+ cacheAlpha*(lpfdataL - lpfdata2L );
dataLeft += lpfdata2L;
lpfdataL = lpfdataL+ cacheAlpha*((( byte >> 7 ) & 0x01)*2-1 - lpfdataL );
lpfdata2L = lpfdata2L+ cacheAlpha*(lpfdataL - lpfdata2L );
dataLeft += lpfdata2L;
byte = readInt >> 16 & 0xFF;
lpfdataL = lpfdataL+ cacheAlpha*((( byte ) & 0x01)*2-1 - lpfdataL );
lpfdata2L = lpfdata2L+ cacheAlpha*(lpfdataL - lpfdata2L );
dataLeft += lpfdata2L;
lpfdataL = lpfdataL+ cacheAlpha*((( byte >> 1 ) & 0x01)*2-1 - lpfdataL );
lpfdata2L = lpfdata2L+ cacheAlpha*(lpfdataL - lpfdata2L );
dataLeft += lpfdata2L;
lpfdataL = lpfdataL+ cacheAlpha*((( byte >> 2 ) & 0x01)*2-1 - lpfdataL );
lpfdata2L = lpfdata2L+ cacheAlpha*(lpfdataL - lpfdata2L );
dataLeft += lpfdata2L;
lpfdataL = lpfdataL+ cacheAlpha*((( byte >> 3 ) & 0x01)*2-1 - lpfdataL );
lpfdata2L = lpfdata2L+ cacheAlpha*(lpfdataL - lpfdata2L );
dataLeft += lpfdata2L;
lpfdataL = lpfdataL+ cacheAlpha*((( byte >> 4 ) & 0x01)*2-1 - lpfdataL );
lpfdata2L = lpfdata2L+ cacheAlpha*(lpfdataL - lpfdata2L );
dataLeft += lpfdata2L;
lpfdataL = lpfdataL+ cacheAlpha*((( byte >> 5 ) & 0x01)*2-1 - lpfdataL );
lpfdata2L = lpfdata2L+ cacheAlpha*(lpfdataL - lpfdata2L );
dataLeft += lpfdata2L;
lpfdataL = lpfdataL+ cacheAlpha*((( byte >> 6 ) & 0x01)*2-1 - lpfdataL );
lpfdata2L = lpfdata2L+ cacheAlpha*(lpfdataL - lpfdata2L );
dataLeft += lpfdata2L;
lpfdataL = lpfdataL+ cacheAlpha*((( byte >> 7 ) & 0x01)*2-1 - lpfdataL );
lpfdata2L = lpfdata2L+ cacheAlpha*(lpfdataL - lpfdata2L );
dataLeft += lpfdata2L;
byte = readInt >> 8 & 0xFF;
lpfdataL = lpfdataL+ cacheAlpha*((( byte ) & 0x01)*2-1 - lpfdataL );
lpfdata2L = lpfdata2L+ cacheAlpha*(lpfdataL - lpfdata2L );
dataLeft += lpfdata2L;
lpfdataL = lpfdataL+ cacheAlpha*((( byte >> 1 ) & 0x01)*2-1 - lpfdataL );
lpfdata2L = lpfdata2L+ cacheAlpha*(lpfdataL - lpfdata2L );
dataLeft += lpfdata2L;
lpfdataL = lpfdataL+ cacheAlpha*((( byte >> 2 ) & 0x01)*2-1 - lpfdataL );
lpfdata2L = lpfdata2L+ cacheAlpha*(lpfdataL - lpfdata2L );
dataLeft += lpfdata2L;
lpfdataL = lpfdataL+ cacheAlpha*((( byte >> 3 ) & 0x01)*2-1 - lpfdataL );
lpfdata2L = lpfdata2L+ cacheAlpha*(lpfdataL - lpfdata2L );
dataLeft += lpfdata2L;
lpfdataL = lpfdataL+ cacheAlpha*((( byte >> 4 ) & 0x01)*2-1 - lpfdataL );
lpfdata2L = lpfdata2L+ cacheAlpha*(lpfdataL - lpfdata2L );
dataLeft += lpfdata2L;
lpfdataL = lpfdataL+ cacheAlpha*((( byte >> 5 ) & 0x01)*2-1 - lpfdataL );
lpfdata2L = lpfdata2L+ cacheAlpha*(lpfdataL - lpfdata2L );
dataLeft += lpfdata2L;
lpfdataL = lpfdataL+ cacheAlpha*((( byte >> 6 ) & 0x01)*2-1 - lpfdataL );
lpfdata2L = lpfdata2L+ cacheAlpha*(lpfdataL - lpfdata2L );
dataLeft += lpfdata2L;
lpfdataL = lpfdataL+ cacheAlpha*((( byte >> 7 ) & 0x01)*2-1 - lpfdataL );
lpfdata2L = lpfdata2L+ cacheAlpha*(lpfdataL - lpfdata2L );
dataLeft += lpfdata2L;
byte = readInt & 0xFF;
lpfdataL = lpfdataL+ cacheAlpha*((( byte ) & 0x01)*2-1 - lpfdataL );
lpfdata2L = lpfdata2L+ cacheAlpha*(lpfdataL - lpfdata2L );
dataLeft += lpfdata2L;
lpfdataL = lpfdataL+ cacheAlpha*((( byte >> 1 ) & 0x01)*2-1 - lpfdataL );
lpfdata2L = lpfdata2L+ cacheAlpha*(lpfdataL - lpfdata2L );
dataLeft += lpfdata2L;
lpfdataL = lpfdataL+ cacheAlpha*((( byte >> 2 ) & 0x01)*2-1 - lpfdataL );
lpfdata2L = lpfdata2L+ cacheAlpha*(lpfdataL - lpfdata2L );
dataLeft += lpfdata2L;
lpfdataL = lpfdataL+ cacheAlpha*((( byte >> 3 ) & 0x01)*2-1 - lpfdataL );
lpfdata2L = lpfdata2L+ cacheAlpha*(lpfdataL - lpfdata2L );
dataLeft += lpfdata2L;
lpfdataL = lpfdataL+ cacheAlpha*((( byte >> 4 ) & 0x01)*2-1 - lpfdataL );
lpfdata2L = lpfdata2L+ cacheAlpha*(lpfdataL - lpfdata2L );
dataLeft += lpfdata2L;
lpfdataL = lpfdataL+ cacheAlpha*((( byte >> 5 ) & 0x01)*2-1 - lpfdataL );
lpfdata2L = lpfdata2L+ cacheAlpha*(lpfdataL - lpfdata2L );
dataLeft += lpfdata2L;
lpfdataL = lpfdataL+ cacheAlpha*((( byte >> 6 ) & 0x01)*2-1 - lpfdataL );
lpfdata2L = lpfdata2L+ cacheAlpha*(lpfdataL - lpfdata2L );
dataLeft += lpfdata2L;
lpfdataL = lpfdataL+ cacheAlpha*((( byte >> 7 ) & 0x01)*2-1 - lpfdataL );
lpfdata2L = lpfdata2L+ cacheAlpha*(lpfdataL - lpfdata2L );
dataLeft += lpfdata2L;
}
i++;
// +6.0db SACD
// if +0db set to dataLeft/64
// 64bit
samplesL[indexL]=dataLeft/32;
indexL++;
}
i -= 512;
for(var mnk:int=0;mnk<512;mnk++){
dataRight = 0;
for( m=0;m<2;m++){
readInt = dsdBytes.readUnsignedInt();
byte = readInt >> 24 & 0xFF;
lpfdataR = lpfdataR+ cacheAlpha*((( byte ) & 0x01)*2-1 - lpfdataR );
lpfdata2R = lpfdata2R+ cacheAlpha*(lpfdataR - lpfdata2R );
dataRight += lpfdata2R;
lpfdataR = lpfdataR+ cacheAlpha*((( byte >> 1 ) & 0x01)*2-1 - lpfdataR );
lpfdata2R = lpfdata2R+ cacheAlpha*(lpfdataR - lpfdata2R );
dataRight += lpfdata2R;
lpfdataR = lpfdataR+ cacheAlpha*((( byte >> 2 ) & 0x01)*2-1 - lpfdataR );
lpfdata2R = lpfdata2R+ cacheAlpha*(lpfdataR - lpfdata2R );
dataRight += lpfdata2R;
lpfdataR = lpfdataR+ cacheAlpha*((( byte >> 3 ) & 0x01)*2-1 - lpfdataR );
lpfdata2R = lpfdata2R+ cacheAlpha*(lpfdataR - lpfdata2R );
dataRight += lpfdata2R;
lpfdataR = lpfdataR+ cacheAlpha*((( byte >> 4 ) & 0x01)*2-1 - lpfdataR );
lpfdata2R = lpfdata2R+ cacheAlpha*(lpfdataR - lpfdata2R );
dataRight += lpfdata2R;
lpfdataR = lpfdataR+ cacheAlpha*((( byte >> 5 ) & 0x01)*2-1 - lpfdataR );
lpfdata2R = lpfdata2R+ cacheAlpha*(lpfdataR - lpfdata2R );
dataRight += lpfdata2R;
lpfdataR = lpfdataR+ cacheAlpha*((( byte >> 6 ) & 0x01)*2-1 - lpfdataR );
lpfdata2R = lpfdata2R+ cacheAlpha*(lpfdataR - lpfdata2R );
dataRight += lpfdata2R;
lpfdataR = lpfdataR+ cacheAlpha*((( byte >> 7 ) & 0x01)*2-1 - lpfdataR );
lpfdata2R = lpfdata2R+ cacheAlpha*(lpfdataR - lpfdata2R );
dataRight += lpfdata2R;
byte = readInt >> 16 & 0xFF;
lpfdataR = lpfdataR+ cacheAlpha*((( byte ) & 0x01)*2-1 - lpfdataR );
lpfdata2R = lpfdata2R+ cacheAlpha*(lpfdataR - lpfdata2R );
dataRight += lpfdata2R;
lpfdataR = lpfdataR+ cacheAlpha*((( byte >> 1 ) & 0x01)*2-1 - lpfdataR );
lpfdata2R = lpfdata2R+ cacheAlpha*(lpfdataR - lpfdata2R );
dataRight += lpfdata2R;
lpfdataR = lpfdataR+ cacheAlpha*((( byte >> 2 ) & 0x01)*2-1 - lpfdataR );
lpfdata2R = lpfdata2R+ cacheAlpha*(lpfdataR - lpfdata2R );
dataRight += lpfdata2R;
lpfdataR = lpfdataR+ cacheAlpha*((( byte >> 3 ) & 0x01)*2-1 - lpfdataR );
lpfdata2R = lpfdata2R+ cacheAlpha*(lpfdataR - lpfdata2R );
dataRight += lpfdata2R;
lpfdataR = lpfdataR+ cacheAlpha*((( byte >> 4 ) & 0x01)*2-1 - lpfdataR );
lpfdata2R = lpfdata2R+ cacheAlpha*(lpfdataR - lpfdata2R );
dataRight += lpfdata2R;
lpfdataR = lpfdataR+ cacheAlpha*((( byte >> 5 ) & 0x01)*2-1 - lpfdataR );
lpfdata2R = lpfdata2R+ cacheAlpha*(lpfdataR - lpfdata2R );
dataRight += lpfdata2R;
lpfdataR = lpfdataR+ cacheAlpha*((( byte >> 6 ) & 0x01)*2-1 - lpfdataR );
lpfdata2R = lpfdata2R+ cacheAlpha*(lpfdataR - lpfdata2R );
dataRight += lpfdata2R;
lpfdataR = lpfdataR+ cacheAlpha*((( byte >> 7 ) & 0x01)*2-1 - lpfdataR );
lpfdata2R = lpfdata2R+ cacheAlpha*(lpfdataR - lpfdata2R );
dataRight += lpfdata2R;
byte = readInt >> 8 & 0xFF;
lpfdataR = lpfdataR+ cacheAlpha*((( byte ) & 0x01)*2-1 - lpfdataR );
lpfdata2R = lpfdata2R+ cacheAlpha*(lpfdataR - lpfdata2R );
dataRight += lpfdata2R;
lpfdataR = lpfdataR+ cacheAlpha*((( byte >> 1 ) & 0x01)*2-1 - lpfdataR );
lpfdata2R = lpfdata2R+ cacheAlpha*(lpfdataR - lpfdata2R );
dataRight += lpfdata2R;
lpfdataR = lpfdataR+ cacheAlpha*((( byte >> 2 ) & 0x01)*2-1 - lpfdataR );
lpfdata2R = lpfdata2R+ cacheAlpha*(lpfdataR - lpfdata2R );
dataRight += lpfdata2R;
lpfdataR = lpfdataR+ cacheAlpha*((( byte >> 3 ) & 0x01)*2-1 - lpfdataR );
lpfdata2R = lpfdata2R+ cacheAlpha*(lpfdataR - lpfdata2R );
dataRight += lpfdata2R;
lpfdataR = lpfdataR+ cacheAlpha*((( byte >> 4 ) & 0x01)*2-1 - lpfdataR );
lpfdata2R = lpfdata2R+ cacheAlpha*(lpfdataR - lpfdata2R );
dataRight += lpfdata2R;
lpfdataR = lpfdataR+ cacheAlpha*((( byte >> 5 ) & 0x01)*2-1 - lpfdataR );
lpfdata2R = lpfdata2R+ cacheAlpha*(lpfdataR - lpfdata2R );
dataRight += lpfdata2R;
lpfdataR = lpfdataR+ cacheAlpha*((( byte >> 6 ) & 0x01)*2-1 - lpfdataR );
lpfdata2R = lpfdata2R+ cacheAlpha*(lpfdataR - lpfdata2R );
dataRight += lpfdata2R;
lpfdataR = lpfdataR+ cacheAlpha*((( byte >> 7 ) & 0x01)*2-1 - lpfdataR );
lpfdata2R = lpfdata2R+ cacheAlpha*(lpfdataR - lpfdata2R );
dataRight += lpfdata2R;
byte = readInt & 0xFF;
lpfdataR = lpfdataR+ cacheAlpha*((( byte ) & 0x01)*2-1 - lpfdataR );
lpfdata2R = lpfdata2R+ cacheAlpha*(lpfdataR - lpfdata2R );
dataRight += lpfdata2R;
lpfdataR = lpfdataR+ cacheAlpha*((( byte >> 1 ) & 0x01)*2-1 - lpfdataR );
lpfdata2R = lpfdata2R+ cacheAlpha*(lpfdataR - lpfdata2R );
dataRight += lpfdata2R;
lpfdataR = lpfdataR+ cacheAlpha*((( byte >> 2 ) & 0x01)*2-1 - lpfdataR );
lpfdata2R = lpfdata2R+ cacheAlpha*(lpfdataR - lpfdata2R );
dataRight += lpfdata2R;
lpfdataR = lpfdataR+ cacheAlpha*((( byte >> 3 ) & 0x01)*2-1 - lpfdataR );
lpfdata2R = lpfdata2R+ cacheAlpha*(lpfdataR - lpfdata2R );
dataRight += lpfdata2R;
lpfdataR = lpfdataR+ cacheAlpha*((( byte >> 4 ) & 0x01)*2-1 - lpfdataR );
lpfdata2R = lpfdata2R+ cacheAlpha*(lpfdataR - lpfdata2R );
dataRight += lpfdata2R;
lpfdataR = lpfdataR+ cacheAlpha*((( byte >> 5 ) & 0x01)*2-1 - lpfdataR );
lpfdata2R = lpfdata2R+ cacheAlpha*(lpfdataR - lpfdata2R );
dataRight += lpfdata2R;
lpfdataR = lpfdataR+ cacheAlpha*((( byte >> 6 ) & 0x01)*2-1 - lpfdataR );
lpfdata2R = lpfdata2R+ cacheAlpha*(lpfdataR - lpfdata2R );
dataRight += lpfdata2R;
lpfdataR = lpfdataR+ cacheAlpha*((( byte >> 7 ) & 0x01)*2-1 - lpfdataR );
lpfdata2R = lpfdata2R+ cacheAlpha*(lpfdataR - lpfdata2R );
dataRight += lpfdata2R;
}
i++;
// +6.0db SACD
// if +0db set to dataRight/64
// 64bit
samplesR[indexR]=dataRight/32;
indexR++;
}
}
//need write data later
for(i=0;i<8192;i++){
// 32bit
sampleEventOutBytes.writeFloat(samplesL);
sampleEventOutBytes.writeFloat(samplesR);
}
}
主要公式是这个:
lpfdataL = lpfdataL+ cacheAlpha*((( byte >> 7 ) & 0x01)*2-1 - lpfdataL )
将二进制右移动7位检查当前1bit二进制是0还是1,0就是-1.0电平 1就是+1.0电平。
然后输出 lpfdataL 会加上高频的目标电平。会缓慢逼近目标电平。相当于 y += (dsd-y) * cacheAlpha
cacheAlpha 取值为0-0.05-0.2-0.5-0.7-1,0则会切除所有频率。1不会动任何频率。(取中间则数则切除DSD高频噪声)
因为在逼近目标电平+1.0 -1.0(因为要切除高频噪声所以cacheAlpha不可能取值1,不然任何频率不会动) 所以DSD出来的声音默认就是比较小的。
|
|