手習ひデジタル信号処理(98) Scilab、アップサンプリングする方法3つのつもりが。

Joseph Halfmoon

過去回のRTLSDRからデータ輸入では復調するためにダウンサンプリングに取り組み?ました。今回はアップサンプリングに使えるScilab関数を勉強してみます。実験ターゲットに使うのは前回解析プロットにかけた音声データです。アップサンプリング(インターポレーション)した結果、どうなってしまうのか?意外なような当然なような。

※「手習ひデジタル信号処理」投稿順 Indexはこちら

アップサンプリングに使えそうなScilab関数3つ

手元のScilabでは、デフォルトでcomm_tbx(こいつがなかなか一筋縄でいかないです)をロードしてあります。信号をアップサンプリングするのに使えそうな関数を検索してみると以下の3種類が見つかりました。

    1. upsample(x, osf)
    2. intdec(x, lom)
    3. resample(x, R)

helpを調べてみると以下のようでした。

第1のupsample関数。データの途中に単純にゼロを挟みこむ「純粋な」アップサンプリングを実行する関数です。係数をosfに与えるますが、整数倍だけでなく、非整数の場合もゼロの個数と位置で調整してくれます。しかし、アップサンプリング後のインターポレーション・フィルタは含まれていないので適宜後段でLPFを実装する必要があります。

第2のintdec関数。リサンプリングを行うための関数です。アップサンプルでもダウンサンプルでも可能みたいです(ダウンサンプリングは試してないけど。)アップサンプリングの場合、インターポレーション・フィルタも実行してくれます。なお、かけてくれるフィルタはDFTベースの強力なものみたいデス。知らんけど。

第3のresample関数。やはりリサンプリングを行うための関数です。問題のcomm_tbx(コミュニケーション・ツールボックス)所蔵の関数です。helpみると上記のintdec関数をディスっており、「よいもの」みたいです。デフォルトでcardinal splineインターポレータを使用とのことで後段LPFまで含まれます。

音声データを準備して早速アップサンプリング

まずは、前々回に準備した音声データをロードしておきます。

[x, Fs1, bits] = wavread('micTestCD.wav');
xL = x(1,:);

ファイル名のとおり、CDクオリティのサンプリング周波数44100Hz(以下Fs1で参照します)のデータです。「ただいまマイクの試験中」なる音声。テスト用に左チャネルのデータのみ取り出して変数 xLに格納しておきます。

xLの「生音声」のFFT結果が以下に。Fs1XL_FFT

あれあれresampleでエラーがでる

早速2倍のアップサンプリング(関数によってはインターポレーションまで)を試みます。まずは期待の comm_tbxのresample。

resampleERROR

上記をみるとデフォルトで適用される筈の、cardinal splineインターポレータのところでエラー発生しているみたいです。なにか別な物を事前インストールしておかないとならないのか?分かりませぬ。ということで今回は(も)パス。

intdecはどうよ

続いて、intdec関数で2倍のインターポレーション(アップサンプリング後LPFかける)を試みてみます。

yA=intdec(xL, 2);

上記のインターポレーションの結果のFFTが以下に。

Fs2YA_FFT

元の信号のナイキスト周波数22050Hz以下は元の信号通りに見え、それ以上の周波数は非常に急峻、ほぼほぼ絶壁で抑圧されてました。intdec関数(というかDFT利用フィルタ)すごいじゃん。

素のままの upsampleではどうよ

さて、素のまま0を挿入してアップサンプリングのみ行う upsample関数で2倍にアップサンプリングしてみます。

yB=upsample(xL, 2);

FFTの結果が以下に。予想どおりというか、期待通りに「折り返し雑音」が現れております。ある意味、見事な。Fs2YB_FFT

注文どおりの折り返しが見えたところで、後段フィルタですな。

LPFを追加してみる

RTLSDRからのデータ輸入のところで使用したFIRフィルタを今回も使いまわし、「インターポレーション・フィルタ」として転用してみます。なお以下のシーケンスで登場するgenFIRLP2とplotFFT2は過去回で作成した Scilab関数の「ラッパ」です。大したものではありませぬ。

coeff100=genFIRLP2(Fs1*2, 100, Fs1, 1);
yC=filter(coeff100, 1, yB);
plotFFT2(Fs1*2, yC, 1)

なんどか掲げてますが、フィルタの特性は以下のようです。

coeff100

上記のフィルタかけて「インターポレーション」したあとの波形をFFTした結果が以下に。Fs2YC_FFT

intdec関数の絶壁とは比較になりませんが、折り返しは弾圧されております。

耳が悪いの?

こうして元の信号 xL(サンプリング周波数Fs1=44100Hz)と、yA(intdecで2倍のサンプリング周波数にインタポレーション)、yB(upsampleで単純2倍にアップサンプリング)、yC(yBにLPFかけたもの)を実際に「音声」として聞いてみました。

playsnd(xL, Fs1);
playsnd(yA, 2*Fs1);
playsnd(yB, 2*Fs1);
playsnd(yC, 2*Fs1);

「耳が良い」という自覚はまったくない年寄なんだけれども、それにしても差が無いです。「ただいまマイクの試験中」ハッキリ聞こえます。自分の声なんだかれども。データ量としてはyA、yB、yCはxLの倍になっているので2倍のサンプルレートであるのは確か。数字でデータ見る分にはちゃんと処理されてるようです。

よく考えると、2*Fs1(88200Hz)のデータを「再生」できるplaysndもある意味凄いです。しかしWindows PC側のスピーカの再生レートはシステムで決まっている(CD or DVD サンプルレート)っぽいので、結局再生にいたるどこかで所定のレートに落としている疑いが。さらによく考えたら20kHz以上の高い周波数のところに雑音が載っていたとして、それが再生できたとしても耳で聞こえるわけないじゃん、超音波だし。ましてや可聴域が狭くなっている筈の年寄ならば聞こえる筈ない。トホホ。

手習ひデジタル信号処理(97) Scilab、音声データの入力と解析プロット へ戻る

手習ひデジタル信号処理(99) Scilab、位相連続のFM変調方法を実験 へ進む