Pre-emphasis☆超·大·全·补完☆

更新:我感觉我搜了下中文圈谈pre-emphasis的不多,而且很多没提到EAC无法识别subcode的问题,我觉得有责任感(大雾)写个摘要提炼下重点。这样别人找起来方便也不用读我这私货奇多的裹脚布。

TL;DR

  1. 关于Pre-emphasis的介绍见前文,那个不长。但是简单来说,为了减少噪声和量化误差的影响,部分老CD(尤其是日本八十年代)会对CD进行预增益,加强高频,并在播放的时候靠CD Player进行de-emphasis来还原。抓碟时需要手动进行这一过程,否则抓出来的音频高频偏高。
  2. 存在只有部分track有预增益的CD
  3. Pre-em的Flag可以写在CDDA的TOC里,也可以写在subcode(正常应该两者皆有)。抓轨软件识别出之后,一般会在CUE里加上FLAGS PRE
  4. 主流rip软件EAC只能识别TOC里的Pre-em flag,不能识别subcode里的!很重要所以再说一遍,EAC的pre-em识别功能是个残疾!要正确地读取subcode里的pre-em flag,Windows推荐使用CUERipper,Mac推荐XLD。
  5. pre-em的音轨即使识别出来,也需要处理。可以用SOX等软件直接进行de-em转换,也可以用foobar2000配合pre-emphasis=1(需要手动添加,CUE里的不识别)的tag和foo_deemph.dll、foo_dsp_deemph.dll等插件进行回放时即时de-em(不修改文件)。
  6. foo_deemph vs foo_dsp_deemph: 前者为后处理滤镜,只支持无损音频(fb2k本身限制),但是可以参与ReplayGain计算(即:RG scan是在考虑了de-em之后计算),另外BUG:暂不支持无损+内嵌CUE+仅部分轨有pre-emphasis=1的特殊情况。后者为DSP(需要DSP中勾选),支持所有格式但是不参与RG计算,无法计算出准确的音量增益。
  7. 可以利用频谱分析(推荐使用周期图,最清晰)来对比音轨和识别pre-em过的音轨。

下面正文。


我发现一个趋势:每次我写点啥文章,绝对会在写完之后发现更多该topic相关的东西,然后……写出一个比本篇还长的续。这次大概也不例外了。

Pre-emphasis危机

上篇说到Pre-emphasis的事情,有提到我对我之前的收藏里有多少没发现的Pre-emphasis的担忧,这不果然说中了。因为知道了这玩意的存在,所以在抓うしろゆびさされ組的第二专《∞》的时候专门留了个心眼,发现和首专不同,这张抓出来并没有pre-emphasis的tag,听起来也一切正常。不过和手头其他版本对比的时候我想起来当年我就觉得《おニャン子クラブ大全集》(下称:大全集)里的「バナナの涙」不太对,但是当时手头其他版本都是MP3的只有这个是无损,所以以为是别的都有问题。这和原版专辑《∞》里的一比就听出问题了:《大全集》里的版本明显尖锐许多。

我赶紧去看《大全集》的CUE,发现并没有FLAG PRE。这下我彻底恐慌了:连官方出的精选集都能搞这幺蛾子(有pre-emphasis却没标明),这到底要怎么避免哦?我进而把这《大全集》的DISC 4 with おニャン子クラブ集又重头到尾听了一遍(同时不断和手头有的其他版本对比),果然发现有多首,包括うしろゆびさされ組的全部四轨都有pre-em的问题。其他有些虽然听着偏尖锐,但是你别说,这个东西单独听真的很难说清楚到底有没有pre-em,尤其是要知道这个pre-emph主要是对某些音色的乐器影响比较大(比如上次提到过的,架子鼓里的钹),对人声尤其是比较粗的人声其实变化不大(嗯新田恵利这种很尖锐的声线就明显多了w),某些歌曲甚至对比着听都不明显。而且和其他版本对比本身也有个问题——你怎么知道其他版本就是正确的呢?尤其是我手里的其他版本很多连无损都不是。

当然,这张DISC 4本身就是从小猫单飞的各个单曲/专辑里采集来的,音源不一,所以有这种问题也算在我的意料之内,不过接下来的事情就更蛋疼了。《大全集》大部分碟是小猫俱乐部八十年代的原创录音专辑+额外曲目的形式。所以如果不出意外,至少前面和原专辑一样的部分的pre-emphasis状态应该统一:要么都有要么都没有。还是通过对比的方式,我发现至少前三张碟的大部分都OK——并没有pre-emph,还顺便发现了反而是我最早下的一张的小猫的碟(网易云扒的MP3),算是最经典的二专《PANIC THE WORLD》(下称:PANIC),其实有pre-em(汗,这碟我感觉听了有快上百遍了,当时也没觉得有啥问题……现在再去听真是尖到不行)。

用Foobar2000回放有损的pre-em音频的方案

这里插播一个实践上的问题。上次提到de-emphasis要用foobar的两个插件,lvqcl开发的foo_deemph和foo_dsp_deemph。前者是后处理插件,也就是说无设置,会无脑应用到后处理里(包含回放和转换,如果勾了后处理选项)。我之前是用的这个。结果这个的问题在于他仅作用于无损音频——关于这点我问了作者,并不是他不想改,而是foobar对后处理插件的限制(或者说foobar的工作流程如此)。所以,我上面提到那个,有pre-emphasis的MP3专辑《PANIC》,自然只能用DSP版本才行。但是这就又引出一个问题:回放增益(ReplayGain)。在进行了deemph之后,音频改动还是蛮大的,回放增益扫描的结果也不会一样。事实上,一般一个音轨deemph之后,回放增益得加个2dB。之前用foo_deemph的时候倒是OK,因为回放增益在计算时会自动考虑进去所有后处理;但是现在换了DSP版,这个在计算回放增益的时候是不工作的。

解决办法倒不是没有,就是非常啰嗦:

  1. 把MP3文件转换成WAV;
  2. 现在因为是无损了,所以foo_deemph工作了,可以扫描RG了。
  3. 把RG用MP3tag复制RG到之前的MP3(这是一个傻逼点,因为foobar2000刻意不支持文件间复制RG信息,只能手动一个个输入…一般的标签倒是支持)。
  4. 然后回放的时候……你得换成foo_dsp_deemph,因为只有这个支持有损(别忘了pre-emphasis的tag还得有,DSP里得勾上)。虽然顺序变成了先apply RG再apply deemph,从数学原理上来讲两者等效。

另外,因为回放的时候你不能同时装foo_deemph和foo_dsp_deemph(否则无损的有pre-emphasis tag的音频就会被deemph两次了),所以整个流程你得重启foobar N次,动用两个软件(foobar2000,Mp3Tag)。

不过这个流程可以稍微简化一下:在转换MP3到WAV的时候,直接用DSP版的把deemph硬编码进去——别忘了之后删掉pre-emphasis的tag——然后和上面就一样了。这个方案的区别在于完全用不到后处理版的foo_deemph,不需要重启foobar,但是总体而言还是很麻烦。

而且更麻烦的一点是,如果你改用foo_dsp_deemph(凡是你要给有损音频de-em,这是唯一的选择),那么就连原来没问题的无损的音频的RG扫描都不能直接进行了。所以,果然我的第一要务是赶紧把这些垃圾MP3洗版买二手CD洗掉。

哦顺便说句,foo_dsp_deemph还有另外一个同名的,由开发者mudlord从他的那个巨型插件foo_dsp_effect里分离出来的独立组件。之前说的有误,这个插件虽然名字叫DSP,但是其实包含上述两个插件的的功能,即后处理+DSP:在安装该插件之后,自动含对有pre_emphasis =1 tag的文件进行de-em;与此同时,你还可以在DSP开启强制de-em。而且其提供了俩DSP,外一个是黑胶的RIAA Curve

至于de-em算法方面,我对比了lvqcl版、mudlord版以及sox,虽然均非bitwise identical但是基本频谱一致,应该不会有任何听感上的差别。(7/5更新)

「およしになってねTEACHER」之谜

实践方面的问题就插播完毕,回到之前的话题,既然我们知道三专《PANIC》有pre-emphasis,那前两专呢?一专《KICK OFF》我手头的是无损,打开CUE一看发现里面大大的FLAGS PRE,这就好说了,直接给wav文件加个tag完事儿。二专《夢カタログ》(下称:夢)我之前虽然下了个MP3,但一直都没解压,因为反正《大全集》里都有了;这不为了对比我又翻出来了。果然这二专一听,也是有pre-emphasis的,但是前面说到的“蛋疼”的事情来了:我发现在de-emphasis之后,二专的大部分曲目听感和《大全集》版一致,唯有第一轨「およしになってねTEACHER」(即第二单曲),不但两者不同,和3专《PANIC》里收录的版本也不同!我又找了多个版本,最后从“尖锐程度”从大到小排列大概是这么个样子(其实有的差别很小,我用了耳朵听之外的方法检测,不过这是下一章的重点。另外,听的时候因为一定要保持平均响度高度一致(否则怎么对比),由于上面提到过的RG+pre-em的配合问题,这里请暂时配合on the fly版的RG DSP:foo_r128norm使用,并放在foo_dsp_deemph的后面):

  1. 《夢》(pre-emph)
  2. 《大全集》 = Single版
  3. 《夢》(de-emph)
  4. 《PANIC》(de-emph) =《SUPER BEST》
  5. 《大全集》(de-emph) = Single版 (de-emph)

这里,4这两个版本听感完全一致,外加精选集《SUPER BEST》是我从实体碟抓的无损(不过有个暂不相关的问题后面讲),所以姑且称之为“标准版本”。那么《夢》和重制《夢》的《大全集》的问题在于:第一,两者莫名地不一致,虽然差别不大;第二,《夢》即使加了de-em(根据其他音轨推算应该加),也比4这个标准版要尖锐一些(但是不至于刺耳);至于《大全集》版,不加de-em处于《夢》加和不加之间,加了就反而比4这个标准版还要低沉。

如果再进一步从听感上选最合理的然后简化,有三个版本(还是按照高频强度从高到低排列):

  • 《大全集》 = Single版
  • 《夢》(de-emph)
  • 《PANIC》(de-emph) =《SUPER BEST》

几乎可以肯定《大全集》制作的时候,是使用单曲音源替换掉了第一轨——因为手头的单曲版和他的特征一致,而且否则也无法解释为啥其他轨《大全集》和《夢》de-em后听感完全一致,唯有这个不同。但是要注意的是「およしになってねTEACHER」这张单曲是只有黑胶版的,并没有发过CD;我手头这个“单曲版”的MP3到底怎么从黑胶Rip出来,规不规范,无从得知;不过对于制作方波利佳音,他肯定有母带所以倒不是问题。

至于《夢》的版本,在正确地加了de-emph之后其实和《大全集》版/单曲版区别并不大,这里这里我大胆猜测,两者的区别可能仅仅是黑胶和CD制作上客观导致的(毕竟一个analog一个digital)。又或者是《夢》里的版本是Album version(当年album version基本都是没任何标记)。

至于后面为什么《PANIC》以及《SUPER BEST》这两张精选集里收的版本互相一致、却和上面的单曲版和专辑版都不同就很难理解了。而且这个“不同”还是相当明显的——从最最开始的前奏就很明显可以听出。一般而言,这类精选集收的应该都是单曲版,其不同的原因现在也很难考证了。

利用频谱分析

上述「TEACHER」这场风波,让我了解到纯靠听来比较音轨,实在是不靠谱,尤其是差别小的时候。而且很多时候,我手头只有一个版本,也很难判断是否有pre-em。介于pre-em技术的原理就是加个EQ,所以第一时间想到的就是用频谱来分析了。

一般而言,直接FFT后的Amplitude spectrum就OK,用频谱密度(Spectral Density)也行,不过基本趋势都是一样的。具体实现上前者没什么好说的,注意用双侧转换成单侧(参见Matlab的fft说明文档里的范例)就是。谱密度的话,可以直接用PeriodogramMatlab函数),或者用Welch’s methodMatlab函数)可能更美观些。

不过,在分析前,得先做一些前处理。为了方便对比,首先需要注意的是音量均衡的问题。虽然我可以在foobar里跑RG,但是为了简单起见我做了个纯粹根据数学RMS(均方根)来均衡强度的函数:


function [ y ] = normalizerms( x, targetdB )
%NORMALIZERMS Summary of this function goes here
% Detailed explanation goes here
%normalize
targetrms=10^(targetdB/20);
myrms=rms(x);
% valueDBFS = 20*log10(abs(myrms));
y=x/(myrms/targetrms);
end

view raw

normalizerms.m

hosted with ❤ by GitHub

这样,我就不用操心响度不一不便于对比的问题了。实际操作上,音轨通过audioread导入之后,要先downmix到单音道,然后跑这个来均衡强度:

 [wave,Fs]=audioread(file);
 x=(wave(:,1)+wave(:,2))/2; 
 x=normalizerms(x, -20);

这里我选了-20dB这个比较低的目标RMS,因为我不想导致clipping。

然后再把信号跑上面的提到的几种频谱法就行了,下面我主要以Periodogram为例。那么,就让我们先随便找一首歌,来对比pre-em和de-em的区别。用的曲目是上次提过的「偏差値BOY」,无损音源。

(左边:原始文件(pre-em),右边:de-em之后。点击查看幻灯片或者大图)

和想象的一样,两者的周期图的区别较为明显,后者高频方向向下倾斜的趋势更明显,也符合de-em的原理。基本上,如果看到曲线接近后者,可以认为是正常的歌曲;如果是前者这种很平的,那就是有pre-em。嗯,还是有点模糊…不过比纯靠听稍微强点。

接下来就看看上面提到过的「TEACHER」的部分版本。

左起:《SUPER》版,《夢》版(de-em后)和《大全集》版(de-em后)

其中,《夢》版(de-em)在16kHZ左右的狂跌是因为MP3格式所导致。不过除掉这部分不看,也可以看出和1的标准版相比,整体更平(即:高频更高)。而最后一个的《大全集》版(de-em后)则比1更斜(即:高频更低)一些。

这里有一点要注意,就是《大全集》版(de-em后)以及这里没贴出来的单曲版(两者基本一样)都在大约1.5kHZ的地方有一个凹槽,这是很不正常的(别的版本都没有)。同样的凹槽其实我在很多音轨上都见过,我强烈怀疑是早期母带制作时,在压制或者是analog转digital时什么过程的痕迹。也许这也能解释为什么《大全集》版(de-em后)比标准版要低,虽然两者听感几乎一致。

其他几种visualization的方法既然我都做了,就贴一下让大家感受一下。

Welch’s method估计PSD:参数我都瞎搞的,不过基本而言,x后面的第一个参数window越小分割次数越高,平滑度越高,也越慢。

左起:《SUPER》版,《夢》版(de-em后)和《大全集》版(de-em后)

另外,我一直想模拟一下类似foobar频谱的按band分开的柱状图:

QQ图片20170701184057

但是有太多的搞不清楚的问题:第一,band怎么分?Foobar明显不是用线性的,每个band的label分别是(以20个band为例):

[50,69,94,129,176,241,331,453,620,850,1200,1600,2200,3000,4100,5600,7700,11000,14000,20000]

看不出有什么规律,只知道肯定不是线性,手动回归了一下大概是类似y=10^(1.5633+0.1368x) (x=1:20)的样子。

第二,每个band里面到底应该怎么把里面的点“累积”起来?是直接相加(因为是离散的)?

总之,我瞎搞了一番,最后成图如下:

左起:《SUPER》版,《夢》版(de-em后)和《大全集》版(de-em后)。单位写错了应该是HZ,懒得改了。

完整代码(含所有的可视化方式,在上方切换):


filenames = {'samples/teacher/super.wav','samples/teacher/yume_deem.wav','samples/teacher/yume2005_deem.wav'};
%'samples/panic.wav','samples/super.wav', 'samples/yume.wav','samples/yume2005.wav','samples/single.mp3'
%filenames = {'old/good_rg.wav','old/bad_rg.wav'};
method = 'peri'; % peri, welch, fft, fftband
close all
for i = 1:length(filenames)
file = filenames{i};
[wave,Fs]=audioread(file);
x=(wave(:,1)+wave(:,2))/2; %Downmix
% %Filter
% N = 200; % FIR filter order
% Fp = 15000; % 20 kHz passband-edge frequency
% Rp = 0.00057565; % Corresponds to 0.01 dB peak-to-peak ripple
% Rst = 1e-4; % Corresponds to 80 dB stopband attenuation
% eqnum = firceqrip(N,Fp/(Fs/2),[Rp Rst],'passedge'); % eqnum = vec of coeffs
% lowpassFIR = dsp.FIRFilter('Numerator',eqnum);
% x=lowpassFIR(x);
x=normalizerms(x, 20);
switch method
case 'peri' % periodogram
figure
periodogram(x,rectwin(length(x)),length(x),Fs)
xlim([0 20])
ylim([-180 20])
case 'welch' % Welch's power spectral density estimate
[pxx,f] = pwelch(x,2000,[],[],Fs); % Disclamer: I have zero idea about those parameters
figure
plot(f,10*log10(pxx)) % You can remove dB conversion
xlabel('Frequency (Hz)')
ylabel('Magnitude (dB)')
xlim([0 20000])
ylim([-105 40])
case 'fft' % FFT (amplitude spectrum)
L=length(x);
f = Fs*(0:(L/2))/L;
Y = fft(x);
P2 = abs(Y/L); % You can choose to not divide it by L, no difference
P1 = P2(1:L/2+1);
P1(2:end1) = 2*P1(2:end1);
figure
plot(f,P1) % you can convert it to dB too, make sure to use 'voltage'
xlabel('f (Hz)')
ylabel('|P1(f)|')
ylim([0 0.004])
xlim([0 20000])
case 'fftband'
L=length(x);
f = Fs*(0:(L/2))/L;
Y = fft(x);
P2 = abs(Y); % I don't divide by L here, because I'm going to use dB later
P1 = P2(1:L/2+1);
P1(2:end1) = 2*P1(2:end1);
bars = 20;
% % Linear spacing
% fvalues = linspace(0,20000,bars+1);
% fvalues = fvalues(2:end);
% % Log10 spacing
% fvalues = logspace(-1,log10(20000),bars);
% Copied from FB
fvalues=[50,69,94,129,176,241,331,453,620,850,1200,1600,2200,3000,4100,5600,7700,11000,14000,20000];
fband = zeros(length(fvalues),1);
% Again, I don'tknow shoul you just add them together.
for k = 1:length(f)
for j = 1:length(fvalues)
if f(k) < fvalues(j)
fband(j) = fband(j)+P1(k);
break
end
end
end
figure
histogram('BinEdges',0:length(fvalues),'BinCounts',round(db(fband,'voltage'))')
ylim([0 180])
labels = [0 fvalues(2:2:length(fvalues))];
xticklabels(num2cell(labels))
xlabel('f (Hz)')
ylabel('dB')
end
title(file)
end

CD rip:正确读取subcode的pre-em flags

之前说过,我最怕的是厂商把明明有pre-em的曲目压到CD里面却不处理也不标明——因为这样作为听众哪怕有实体碟那么听到的也是错误的。那么我上面提到的几个例子,尤其是我手头有无损的《大全集》真的一定就是这样吗?答案是否定的。没错,虽然我手里的大全集的CUE,并没有FLAGS PRE,但是这并不代表原碟就一定没有对pre-em进行标记。

这要先从pre-em的标记方式说起。在CDDA中,可以有两个地方标记各种flag:一个是在目录(Table of contents,TOC)中,一个是在“subcode”(又称subchannel data)中。其实CDDA实际的结构要更复杂一些,简单地说就是除了16位的音频数据的部分,其他有大量的类似元数据的subcode存在。其中,每一轨都可以有自己的subcode,而在整张光碟的头部、尾部又各有一个区域完全是subcode。其中,头部的subcode包括了一些诸如discid之类的元数据,另外也有TOC(所谓的TRACK 00):TOC其实就是对整张专辑各个轨道的简单描述,主要是每轨的开始时间(便于跳转),但是也可以包括诸如pre-em在内的tag。

然而与此同时,在每一轨的subcode中,同样可以包含这样的信息。这问题就来了:虽然理想情况下两者应该是一致的,但是大量实践证明,有许多CD,只在其中一个中包含了pre-em的flag(一般是subcode)。

这俩不一致本身其实不是什么大事儿,但是问题在于,Win平台下最流行的CDrip软件,大名名鼎鼎的的EAC,不支持subcode flag。呃,其实准确地说,也是有难言之隐:早在01年左右的0.9x版本的EAC,包含一个叫做“Detect TOC Manually”的功能,说白了就是用subcode里的信息手动重建TOC(而不依赖于TRACK 00的TOC),这个功能就能检测到subcode-only的pre-em tag。但是由于当时有些CD利用hack TOC的方式来防复制,所以EAC这种功能有违反欧洲法规的风险(等于你绕过了TOC的加密),作者就在后面移除了该功能。大概这也是为什么我在论坛有时候会看到有人强调要用旧版EAC的缘故?

无论如何,身为几乎在烧友圈(至少国内)被神化的EAC居然缺失这么明显一个功能,也是略显讽刺。所以,即使碰到有的碟,正确用EAC抓取、CUE没有pre-em的flag,听起来却尖锐,也就是上面说的《大全集》中的某些轨,也不一定就是厂商搞砸,而是subcode的flag没被抓出来。当然现实来说,《大全集》是21世纪的2005年发售的,感觉还在发行带pre-em的CD概率并不高……大概还是搞砸了罢,这个没有实体版实在是无从确认了。别忘了之后波利佳音又洗过一版,说不定正是为了擦屁股呢?(笑)

不过虽然那个手头没有实体无法验证,我之所以会深入研究这个正是因为我手里就有一张这样的碟:[1986-10-21] [D32P6003] おニャン子クラブ – スーパーベスト(即前文所说的《SUPER BEST》)。这碟我用EAC抓,是显示没有pre-em:

QQ截图20170701222211

抓出来的CUE自然也没有flag。但是实际上呢?用听的就知道,第一轨「お先に失礼」肯定有pre-em,后面的第二轨又明显没有。可见这碟应该是属于部分pre-em那种(考虑到是选集,也说得通)。

既然EAC不行,我们只能换软件了。hydrogenaudio提供了一个非常完善的ripper软件列表。不过排除一些收费软件和非Win平台的(比如很有名的Mac平台的XLD),外加上我从这贴了解到的其他一些,我大概筛选出这几个:

于是先来试试最简单的CUERipper。

QQ图片20170701234441

选项非常简单,要我说是EAC过分复杂了。虽然这里看不出来,但是抓出来的CUE确实有正确的FLAGS PRE没错。具体来说,是tr. 1/6/9/11有,也和试听听感完全一致。

再让我们试试其他俩软件。cdda2wav和cdrdao都是命令行工具;而且更不方便的是两者官方网站都不提供binary,只有source code。cdda2wav现在是软件包“cdrtools”(原名:cdrecord)的一部分,这里可以找到Win-32原生的编译版本(最新:v3.02a07),或者用第三方的GUI版本——cdrtfe,里面也有编译好的cdda2wav(不过是虚拟版,如果你要单独运行,得把cygwin目录下的cygwin1.dll复制到和cdda2wav.exe一起)。

但是这个cdda2wav……用起来有问题。还是上面这张碟,让我们跑个-J(仅输出信息)来看看:

C:\Users\Administrator\Desktop\schily-cdrtools-3.02a07\win32>cdda2wav -J
No target specified, trying to find one...
Using dev=7,0,0.
Type: ROM, Vendor 'HL-DT-ST' Model 'DVDRAM SP80NB60 ' Revision 'RA00' MMC+CDDA
261632 bytes buffer memory requested, transfer size 64512 bytes, 4 buffers, 27 s
ectors
#Cdda2wav version 3.02a07_mingw32_nt_1.0.17-0.48-3-2-_i686_i686, libparanoia sup
port
AUDIOtrack pre-emphasis copy-permitted tracktype channels
 1-15 no no audio 2
Table of Contents: total tracks:15, (total time 57:28.72)
 1.( 3:50.00), 2.( 4:16.50), 3.( 3:59.45), 4.( 3:28.52), 5.( 3:44.08),
 6.( 3:12.20), 7.( 3:52.20), 8.( 3:45.20), 9.( 4:08.45), 10.( 4:00.65),
 11.( 3:58.67), 12.( 3:50.70), 13.( 3:50.15), 14.( 3:08.60), 15.( 4:21.60),

Table of Contents: starting sectors
 1.( 0), 2.( 17250), 3.( 36500), 4.( 54470), 5.( 70122),
 6.( 86930), 7.( 101350), 8.( 118770), 9.( 135665), 10.( 154310),
 11.( 172375), 12.( 190292), 13.( 207612), 14.( 224877), 15.( 239037),
 lead-out( 258672)
CDINDEX discid: Bk20VmlSPt6WEen5bpehBUBc6no-
CDDB discid: 0xc20d780f
CD-Text: not detected
CD-Extra: not detected
No media catalog number present.
scanning for ISRCs: 15 ...
index scan: 1...difference: TOC:without, subchannel:with preemphasis
correcting TOC...
difference: TOC:with, subchannel:without preemphasis
correcting TOC...
index scan: 5...difference: TOC:without, subchannel:with preemphasis
correcting TOC...
difference: TOC:with, subchannel:without preemphasis
correcting TOC...
difference: TOC:without, subchannel:with preemphasis
correcting TOC...
index scan: 6...difference: TOC:without, subchannel:with preemphasis
correcting TOC...
difference: TOC:with, subchannel:without preemphasis
correcting TOC...
index scan: 8...difference: TOC:without, subchannel:with preemphasis
correcting TOC...
difference: TOC:with, subchannel:without preemphasis
correcting TOC...
difference: TOC:without, subchannel:with preemphasis
correcting TOC...
index scan: 9...difference: TOC:without, subchannel:with preemphasis
correcting TOC...
difference: TOC:with, subchannel:without preemphasis
correcting TOC...
index scan: 10...difference: TOC:without, subchannel:with preemphasis
correcting TOC...
difference: TOC:with, subchannel:without preemphasis
correcting TOC...
difference: TOC:without, subchannel:with preemphasis
correcting TOC...
index scan: 11...difference: TOC:without, subchannel:with preemphasis
correcting TOC...
difference: TOC:with, subchannel:without preemphasis
correcting TOC...
index scan: 15...

前面的不重要,不过也可以看到TOC里没扫到pre-em。但是从每个track的subcode scan开始:

index scan: 1...difference: TOC:without, subchannel:with preemphasis
correcting TOC...
difference: TOC:with, subchannel:without preemphasis
correcting TOC...
index scan: 5...difference: TOC:without, subchannel:with preemphasis
correcting TOC...
difference: TOC:with, subchannel:without preemphasis
correcting TOC...
difference: TOC:without, subchannel:with preemphasis
correcting TOC...

这就很诡异了:扫第1轨的时候,显示发现了TOC和subchannel不一致(subchannel=有,pre-em,TOC=无),于是纠正TOC,到这步没问题;但是紧接着,居然又来了一遍,不过这次是说TOC有(废话,你自己刚改的),subchannel没(??),于是又改了一次,把TOC给改回成无了!

同理第5轨,不过这次不同的是这么翻来覆去改了三次,即TOC为无->有->无->有,最后结论是有pre-em。

那么上面的全部总结下来,最后留在.inf文件里的居然是:tr. 5/8/10有pre-em。发现问题没有?正好和之前用CUERipper测得的向前偏移了一轨(1前面是0所以没有了)。为了保险起见,我又把这几轨全部找出来,和其他碟里收录的同一轨进行反复对比。虽然有的确实比别的版本稍微锐那么一点点(例如tr. 10那首「シンデレラたちへの伝言」我手头有俩无损版本的,有一个还是我自抓),但是如果真的去跑de-em,那又钝太多(靠频谱),所以基本可以90%肯定是没有pre-em的。

好家伙,Linux下最有名DAE(digital audio extraction)软件的cdda2wav居然有毛病,这事儿我得去hydrogenaudio反馈一下了。那让我们看看cdrdao好了。这里先说个笑点:EAC的目录里赫然有个cdrdao.exe(虽然是很老的1.1.9版),可见他也是调用了cdrdao来进行TOC提取的……然而阉割了cdrdao带的从track subcode里提取信息的功能。这软件的Windows binary也是相当的难找,最后在这个已经404的网页Archive里找到了一个编译好的1.2.3版(2009年最后版)和相应的dll文件(其实就是上面提过的cygwin1.dll)。

废话不多说,上log。

E:\sync\Software\cd\cdrdao-1.2.3-bin\cdrdao-1.2.3-win32>cdrdao read-toc --device
 8,0,0 test.toc
Cdrdao version 1.2.3 - (C) Andreas Mueller <andreas@daneb.de>

8,0,0: HL-DT-ST DVDRAM SP80NB60 Rev: RA00
Cannot read driver table from file "/usr/local/share/cdrdao/drivers" - using bui
lt-in table.
Using driver: Generic SCSI-3/MMC - Version 2.0 (options 0x0000)

ERROR: Unable to determine drive letter for device 8,0,0! No OS level locking.
Reading toc data...

Track Mode Flags Start Length
------------------------------------------------------------
 1 AUDIO 0 00:00:00( 0) 03:50:00( 17250)
 2 AUDIO 0 03:50:00( 17250) 04:16:50( 19250)
 3 AUDIO 0 08:06:50( 36500) 03:59:45( 17970)
 4 AUDIO 0 12:06:20( 54470) 03:28:52( 15652)
 5 AUDIO 0 15:34:72( 70122) 03:44:08( 16808)
 6 AUDIO 0 19:19:05( 86930) 03:12:20( 14420)
 7 AUDIO 0 22:31:25(101350) 03:52:20( 17420)
 8 AUDIO 0 26:23:45(118770) 03:45:20( 16895)
 9 AUDIO 0 30:08:65(135665) 04:08:45( 18645)
10 AUDIO 0 34:17:35(154310) 04:00:65( 18065)
11 AUDIO 0 38:18:25(172375) 03:58:67( 17917)
12 AUDIO 0 42:17:17(190292) 03:50:70( 17320)
13 AUDIO 0 46:08:12(207612) 03:50:15( 17265)
14 AUDIO 0 49:58:27(224877) 03:08:60( 14160)
15 AUDIO 0 53:07:12(239037) 04:21:60( 19635)
Leadout AUDIO 0 57:28:72(258672)

PQ sub-channel reading (audio track) is supported, data format is BCD.
Raw P-W sub-channel reading (audio track) is supported.
Cooked R-W sub-channel reading (audio track) is supported.
Analyzing track 01 (AUDIO): start 00:00:00, length 03:50:00...
Found 38 Q sub-channels with CRC errors.
WARNING: Pre-emphasis flag of track differs from TOC - toc file contains TOC set
ting.
Analyzing track 02 (AUDIO): start 03:50:00, length 04:16:50...
Found pre-gap: 00:02:10
Found 28 Q sub-channels with CRC errors.
Control nibbles of track match CD-TOC settings.
Analyzing track 03 (AUDIO): start 08:06:50, length 03:59:45...
Found pre-gap: 00:02:08
Found 21 Q sub-channels with CRC errors.
Control nibbles of track match CD-TOC settings.
Analyzing track 04 (AUDIO): start 12:06:20, length 03:28:52...
Found pre-gap: 00:02:00
Found 11 Q sub-channels with CRC errors.
Control nibbles of track match CD-TOC settings.
Analyzing track 05 (AUDIO): start 15:34:72, length 03:44:08...
Found pre-gap: 00:01:72
Found 9 Q sub-channels with CRC errors.
Control nibbles of track match CD-TOC settings.
Analyzing track 06 (AUDIO): start 19:19:05, length 03:12:20...
Found pre-gap: 00:02:03
Found 12 Q sub-channels with CRC errors.
WARNING: Pre-emphasis flag of track differs from TOC - toc file contains TOC set
ting.
Analyzing track 07 (AUDIO): start 22:31:25, length 03:52:20...
Found pre-gap: 00:02:03
Found 20 Q sub-channels with CRC errors.
Control nibbles of track match CD-TOC settings.
Analyzing track 08 (AUDIO): start 26:23:45, length 03:45:20...
Found pre-gap: 00:02:03
Found 17 Q sub-channels with CRC errors.
Control nibbles of track match CD-TOC settings.
Analyzing track 09 (AUDIO): start 30:08:65, length 04:08:45...
Found pre-gap: 00:02:03
Found 13 Q sub-channels with CRC errors.
WARNING: Pre-emphasis flag of track differs from TOC - toc file contains TOC set
ting.
Analyzing track 10 (AUDIO): start 34:17:35, length 04:00:65...
Found pre-gap: 00:02:05
Found 10 Q sub-channels with CRC errors.
Control nibbles of track match CD-TOC settings.
Analyzing track 11 (AUDIO): start 38:18:25, length 03:58:67...
Found pre-gap: 00:02:03
Found 15 Q sub-channels with CRC errors.
WARNING: Pre-emphasis flag of track differs from TOC - toc file contains TOC set
ting.
Analyzing track 12 (AUDIO): start 42:17:17, length 03:50:70...
Found pre-gap: 00:02:02
Found 11 Q sub-channels with CRC errors.
Control nibbles of track match CD-TOC settings.
Analyzing track 13 (AUDIO): start 46:08:12, length 03:50:15...
Found pre-gap: 00:02:00
Found 9 Q sub-channels with CRC errors.
Control nibbles of track match CD-TOC settings.
Analyzing track 14 (AUDIO): start 49:58:27, length 03:08:60...
Found pre-gap: 00:02:00
Found 7 Q sub-channels with CRC errors.
Control nibbles of track match CD-TOC settings.
Analyzing track 15 (AUDIO): start 53:07:12, length 04:21:60...
Found pre-gap: 00:02:00
Found 6 Q sub-channels with CRC errors.
Control nibbles of track match CD-TOC settings.

Reading of toc data finished successfully.

可以看到,找到且只在1/6/9/11轨中找到了pre-em信息,和CUERipper一致。不过有一点,他只是提醒你“WARNING: Pre-emphasis flag of track differs from TOC – toc file contains TOC setting.”,实际在提取出来的TOC文件里并自动没有修改成正确的、来自subcode的pre-em tag,这个还得自己手动来。

部分Pre-em的CD rip的存储和回放方式

碟算是抓完了,pre-em信息也有了,这就引出下一个问题:如何存储/回放这样的碟。WAV+CUE的方式是行不通的——因为上篇说过了,外置CUE里的FLAG PRE foobar2000不认,你也无法给CUE加pre_emphaiss的tag,加到音频文件里又会适用给整张碟。

保持整轨的前提下,唯一的解决方案就是FLAC+内嵌CUE了(其他无损格式应该也行)。要注意的是,FLAC+内嵌CUE,并不仅仅等价于“FLAC+CUE,只不过CUE内嵌”。在这里,内嵌的CUE主要起一个提供时间戳分轨的功能,但是实际上你对每一轨的metatag的自由度非常高,和单独的FLAC没有两样。也就是说,你完全可以做到给单个FLAC文件里每一轨加不同的pre_emphaiss的tag——即使CUE不支持。你甚至可以做到:每一轨的album不一样!不过如果你真的这么做,然后用foobar2000带的内嵌CUE查看器你会发现,CUE里的album还是老的值,可见这些元数据里并不是真的存在CUE的(不过,如果你进行一些CUE能支持的metatag操作,比如同时修改所有轨的albumalbum artist,或者单独轨的artisttitle,内嵌的CUE还是会跟着同步更新的)。

这个方案算是不错,但是和直接用分轨FLAC+pre-em tag一样都有一个问题前面提过:RG。因为我有一些lossy的需要加pre-em tag的文件,所以我被迫用了DSP版的de-em;但是DSP和RG不兼容(计算RG时不考虑DSP)。所以我现在俩抉择:1) 转成分轨FLAC,且同时直接将de-em硬计算进去;2) 换回后处理版的de-em,但是把那些有损音频强行transcode成无损一份来存储。实话说,两种方案都很蠢。现在我暂时还没想好到底要用哪种方案,姑且先去foobar论坛发了一贴问。

更新:今天又发现一个foo_deemph的bug:丫不支持FLAC+内嵌CUE的pre-emphasis tag,加了也不会de-em,orz 所以指望靠FLAC+InCue来保持最大程度的原Image是不现实了。我现在采用的方案是:使用foo_deemph插件,但是把所有 1) 只有部分轨有pre-em的CD 2) 有损带pre-em的音频 全部转一份分轨FLAC然后加pre_emphasis = 1 的tag。老的文件打包备份(防止被foobar20000的数据库读取;我在FB里filter掉了*.rar和*.zip)。这样的缺点是很占空间(有损转无损,还保留两份…)

OK,这个话题到此算是结束了。接下来我得强迫症般地把之前抓的碟都拉出来看一看,以保证没有subcode的pre-em flags……

收集老CD要注意Pre-emphasis的存在

Blog荒废了好几个月,本来正好前天有个题材(压片相关)要写,结果正巧碰到另外个事儿,觉得得先写写这个。无损音乐自己玩了这么多年,以为算是太阳下面没什么新鲜事,没想到上次一个Replay Gain一个Media server把我好好折腾了一番。这不,今天又接触了一个前所未闻的概念——emphasis。

这个问题其实要从几个月前说起。当时我在收集小猫俱乐部相关CD的时候,下到这么一盘——うしろゆびさされ組的首专「ふ・わ・ふ・ら」。

うしろゆびさされ組 - ふ・わ・ふ・ら

当然,这种80年代的老碟都是基本只能找到MP3或者网易云音乐(这里顺便提一句,网易云绝大多数老一些的、尤其是非华语音乐资源都是网上找的,那么多码率选项显然都是二次转换出来的。那伪320kbps实际一般看频谱都是128kps级别,还不如直接128呢,少一次有损压缩),我倒也没要求太高。

但是这张碟的奇怪之处在于,听起来非常“不舒服”。什么程度呢?我听完一张甚至会觉得耳朵疼(我听音乐一般声音很小)。我自认对这些东西比较敏感,觉得这碟肯定是哪里不对。我找遍网上所有的版本,都有这个问题。其中比较明显的是其中收录的单曲1、2,「うしろゆびさされ組」和「バナナの涙」,和单曲版一比就能发现明显区别。

不过,后来我在维基百科看到,说是其中收录的单曲曲目虽然未标记但是是Album version,所以这也算解释的通。不过,这事儿我一直放在心里没忘。

后来,在网上漫无目的地搜索下不到的「AN bALANCING TOY」时,发现骏河屋有人卖二手的「ふ・わ・ふ・ら」等其他几张指指点点组的专辑,外加写真集什么的。正好从来没在骏河屋里买过东西,也试试代购靠不靠谱,就准备把上面有的东西都一起扫了。国内的几个,2poi啊玛莎多拉啊啥的试了下,总有支付或者快递之类的种种问题,于是转投面向西方的服务。最开始试的就是在骏河屋下面打广告条的“Buy Smart Japan”,网站倒是非常简单好用,全自动和亚马逊差不多,不过快递只支持EMS,那4500円的运费把我吓到了(毕竟日亚直购运费便宜的一笔)。

于是我又找了另外一家,Proxyrabbit Japan。这个的界面就蠢多了,买骏河屋一次最多5件,而且你填完表格之后他是通过人工确认和你邮件交流……并且不能即时出运费价格,要先交定金(最低25%商品价格)然后他那边到货了才告诉你邮费。不过我当时抱着上当一次也无所谓的心理就上了。大概quote后过了2天我交了定金(PayPal),又过了一周多那边才收到(据说骏河屋就是挺慢?)货。运费这次倒是有几个档可以选,结果EMS还是4500,于是我选了两千多的Air mail。

废话不多说,总之就是昨天才到我家,还没投递成功我去邮局自取的,前前后后快一个月了。以后还有需求的话,估计会试试转运而不是代购的(看到推荐了两家,http://www.biginjap.com 和 http://www.tenso.com/en/)。二手卖相还可以,没侧标就是了。

IMG_20170621_220513

EAC的话我虽然用得很少,前个月倒也抓过几次,我的经验就是没必要看什么“教程”,按照软件自带的指引一步步点,把offset之类的硬件相关设好就OK。我当年第一张是用的安全模式抓的,速度慢到发指(1.几x),我于是直接改用爆发模式抓(速度7-8x),反正抓完之后有AccurateRipCTDB两个数据库比较CRC32,如果都一致,都是bitwise identical了还觉得只有安全模式才行那只能认为是没文化了。这里容我吐槽下,都CURRENT YEAR了EAC抓出来的CUE居然还只能是ANSI(非Unicode)的,蠢哭。

总之……回到正题。于是我自然先赶紧抓了这张碟来听。嗯?听感好像和之前的完全一致,看来这碟本身就这样?就在我放弃治疗去改CUE的时候,发现有个没见过的玩意:

REM DATE 1986
REM DISCID 9109350A
REM COMMENT ExactAudioCopy v1.3
PERFORMER "うしろゆびさされ組"
TITLE "ふ・わ・ふ・ら"
FILE "うしろゆびさされ組 - ふ・わ・ふ・ら.wav" WAVE
 TRACK 01 AUDIO
 TITLE "SE・KI・LA・LA"
 FLAGS PRE
 INDEX 01 00:00:00

FLAGS PRE是什么鬼?

结果一查不得了,这正是问题的关键。原来,通信中存在一个叫做“emphasis”的技术。说来也很弱智,就是对于多少频率的信号(一般是高频),会进行放大;在信号到达接收端之后,再用反函数把信号衰减回去。放大的过程叫“pre-emphasis”,衰减叫“de-emphasis”。不用说,其目的是减少传输过程中噪音的影响,因为中间引入的噪音会被同样衰减,从而达到更高的信噪比。

这个技术在黑胶唱片、磁带等Analog领域广泛应用,但是在CD这种数字媒体中的应用很少。准确地说,在早期CD(70-80年代)只有14bit的时候,这个应用在其中来减少量化误差(为什么?留作思考题了w)。后来CD的精度变成16bit之后,就基本很少用了,但是其依然存在于CD的标准中,想用的话也是可以的。

事实上,带pre-emphasis的CD恰恰就仅在日本的80年代最流行(注意,日本的CD从80年代后半才开始普及,之前基本发音乐只发黑胶、磁带),其他国家不多。另外需要说明的是“pre-emphasis”(即:特定高频的信号的增益)是直接压在CD里的,不过一般同年代的CD player都会识别metatag里的相关flag,从而自动进行进行de-emphasis来还原信号。

但是到了电脑光驱,这就取决于你的软件端怎么处理了。我们上面可以看到,对于EAC抓轨,他会识别出相关的tag,并标记在CUE中。接下来就全看你的播放器了。

对于绝大多数人,和绝大多数软件,他们是完全无视这个信息的,所以就导致了我最开始提到的那张碟“很怪”的声音——高频被增益了(具体算法根据hydrogenaudio,是“a first-order filter with a gain of 10 dB (at 20 dB/decade) and time constants 50 μs and 15 μs”,我虽然大概能理解但是就不硬着翻译了,毕竟不是科班出身),所以听着耳朵疼,架子鼓里的钹的声音也变了。另外因为这个东西的存在过于冷门,大多数人估计根本没处理过,这也是为什么网上流传的版本全是这个德行的原因。仔细想想可怕极了,到底有多少手里的80s音乐会有这种问题而没被发现呢?

既然知道了原因,解决方案就很简单了。用Foobar2000的话,有网友开发出两个插件来处理这个问题——一个是后处理,一个是DSP插件,前者会自动在播放、计算音量增益、转换(前提你勾选了后处理)时进行de-emphasis,后者顾名思义需要在DSP里作为一个滤镜勾选。需要注意两个默认都不工作,需要对音频文件(而且前者仅限无损)添加PRE_EMPHASIS的tag,值为“1”,“ON”或者“Yes”。

这里有几个细节我啰嗦几句。一个就是CUE里的FLAGS PREFoobar是完全无视的,所以对于无损+CUE的方案,你要把上述的Tag加到你的无损文件里去。另外一个就是转换时,如果勾选了后处理(你一般应该勾选)会自动把de-emphasis给硬编码进去,所以出来的output是已经进行过de-emphasis的了。但是因为转换器默认会把tag都复制到新文件里,所以新文件还有PRE_EMPHASIS的tag,需要手动移除,否则就相当于de-emphasis两次,声音就变钝了。另外,虽然可能性很小,万一有别的软件支持识别CUE的flag,那么播放CUE+有PRE_EMPHASIS tag的无损音频可能会导致多重de-emphasis?嘛估计应该没软件这么蠢就是……

其他的处理软件比较著名的有命令行工具sox,用sox input.wav output.wav deemph可以轻松de-emphasis。虽然和foobar插件两者的结果并不是波形级一致,但是听感无区别。

至于我这张CD的处理方法自然可以是两种,一个就是直接硬编码进去,另外一个就是播放的实时进行de-emphasis。我暂时选的是第二种,这样就不用保留一个单独的原版WAV了,毕竟是破坏性操作;因此,转WAV为FLAC(节省体积)的时候要特别注意去掉勾选“后处理”选项,或者先转换格式,后加pre-emphasis tag。

最后,以这张专辑中我最喜欢的一首歌曲,『偏差値BOY』作为结尾吧 😀