mattintosh note

どこかのエンジニアモドキの備忘録

2024-06-05: 現在ホビー関連の記事を 新しいブログ に移行しています(一部の国、ISP からは閲覧できません)

SOX で Upsampling? stdout with mpv とか

この前、Raspberry Pi で cdrdao と toc2cue、bchunk でオーディオの取り込みが出来るようにした。

mattintosh.hatenablog.com

AAC へのエンコードは長い間 Nero AAC Codec を使ってたが、結構古いしそろそろ最近のエンコーダの方がいいかなと思い、変えてみることにした。

最近よく「ハイレゾ」って聞くけど色々放浪してたら、SoX でサンプリングレートを弄ったりする遊びがあるらしい。(Windows では foober2000 のプラグインに入ってるっぽい?)

http://www.hcn.zaq.ne.jp/___/unix/sox-ja.html#E-rate にある最高品質再サンプルを参考に 44.1kHz s16le を 96kHz f32le に変換。

sox -G infile.wav outfile.wav rate -v -I -b 90 96000 dither -S

ファイルサイズがトンデモナイことになる。これは流石に困るので、mpv で AAC に変換する。Libavcodec だから FFmpeg とかと同じかね。FFmpegAAC を使うときに -strict experimental の指定が面倒くさい。

sox から標準出力(stdout)を行う場合はタイプを指定する必要がある。標準出力ファイル名は -。(-t f32 でもいいのか? Precision が 32-bit にならない?)

sox -G infile -e floating-point -b 32 -t raw - rate -v -I -b 90 96000 dither -S

mpv 側の標準入力で受け取る場合も - でもいいが、明示的にファイルディスクリプタを指定できる fd://012 書式があるのでそちらを使う。RAW で送られてくるのでソースのフォーマットなどを指定する必要がある。オプションの書き方が FFmpeg ともまた違って面白い。--oac=aac を指定するとバージョンによっては Experimental Codec の注意書きが出るようだ(Arch Linux ARM の mpv では出ないが、Ubuntu の 16.04 の mpv では出る)。

mpv --no-config --demuxer=rawaudio --demuxer-rawaudio-channels=2 --demuxer-rawaudio-format=floatle --demuxer-rawaudio-rate=96000 fd://0 --oac=aac --oacopts=ab=192k

SoX ではスペクトログラムも作成出来るのでやってみる。

sox infile.wav -n spectrogram -h
Input File : '干物妹!うまるちゃん - UMARU THE BEST - 01.wav' Channels : 2 Sample Rate : 44100 Precision : 16-bit Duration : 00:03:32.01 = 9349788 samples = 15901 CDDA sectors File Size : 37.4M Bit Rate : 1.41M Sample Encoding: 16-bit Signed Integer PCM

f:id:mattintosh4:20160824001803p:plain

Input File : '干物妹!うまるちゃん - UMARU THE BEST - 01 (96kHz).wav' Channels : 2 Sample Rate : 96000 Precision : 24-bit Duration : 00:03:32.01 = 20353280 samples ~ 15901 CDDA sectors File Size : 163M Bit Rate : 6.14M Sample Encoding: 32-bit Floating Point PCM

f:id:mattintosh4:20160824001817p:plain

ぱっと見、44.1kHz の方は 22.05kHz をぶっちぎってるような…。

では AAC に変換したものから PCM に書き戻してスペクトログラムを見てみる。mpv はオプション調べるのがめんどくさかったのでとりあえず ffmpeg を使う。

ffmpeg -i infile-96kHz.m4a -f f32le hoge.f32le
sox -b 32 -c 2 -r 96000 -t f32 hoge.f32le -n spectrogram -h

f:id:mattintosh4:20160824010652p:plain

なんか所々ぴょんぴょんしたものもある。これはそこそこまともに戻ってる方なんだろうか。


今回から mpv でエンコードしてみたけど、音質は AAC にしては頑張ってる方なんじゃないだろうか。(iPhone で聴く限りは)

とりあえず一括変換用のスクリプト書いてみた。設定はまた暇なときだなぁ。仕事あがりで聴き比べようとしても疲れてもう無理だ…。

#!/bin/sh
set -e
set -x

: ${1:?}

which sox mpv

for f
do
    case ${f} in
    *.wav|*.WAV)
    ;;
    *)
         continue
    ;;
    esac
    
    sox -G "${f}" -e floating-point -b 32 -t raw - rate -v -I -b 90 96000 dither -S \
    | mpv --no-config --demuxer=rawaudio \
                      --demuxer-rawaudio-channels=2 \
                      --demuxer-rawaudio-format=floatle \
                      --demuxer-rawaudio-rate=96000 \
                      fd://0 \
                      -o "${f%.*}".m4a --oac=aac --oacopts=ab=192k
done

追記(2016年8月24日)

SoX のオプションを少し読んだのでちょい修正。

書式が少し特殊である。

sox [gopts] [[fopts] infile]... [fopts] outfile [effect [effopt]]...

ショートオプションだとわかりづらいのでロングオプションを使用。

今回のサンプルは bchunkcdr として書き出したので --endian も指定する。自分の場合、cdrdao のあと、dd conv=swab をかけているので little だが場合によっては big かもしれない。

sox -V3 --buffer 65536 \
        --guard \
        --multi-threaded \
        --show-progress \
        --type cdr \
        --endian little \
        CROW\'SCLAW\ -\ Shelling\ And\ Torpedoing\ -\ 02.cdr \
        --bits 24 \
        --type raw - \
        rate -v -I 96000 \
        dither -S \
| mpv --no-config \
      --demuxer{=rawaudio,-rawaudio-{channels=2,format=s24le,rate=96000}} \
      fd://0 \
      -o outfile.m4a \
      --oac=aac \
      --oacopts=ab=192k
sox: SoX v14.4.2 sox INFO formats: `CROW'SCLAW - Shelling And Torpedoing - 02.cdr': overriding file-type byte-order Input File : 'CROW'SCLAW - Shelling And Torpedoing - 02.cdr' Channels : 2 Sample Rate : 44100 Precision : 16-bit Duration : 00:03:10.65 = 8407812 samples = 14299 CDDA sectors File Size : 33.6M Bit Rate : 1.41M Sample Encoding: 16-bit Signed Integer PCM Endian Type : little Reverse Nibbles: no Reverse Bits : no Output File : '-' (raw) Channels : 2 Sample Rate : 96000 Precision : 24-bit Duration : 00:03:10.65 = 18302720 samples ~ 14299 CDDA sectors Sample Encoding: 24-bit Signed Integer PCM Endian Type : little Reverse Nibbles: no Reverse Bits : no Comment : 'Processed by SoX' sox INFO sox: effects chain: input 44100Hz 2 channels sox INFO sox: effects chain: gain 44100Hz 2 channels sox INFO sox: effects chain: rate 96000Hz 2 channels sox INFO sox: effects chain: gain 96000Hz 2 channels sox INFO sox: effects chain: dither 96000Hz 2 channels sox INFO sox: effects chain: output 96000Hz 2 channels

追記(2016年8月25日)

dd で conv=swab してしまった(cdr だとバイトオーダー変更必要なかったのに…)バイナリファイルを bchunk で cdr として書き出したときのためのスクリプトを書き直した。

compand エフェクトの項目に騒音が多くても聴きとりやすくなるというサンプルが載っていたのでそれを入れてみた。rate のあとと前だとどっちがいいんだろうか…。FFmpeg は 3.0 から AAC が正式なものになったらしい(そういや Ubuntu は libav だったから自分で ffmpeg ビルドしたの忘れてた)。最新版をビルドしたら -strict experimental を要求されなくなった。

なかなか Nero AAC Codec との比較をしている時間がない。cdrdao の取り込みやり直そうかなぁ。リトルエンディアンにしておいて方が楽ではあるんだけど。