スキップしてメイン コンテンツに移動

WAVライブラリ

プログラムで音声フォーマットのWAVファイルが扱えるようになれば、それを読みこんで、エフェクト処理して、それを書き出す、自作のデジタルエフェクターではそれをリアルタイムで行うだけの違いでしかありません。PCでプログラムのひな形を作るのがサウンドエフェクトプログラミングの第一歩となります。

 WAVライブラリ 

C言語ではじめる音のプログラミング
http://floor13.sakura.ne.jp/book03/book03.html

サウンドプログラミング入門
http://floor13.sakura.ne.jp/book06/book06.html

良本なのでぜひ両方ともお手元に置いてあげてください。

サンプル音源やソースコードも上記サイトで全公開されています。そのソースコードの中にWAVファイルを読み書きするCプログラムがあるのですが、Cではちょっとアレなので、それをC++で書き直してみました。

wave.hpp(C++)
https://github.com/DIYFXWorld/Other

オリジナルのソースコードではデータ圧縮もサポートしていますが、面倒なので非圧縮データのみの扱いとしました。

 wavファイルの情報を表示する 

手始めにwave.hppを使ってWAVファイルの情報を表示するプログラムを作ってみます。wave.hppを同じフォルダにコピーしておきます。プログラムファイル名はwav_info.cppとします。

wav_info.cpp

#include  "wave.hpp"

main( int argc, char *argv[] )
{
  if( argc < 2 )
  {
    printf( "usage : wav_info file_name.wav" );
    return 0;
  }

  wav_info  wi = get_wav_info( argv[ 1 ] );

  puts( "" );

  printf( "Sampling rate : %d Hz\r\n", wi.fs );
  printf( "Sample bits   : %d bit\r\n", wi.bits );
  
  printf( "Channel       : " );
  if( wi.channel == 1 )  puts( "1 (Mono)" );
  if( wi.channel == 2 )  puts( "2 (Stereo)" );

  printf( "Time length   : %f s\r\n", (double)wi.length / wi.fs );
}


 サイン波データを作ってみる 

1000Hzの正弦波データを作ってWAVファイルに書き込んでみます。データ型はfloat型を使いました。

wave_sine.cpp

#include  "wave.hpp"
#include  <cmath>

main()
{
  int     fs      = 44100;     // サンプリングレート
  int     freq    = 1000;      // 周波数
  float   length  = 5.f;       // 音声データの長さ(秒)
  float   gain    = 0.2f;      // ゲイン

  wave<float> src( fs, fs * length );

  float  t = ( 2.0*M_PI ) / fs * freq;

  for( auto i( 0 ); i < src.length; ++i )
  {
    src[ i ] =  sin( t * i ) * gain;
  }

  save( "wave_sine.wav", src );
}


waveクラスが音声データを扱うクラスです。テンプレートでデータ型を指定します。使用できるデータ型と数値範囲は以下の通りです。数値範囲を超えると数値が反転してノイズになります。実数を使う時は1.0にならないように気を付けます。

double             -1.0~0.99999...  ( -1.0 <= x < 1.0 )
float                -1.0~0.99999...  ( -1.0 <= x < 1.0 )
int                   -32768~32767
short               -32768~32767
char                -128~127
unsigned char    0~255

wave::fs  ---- サンプリングレート
wave::length ---- 音声データの個数
wave::channel ---- 1=モノラル, 2=ステレオ

 データフォーマットを決める 

・STM32などの32ビットマイコンで扱うのなら符号付き16ビットデータ(short)が恐らくもっとも高速に扱えます。

・最初に紹介した参考書籍のC言語ではじめる音のプログラミング、サウンドプログラミング入門では( -1.0 <= x < 1.0 )に正規化されたdouble(64ビット)で音声データを扱っています。

・ネットで多く見られるVST用のソースコードは( -1.0 <= x < 1.0 )に正規化されたfloat(32ビット)でデータを扱っています。

データ型は各自で好きなのを使えば良いです。実数を使えば精度は高くなりますが、FPUの無いマイコンで動作させることは難しくなります。

WAVフォーマットの内部表現(非圧縮)は符号付き16ビット、または符号なし8ビットデータどちらかしかありませんので、ファイルに落とす際にデータ変換されて書き込まれます。WAVファイルから読み込むときも、任意のデータ型と数値範囲に変換されます。


 ステレオデータとビット深度 

ステレオ(2ch)の音声データを作るにはwaveクラスのコンストラクタの第3引数に2を渡します。(デフォルトは1=モノラルです)。データへのアクセスはL[], R[]で行います。

wave_sine_st.cpp

#include  "wave.hpp"
#include  <cmath>

main()
{
  int       fs      = 44100;   // サンプリングレート
  int       freq    = 1000;    // サイン波の周波数
  int       length  = 5;       // 音声データの長さ(秒)
  float     gain   = 0.2;      // ゲイン

  wave_f  src(  fs, fs*length, 2 ); // 第3引数に2を指定するとステレオ

  double  s = (2.0*M_PI) / fs * freq;

  for( auto i( 0 ); i < src.length; ++i )
  {
    float  v = sin( s * i ) * gain;
    src.L[ i ] =  v;    // L channel
    src.R[ i ] =  v;    // R channel
  }

  save( "wave_sine_st_8bit.wav", src, 8 );  // 8ビットフォーマット
//  save( "wave_sine_st_16bit.wav", src );    // 16ビットフォーマット(デフォルト)
}


WAVファイルのビット深度はsave関数の第3引数に8を指定します。16ビットで書き出すには第3引数を省略するか16を指定します。

wave<float>とか書くのが面倒であれば、次のエイリアスが使えます。

wave_d ---- wave<double>
wave_f ---- wave<float>
wave_i ---- wave<int>
wave_s ---- wave<short>
wave_c ---- wave<char>
wave_uc ---- wave<unsigned char>


 トレモロエフェクト 

最後に簡単なサウンドエフェクトのトレモロ効果を作ってみます。WAVデータを読み込んでトレモロ効果を加えてから、WAVファイルへ書き出すプログラムです。

tremolo.cpp

#include  "wave.hpp"
#include  <cmath>

main()
{
  wave_f  src;

  load( "_aruhinokuregatanokotodearu.wav", src ); // ファイルから読み込み

  wave_f  dst( src.fs, src.length );              // 出力データの入れ物

  float   freq = 1.f;                             // 周波数
  float   t = (2.f*M_PI) / src.fs * freq;

  for( auto i( 0 ); i < src.length; ++i )
  {
    dst[ i ] = src[ i ] * sin( t * i );           // トレモロ効果
  }

  save( "toremolo.wav", dst );                    // ファイルへ書き出し
}



 C/C++ビルド用スクリプト 

最後にMinGWコンソールでC/C++プログラムをコンパイルする時のスクリプトを紹介します。ふつうC/C++プログラムをコンパイルするには


$gcc helllo.c


または

$g++ hello.cpp


といった感じでやります、これだと出力ファイル名がa.exeという名前になってしまいます。これでは使いづらいので、buildという拡張子無しのファイルを作って以下の内容をコピーします。

build

#!/bin/bash

path=$1
#echo "path: $path"

basename=${path##*/}
#echo "basename: $basename"

filename=${basename%.*}
#echo "filename: $filename"

extension=${basename##*.}
#echo "extension: $extension"

g++ $1 $2 $3 $4 $5 $6 $7 $8 $9 -o $filename


MinGWコンソールで


$build helllo.c
または
$build helllo.cpp


これで出力ファイル名とソースファイル名が一致します。21世紀にもなってこんなこと、いちいちユーザーに書かせるな!って感じですが、Linuxの人達はこうゆうこのが萌えらしいです。文化の違いなんでしょう。

よく使うオプションやソースコードはbuildスクリプトに書き込んでいけば良いので、小規模構成のプログラムならわざわざmakefileを書くまでもなく、これだけで間に合います。

コメント

このブログの人気の投稿

中国製ゲルマニウムトランジスタ

Aliexpressで購入したゲルマニウムトランジスタです。AC128のセカンドソース(らしきものw)です。最近の安い中華ゲルマエフェクターで使われているようです。10個で送料込み¥1000くらいでした。そもそもCANタイプのトランジスタは現行品でも高いので1個¥100ならお買い得でしょうか。 テスターでhfeを測定した結果 20,36,34,37,40,67,149,190,214,216, かなりのバラつき具合です。hfeが高いのも欲しかったので丁度良かったのですが・・・ 20とかは動くんでしょうか?

Blue Pill FX Projects~デジタルディレイ~

■$2の格安マイコンボードBlue Pill STM32を使って、E.ギター用のデジタルディレイを作りました。 モノラル-シングルエフェクトです。ノーマルディレイ、アナログディレイ、リバースディレイのどれか1つをトグルスイッチで切り替えられます。 ・最長ディレイタイム        ・ノーマルモード : 425ms (周波数特性:7kHz)       ・アナログモード : 800ms (周波数特性:1.5kHz)       ・リバースモード : 420ms (周波数特性:7kHz) ・消費電力 DC9V 55mA 音は普通のディレイです。ノーマルモードの周波数特性が7kHz(-6db)なのでBBDやPT2399よりはクリアな音です。S/NはPT2399ディレイと同じくらいです。 このデジタルエフェクターに使用した小型のマイコンボードです。海外のホビーマイコンユーザーの間でBlue Pill(青い錠剤)と呼ばれているものです。大きさ23mm x 55mmの基板でエフェクターケース(1590B/TD6-11-3)に余裕で入ります。Aliexpressなら$2(+送料)で手に入ります。日本国内ではAmazonやaitendoで取り扱いがあります。米国ではebayで見つかります。"STM32F103C8T6"で検索します。  マイコンボード のスペック   ■STMicroelectronics製STM32F103C8T6(Cortex-M3 32ビットARMマイコン) ■動作クロック 72MHz ■プログラムFlash 64k ■SRAM 20k ■ADC 12ビット 2系統 ■DACなし このMCUにはDACが内蔵されていません。そこでDual PWM DACという方法でアナログ信号を出力しています。疑似DACといったところでしょうか。2本の抵抗と1個のコンデンサでデジタル信号をアナログ信号へ変換する面白い回路です。 あと、このマイコンボードの他にプログラムを書き込む為のプログラムライターが必要になりますが、詳しくは別の記事で書いているので参照してください。プログラムライターもAliexpressでなら$2程度で入手できます。

Blue Pillマイコンボードへプログラムを書き込む (1)

 STM32CubeProgremmer  Blue Pillマイコンボードへブログラムを書き込むためには、まず書き込み用のソフトウェアが必要です。今回はSTマイクロ社の純正ソフトウェアSTM32CubeProgremmerを使います。このソフトウェアはSTマイクロ社のサイトからダウンロードできますが、ダウンロードする前にユーザー登録が必要になります。登録は無料です。利用についても全く無料ですが、ユーザー登録するとその後にちょこちょこと広告メールが送られてくるようになります。それが嫌な方は各自で対処してください。本音をいえばこの程度のソフトウェアはユーザー登録なしで公開して欲しいです。ちなみにフリーウェアではstm32flashというソフトウェアがあるのですが、今のところwin64版しかありません。 STM32CubeProgremmerのインストールは指示に従って行えば特に問題はないと思います。  プログラムの書き込む手順  Blue Pillマイコンボードのジャンパー設定をプログラム書き込みモードへ変更します。 USBシリアルモジュールとBlue Pillマイコンボードをケーブルで配線して、USBシリアルモジュールをパソコンと接続します。 STM32CubeProgrammerを起動してUARTとPortを設定します。 ・Prot番号(COM番号)はパソコンが自動で割り振るので上のスクショと同じ番号にはならないと思います。 ・パソコンでCOMポートを複数使用している場合は、ドロップダウンリストでPort番号を変更してください。 ・Portに"No COM...(No COM Detected)"と表示される場合は、USBシリアルモジュールがパソコンから認識されていないので、ドライバをインストールしてください。 ※充電専用のUSBケーブルは使用できません。100均で買ったUSBケーブルを使っている方は要注意です。 次にBlue Pillマイコンボードのリセットボタンを押してから、STM32CubeProgrammerのConnectボタンを押します。UART接続ではConnect(接続)ボタンを押す直前にマイコンボードのリセットするという約束があるので