オーディオ ストリームを録音する最適な方法を見つける必要があります。低レベルのコードは既に C++ で作成しており、その一部を C# にインターフェースしています。
だから私は浮動小数点数の配列の配列 - オーディオ信号 - を与える C++ コールバックを持っています。現時点では、私の C++ ライブラリは wav 形式でファイルに直接データを記録しており、記録が終了したときに C# アプリに通知するだけです。
しかし、UI 側でのインタラクティブ性、たとえば「無限」のプログレス バー、記録されるデータの量、キャンセル ボタンなどをもっと増やしたいと思っています。私は .NET と C# のメモリ管理についてほとんど知らないので、効率的に作成する方法がわかりません。
データを内部に配置して、後で配列のようにアクセスできる、C# に高速でサイズ変更可能なコンテナーはありますか?
また、波形イメージを作成したいと思います。私はすでにこれらのことをC++で行っていますが、どういうわけか、メッセージを書きすぎたり、オブジェクトを転送したりするという考えは好きではありません.
まとめると、次のようになります。
私はいくつかのことを行う C++ アンマネージ コールバックを持っており、データを処理したら C# メソッドを呼び出したいと思います。C プロトタイプは次のようになります。
void プロセス (float **signal, int n); (通常は [2][n] - ステレオ用)
C#に相当するものは何ですか?そのC++コールバックからどのように呼び出すのですか?
連続ストリームを書き込み ( mem.put(float[][] data, int size) など)、配列として、または他の簡単な方法で読み取るのに最適なクラスは何ですか (たとえば、そこから wav ファイルを保存するため、または波形ビットマップを作成します)
C# で実行すると、パフォーマンスが大幅に低下しますか? (C#関数などを呼び出すマネージC ++ラッパー...そしておそらくいくつかのDSPのもの)または私はただの偏執症ですか?:)
乾杯、
パブロックス
私の解決策
わかりました私はそれをそのように解決しました:
私のC++ヘッダーファイルでは、転送構造を取得しました:
public ref struct CVAudio {
public:
float *left;
float *right;
int length;
};
次に、マネージ C++ クラスで次のように宣言しました。
delegate void GetAudioData([In, Out] CVAudio^ audio);
次に、オーディオを初期化するメソッドへの引数として使用できます。
void initializeSoundSystem(void *HWnd, GetAudioData ^audio);
そのデリゲートには、次の C プロトタイプもあります。
typedef void (CALLBACK *GETAUDIODATA)(CVAudio ^a);
内部 C++ クラスで次のように使用されます。
void initializeSoundSystem(HWND HWnd, GETAUDIODATA audio);
次に、最初のメソッドの本体は次のとおりです。
void VDAudio::initializeSoundSystem(void *HWnd, GetAudioData ^audio)
{
HWND h = (HWND) HWnd;
acb = audio;
pin_ptr<GetAudioData ^> tmp = &audio;
IntPtr ip = Marshal::GetFunctionPointerForDelegate(audio);
GETAUDIODATA cb = static_cast<GETAUDIODATA>(ip.ToPointer());
audioObserver->initializeSoundSystem(h, cb);
}
audioObserver の本体は、そのコールバックをオブジェクトに格納し、オーディオ関連の処理を行うだけです。
コールバックは、次のように処理メソッドで呼び出されます。
VDAudio^ a = gcnew VDAudio();
a->left = VHOST->Master->getSample()[0]; //returns left channel float*
a->right = VHOST->Master->getSample()[1];
a->length = length;
(*callback)(a);
そして、C# デリゲートの本体:
public void GetSamples(CVAudio audio)
{
unsafe
{
float* l = (float*)audio.left;
float* r = (float*)audio.right;
if (l != null)
{
SamplePack sample = new SamplePack();
sample.left = new float[audio.length];
sample.right = new float[audio.length];
IntPtr lptr = new IntPtr((void*)l);
IntPtr rptr = new IntPtr((void*)r);
Marshal.Copy(lptr, sample.left, 0, audio.length);
Marshal.Copy(rptr, sample.right, 0, audio.length);
this.Dispatcher.Invoke(new Action(delegate()
{
GetSamples(sample);
}));
}
}
}
したがって、おそらくそれは最善のコードではありません-私にはわかりません。それが機能しているとしか言えず、漏れていないようです:)