質問
元々は次を使用して書かれた古いメトロノーム アプリケーションを再構築しようとしています。 MFC
C++ で記述する .NET
を使用して C#
. 。私が直面している問題の 1 つは、メトロノームの「クリック」を表すために使用される MIDI ファイルの再生です。
プレイに関するオンライン記事をいくつか見つけました MIDI
.NET では使用できますが、そのほとんどは、誰かがまとめて利用できるようにしたカスタム ライブラリに依存しているようです。私はこれらを使用することに抵抗はありませんが、これがどのように行われているかを自分で理解したいと思っています。 すべき ほとんど簡単な練習になります。
それで、私は何かを見逃していますか?それとも、.NET アプリケーション内で MIDI を使用するのが難しいだけなのでしょうか?
解決
.net から MIDI ファイルを再生できるようにするには、Windows API を p/invoke する必要があると思います。
このコードプロジェクトの記事では、これを行う方法について説明しています。MIDI ファイルを再生するための vb.net の記事
これを C# で書き直すには、mciSendString の次のインポート ステートメントが必要になります。
[DllImport("winmm.dll")]
static extern Int32 mciSendString(String command, StringBuilder buffer,
Int32 bufferSize, IntPtr hwndCallback);
これがお役に立てば幸いです - 頑張ってください!
他のヒント
私は現在 C# MIDI アプリケーションに取り組んでいますが、他のアプリケーションは正しいです。これには p/invoke を使用する必要があります。アプリケーションにより適していると思われるので、私は独自のものを作成しています(MIDI 機能の小さなサブセットのみが必要です)が、あなたの目的のために、 C# MIDI ツールキット の方が適しているかもしれません。これは、少なくとも私が見つけた最高の .NET MIDI ライブラリであり、プロジェクトを開始する前に徹底的に検索しました。
私はそれについて多くを知っているとは言えませんが、それがそれほど単純ではないと思います - カール・フランクリン ドットネットロックス 名声はそれでかなりのことを成し遂げました - 見たことがありますか 彼のDNRTV?
メディアプレーヤーを使用できます。
using WMPLib;
//...
WindowsMediaPlayer wmp = new WindowsMediaPlayer();
wmp.URL = Path.Combine(Application.StartupPath ,"Resources/mymidi1.mid");
wmp.controls.play();
最近追加されたのは、 MIDI.NET Midi ポート、Midi ファイル、SysEx をサポートします。
システム.メディア。サウンドプレーヤー は、WAV ファイルを再生する優れた簡単な方法です。WAV ファイルには MIDI に比べていくつかの利点があり、その 1 つは、(コンピューターの内蔵シンセサイザーに依存するのではなく) 各楽器のサウンドを正確に制御できることです。
申し訳ありませんが、この質問は少し古いですが、次の質問は私にとってはうまくいきました(からの一部をコピーしたものです) Win32 - MCISendString を使用した MIDI ループ):
[DllImport("winmm.dll")]
static extern Int32 mciSendString(String command, StringBuilder buffer, Int32 bufferSize, IntPtr hwndCallback);
public static void playMidi(String fileName, String alias)
{
mciSendString("open " + fileName + " type sequencer alias " + alias, new StringBuilder(), 0, new IntPtr());
mciSendString("play " + alias, new StringBuilder(), 0, new IntPtr());
}
public static void stopMidi(String alias)
{
mciSendString("stop " + alias, null, 0, new IntPtr());
mciSendString("close " + alias, null, 0, new IntPtr());
}
コマンド文字列の完全なリストが表示されます。 ここ. 。これのすごいところは、シーケンサー以外にもさまざまなものを使って演奏できることです。 異なるもの, 、.wav ファイルを再生する場合は waveaudio とします。ただし、.mp3 を再生する方法がわかりません。
また、stop コマンドと close コマンドは、open コマンドと play コマンドが送信されたのと同じスレッドで送信する必要があることに注意してください。そうしないと、それらのコマンドは効果がなく、ファイルは開いたままになります。例えば:
[DllImport("winmm.dll")]
static extern Int32 mciSendString(String command, StringBuilder buffer,
Int32 bufferSize, IntPtr hwndCallback);
public static Dictionary<String, bool> playingMidi = new Dictionary<String, bool>();
public static void PlayMidi(String fileName, String alias)
{
if (playingMidi.ContainsKey(alias))
throw new Exception("Midi with alias '" + alias + "' is already playing");
playingMidi.Add(alias, false);
Thread stoppingThread = new Thread(() => { StartAndStopMidiWithDelay(fileName, alias); });
stoppingThread.Start();
}
public static void StopMidiFromOtherThread(String alias)
{
if (!playingMidi.ContainsKey(alias))
return;
playingMidi[alias] = true;
}
public static bool isPlaying(String alias)
{
return playingMidi.ContainsKey(alias);
}
private static void StartAndStopMidiWithDelay(String fileName, String alias)
{
mciSendString("open " + fileName + " type sequencer alias " + alias, null, 0, new IntPtr());
mciSendString("play " + alias, null, 0, new IntPtr());
StringBuilder result = new StringBuilder(100);
mciSendString("set " + alias + " time format milliseconds", null, 0, new IntPtr());
mciSendString("status " + alias + " length", result, 100, new IntPtr());
int midiLengthInMilliseconds;
Int32.TryParse(result.ToString(), out midiLengthInMilliseconds);
Stopwatch timer = new Stopwatch();
timer.Start();
while(timer.ElapsedMilliseconds < midiLengthInMilliseconds && !playingMidi[alias])
{
}
timer.Stop();
StopMidi(alias);
}
private static void StopMidi(String alias)
{
if (!playingMidi.ContainsKey(alias))
throw new Exception("Midi with alias '" + alias + "' is already stopped");
// Execute calls to close and stop the player, on the same thread as the play and open calls
mciSendString("stop " + alias, null, 0, new IntPtr());
mciSendString("close " + alias, null, 0, new IntPtr());
playingMidi.Remove(alias);
}
新しいプレイヤーが登場します。
https://github.com/tsushieno/managed-midi
https://www.nuget.org/packages/managed-midi/
ドキュメントとしてはそれほど多くはありませんが、このライブラリの焦点の 1 つはクロスプラットフォームのサポートです。
MIDI データ再生のための高度な機能を備えたライブラリを自分で実装するよりも、使用する方がはるかに良いと思います。たとえば、 ドライウェットMIDI デフォルトのシンセサイザーを介して MIDI ファイルを再生するには (Microsoft GS ウェーブテーブル シンセ):
using Melanchall.DryWetMidi.Devices;
using Melanchall.DryWetMidi.Smf;
// ...
var midiFile = MidiFile.Read("Greatest song ever.mid");
using (var outputDevice = OutputDevice.GetByName("Microsoft GS Wavetable Synth"))
{
midiFile.Play(outputDevice);
}
Play
ファイル全体が再生されるまで呼び出しスレッドをブロックします。MIDI ファイルの再生を制御するには、次のファイルを取得します。 Playback
反対してそれを使用する Start
/Stop
メソッド (詳細については、 再生 図書館の記事 ウィキ):
var playback = midiFile.GetPlayback(outputDevice);
// You can even loop playback and speed it up
playback.Loop = true;
playback.Speed = 2.0;
playback.Start();
// ...
playback.Stop();
// ...
playback.Dispose();
outputDevice.Dispose();