PCM入出力DLL(WaveIO2.DLL)
簡単WAVE録音再生DLL(WaveIO2.DLL)
Wave録音・再生.NETアセンブリ
前述の、音の周波数測定プログラムを、サンプルに加え、Studio C# 2008 Expressのプロジェクトとして扱えるようにしました。
まことに勝手ながら、旧版とは無縁なものになってしまいました。
http://www.vector.co.jp/soft/winnt/prog/se341363.html
1.ファイル構成
AudioFC.exe -------------- 音の周波数測定サンプルの実行形式
SamplePlayer.exe --------- WAVファイルの再生のサンプル
SampleRecorder.exe ------- WAVファイルの録音のサンプル
WaveDevs.exe ------------- デバイス列挙機能のサンプル
MusicalScale.exe --------- 音階をサイン波の純音で鳴らすサンプル
MusicalVoice.exe --------- 音程測定のサンプル
TestCtrl1.exe ------------ グラフィカルにマイク入力の状態を表示するサンプル
SlowVoice.exe ------------ 入出力をリアルタイムに。ゆっくり再生。無音検出のサンプル
WaveSpeedCCF.exe --------- WAVファイルの再生時間を伸縮するサンプル
WaveIO2.dll -------------- WAVE入出力用のダイナミックリンクライブラリ
ClassLibrarySub3.dll ----- 共通部分をまとめました。
source ------------------- 以下、上記サンプルのVisual Studio C# 2008 Expressのプロジェクト
2.概要
MMSYSTEM.Hで宣言されている、waveIn...、waveOut...の関数を使ってPCMの入出力をします。
また、RIFF形式のWAVEファイルの読み書きをします。
PCMは、符号付の16ビットサンプルに限られます。
3.DLLの使い方
1.任意の場所に、WaveIO2.dll、ClassLibrarySub3.dllをコピーします。
2.プロジェクトを開いて、「ソリューションエクスプローラ」の「参照設定」を
選択します。左ボタンメニューから「参照の追加」を選びます。
3.「参照の追加」ダイアログが表示されるので、「参照」タブを選択します。
WaveIO2.dll、ClassLibrarySub3.dllの格納ディレクトリ、ファイルを選択して、「OK」をクリックし
ます。
4.WaveIO2.dll、ClassLibrarySub3.dllを、使用するプログラムには、以下のusing宣言を加えてください。
using LIB;
using MMSYSTEM;
using RIFF;
5.添付のサンプルを見ていただいてご利用ください。
インテリセンスで、ある程度はドキュメントの代わりをすると思います。
1)再生
・Formクラスのメソッドの追加位置にカーソルを合わせ、overrideと
打ち込むと、可能なメソッドの一覧が表示されます。最後ある、WinProcを
選択します。WinProc()メソッドが追加されます。
・ここに、MM_WOM_DONEの処理を書きます。サンプルでは、ファイルから
データを読み込んで、バッファにセットしています。
2)録音
・Formクラスに、IPCMRecorderの継承を宣言してください。
public partial class Form1 : Form , IPCMRecorder
{
・IPCMRecorderにカーソルをセットし、「編集」「Intellisense」
「インタフェースの追加」とすると、メソッドが追加されます。
・追加されたメソッドは、PCMデータをファイルに書き込んでいます。
4.録音
4.1.SampleRecorder
PCMの入力には、PCMRecorderクラス、IPCMRecorderクラスを使用しています。WAVEファイルの書き込みには、WavWriterクラスを使用しています。
4.2.AudioFC
PCMの入力のためにInPCMクラスを作りました。このクラスは、WaveInを使用しています。また、データの授受には、PcmInBufferクラスが使われています。
データのコピー回数を減らすことが目的です。
また、このプログラムは、FFTを行うので、FFTクラス、FFT3クラス、Complexクラスを使用しています。
5.再生
5.1.SamplePlayer
WAVEファイルを読み込むために、WaveReaderクラスを使用します。また、RIFFファイルの参照に、GetChunksクラス、Chunkクラスが使われます。PCMの再生には、PCMPlayerクラスを使います。Formクラスが、MM_WOM_DONEを受信したときに、PcmOutBufferクラスで再生データを渡します。
6.デバイス列挙
WinMMHelperクラスのメンバを使用しています。データの構造の定義は、MMSYSTEMクラスにあります。
7.主要なクラスの説明
クラスとメンバは、下図のように、インテリセンスが機能するので個別の説明はしません。
■ PCMRecorderクラス、IPCMRecorderクラス
PCMRecorderは、CALLBACKを使用してデバイスからPCMデータを受信します。このデータをアプリケーションに渡すために、IPCMRecorderを使用します。FormでIPCMRecorderを継承し、インタフェースを実装すると、CALLBACKから、そのインタフェースが呼び出されるようになります。
■PCMPlayerクラス 、PcmOutBufferクラス
PCMPlayerクラス は、再生完了通知(MM_WOM_DONE)をWindowsメッセージで通知するようにします。この通知は、複数あるバッファのそれぞれが再生された後で送られます。Formクラスで、WinProc()をoverrideして、このメッセージを処理します。処理は、続きのPCMデータを、完了したバッファに再設定することです。
WinProc()の引き数のm.LParamがwavehdrを示します。ここから、PcmOutBufferを取得します。PcmOutBufferのWrite()で、このバッファにデータがセットされ、再度再生に使われます。
■GetChunks、Chunk
.wavファイルは、RIFF形式です。この形式では、データはChunkと呼ばれるブロック単位に格納されています。Chunkクラスは、Chunkの名前、ファイル中の位置、サイズを保持します。GetChunks.Chunks()は、ファイルの先頭から、指定の範囲でChunkを探して列挙します。このうち、"fmt "、"data"の名前を持つChunkを使用します。前者は、WAVEFORMATEXと同じ内容で、サンプリングレートなどを含んでいます。後者のChunkは、PCMデータそのものです。
また、ファイル形式が正しいかのチェックも行われます。
■FFT
FFT.fft()は、入力が2の整数乗個に限られます。出力は、入力の半分の個数のComplexになります。入力値は、内部で個数で割られるので、サンプリングされたデータをそのまま渡します。ただし、Complex[]を受けtるメソッドは、個数で割る処理をしません。今回、2つの整数配列を引き数に持つメソッドを追加しました。これは、2面のバッファをシフトして使っていて、内容をコピーせずに渡したいと考えたものです。
このメソッドは、staticで、テーブルを使っていません。
■FFT2
サンプル数に制限の無いFFTです。2,3,4,5,その他の混合基数です。サンプル数で割りません。出力は、入力の半分の個数のComplexになります。
■FFT3
入力が2の整数乗個に限られます。出力は、指定範囲の個数のComplexになります。入力値は、内部で個数で割られるので、サンプリングされたデータをそのまま渡します。ただし、Complex[]を受けtるメソッドは、個数で割る処理をしません。
このFFTは、staticではなく、FFT3クラスをコンストラクトした上で使います。サンプル数と、FFTの結果(0からサンプル数/2-1)の範囲を指定します。この条件で、予めテーブルを用意します。途中で、算出範囲を変更する場合は、ReCalcPair()を呼びます。
■HSB
計算値を色で表示するのは、私にはなかなか難しいです。色の性質を知らないと、RGBの各値をどうすれば連続的に変化させられるのかわかりません。そこで、HSBカラーを使います。角度で色を連続的に指定できます。簡単チャート(ChartCtrl)のサンプルで使っています。
5/27 2008
「音声再生速度変換プログラム」に書いたプログラムをサンプルに加えて差し替え依頼しました。
WaveIO2_1_5.zip
5/21 2008
FFTの逆変換のデバッグで気が付きました。FFTから戻ると、入力が書き換えられています。そのうち、呼び出し元へ影響しないようにしたいと思います。
5/15 2008
FFT2の結果がN/2+1になってます。いずれN/2にします。
5/13 2008
大きなサンプルの部分的なFFTを使って、AudioFCを書き直しました。その他の、サンプルプログラムの、おかしなところも直しました。MusicalScale.exeは、音階の各音のなる時間を2秒にして、AudioFCで表示できるようにしてあります。また、音名の表記を、ドイツ表記から国際式に変えました。DLLを目的に応じて分離しました。
4/7 2008
このページを書きながら気が付きました。どのサンプルも、タイトルバーが「WaveIO2」になっています。
デバック中は、一緒にリンクしていたのを、DLLに分離したことによります。今回の差し替え完了通知が来たら、差し替えます。
Assembly.GetExecutingAssembly()
で、取得していたアプリケーションの名前を
Assembly.GetEntryAssembly()
に、変更します。 |