デジタルオーディオのボリュームをやってみる
DSP(Digital Signal Processor)のファームウェアを実装する時、いつも悩むことは、自分が実装した信号処理のプログラムが正しいか(?)、どのように検証するかで、 WindowsやLinuxでその期待の動作を十分に検証し(期待値を作り)、組み込んだファームウェアが正しいか(?)、その手法を考えます。
(超入門)デジタル信号処理とは・・・
デジタル信号処理の組み込み(ファームウェア)を考えた時、フィルタ処理や、FFT(高速フーリエ変換)をどう実現するかが重要なポイントになると思います。一方、 信号処理の経験者が少ないプロジェクトでは、まず、簡単なデジタル信号処理を紹介する意味で、ボリュームの制御を例に説明をすることがあります。
デジタルボリューム デシベル(dB)
現代のソフトウェア開発では、目的に応じた開発環境からその言語を選択する時代ですが、 組み込みの分野では、Cコンパイラによるファームウェア開発が中心です(それでも、アセンブラよりは有難いですね)。
サンプルコード【C言語】
このような背景も含めて、C言語でボリュームのサンプルコードを書いてみました。 16bitのリニアPCMを処理するもので、デシベル(dB)から倍率を計算しています。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> int main(int argc, char** argv) { FILE* fp_in; FILE* fp_out; int vol_dB; double vol_level; if ((fp_in = fopen(argv[1], "rb")) == NULL) { // PCM入力ファイル printf("can not open %s\n", argv[1]); exit(EXIT_FAILURE); } if ((fp_out = fopen(argv[2], "wb")) == NULL) { // PCM出力ファイル printf("can not open %s\n", argv[2]); exit(EXIT_FAILURE); } vol_dB = atoi(argv[3]); // ボリュームdB vol_level = pow(10.0, vol_dB / 20.0); printf("%ddB (%f)\n", vol_dB, vol_level); while (1) { short in, out; if (!fread(&in, sizeof(short), 1, fp_in))break; // PCM入力(16bitモノラル) out = (short)((double)in * vol_level); // ボリューム処理 fwrite(&out, sizeof(short), 1, fp_out); // PCM出力(16bitモノラル) } fclose(fp_in); fclose(fp_out); return EXIT_SUCCESS; }
起動方法
例えばビルド出力をvolとしたとき(WindowsでVisual Studioなど)、コマンドラインの引数は、入力PCM(input.pcm)、出力(output.pcm)、ボリューム値(dB)です。
例) ボリューム 6dB
> vol.exe input.pcm output.pcm 6
PCMではなくWAVにしたい場合は、こちら PCMにWAVヘッダを付ける