旧文备份:汉字的全角半角

今天在BGM闲逛看到有人发了一篇Eric Q. LIU写的《全角半角碎碎念》。在学到了很多知识之外,突然想起自己当年(不晚于16年)在S1也扯过这个话题。翻了半天发现有在Evernote备份,可能是当初想稍微扩展一下写成博文,但是后来搁置了。和上面这篇专业人士所写的相比,实在有点太小巫见大巫,所以也没有什么再继续写的必要;但是好歹是自己创作的东西,就在这里不做修改备份一下吧。稍微看了下,除了排版方面的纯粹胡诌以外,其他的倒也算没太多事实错误(笑)。


首先你需要定义到底什么叫做“全角”

到底是指字符(Glyph)宽度(占一个汉字的字符宽度),还是指字符编码的字节数(2字节,和GB编码下的一般汉字一样)

如果是指编码的字节数:
这是“半角”的双引号(不分左右):”(U+0022)(只要一个字节)
这是“全角”的双引号(分左右):“”(U+201C,U+201D)(各要两个字节)

p.s. 这是“全角”的双引号(不分左右)"(U+FF02)←这个非常少用 下面略去不讲

具体显示成什么样的字符(glyph)根据字体不同,但是编码是定死的,你复制出去用Unicode decoder查永远是上面显示的那些

如果指的是字符宽度,那则和字体有关系:
Win9X年代的中文字体,如宋体,一般会把前者显示为半个(一个)字符宽,后者显示为一个字符宽,所以许多人习惯称后者为全角引号,前者半角;
在雅黑下,两个字符的字形虽然不一样,但是都会显示成一个字符宽;
在绝大部分英文字体下,两者都会显示成半个字符宽。

但是问题在于,对于非等宽字体(如雅黑,和世界上绝大部分字体),区分“半个字符宽”和“一个字符宽”没有任何意义——在这些字体下,符号、字符都只会占据其需要的宽度。这也是为什么所谓的“全角引号”看上去好像也是“半角”一样——重复一遍,这取决于你的定义。

大部分时间,这两个定义是统一的——一个“全角”字符会占用两个字节并且显示为一个字符的宽度,和汉字一样。

另外需要厘清一点,全角字符这一概念基本只有汉字圈儿才用。因为拉丁字母等除非特殊用途(如代码)以外,根本没有列对齐的需求(字母天然都是不等宽的,不像汉字)。所以字符意义上说,他们用的符号都是“半角”的,自然这也会反映到字体的字形设计上。所以对于字符“AvsA”(前者全角,后者半角),外国人几乎从来不会用到前者(事实上,许多英文字体,例如Arial,根本就不会包括前面那个字符)。

但是“”(U+201C,U+201D)这对双引号有点不一样,这大概也是你问题的来源。和很多中国人的想象不同,其实英文是会用这对引号的——因为普通的所谓“半角”双引号,”,是不分左右的。而英文的引文符号其实和中文一样,是需要分左右的。所以无论是中文还是英文,在正式文章中你需要使用引用时,你想要的是分左右的双引号——至于到底是一个字符宽还是半个,长什么样,和你的字体有关。但是他的编码是双字节的这点不变——从这个角度来说,你即可以说它是全角,也可以说他是半角。
一般人会把”(U+0022)叫做半角,“”(U+201C,U+201D)叫成全角,但这只是一种说法而已。

但是问题在于,普通PC键盘,默认用shift+’(L右边两个那个键)键入的是”(U+0022)这个引号(英文输入法下)。这个不分左右的双引号,这说白了也是打字机时代键位紧张、外加ASCII(单字节编码)字符位紧张的遗留问题罢了。但是一般(外国人)日常打字用它代替漂亮的弯引号也不会产生什么歧义就是了。如果你用英文word试试就知道,word就会自动把它纠正成“”(U+201C,U+201D)。

说了这么多废话,总结一下就是

如果你从编码的角度出发,分别存在全角和半角的引号
如果你从字形宽度的角度出发,“、”在许多中文字体下会被显示为“全角”,“会被显示为半角;但是”、“、”在英文字体下和许多新的中文字体下全部都会显示成半角。

—-

最后修改时间:2016/3/8

ShadowPlay录屏的色域问题及如何正确处理BT.601 (SMPTE 170M) 视频

前几天因为某些需求,使用nV家的ShadowPlay(下称:SP)进行录屏。我录屏一般都是用较高的码率(60Mbps)录制,然后再手动二压一次。这次由于视频比较长而且质量不是很关键,就用NVEnc直接压了遍。

压完之后随便拖了下进度条对比——咦,颜色怎么有点不一样?

左:原始SP录制视频用Pot播放;右:NVEnc压制后用Pot播放

可以明显看到,左边的图红色要暗一些,右边(压制后)则艳丽许多。

根据我的经验,知道这肯定是YUV色彩空间的问题。赶紧来看看metatag:好家伙,SP录出来的视频居然是:

Color range                              : Limited
Color primaries                          : BT.601 NTSC
Transfer characteristics                 : BT.601
Matrix coefficients                      : BT.601

(注:比较老版本的SP,transfer用的是 BT.470 System M。)

那么看来,似乎应该很简单就是NVEnc转换时没有进行任何处理,生成的视频又没有tag,导致播放器默认按照BT.709播放错误了呗。至于原始视频,虽然是BT.601,但是由于有加正确的tag,那么肯定解码、转换成RGB域之后是正确的。

不过为了谨慎起见,让我们换个播放器来试试。一般而言,如果出现播放异常的情况,我第一个排查的方式就是分别用:MPV、LAV+MadVR(MPC-BE)、LAV+EVR各播放一遍来和PotPlayer的结果对比。即是说,我一般是不信任Pot的结果的“正确性”的。虽然我的PotPlayer在我调教下已经基本可以*正确*播放99%的视频,但是总有无法覆盖的奇怪情况不是。

这么一对比果然就发现了问题:同样播放原始视频的情况下,MPV和LAV+EVR结果一致,但是和LAV或者Pot内置解码器+MadVR的结果不一致。不过这里的不一致和上面情况不一样,更加微小:

左:MPV 右:Pot或LAV+MadVR

这里可以看到,会导致不同的是MadVR,而不是解码器部分。在继续分析为什么不同之前,我们需要知道哪个是“正确”的结果。这里有个很简单的方案:用PS绘制一张红色(BT.601和709矩阵区别在红色最明显)图片(我测试时没用纯红而是用了250,0,0,防止clipping影响对比),然后SP录屏,查看结果用吸管工具取色看哪个对即可。图我懒得贴了,结果就是,用MPV的结果是正确的,MadVR错误。

接下来的过程,我尝试使用ffmpeg的各种色域转换命令对视频”修复“,搜索了不少网上的帖子,花了几个小时也绕了很多弯路,感觉按时间顺序叙述就过于啰嗦,所以我直接写最终结论。

结论1:SP录制的视频确实是BT.601的color matrix,但是并不是BT.601的color primaries。metatag标注错误。

这里首先要复习下我在这个帖里讲过的matrix、primaries、和transfer function的区别(下称M、P、T)。

  • Color primaries:指定gamut的范围(三个原色[即“primaries”]的位置,白点位置)。理论上回放时只和校准(显示器)颜色有关,所以绝大部分播放器不会使用这个属性。
  • Transfer characteristics:指定gamma ramp。譬如,你可以指定为linear等。几乎所有播放器都无视,直接用那个标准的nonlinear的ramp(见下文)。
  • Matrix coefficients:这个是比较关键的也几乎是唯一会被播放器读取并采用的,指定了YUV和RGB的转换矩阵。

然后他们的值的区别:

  • P:BT.601 NTSC=SMPTE 170M,不等于BT.601 PAL=BT.470 B/G,不等于BT.709,标错理论上会导致显示错误(下述)
  • T:所有常见标准的 transfer function 基本都一致,所以即使标错也影响不大
  • M:BT.601=BT.470 B/G (PAL)=SMPTE 170M但是同样不等于 BT.709,标错几乎一定会导致显示错误

SP录制出来的视频,确实是用了BT.601的矩阵(M),但是实际上用的依然是BT.709的P——这里可以通过强行修改metatag之后再播放来验证。至于T,由于所有的标准其实都一样,所以标成601还是709不重要。

结论2:一般播放器会无视P,所以metatag写成什么都无所谓;但是MadVR开启calibration之后会对P进行转换。

如上所述,由于P的特性导致在屏幕没有校准的情况下是无法去适配的,所以一般播放器都完全无视了这个metatag。这也是为什么上述SP录制出来的视频用MPV或者LAV+EVR播放显示“正确”。但是MadVR这边,虽然我的屏幕并没有校准,但是为了能让BT.2020的HDR内容tone-mapping到感知上比较合理的SDR颜色,我“被迫”开启了MadVR的“我的屏幕已经calibrated“的选项并且把校准目标设置为BT.709:

否则,HDR视频的颜色直出,和屎一样:

我不知道为什么MadVR没有单独的tone-mapping HDR content的选项,反正我试了hdr tab下的所有选项,都没有用。MPV其实也需要设置,需要开启vo=gpu(或者直接开启copyback的硬解hwdec=auto-copy,会自动开启vo=gpu)。

这里提供一段BT.2020的视频谁想用可以拿去测试自己的视频播放方案: https://1drv.ms/u/s!Akq11jtCTJYwguclNUTq5MsccSRZ3w

呃,有点跑题了。总之,为了能”正确“显示BT.2020的内容,我开启了这个“我的屏幕已经calibrated”的选项。然而这就导致MadVR会把BT.601的Primaries也转换到BT.709。而SP的视频虽然metatag标注是P=BT.601,但是实际是只有按照P=BT.709来播放才能显示正确的RGB颜色,所以在M转换之后(这个是正确的、应该的)MadVR又进行了一次额外的P转换,导致显示结果错误。

细心点可以看到这里transfer function也被指定了。根据我的测试,如果在发生P转换的时候,这个T选项(尤其是gamma)也是会对结果有影响的。不过,如果如果仅有M转换发生时,这个选项选成什么都没有区别。

要不重新编码修复这个视频,最简单的办法是:

  1. 用ffmpeg指定P:
ffmpeg -i shadowplay.mp4 -color_primaries bt709 -c copy fixed.mkv

这里注意,要保存成mkv,mp4容器无法覆盖掉视频流的P的metatag。麻烦点也可以先直接转换成MKV,然后用MKVToolNix的header editor编辑。总之,最后出来的MKV用mediainfo查看大概是这样:

Color range                              : Limited
Color primaries                          : BT.709
colour_primaries_Original                : BT.601 NTSC
Transfer characteristics                 : BT.601
Matrix coefficients                      : BT.601

播放是正常的,会认为是BT.709的P,MadVR不会再进行转换,结果和MPV一致了(这里Pot的OSD是显示错误的,大概他直接读取了视频流的tag,没有显示MKV容器覆盖上的,请无视):

以上就是SP视频的Primaries metatag的错误和修复方式。

MadVR转换Primaries的正确性

虽然我们看到了如果开启calibrated,MadVR会对P不为BT.709的视频进行一次转换,但是这个转换结果是否正确呢?

让我们试验一下。还是用250,0,0的颜色来举例——我先用zscale制作一个BT.709的视频,用MPV和MadVR播放都正常显示为250,0,0。然后,我们用ffmpeg的colorspace vf,分别转成bt601-6-625、smpte170m、bt601-6-525:

ffmpeg -i zscale.mp4 -vf colorspace=iall=bt709:all={target_colorspace}:format=yuv420p -sws_flags accurate_rnd  zscale_to_{target_colorspace}.mp4

(Where target_colorspace = bt601-6-625, bt601-6-525, smpte170m)

接下来我们分别用Pot和MPV播放生成的视频,然后截图取色,结果如下(前两行其实是一样的):

New colorspacemediainfo Pmediainfo Tmediainfo MMadVRMPV
smpte170mBT.601 NTSCBT.601BT.601235,37,0243,0,0
bt601-6-525BT.601 NTSCBT.601BT.601235,37,0243,0,0
bt601-6-625BT.601 PALBT.601BT.470 System B/G249,0,0245,0,0

这里辨析一下几个非常迷惑的term,基本上:

NTSC标准系列:BT.601 NTSC = smpte170m = bt601-6-525(转换矩阵在mediainfo里就叫“BT.601”无后缀)

PAL标准系列:BT.601 PAL = BT.470 System B/G = bt601-6-625

有些细节问题(比如这俩的M其实是一样的;又比如T在FFMPEG里SMPTE-170M, BT.601-6 625 or BT.601-6 525都用同一个,bt470bg反而是略有不同)这里按下不表。

其中,MPV的结果就是仅做M转换,不做P转换的数值。而MadVR做了P转换之后,可以看到只有PAL的结果是比较正确的,如果是NTSC,反而比不做转换还要差好远。为什么?鬼知道。这里我不是说MadVR的结果一定是错误,毕竟整个流程可以出错的地方太多了(ffmpeg滤镜可能算法有误,我对整个流程的理解可能有误,等等)。但是总体而言,不同matrix的回放已经很成熟,也一般都很准确;但是我们尽可能要规避回放时的Primaries的转换。

我在前文“用ffmpeg静态图转视频”提到过静态图转视频需要进行一次BT.601到BT.709的转换,这个说法是没错的。但是这个转换仅限于矩阵,P是不需要转换的。所以如果真的想用我提到的“不转换,只添加metatag”的方式,也只需要添加M的tag,而不需要添加P的(添加了反而错了——虽然大部分播放器不会表现出区别)。同理,如果要用colorspace vf,也别用iall和all了,而是用ispace和space(但是这个vf要求你必须把所有的转换都显式写出来才能运行,所以你得用超长的 -vf colorspace=iprimaries=bt709:primaries=bt709:ispace=smpte170m:space=bt709:itrc=bt709:trc=bt709:format=yuv420p)。(这里用 bt601 或者 smpte170m 都可以,一样的。)

转换BT.601 Matrix到BT.709

OK,我们已经讲了如何修复SP录制的视频的P的tag的问题,但是他这个BT.601 NTSC的Matrix,虽然正常的播放器播放不会有啥大问题,但是为了兼容性(而且我们本来就要二压),还是把他转成BT.709吧。我们已经知道了P和T没有转换的必要,所以只需要转换M。

基本上,之前提到过的那些转静态图的命令都能用。唯一需要注意的是某些滤镜,例如scale,会复制旧视频的metatag而不是生成新的BT.709的,需要显式覆盖掉。

# in_color_matrix不用写,默认是auto。需要手动加output的metatag覆盖。
ffmpeg -i bt601.mp4 -vf scale=out_color_matrix=bt709:flags=accurate_rnd+full_chroma_int -colorspace bt709 -color_primaries bt709 -color_trc bt709 scale.mp4

# 因为P的tag错误,所以别用iall,逐个显式声明罢。Output metatag自动加。
ffmpeg -i bt601.mp4 -vf colorspace=iprimaries=bt709:primaries=bt709:ispace=smpte170m:space=bt709:itrc=bt709:trc=bt709:format=yuv420p -sws_flags accurate_rnd+full_chroma_int colorspace.mp4

# Input不能自动识别,需要显式声明。Output metatag自动加。
ffmpeg -i bt601.mp4 -vf colormatrix=smpte170m:bt709,format=yuv420p -sws_flags accurate_rnd+full_chroma_int colormatrix.mp4

# 还是推荐用zscale了,精度高。Input自动识别,output metatag自动加
ffmpeg -i bt601.mp4 -vf zscale=matrix=709,format=yuv420p zscale.mp4

用NVEnc的话,是

nvencc64 -i input.mp4 --vpp-colorspace matrix=smpte170m:bt709 -o output.mp4 --audio-copy

这里我偷懒没加tag,反正不会继承旧的,所以一般播放都没差。好像有个命令可以显式加上tag来着。

参考文献

直播平台Stagecrowd的画质问题

Stagecrowd(下称:SC)是大网络直播时代索尼赶鸭子上架搞的第一方直播平台。各个地方都透出一股草班台子的味道,比如不同直播的账号不互通等等,这里按下不表,专门来黑一下画质问题。

Go for a Sail STUDIO LIVE

第一次用SC是看8月的“LAWSON presents TrySail 5th Anniversary Go for a Sail STUDIO LIVE”。当然,这个活动本身就是音雨骗钱登峰造极之作,下面简单罗列下:

  1. 分割放送上下part,而且事先不公布,硬是在part1播完后才说还有part2。
  2. 每个part都有两个aftertalk,预购只能看aftertalk1,需要专门购买回放门票(“見逃し配信チケット”)才能看(且只能看)aftertalk2。
  3. 播放前有个所谓的“直前talk”,只有预购并且直播才能看到,timeshift没有。(但是,由于他们弱智,part1的timeshift其实并没有剪掉,是可以看到直前talk的233。在part2里修复了这个“bug”。)

这玩意的复杂程度之高,官方甚至“很贴心地”专门准备了个表格来罗列不同票的情况。总之,要看到所有内容,你需要付3800*4+手续费差不多小两万。

另外,官方还在B站进行了转播。票价便宜得多倒是无所谓,但是在回放时,居然事先无预告的突然包含了aftertalk2,让刚交了4000的我和吃了苍蝇一样恶心(甚至没忍住去动态喷了一波)。

不过搞笑的是,放part2的时候(只有录播,part1时延迟半小时突击加的字幕由于太差闹了大笑话,估计不敢了),虽然官方说明依然是是包含aftertalk2,但是实际并没有(不过好像也没有任何人发现的样子)。另外也没有直前talk。总之算是有点心理安慰……

呃跑题了,让我们来继续说画质。这个活动是直播talk+播片的形式,客观来讲直播部分的画质还是不错的,码率够。

但是播片的部分(正片)画质奇差,码率低全屏马赛克不提,最重要的是颜色完全错误,整个画面偏深,这点和B站版的片源一比就可以很明显看出:

SC直播版
B站直播版

注意这里还仅仅是B站直播的720P版,在回放时升级成1080P画质会更好一些。不过,这个我怀疑不是SC的问题,是片源没提供对(反正你们都是索尼一起骂了吧),因为在Part2没有这个颜色问题。更吊诡的是我搞不懂这个画质是怎么搞出来的,一开始以为是缺了一次TV/PC色域伸张,但是研究了下发现并不是,不懂了不懂了,反正有BD,不纠结。

另外一个问题就是timeshift(archive)的画质差异问题了。一般而言,这类平台的timeshift有很多种情况,有的就是把直播的源直接再摆出来(比较常见),也有回放重新压制的——由于没有串流的严格要求,回放可以码率、压制参数更高一点。当然,这里有个重要的前提,就是你得用的是更“raw”的源来压制才有意义,否则直接把直播的视频流二压一遍,不管用多高的参数,画质只可能劣化。比如YouTube的回放就是这样,经过服务器转换过一次后,画质只会变差(之前虾泥的感谢祭直播,甚至出现了回放视频比例变扁的搞笑现象)。

SC这里,很不幸地就属于后者。根据前面描述的商法,可以知道有三个视频档:直播,直播的archive,“見逃し配信チケット”进的录播。由于每个都有剪辑的需求(直播的archive不包含直前talk,录播版不包括直前talk且aftertalk从1换成了2),所以内容是不一样的。这里我是不清楚SC是在线提供粗剪功能还是线下剪好再上传(大概率是后者),无论如何,事实就是每个版本的视频画质都有肉眼可见的下降,估计是直接用直播流剪辑二压的:

直播版
直播的archive
見逃し配信チケット

这里截取了正片前的短暂talk(不是直前talk),也就是三个片源都有的部分来对比。当然介于不同视频关键帧不一定一样,这样随便选一帧对比不是100%科学,但是看衣服的纹理也可以看出二压有多过分了:

花纹逐渐消失

再补个B站版对比。虽然加了一次硬字幕,但是画质几乎和SC直播版一致,赞一下。

B站版

哦对了,码率方面SC的直播、录播都是4Mbps左右,当然这个数据本身没啥意义,颜色都不对、或者你播片的片子本身都糊成一坨了nominal码率再高有啥用呢。

TrySailのMusicRainbow07

时间来到前几天,这次观看的是MR07,播片(非生放送)。直播观看其实感觉画质还好,有点欠码但是没大问题。于是让我们来看看archive版。

这次和上次不同,archive版是个单独的片源,而且码率有提升(直播:4Mbps,archive:7Mbps)。但是,又出了新的乌龙:颜色又㕛叒叕错了。先上对比:

直播版
Archive版

如果对比细节,会发现archive版画质确实略微有所提升,但是这个颜色是怎么回事?为什么又变深了?还好,这次的原因很简单:两者错了一次gamma——一个是gamma1.8,一个是gamma2.2的效果(至于为啥是这俩数字,一个是Mac一个是PC,具体自己看维基)。如果要修复,只要把后者加个1.22 (2.2/1.8)即可还原成和前者一样的效果(不同软件对gamma或者gamma correction的定义不同,有的软件可能需要用倒数。这里是指PS色阶gamma改 1.22):

PS修改gamma方式 很多播放器也提供播放时修改gamma的功能

但是我们怎么知道哪个是正确的呢?毕竟有的人可能会觉得反而是上面的太亮。这就需要客观对比了。在转场画面,会出现本次活动的logo:

虽然我没有找到这个logo本身的的高清大图,但是在音雨商店的banner里可以找到一个类似的大图

我们这里只需要把七色色段部分提取出来,然后对比颜色就行了。其实都不需要进PS吸管,肉眼就可以看出明显是直播版颜色更接近这个。

以上是SC内部的颜色问题。那么和其他直播平台比如何呢?这里用Zaiko的来对比。之前就有听说Zaiko码率更高一点(5Mbps),逐帧对比的话,确实细节要多点。但是重点不在这里,而是两者的颜色又有细微的差别:

SC直播版
Zaiko版

可以看到,两者的颜色基本是一致的——但是仔细看,会发现SC版会在接近白色的地方有过爆的问题,注意右上角背景和鼻子高光。下面这帧可能更明显:

左:SC 右:Zaiko

为什么会出现这种现象?鬼知道。可以确定的是并不是错误地进行了一次色域伸张那么过分,两者的平均亮度只错了1(RGB)而已。另外也不是BT601/709的区别。我拆成YUV通道对比了下,可以看到只有U通道有较大区别:

左:SC 右:Zaiko

更搞笑的是,如果把archive版那个gamma错误的图,用PS色阶修复一下……

反而是和Zaiko版一样的正确版,而不是直播的那个过爆版(注意看手上的高光)!

(顺便Mocho这皮肤该保养了。)

这次是没办法已经买过票,以后可能尽量不会再买SC了。但是听说Zaiko不能多端登录(我自己没试过),不便于和别人拼车。

僕だけに見える星

好久没更新,正好今天Live,fan from home(笑)也没啥事做随便写点相关杂记。

歌曲

这次两首都不错,尤其喜欢c/w的『あしあと』,瞬间可以挤进前五!Mocho的single的c/w一向很对我胃口,掐指一算甚至比主打更喜欢的次数更多点(花に赤い糸、箱庭ボーダーライン、No Distance、シュークリーム,さよなら観覧車也算和365×LOVE打平)。说实话我也不知道这种曲风叫啥(访谈是说R&B),和三森那个『アレコレ』差不多。

主打么感觉副歌部分一般,mocho对于这类高音的驾驭能力还不太行,发声方式感觉不是很符合甜美的声线。之前专辑里的『秘密のアフレイド』也有同样的问题。

MV

和上次的『今すぐに』一样,这次依然可以在Apple Music/iTunes获取1080p版。不过这次有个小插曲,我购买了之后本来想顺手塞份b站,结果被提示撞车:

结果下面那个“撞车”的链接还打不开。用biliplus的API获取了下发现是索尼音乐中国传的,挂代理看了下那个账号发现,和其他流媒体服务类似,索尼也开始在B站提供最新MV的更新了。好处是介于国内付费习惯的问题,不像Apple Music或者YouTube Premium Music,不用购买高会即可观看(只是要有大陆IP)。当时看到时候(刚更新几个小时)这个MV还只有十几的播放,毕竟用的是罗马字名字+tag,一般估计很难搜到。后来好像在圈里传开了,现在已经飙到了一千多。

画质方面,iTunes版虽然是1440×1080,但是凭借着5Mbps的码率还是在动态方面秒了B站的3M出头的版本;但是如果是静态画面,那B站版毕竟像素多还是要锐度更高一些。总之各有优缺。这里share下iTunes版。

重点批评下辣鸡YouTube Music,本来那屎一样的UI(作为音乐服务)如果不是订阅频道有推送,根本几乎无可能找到那MV(地址);而且非日本时区好像得等到当地时间到了11日才能看(否则得挂日本代理)。最重要的是,画质非常差,码率低不谈,颜色不对,甚至比例也不对——要横向缩小到1904px才对(外面的像素?自然被它给出血掉了)。难道你也是我之前黑过的mora那样按ITU DAR瞎转换?

下面对比:

iTunes版
B站版
YouTube h264版 (注意颜色,深色部分已经有点clip)
YouTube VP9版 (只有30M,画质最可怕)
附赠DVD版:DAR已经修正。注意上下出血

MV内容没啥好点评的,很喜欢这个条纹衣服(想起kraz去年Live那个睡衣)。

封面

这次封面倒是简单,没有一万个版本,基本所有的颜色都是一致的,那只需要找个画质最好的就行了。目前看到最大的是akiba-souken的1644p(图片URL去掉t640_获得原始画质)(Amazon也是同样大小,但是压缩率极高)。

iTunes的3000px依然是upscale的,不要用(顺便吐槽,这些流媒体网站对于非正方形的封面总是很多余的加白边,在很多播放器里都巨丑,求求你们不要了好吗)。

mocho的碟似乎通常半身照/初回全身照都快成惯例了。我还是喜欢大头照,一般移动设备都用那个。

公式照

除了封面还有个同一时期拍摄的新公式照,被用在官推等大量地方。这个图的最大图同样在上面的访谈的第一页可以找到。但是,这个接近正方形的其实是剪裁版,原始长方形版可以在SonyMusicShop以及mocho SME官网看到(虽然尺寸小很多)。不幸的是这里则出现了颜色的不一致:SME官网的和别人都不一样,明显发蓝。

按照经验,发蓝一般是CMYK的CMY通道错误强制当成RGB用导致的;但是我按照前文所述的方法反向了下(试了PS自带的大部分CMYK profile),色调还是差不少。右边这图也有点意思,虽然是RGB但是里面却莫名其妙的内嵌的有个“SMC_coated_CMYK2006”的CMYK的ICC文件,直接导致在我explorer没法生成略缩图(PS倒是能打开,会报个错)。这有两种解释:图片确实正确地转换成RGB了,只是ICC莫名地没去掉;或者图像其实应该是CMYK但是错误地保存成了CMYK。介于几乎所有地方都用的是这个版本,外加和其他宣传图(特典等)的色调也一致,我倾向于这图颜色本身是没有错的,只是残留了ICC而已。我也试过把这个ICC提取出来套到SME那张偏蓝的图上当做profile,没什么进展。

更新:刚写完就发现,Apple Music的公式照更新了,也是这个偏蓝的颜色;外加animate的特典似乎也是类似的颜色(明度高一些)。但是A/G的宣传卡则是和官图一致,我现在已经彻底不确定哪个才是正确的了……

Hi-Res的意义(外一则)

(本文部分观点已经在在各种旧文中发表过,如果有既视感为正常现象。)

Hi-Res音频(相比CD)是否有意义?首先要客观分析HR到底改变了什么。

Remastering / remix

之前提过,很多时候Hi-Res最大的意义并不在于“High”本身,而是给了厂牌一次re-release的机会。这本质上和是否HR是没有任何关系的,唱片公司如果愿意,完全可以发行remastered的CD(事实上,很多精选集CD里的旧曲都进行了remaster)。注意这里的remastering是指狭义的、即混音有明显的变化的情况,从物理角度来说就是波形或频谱有明显的变化,不包括单纯的音量、动态范围变化(compress),那个下面专门叙述。

当然,重新混音并不是单纯的技术问题,而且还有艺术发挥的成分,所以这个主观性就很大了。很多时候可能重混后的版本不如原版(个人喜好)。随便举个例子,Lantis的HR版的『U・N・M・E・I ライブ』和CD版混音有较为明显的区别,HR版声场重新调整过,但是我个人觉得人声偏小,更喜好CD版。另外就是上次说过的「THE IDOLM@STER MILLION THE@TER GENERATION 11 UNION!!」这张碟也有类似区别。

对于新发行的音乐,一般CD版和HR版不会也不应该有混音(狭义)的区别——几乎不存在某波形HR能发挥、CD发挥不出来的情形。如果厂商这么做,那只能认为是为了商业考虑故意劣化CD版,而不是什么技术限制。

高采样率

一般HR都是从CD的44100Hz提升到96000Hz。由于采样定理和人耳的频率听觉极限客观摆在那里,可以自信地说,高采样率应该是HR最无用的提升没有之一。

硬要说的话,有个小问题就是现在音乐大多在制作过程中使用96000Hz(或者48000Hz?),而CD的采样率由于历史原因是44100这个不能整除的数字,所以resample可能会有时域上的aliasing等问题。不过,有大量高质量的resampling算法的存在,这个问题在主观听感上的影响可以忽略不计。

高量化精度

CD的量化精度(位深)是16bit,HR一般提升到24bit或者32bit。虽然从听感上来说这个到底能否能产生肉耳可辨的区别也很难讲,但是考虑到类比图像的话,8bit/channel这个在当年被普遍认为绰绰有余的位深现在肉眼可见的捉襟见肘(更不要提当年为了work around这个位深在深色感知灰度不足的问题,搞出的遗毒万年的gamma空间,这里按下不表),这里我们还是保守点说高位深还是大概有用的。而且高量化精度最大的优点就是给响度/振幅调整留下了足够的空间——这点在下面详述。

动态范围

前面铺垫了这么多,重头戏其实就是想说这个。CD明明是一个各种指标上都优越于黑胶的介质,为什么许多人却在追求70、80年代的老唱片,而且两者确实有明显的听感区别?一言以蔽之:万恶的响度战争

在追求“越来越响”的前提下,导致音乐的平均音量(我们用一个简单的客观指标:RMS)不断上升,而波形的振幅极限则是固定的0 dBFS,所以能做的只有不断压缩动态范围,使得音乐越来越平(再多不再展开,参见旧文)。

响度战争在进入21世纪之后已经基本进入一个平稳期,基本商业作品(指我一般听的日本ACG)稳定在单边动态范围(RMS->Peak)9-11dB这个数字上。

眼尖的可以发现,响度战争这个问题,和CD vs HR又是没有直接关系的:你完全可以塞高动态范围(因而平均音量也要小很多)的母带进CD(严谨地说,高动态范围配合高量化精度当然最好,但是CD的位深一般也绰绰有余了),只是厂商为了听起来够响不这么做而已。

幸好,HR一般是面向所谓audiophile的,所以比较重视这个问题,不会过度压缩动态范围。而这,也几乎是任何新发行音乐唯一值得追求HR的原因。

反过来讲,如果你发行的HR和CD完全一样的动态范围、更没有mastering上的区别,仅仅是数字96/24好看,那真的有意义么?请容我大言不惭地说一句,没有!

这里让我们有请Lantis选手:

TitleVersionRMSPeakDiff
Glow MapCD-8.84-0.18.74
Glow MapHi-Res-8.83-0.18.73
あの花のようにHi-Res-9.42-0.68.81
なんどでも笑おうHi-Res-16.8016.8
眠り姫 [ORT]Hi-Res-16.33-0.0916.24

不用多说什么了吧。下面两首是作为对比的哥伦比亚的最近发行的的HR。HR和CD完全一样的动态范围就不提了,更可怕的是烂铁的CD们的RMS已经拉到了-8.x这个水平,还剩多少动态范围可想而知了。

当然这个问题不是只有烂铁一家有,只不过一般没这么夸张。看看もちょ最近几张CD(这里同时列出单曲版和专辑版,因为部分有变化):

ArtistSgAlSongSourceVersionRMS (dB)Peak (dB)Diff (dB)
麻倉もも52365×LOVEAlbumCD-9.922-0.0289.894
麻倉もも52365×LOVESingleCD-10.847-0.00110.847
麻倉もも52365×LOVESingleHi-Res-12.595-0.19812.397
麻倉もも52365×LOVEAlbumHi-Res-11.323-0.20111.122
麻倉もも62シュークリームAlbumCD-10.388-0.00110.388
麻倉もも62シュークリームSingleCD-10.928-0.00110.927
麻倉もも62シュークリームSingleHi-Res-12.639-0.19812.442
麻倉もも62シュークリームAlbumHi-Res-11.805-0.20011.605
麻倉もも62スマッシュ・ドロップAlbumCD-9.808-0.0019.808
麻倉もも62スマッシュ・ドロップSingleCD-9.990-0.0019.990
麻倉もも62スマッシュ・ドロップSingleHi-Res-11.945-0.19811.747
麻倉もも62スマッシュ・ドロップAlbumHi-Res-11.247-0.20011.047
麻倉もも72“さよなら”聞いて。AlbumCD-10.814-0.00110.814
麻倉もも72“さよなら”聞いて。SingleCD-9.392-0.1139.279
麻倉もも72“さよなら”聞いて。SingleHi-Res-10.057-0.1169.942
麻倉もも72“さよなら”聞いて。AlbumHi-Res-12.201-0.20112.000
麻倉もも72ユメシンデレラAlbumCD-10.376-0.00910.367
麻倉もも72ユメシンデレラSingleCD-9.107-0.1748.934
麻倉もも72ユメシンデレラSingleHi-Res-9.709-0.1729.537
麻倉もも72ユメシンデレラAlbumHi-Res-11.783-0.20111.582

もちょ早期几张也存在CD版和HR版动态范围完全一样的问题,不过最近发行的至少能多出2dB左右。另外比较搞笑的是同样是音雨人,制作还有细微的差别,もちょ这里可以看到HR版一般有很多余(正确制作的音频有没有headroom,并没有任何区别)的-0.2dB的headroom,而ナンス的碟则基本全都是CD、HR无论RMS/Peak都完全一样的。手头的CD没抓只存了HR版,就不贴数据了。

不过,不同动态范围听起来区别大不大?这个和个人听力、设备、以及更重要的音乐类型还是关系比较大的(例如交响乐一般很需要大动态),我一般听听日呆流行也听不太出区别(事实上,为了车上放歌方便,我放手机的音乐全都是手动压缩过的动态范围均衡过音量的,我有罪)。但这至少是一个实打实、肉眼可见(笑)的客观的区别。

外一则:Python的音频库

在写DR计算的脚本时,发现Python的音频处理库中,似乎并没有一个明显的first choice。当然,数学计算部分都是用Numpy做的,我这里需要的仅仅是一个解码read的库而已。

搜刮了一阵,大概有这么一下几个选择,这里简单介绍下区别:

def read_wavefile(f): 
    from scipy.io import wavfile
    samplerate, data = wavfile.read(f)
    return data, samplerate

最简单的scipy里的wavfile,基本不支持wave/PCM之外的任何类型。输出就是原始整型,取决于位深,int16或者32。注意输出顺序是采样率/值,我颠倒了下便于和别的几个一致。

def read_sf(f):
    import soundfile as sf
    return sf.read(f) 

SoundFile库。输出似乎永远是float64。支持的格式比上面多,但是不支持m4a(好像支持raw AAC?)。

def read_librosa(f, resampling=None):
    import librosa
    data, samplerate = librosa.load(f, sr=resampling, mono=False) #mono by default, resampling super slow
    data = np.transpose(data)
    return data, samplerate

librosa。其本质是调用SF(上述)或者audioread,所以支持的格式也有限。另外参见注释:默认是mono输出很迷惑,自带的resampling巨慢。值的矩阵要转置下和别的统一。好像永远是float32。

def read_pydub(f, normalized=True):
    import pydub
    a = pydub.AudioSegment.from_file(f)
    # a = a.set_frame_rate(44100)
    y = np.array(a.get_array_of_samples())
    if a.channels == 2:
        y = y.reshape((-1, 2))
    if normalized:
        if y.dtype == np.int16:
            power = 15 
        elif y.dtype == np.int32:
            power = 31
        else:
            raise Exception
        return np.float32(y) / 2**power, a.frame_rate # convert to float32 should be more than enough
    else:
        return y, a.frame_rate # y is same as PCM (int16 or 32)

pydub是我比较推荐使用的库了,他是调用FFMPEG来解码的,所以基本支持任何格式。可以通过set_frame_rate来resampling。唯一的问题就是他默认输出的格式和别人比较与众不同,所以要通过上面这一坨子来输出和别人一样的东西。

这里的normalized是指把PCM的整型normalize到[-1,1]的float,并不会改变振幅啦。因为我后面发现做数学计算的时候整型会比较烦,所以我直接在这里面转了float32。

题外话,int16转float [-1,1]无论是除以2^15还是2^15-1都会有小问题(前者会导致32767无法变成1,后者会导致-32768溢出,虽然业界惯例是前者),不是左右对称的辣鸡有符号整型真的超纠结……

另外一个巨坑是如何判断np.array的dtype,参见这个SO,辅助阅读这个

最后前几天发现pydub有个bug:读取24bit的wav巨慢,比同样的FLAC慢几十倍,原因不明。