C言語

【C言語】第10章第13回:音声信号処理プログラムの実装

本記事では、C言語を用いて基本的な音声信号処理プログラムを構築します。オーディオデータの読み込み、処理、保存方法を学びます。

0. 記事の概要

この記事を読むメリット

  • 信号処理の基礎理解:音声データの操作や編集方法を学べます。
  • 実践的なプログラム作成:フィルタリングや増幅など、オーディオデータの加工スキルを身につけられます。
  • 応用力の向上:音声処理の技術を活かして、音響効果や音声認識システムの構築に挑戦できます。

この記事で学べること

  • WAVファイルの基本構造
  • オーディオデータの操作方法
  • 音量増幅の実装

1. 音声信号処理プログラムの基本設計

1.1 WAVファイルの基本構造

WAVファイルは以下の部分で構成されています。

  • RIFFヘッダー(ファイルの識別情報)
  • フォーマットチャンク(音声のサンプルレートやチャネル数を記録)
  • データチャンク(音声データの実際の波形情報)

1.2 プログラムの機能

このプログラムでは以下の基本機能を実装します。

  • WAVファイルの読み込み
  • 音量増幅の実装
  • 加工済みデータの保存

2. コード例と詳細解説

2.1 基本コード例

#include <stdio.h>
#include <stdlib.h>

typedef struct {
    char chunkID[4];
    unsigned int chunkSize;
    char format[4];
} RIFFHeader;

typedef struct {
    char subchunk1ID[4];
    unsigned int subchunk1Size;
    unsigned short audioFormat;
    unsigned short numChannels;
    unsigned int sampleRate;
    unsigned int byteRate;
    unsigned short blockAlign;
    unsigned short bitsPerSample;
} FormatChunk;

typedef struct {
    char subchunk2ID[4];
    unsigned int subchunk2Size;
} DataChunk;

void amplifyAudio(short *data, unsigned int dataSize, float factor) {
    for (unsigned int i = 0; i < dataSize; i++) {
        int amplified = data[i] * factor;
        if (amplified > 32767) amplified = 32767;
        if (amplified < -32768) amplified = -32768;
        data[i] = amplified;
    }
}

int main() {
    FILE *input = fopen("input.wav", "rb");
    if (!input) {
        perror("ファイルを開けませんでした");
        return 1;
    }

    RIFFHeader riffHeader;
    FormatChunk formatChunk;
    DataChunk dataChunk;

    fread(&riffHeader, sizeof(RIFFHeader), 1, input);
    fread(&formatChunk, sizeof(FormatChunk), 1, input);
    fread(&dataChunk, sizeof(DataChunk), 1, input);

    short *audioData = malloc(dataChunk.subchunk2Size);
    fread(audioData, dataChunk.subchunk2Size, 1, input);
    fclose(input);

    amplifyAudio(audioData, dataChunk.subchunk2Size / sizeof(short), 1.5f);

    FILE *output = fopen("output.wav", "wb");
    if (!output) {
        perror("出力ファイルを作成できませんでした");
        free(audioData);
        return 1;
    }

    fwrite(&riffHeader, sizeof(RIFFHeader), 1, output);
    fwrite(&formatChunk, sizeof(FormatChunk), 1, output);
    fwrite(&dataChunk, sizeof(DataChunk), 1, output);
    fwrite(audioData, dataChunk.subchunk2Size, 1, output);

    fclose(output);
    free(audioData);

    printf("音声信号の増幅が完了しました!\\n");
    return 0;
}
動作解説
  1. データ読み込み:WAVファイルのヘッダー情報と音声データを読み取ります。
  2. 音量増幅:`amplifyAudio`関数で各サンプル値を指定した倍率で増幅します。
  3. 結果の保存:加工済みデータを新しいWAVファイルに保存します。

3. 練習問題

以下の課題に挑戦して、音声信号処理プログラムを拡張してみましょう。

  1. 音声データの逆再生機能を追加してください。
  2. 高音域を強調するフィルタリング機能を実装してください。
  3. データをリアルタイムで可視化する機能を追加してください。

4. 練習問題の解答と解説

問1の解答例

// 音声データの逆再生
void reverseAudio(short *data, unsigned int dataSize) {
    for (unsigned int i = 0; i < dataSize / 2; i++) {
        short temp = data[i];
        data[i] = data[dataSize - 1 - i];
        data[dataSize - 1 - i] = temp;
    }
}

この関数を使用して、音声データを逆順に並べ替えます。

5. まとめ

本記事では、C言語を用いてWAVファイルの読み込み、編集、保存を行う音声信号処理プログラムを作成しました。さらに高度な機能を追加して、実用的な音声処理ツールを開発してみましょう。