找回密码
 -注册-
查看: 8529|回复: 66
打印 上一主题 下一主题

终于从数学原理上明白为什么SACD和CD出来的声音不一样和DSD的电平比较低了

[复制链接]
跳转到指定楼层
1
发表于 2023-4-13 20:59 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式 来自 中国
本帖最后由 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出来的声音默认就是比较小的。



2
发表于 2023-4-13 21:45 来自手机 | 只看该作者 来自 中国
技术大佬,我们都是平民玩家,直接说结果
回复

使用道具 举报

3
 楼主| 发表于 2023-4-13 21:47 | 只看该作者 来自 中国
本帖最后由 zasflower 于 2023-4-13 22:34 编辑
大黄狗将军 发表于 2023-4-13 21:45
技术大佬,我们都是平民玩家,直接说结果

DSD 最终输出的电平比CD低一半左右。6db

然后不同的低通滤波器会是不同的声音,音色不同。我自己手撸了一个音乐播放器用来放SACD,换一个低通滤波器出来的声音都不一样。其它环境变量都一样,就是滤波器代码和算法参数不一样。


回复

使用道具 举报

4
发表于 2023-4-13 22:35 来自手机 | 只看该作者 来自 广东
zasflower 发表于 2023-4-13 21:47
DSD 最终输出的电平比CD低一半左右。6db

然后不同的低通滤波器会是不同的声音,音色不同。我自己手撸 ...

因为电平低所以听起来更柔和?
回复

使用道具 举报

5
 楼主| 发表于 2023-4-13 22:37 | 只看该作者 来自 中国
本帖最后由 zasflower 于 2023-4-13 22:38 编辑
kevin_dp 发表于 2023-4-13 22:35
因为电平低所以听起来更柔和?

不是,滤波器的原因。

你看那个代码应该能理解。
做过电路板的就知道那个一阶滤波器的意思。
一个乘法器,一个加法器。


DSD的高频听起来比较柔和,没有CD那么冲。
回复

使用道具 举报

6
发表于 2023-4-13 23:12 | 只看该作者 来自 上海
再次说明了玩滤波跟别的比是数字音频时代更正确的选择(自我骄傲
回复

使用道具 举报

7
发表于 2023-4-13 23:28 来自手机 | 只看该作者 来自 北京丰台
电平低就会显得柔和,不同版本的CD/pcm差距就很大,另外有些再版厂牌也会把声音做柔和一点。这样声音兼容度好一点,不然低端CD机听原版会刺激。器材好的话就不怕原版的刺激。
回复

使用道具 举报

8
发表于 2023-4-13 23:58 来自手机 | 只看该作者 来自 上海
DSD是噪音整形之后动态范围变小 +-0.5 而PCM是+-1
回复

使用道具 举报

9
 楼主| 发表于 2023-4-14 04:19 | 只看该作者 来自 中国
本帖最后由 zasflower 于 2023-4-14 04:25 编辑

byte = readInt  & 0xFF;
lpfdataR = lpfdataR+ cacheAlpha*((( byte >>   7  ) & 0x01)*2-1 - lpfdataR );
lpfdata2R = lpfdata2R+ cacheAlpha*(lpfdataR - lpfdata2R );
lpfdata3R = lpfdata3R+ cacheAlpha*(lpfdata2R - lpfdata3R );
lpfdata4R = lpfdata4R+ cacheAlpha*(lpfdata3R - lpfdata4R );
dataRight += lpfdata4R;

这个是一个4次的低通滤波器。而这个滤波器的公式就来自于DSD直通模拟滤波器的电路板原理。
lpfdataR = lpfdataR+ cacheAlpha*((( byte >>   7  ) & 0x01)*2-1 - lpfdataR );

DSD SACD 经过多阶的滤波后确实声音要安定很多,高频柔和不冲了。实际上可以进行更多阶数的低通滤波器,只要CPU DSP能撑住。

但是原理是类似的,就是滤波器造成的。
回复

使用道具 举报

10
 楼主| 发表于 2023-4-14 04:43 | 只看该作者 来自 中国
本帖最后由 zasflower 于 2023-4-14 07:39 编辑

https://github.com/sulinhuang/KMusicPlayerWindows/releases/tag/v171Release

你可以拿这个试一下。KMusicPlayerWindows-v1.7.1-RC2.rar 按理我这个播放器后端仍然是使用PCM来播放,所以这个仍然是PCM的声音。但是用CPU滤波器处理后,
声音仍然是DSD那种声音安定和高频柔和的声音。

使用PCM系统播放DSD仍然会有模拟味,声音和高频很安定的感觉。即使这个DSD文件是由CD转换过来。


设定成这样。

DSD的文件即使在PCM系统播放仍然能听出和CD的音色区别。

按照SONY大法的说法,DSD要模拟电路直接模拟低通滤波器。但是用cpu来模拟那个模拟电路算法之后即使播放系统是PCM的,仍然和CD有区别。

现在像 Playback Designs 这类顶级DSD播放器也是用FPGA可程序化芯片来自行设计DSD算法。

所以我想来想去,就是DSD低通滤波器和程序算法造成的。
回复

使用道具 举报

11
发表于 2023-4-14 04:52 来自手机 | 只看该作者 来自 中国
回复

使用道具 举报

12
 楼主| 发表于 2023-4-14 06:56 | 只看该作者 来自 中国
本帖最后由 zasflower 于 2023-4-14 07:39 编辑

我今天本来在测试代码优化后dsf文件播放有没有问题。然后手上刚好又没有dsf文件,就用TASCAM Hi-Res Editor随手转了一首我常听的wav为SACD的dsf。

然后播放出来声音和CD很明显不同。

按理来说这个dsd是由CD转过来的。播放也是用PCM系统播放。耳机电脑什么的都一样。

所以我后来仔细想了想,唯一的变量就是滤波器,就是DSD那个模拟滤波器造成的模拟味。

同样的CD的音源转换成DSD,然后用DSD模拟滤波器播放出来的声音即使在PCM回放系统声音也是DSD味道的。

就是那种高频柔和,声音不冲的DSD模拟味。

既然整个系统唯一的变量就是DSD的滤波器,所以我觉得DSD模拟味的来源就是低通滤波器。不管这个低通滤波器是用电路板用电阻实现还是cpu模拟出来的。它底层数学原理就会有模拟味道。

如果在PCM系统播放DSD也带模拟味能和CD听出很明显的区别(就是声音很安定,很柔和)。那这个模拟味就是来源于低通滤波器。不管它是电路板实现这个滤波器还是cpu模拟这个滤波器(我是用软件CPU模拟的)。像 Playback Designs 这类顶级DSD播放器也是用FPGA可程序化芯片来自行设计DSD回放算法。FPGA 其实就是弱化版本的CPU。
回复

使用道具 举报

13
发表于 2023-4-14 07:18 来自手机 | 只看该作者 来自 中国
学习了
回复

使用道具 举报

14
发表于 2023-4-14 07:40 来自手机 | 只看该作者 来自 上海
不同意楼主观点 楼主代码是DSD转PCM 如果在DSD直通情况下 是直接DSD转模拟信号 然后低通模拟滤波器,40/50K 滤波 然后给运放
回复

使用道具 举报

15
发表于 2023-4-14 08:07 来自手机 | 只看该作者 来自 江苏
hqplayer是不是就是楼主说的这种硬件处理滤波  让声音有各种变化?
回复

使用道具 举报

16
 楼主| 发表于 2023-4-14 08:20 | 只看该作者 来自 中国
番茄炒蛋饭 发表于 2023-4-14 07:40
不同意楼主观点 楼主代码是DSD转PCM 如果在DSD直通情况下 是直接DSD转模拟信号 然后低通模拟滤波器,40/50K ...

实践是检验真理的唯一标准。
https://github.com/sulinhuang/KMusicPlayerWindows/releases/tag/v171Release

这个你下载下来。然后解压KMusicPlayerWindows-v1.7.1-RC2.rar

播放器先启动设置成这样。




然后选一首DSD播放,看PCM系统是不是出现了模拟味道。

就是那种DSD特别的背景和声音很安定,声音很柔和的味道。



回复

使用道具 举报

17
 楼主| 发表于 2023-4-14 08:21 | 只看该作者 来自 中国
本帖最后由 zasflower 于 2023-4-14 08:29 编辑
handsdady 发表于 2023-4-14 08:07
hqplayer是不是就是楼主说的这种硬件处理滤波  让声音有各种变化?

有可能,具体没有软件源代码不清楚。

不过算法确实是可以改变声音回放风格的。Playback Designs也是用软件算法改变DSD回放声音风格。DSD格式就是这个大师发明的,只是他是写在FPGA里面的,FPGA就是个mini CPU.
回复

使用道具 举报

18
发表于 2023-4-14 08:29 来自手机 | 只看该作者 来自 广东深圳
楼主是电脑模拟支出吗?
回复

使用道具 举报

19
 楼主| 发表于 2023-4-14 08:30 | 只看该作者 来自 中国
本帖最后由 zasflower 于 2023-4-14 08:38 编辑
耳机俱乐部小黑 发表于 2023-4-14 08:29
楼主是电脑模拟支出吗?

是用CPU模拟DSD那个模拟低通滤波器。

这个是PCM系统的。因为我只能在PCM系统编辑处理声音。只是运行在64bit 2.8mhz这个虚拟频率。DSP系统运行在这个的虚拟PCM空间。

最终输出32bit 44.1khz PCM.
回复

使用道具 举报

20
发表于 2023-4-14 08:32 | 只看该作者 来自 上海长宁区
这个资料好

回复

使用道具 举报

您需要登录后才可以回帖 登录 | -注册-

本版积分规则

Archiver|手机版|粤icp备09046054号|耳机网-耳机大家坛

粤公网安备 44030602000598号 耳机大家坛、www.erji.net、网站LOGO图形均为注册商标

GMT+8, 2024-11-30 03:03

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表