mikeo_410


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()
に、変更します。


mikeo_410@hotmail.com