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.AudioFCPCMの入力のためにInPCMクラスを作りました。このクラスは、WaveInを使用しています。また、データの授受には、PcmInBufferクラスが使われています。 データのコピー回数を減らすことが目的です。 また、このプログラムは、FFTを行うので、FFTクラス、FFT3クラス、Complexクラスを使用しています。 5.再生5.1.SamplePlayerWAVEファイルを読み込むために、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() に、変更します。 |