#音声処理#Seed-VC#サンプリングレート#信号処理

22.05kHz vs 44.1kHz — 『本物の広帯域』とアップサンプリングは何が違うのか


音声変換の出力を聴き比べていて、こんな疑問を持ったことはないでしょうか。

「44.1kHz で書き出しているのに、なんだか音がこもって聞こえる」

書き出しのサンプリングレートは確かに 44.1kHz。ファイルのプロパティにもそう出ている。なのに、CD音質の空気感がない。実はこれ、サンプリングレートの数字と、実際に含まれる音の帯域は別物だからです。この記事は、「声のデザイン」アプリで 22.05kHz モデルから 44.1kHz の F0 条件付きモデルへ切り替えたときに確かめた、“本物の広帯域” とアップサンプリングの決定的な違いの記録です。

前提: サンプリングレートは「上限」を決めるだけ

まず基本の確認から。ナイキスト定理により、サンプリングレート fs の音声が表現できる周波数の上限は fs / 2 です。

  • 22.05kHz → 上限 約11kHz
  • 44.1kHz → 上限 約22kHz

ここで大事なのは、「44.1kHz にすれば22kHzまで表現できる」だけであって、「22kHzまで中身が詰まる」わけではない、という点です。器の大きさが決まるだけで、中身が自動で増えるわけではない。

22.05kHz で作られた音声には、そもそも11kHzより上の成分が存在しません。これを 44.1kHz にリサンプル(アップサンプル)しても、空いた高域は空のままです。器を2倍に広げても、無かったものは生まれてこない。これが直感に反するポイントです。

22.05kHz モデルと 44.1kHz モデルは別物

「声のデザイン」の推論サービスは、環境変数でモデルを切り替えます。

# 44.1kHz F0条件付きモデル(本物の広帯域出力)を使うか。既定OFF(従来22.05kHz)。
F0_COND = os.environ.get("VOICE_CANVA_F0", "0") == "1"

そして 44k モードの起動スクリプトはこうなっています。

export VOICE_CANVA_F0="${VOICE_CANVA_F0:-1}"                    # 44k F0条件付きモデルを使う
export VOICE_CANVA_OUTPUT_SR="${VOICE_CANVA_OUTPUT_SR:-44100}"  # 出力も44.1kHz(ダウンサンプルしない)
export VOICE_CANVA_AUTO_F0="${VOICE_CANVA_AUTO_F0:-1}"          # キャリアF0を目標音域へ寄せる

ここが決定的です。VOICE_CANVA_F0=1 は単に「出力ファイルのレートを上げる」設定ではありません。生成モデルそのものを、44.1kHz で学習された別のモデルに差し替えているのです。

内部的には、22kモデルと44kモデルはチェックポイントもボコーダも異なります。44kモデルは高いサンプリングレートで学習された BigVGAN ボコーダを持っており、メルスペクトログラムから波形へ戻す段階で、11kHzより上の帯域をモデルが生成できる。つまり空の高域を、リサンプルで機械的に埋めるのではなく、学習した知識に基づいて中身として作り出すわけです。

sr もモデルに追従して切り替わります。

sr = mel_fn_args["sampling_rate"]   # f0モードは44100

出力レートも 44100 のまま維持し、ダウンサンプルしません。「44kで生成 → 44kで出力」という一貫した経路を保つことで、せっかく作った高域を途中で捨てないようにしています。

実測: 高域にエネルギーが乗っているか

「本当に高域の中身が増えたのか」は、数字で確かめないと意味がありません。そこで、同じ入力から生成した音声のスペクトルを見て、11kHzより上の帯域が全体エネルギーに占める割合を測りました。

結果はこうでした。

  • 44.1kHz モデルで生成した出力: >11kHz 帯に全エネルギーの 約7.4% が乗っている
  • 22.05kHz 出力を 44.1kHz へアップサンプルしたもの: >11kHz 帯は ほぼゼロ

同じ 44.1kHz のファイルでも、中身がまるで違います。アップサンプルした側は、器こそ22kHzまであるのに、11kHzより上は空っぽ。一方、44kモデルの出力にはちゃんとエネルギーが乗っている。この7.4%が、子音の抜けや息の空気感、“CD音質らしさ” として耳に届く成分です。

数字にすると当たり前に見えますが、耳だけで聴き比べると「なんとなくこっちがクリア」で終わってしまいがちです。スペクトルで帯域ごとのエネルギーを見て初めて、「高域が生まれている / いない」を客観的に切り分けられました。

なぜアップサンプルでは高域が生まれないのか

理屈をもう少しだけ。アップサンプリングは、既存のサンプル点の間を補間する処理です。線形補間にせよ、より高品質なローパス補間にせよ、やっていることは「今ある波形をなめらかにつなぐ」こと。新しい周波数成分をでっち上げることはしません(むしろ真っ当なリサンプラーは、折り返し雑音として偽の高域が出ないよう、上限より上を積極的に消します)。

だから「22.05kHz音声を44.1kHzにする」と「44.1kHzで音声を生成する」は、結果の器が同じでも中身が根本的に違う。前者は補間、後者は生成です。高域という “情報” は、それを知っているモデルにしか作れません。

落とし穴と学び

  • サンプリングレートの数字を音質の証明に使わない。「44.1kHz出力」はスペック表の飾りになりがちですが、中身が伴っているとは限りません。帯域ごとのエネルギーを実測して初めて “本物” を主張できます。
  • 44kモデルは重い。起動スクリプトにも「モデルが大きくCPUでは生成が遅い(GPU推奨)」と明記しています。広帯域は無料ではなく、モデルサイズと推論コストの対価です。用途に応じて 22k と使い分ける前提で設計するのが現実的です。
  • 経路のどこかでダウンサンプルすると台無し。せっかく44kで生成しても、後段のどこかで22kに落とせば高域は消えます。VOICE_CANVA_OUTPUT_SR=44100 を明示し、生成から出力まで一貫させることが重要でした。
  • “高域が足りない” は根本原因を疑う。こもって聞こえるとき、EQで高域を持ち上げるのは応急処置にすぎません。無い成分は持ち上げようがない。真の解決は「高域を生成できるモデルに切り替える」ことでした。

まとめ

  • サンプリングレートは表現できる周波数の上限を決めるだけで、中身が自動で詰まるわけではない
  • 22.05kHz音声を44.1kHzにアップサンプルしても、11kHzより上の高域は生まれない(補間であって生成ではない)
  • VOICE_CANVA_F0=1 は出力レートを上げる設定ではなく、44.1kHzで学習された別モデル(BigVGANボコーダ込み)への切り替え
  • 実測では、44kモデル出力は >11kHz 帯に全エネルギーの約7.4%が乗り、22kアップサンプルはほぼゼロ
  • 広帯域はモデルサイズ・推論コストの対価。生成から出力まで44kを一貫させ、途中でダウンサンプルしないことが肝心
← 記事一覧へ