Smile Engineering Blog

ジェイエスピーからTipsや技術特集、プロジェクト物語を発信します

デジタルオーディオのボリュームをやってみる

f:id:jspnet:20191015234008p:plain:left

DSP(Digital Signal Processor)のファームウェアを実装する時、いつも悩むことは、自分が実装した信号処理のプログラムが正しいか(?)、どのように検証するかで、 WindowsLinuxでその期待の動作を十分に検証し(期待値を作り)、組み込んだファームウェアが正しいか(?)、その手法を考えます。

(超入門)デジタル信号処理とは・・・

デジタル信号処理の組み込み(ファームウェア)を考えた時、フィルタ処理や、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としたとき(WindowsVisual Studioなど)、コマンドラインの引数は、入力PCM(input.pcm)、出力(output.pcm)、ボリューム値(dB)です。


例) ボリューム 6dB

> vol.exe input.pcm output.pcm 6


PCMではなくWAVにしたい場合は、こちら PCMにWAVヘッダを付ける