作者john0312 (Chen John L)
看板Audiophile
标题Re: [心得] 播放软体的强度
时间Tue Feb 16 00:40:03 2010
看完这篇讨论串, 我也很好奇为什麽会有这样子的差距, 所以决定
对播放软体做一点研究, 另外也对Sound Forge Pro 10.0的程式
做一些分析.
本篇对於非电资主修的朋友可能不是那麽容易理解, 所以建议从结论
那边开始看.
由於在作业系统里面, 所有的应用程式都跑在使用者模式(Usermode,
a.k.a Ring 3 on x86), 基於安全考量, 及确保系统安定, 使用者
模式内不能跟硬体沟通. 而跟可以跟硬体沟通的程式, 也就是驱动程式
都在核心模式(Kernelmode, a.k.a Ring 0 on x86)下面运行. 因此,
所有播放声音的动作都需要透过核心模式的驱动程式.
在Windows作业系统下面, 由於时常有不同的程式会需要输出声音,
作业系统就内建有mixer, 他会将不同程式丢出来的声音混合起来,
并且在需要的时候(硬体不支援时), 执行Sample Rate Conversion,
或是Bitrate Conversion.
当然, 刚刚提到Kernelmode跟Usermode的概念, 也就是说SoundForge,
Foobar2000之类的软体不能之接跟硬体沟通, 他们需要透过一些方法
跟核心的驱动程式沟通, 才能够播放声音. 常见的方法有:
- WaveOut:
这种方式是最常见的, 一般来说没有特别需求的程式都使用种方式.
WaveOut的输出会到核心里面的mixer, 做混音的动作. 使用这种方法
的程式会载入winmm.dll, 并且呼叫里面的函数.
- DirectSound:
比起WaveOut, 这种方式题供较多的功能, 但他在旧版的Windows上面
(Windows NT, 98, 95... etc)的支援比较差. DirectSound是DirectX
的一部分, 他原本的设计是用於游戏上面. DirectSound的输出也是
到核心的mixer, 使用这种方法的程式会载入dsound.dll, 并呼叫里面
的函数.
- WASAPI:
在Windows Vista/7下面, 由於微软认为有DirectSound跟WaveOut两个
API很麻烦, 所以微软开发了WASAPI. WASAPI只被Vista/7支援, 而且
Vista/7下面, DirectSound/WaveOut都是透过WASAPI来运作的. WASAPI
的输出也是到核心的mixer.
- ASIO:
前面三种方法都有一个共同的问题, 就是他们透过系统的mixer. 系统的
mixer可能会改变音讯资料, 而且也会延长程式送资料到硬体收到资料的
时间(latency). ASIO解决了这个问题, 他直接将软体的资料, 没有处理的丢给
硬体. 这样延迟就会减少, 而且音讯资料不会被更改.
再来我们研究Sound Forge的主程式, forge100.exe. 首先我们检查程式的
PE Header, 发现这支程式是Microsoft Visual C++ 2008写的, 而且没有加壳.
另外我们查看他们Import Address Table, 里面有导入WinMM.dll的函数,
但是没有发现dsound.dll.
此时我们再用OllyDbg载入主程式forge100.exe. 在CreateFileA()/
CreateFileW()上面下Log断点, 这样可以看这支程式存取了哪些东西. 一般
来说, 如果程式有自己的驱动程式, 他会先存取那个.sys, 并且将那个
.sys载入系统, 然後CreateFile()那个.sys的Device Name. 我们在
CreateFile()上面下断点的用意就是要确认这个程式是否有自己的
驱动程式. 经过检查, forge100.exe并没有自己的驱动程式, 所以他应该
是透过上述的四种方法来播放音讯. 当然过程中我们也发现一些有趣的
事情, 例如说forge100.exe有存取一个叫做lsarpc的pipe, 这个pipe是
用来存取系统帐号密码管理程式的, 当然forge100.exe要存取他来干麻
就不知道了.
再来, 由於我们之前检查IAT发现没有dsound.dll, 但是, 这个DLL模组
仍然可能在程式执行的时候载入, 因此我们断点在LoadLibraryA()/
LoadLibraryW()上面. 执行後发现, dsound.dll在sfdsound.dll载入之後
就被载入了. 因此Sound Forge有可能是使用Direct Sound. 为了确定,
我们断点在DirectSoundCreate()跟waveOutOpen()上面, 执行之後,
都没有break, 但是当我们开启档案并且播放时, 发现waveOutOpen()
被执行了, 此时我们Log断点在waveOutWrite()上面, 在播放的过程中,
waveOutWrite()被重复的呼叫, 直到播放暂停为止. 因此我们可以确定
Sound Forge 也是使用waveOut API.
当然, Sound Forge的资料匣内有看到一个资料匣叫做"Audio Hardware Drivers"
里面有两个档案sfasio.dll跟sfdsound.dll, 他们的功用到目前无法
被确认, 或许在经过设定之後这两个档案就会被使用了.
----------------------------- 结论 ---------------------------------
经研究发现, Sound Forge使用waveOut系列的API来播放音讯,
这种方法很普遍, 一般的应用程式都是使用他, 而其他播放程式
也有不少有支援waveOut, 或是预设使用waveOut.
所以, Sound Forge在输出音讯方面并无过人之处.
对於那些听到差别的, 我认为有下列解释:
- 软体设定:
大多播放软体都有插件的功能, 甚至有一些内建有预设就启用的插件,
这些插件会造成声音的差别. 另外音量也是很重要的, 一般来说较大的
音量会比较好听.
- Mixer设定:
Mixer对於不同的输入有不同的音量控制, 所以当设定不一制时, 会造成
音量的差距. Sound Forge预设waveOut, foobar2000预设Direct Sound, 因此
有可能会有这样的问题.
- SRC ( Sample Rate Conversion ):
这个晚一点解释.
- 心理作用:
这个时常发生, 因此我建议使用ABX盲测来确认. 实际方法在两页之後.
接下来我要讲有关Sample Rate Conversion, 但在这之前, 我要建议非
电资主修的朋友们先看一下我上一篇文. Sample Rate Conversion 就是
将音讯从一个采样率转换成另一个采样率, 也就是说, 我们音讯里面
原本是每秒有n个资料, 我们把他变成每秒有m个资料, 而且之前跟之後的
资料在转换成类比讯号之後应该要相同. 当然, 这是理想状况下面,
有许多写的不好, 或是不想要使用太多CPU的SRC程式在转换之後, 会让之前
跟之後的类比讯号有差别. 一般来说, 一个SRC程式在撰写的时候,
会於到一个抉择, 就是你要输出品质好(跟原本的讯号差异小), 还是
执行速度快. 一般驱动程式跟核心Mixer里面的SRC都是选择後者,
因为如果一个驱动程式就占你90%的CPU, 一般的使用者当然会不爽.
再来, 为什麽我们需要SRC? 其实, 大多时候我们不需要. 当我们的
DAC可以接受原始音讯的采样率时, 我们可以直接将音讯交给DAC,
不需要转换. 但是当我们的DAC不支援这个采样率的时候, 我们就
需要做SRC, 这样DAC才能接受这些音讯资料.
所以对於SRC, 重点在於, 如果可以不用, 那就尽量不用, 但是如果需要,
就要做到好.
--------------------------------- ABX 盲测 -------------------------------
ABX盲测其实就是在当你听过A跟B之後, 随便从A跟B之中选一个(X), 然後在
你不知道的情况下给你听, 要你判定是A还是B. 一般这种测试会重复几次
(通常来说12~20), 然後用统计学的方法计算出你用猜的可能性.
由於我目前没有看到可以ABX两套软体的程式, 所以我就顺手写了一个小程式,
载点如下: ( 原始码+执行档, 直接执行ABXClick.exe即可 )
http://stashbox.org/796583/ABXClick.zip
这支程式会帮你乱数选软体A或是软体B, 然後帮你按下"播放"键. 使用步骤:
1. 先将两个程式(Sound Forge, Foobar2000)开启, 然後开启ABXClick.exe
2. 在两个程式中开启待测的音乐.
3. 将Sound Forge跟Foobar2000的视窗缩小并且同时放在萤幕上面,
确保两个程式的拨放按钮都可以被看的到. 如图一.
图一:
http://stashbox.org/796596/ss1.JPG
4. 回到ABXClick视窗, 但是将滑鼠移到Foobar2000的播放按钮上面,
并且按下F1, 此时, A Position栏位中会出现Foobar2000播放按钮的萤幕座标,
5. 将滑鼠移到Sound Forge的播放按钮, 按下F2. B Position栏位中
会出现Sound Forge播放按钮的座标.
6. 关闭你的萤幕.
7. 此时按下F3, 程式会随机将滑鼠移到A或是B的位置, 然後按下去,
因此音乐会开始播放.
8. 判定是Sound Forge还是Foobar2000, 并将他写下.
9. 打开萤幕, 看哪一个程式正在播音乐.
10. 停止播放音乐, 并且回到ABXClick视窗.
11. 重复第六步数次. (建议: 16次)
12. 统计总共几次测验中, 有多少次是正确的.
另外你可以从以下Excel档案中查出你在猜测的可能性:
(纵轴是测试数目, 横轴是正确数目)
http://www.kikeg.arrakis.es/winabx/bino_dist.zip
一般来说, 猜测可能性在1%(0.01)以内就是真的听的出来. 当然,
那些很明显的差异, 几乎都会导致全对. 我之前有ABX过一个
MP3 320 cbr vs. FLAC, 由於那MP3有Transient Smearing的
问题, 所以ABX出来就25/25全对. 不过我自己测试Foobar2000
vs. Sound Forge是16/11, 猜测可能性为10.5%, 这代表说我
听不出来. (大概是太木耳)
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 114.32.68.68
1F:推 jacky2523555:未看先推大大认真分享 夜深了= =明天再读XD 02/16 00:48
2F:推 sent3:推专业 02/16 00:50
3F:推 rayzart:你真有实验精神! 02/16 00:51
4F:推 djo:太过专业只能END推@@ 02/16 01:06
5F:推 jikanson:哇靠 这超强的 XDD 02/16 01:14
6F:推 capri75:这一篇文章值 1000 元 超强! 02/16 01:29
7F:推 greenguy:推荐这一篇屌文 还是懒人好用foobar最棒了XD 02/16 01:31
8F:推 levine21:推啊 超强大的!! 想请问有办法弄出同一套软体 02/16 01:56
9F:→ levine21:然後不同的输出(例如音效卡或是KS DS这类的) 02/16 01:57
10F:→ levine21:有办法用类似的方式"关萤幕盲测"吗? 02/16 01:57
我建议你可以将一个支援多输出选项的软体连续开两次, 然後两个视窗
用不同的输出选项, 然後同上述方法做ABX.
11F:推 lyokuhana:专业推 02/16 03:17
12F:推 sadowsky:好文:D 02/16 04:35
13F:推 sifun:推专业好文 输出的部分跟我试用的判断的吻合 02/16 05:03
14F:→ wylscott:看无只能end推 02/16 08:40
15F:推 motokare:推ABX 看音响板长知识!! 02/16 08:44
16F:推 wumin0304:推认真与专业!! 02/16 08:53
17F:推 pai74424:不推怎麽行... 02/16 09:31
18F:推 sweshi:推。不过音响这东西,靠理论是说不清的...XD 02/16 10:27
19F:推 edcrfvm45:这个软体不支援ASIO吗? 但我输出选项可以选LYNX ASIO 02/16 11:55
我对Sound Forge这个软体不熟, 文中也提到发现有两个类似输出插件的DLL,
但是这两个DLL并没有被程式使用, 我当时也没有发现有什麽方法可以使用
这两个DLL. 如果你知道如何设定Sound Forge使他使用不同的输出方法,
我希望你可以跟大家分享, 因为我也很想知道.
20F:→ edcrfvm45:A和B我觉得差异不大,不排除是心理作用 02/16 11:56
21F:→ edcrfvm45:但C就很明显 02/16 11:56
如果驱动程式没有做好SRC, 那确实会差很多. 如果你发现SRC造成你音质变差,
那我建议用Sound Forge的SRC, 然後重新存档. 之後再用你觉得方便的播放程式
来播放, 这样就可以得到方便性跟音质.
22F:推 aalaya:这太专业了! 02/16 12:46
23F:推 blackstyler:先推~另外想问问题 WASAPI也会过mixer罗? 02/16 12:47
24F:→ blackstyler:有看过WASAPI也是直接跟硬体沟通的方法 02/16 12:48
25F:→ blackstyler:还是说过不过mixer跟有没有直接跟硬体沟通没有关系呢? 02/16 12:49
我是没有写过或是研究过使用WASAPI的程式, 不过我刚刚去MSDN了解一下.
WASAPI有两种运作模式:
- Shared Mode:
这种模式是一般程式使用的, 会透过Mixer, 所以可以让很多程式同时
播放声音, 也可以做音量控制.
- Exclusive Mode:
这种模式类似ASIO, 他直接跳过Mixer, 以降低Latency, 他也不会
对你的音讯做任何处理, 因此无法透过一般的方法调整音量,
而且同时也只能有一个程式使用Exclusive Mode.
26F:→ blackstyler:另外想请问KS的运作方式是什麽呢? 02/16 12:49
27F:→ blackstyler:所以这样看来要得到最原始的资讯还是需要用ASIO? 02/16 12:51
KS跟ASIO很类似. ASIO是由一间叫做Steinberg的公司开发的, 而
Kernel Streaming是微软开发的. 基本上来说他们解决的问题是一样的,
他们都穿越mixer, 而且有低Latency.
28F:推 bear0418:对於流程的概念受益良多 想弃物理改电资了(误 02/16 13:07
物理是电资的基础, 而且大学入学分数物理还比资工高, 说真的我当时也很想去念物理.
29F:推 bear0418:请问如果想多了解此类知识可以看什麽书籍呢? 02/16 13:17
如果对Windows作业系统有兴趣的, 有一本叫做Windows Internal的书,
写的很详细. 当然如果只是要多了解API, 那去MSDN上面找一找即可.
30F:推 artf08:专业+1 02/16 13:42
※ 编辑: john0312 来自: 114.32.68.68 (02/16 14:42)
31F:推 gloryhzw:GJ 02/16 14:25
32F:推 wayne0411:电资是从物理分出来的...抓着物理好好念比较猛拉XD 02/16 14:44
33F:推 LittleKuu:推专业文! 02/16 15:32
34F:→ levine21:专业回答 再推!! 02/16 18:25
35F:推 bear0418:= =好吧 我继续把我的物理念完 不过这领域还真有趣xd 02/16 19:08
36F:→ bear0418:感谢你推荐的书籍 我会找找看的@@希望会看的懂 02/16 19:09
37F:推 lastfantasy:高手!! 02/16 19:12
38F:推 edcrfvm45:个人是无法判断它到底使用哪个API 02/16 19:12
39F:→ edcrfvm45:但是preference->输出选项中 有ASIO选项可以选 02/16 19:13
40F:→ edcrfvm45:我的AES16应该是没有SRC的问题 02/16 19:14
41F:推 louis0407:John 你弄不出asio会不会是因为你的音效装置不支援啊 02/16 19:28
42F:→ louis0407:这类专业软体应该会自动侦测音效装置是否支援asio 02/16 19:28
43F:→ edcrfvm45:XD 有可能 那以上都白讲了... 02/16 20:12
44F:推 f9999:应该没有自动侦测自动设定这麽神,预设还是会用WDM 02/17 00:17
45F:→ f9999:ASIO都要另外设定 02/17 00:18
46F:推 davidbright:不推不行.. 02/17 13:12
47F:推 scfty:帅强阿!! 实在太夸张惹!! 02/18 22:50
48F:→ Zender:楼上你好阿 02/19 00:09
49F:推 tubahorn:太专业!不推不行,找时间慢慢研究,感谢! 03/06 19:03