mikeo_410


MP4のAAC

  mp4コンテナのAAC音声でサンプリングレートを半分に誤認する問題がありました。
  同じ問題が、ffmpeg と DirectShowで別々に起きていて何か根本的な問題のようです。

1.コンテナとデコーダの関係

  mp4コンテナに格納されたAAC音声ストリームにはフレームヘッダがありません。旧来、AVIのように、コンテナとストリームの独立した関係ではないと言うことです。

2.AACのSBR (Spectral Band Replication) 、PS (Parametric Stereo)

  旧来のデコーダとの互換性を取る手段として、サンプリングレート、チャネル数を減らしてヘッダに記す方法が採用された、と言うことのようです。
  実際に問題のあった、48KHzサンプリング、ステレオの音声を例に説明します。
  SBRでは、24KHzにして(おそらく1つ飛びにサンプルを使って)AACのフレームを作ります。このデータは、旧来のAACと互換で、旧来のデコーダはこの部分を再生します。失われる高い周波数部分は別に格納します。旧来のソフトエアで処理していたヘッダ情報にも24KHzと記して置きます。旧来のソフトウエアでは、24KHzで再生され、新しいソフトウエアでは48KHzで再生されるように仕組んであると言うことです。
  PSは、ステレオをモノラルにします。2CHに復号するための情報は別に書き、新しいソフトウエアだけが認識すると言うものです。

3.具体的な問題

3.1.ffmpeg

  ffmpegで使われているfaad2は、SBR、PSに対応しています。(完全な対応かどうかはわかりませんが、24KHzから48KHzのPCMを出力します。)
  ffmpegでは、デコーダはファイルの入出力をしません。AACのフレームデータを受け取って、PCMデータを返します。例として24KHzサンプリングAACフレームから、48KHzサンプリング相当のデータを返します。これを出力コンテナに入れるのは、ffmpegで、ffmpegはmp4コンテナのヘッダの値(24KHz)を信じて付与しています。

3.2.DirectShowフィルタの出力ピンのサンプリングレート

  1. ffdshowやスプリッタを入れても、Microsoft DTV-DVD AudioDecoder でデコードされます。このデコーダは、SBRをサポートするようで、前述の例では48KHzを出力します。
    しかし、Pinの情報は24KHzになっています。
  2. 同じことを、(DTV-DVD AudioDecoder を削除して)ffdshow(faad2)で試すと、Pinは48KHzになります。

  これは、DTV-DVD AudioDecoder の間違いに思えます。

4.実際にSBRが機能しているのか

  24KHzサンプリングのPCMデータを、NeroAacEnc でエンコードして作ったファイル(lc24.mp4)は、MediaInfoで 48KHz LC SBR と表示される。また、この lc24.mp4 から aacフレームデータのみを抜き出して lc24.aac を作り、 faad2 でデコードすると48KHzサンプリングのPCMファイルが出来上がる。
  MediaInfo も faad2 も、実質 24KHzサンプリングなのに、48KHzと認識しています。
  表示やサンプリングレートを見ても実質はわからないようです。

4.1.faad2、NeroAacEnc、MediaInfo

  R言語のスクリプトで、13KHzのサイン波を48KHzと24KHzでサンプリングした状態のPCMデータ(48.wav、24.wav)を作りました。
  24KHzサンプリングでは 13KHzは認識できないので、そのパワーは 12KHz以下に誤認されることになります。

  1. #13KHz  SIN波を1分間収集
  2. #192KHzでサンプリングした状態のデータを作る
  3. x<-seq(0,by=2*pi*13000/192000,length.out=192000*60)
  4. y<-sin(x)
  5. #サンプリングレートが48KHzの状態(4つ飛びに)
  6. pos<-seq(1,by=4,length.out=(length(x)/4))
  7. x48<-x[pos]
  8. y48<-y[pos]
  9. #サンプリングレートが24KHzの状態(8つ飛びに)
  10. pos<-seq(1,by=8,length.out=(length(x)/8))
  11. x24<-x[pos]
  12. y24<-y[pos]
  13. #確認のためプロット
  14. # 背景に 1ms=192サンプル
  15. plot(x[1:192],y[1:192],type="l",col="cyan",lwd=1,axes=F,xlab="",ylab="")
  16. par(new=T)
  17. plot(x48[1:48],y48[1:48],type="b",lty="dashed",pch="x",col="red",lwd=1,axes=F,xlab="",ylab="")
  18. par(new=T)
  19. plot(seq(0,to=1,length.out=24),y24[1:24],type="b",lty="dotted",col="blue",lwd=1,axes=F,xlab="",ylab="")
  20. axis(1)
  21. mtext("時間(ms)",1,line=2)
  22. axis(2)
  23. mtext("振幅",2,line=2)
  24. title(main="13KHzの音を24KHzと48KHzでサンプリング")
  25. #音を聞いて見るためにWAVファイルに出力
  26. source("WavIO_R.R") #これは一度だけ
  27. #48KHzサンプリングレート
  28. tmp<-matrix(0,ncol=length(y48)*2)
  29. for( i in 1:length(y48)){ 
  30. tmp[i*2-1]=y48[i]*30000
  31. tmp[i*2]=y48[i]*30000}
  32. wav16write("48.wav",tmp,2,48000)
  33. #24KHzサンプリングレート
  34. tmp<-matrix(0,ncol=length(y24)*2)
  35. for( i in 1:length(y24)){ 
  36. tmp[i*2-1]=y24[i]*30000
  37. tmp[i*2]=y24[i]*30000}
  38. wav16write("24.wav",tmp,2,24000)
  39.  
  40. #48KHz サンプリングのFFT
  41. tmp<-fft(y48[1:48000])#1秒分をFFT
  42. f48<-sqrt(Re(tmp)*Re(tmp)+Im(tmp)*Im(tmp))
  43. plot(1:24000,f48[1:24000],type="l",xlab="Hz",ylab="Power")
  44. title(main="48KHzでサンプリングしたときのFFTの結果")
  45.  
  46. tmp<-fft(y24[1:24000])#1秒分をFFT
  47. f24<-sqrt(Re(tmp)*Re(tmp)+Im(tmp)*Im(tmp))
  48. plot(1:12000,f24[1:12000],type="l",xlab="Hz",ylab="Power")
  49. title(main="24KHzでサンプリングしたときのFFTの結果")

  48.wav、24.wav を NeroAacEnc で、-lc オプションを指定して、エンコードします。それぞれ、48.mp4、24.mp4とします。
  48.mp4、24.mp4 から、ffmepgで、 -acodec copy を使ってフレームデータのみの 48.aac、24.aac を作ります。
  48.aac、24.aac を、faad.exe(faad2)でデコードして、faad48a.wav、faad24a.wav を作ります。
  48.mp4、24.mp4 を、faad.exe(faad2)でデコードして、faad48b.wav、faad24b.wav を作ります。

  MediaInfo  備考
48.mp4  48.0KHz,2チャンネル,AAC(Version 4)(LC)  
24.mp4  48.0KHz,2チャンネル,AAC(Version 4)(LC)(SBR)  24KHzは、SBR付きと認識される
48.aac  48.0KHz,2チャンネル,AAC(ATDS)(Version 4)(LC)  
24.aac  48.0KHz,2チャンネル,AAC(ATDS)(Version 4)(LC)(SBR)  24KHzは、SBR付きと認識される
faad48a.wav  48.0KHz,2チャンネル,PCM(Microsoft)  
faad24a.wav  48.0KHz,2チャンネル,PCM(Microsoft)  mp4コンテナにないとSBRを実行
faad48b.wav   48.0KHz,2チャンネル,PCM(Microsoft)  
faad24b.wav

 24.0KHz,2チャンネル,PCM(Microsoft)

 mp4コンテナにあるときはOK

  サンプリングレートが 24KHzなのに、48KHzのSBRと誤認します。当然、13KHzは復号されません。

 

4.2.DTV-DVD AudioDecoder は、高い周波数を復元するか

  前述のように DTV-DVD AudioDecoder は、出力としては 48KHz なのに、Pin情報は 24KHz といった問題があります。しかし、ffdshow フィルタが使えず、常にこれが使われてしまいます。
  このフィルタの出力は、Pin情報が正しくないだけで、実質 48KHzサンプリング(SBR有効)になっているのでしょうか。
  左図から見て、DTV-DVD AudioDecoder は、SBRサポートのようです。
 

 

 

 

 

 


アルパイン 田園都市線 不動産 東戸塚 マンション ECサイト構築 ヴォクシー