سؤال

أحاول إعادة بناء تطبيق بندول الإيقاع القديم الذي تمت كتابته في الأصل باستخدام MFC في C++ ليتم كتابتها .NET استخدام C#.إحدى المشكلات التي أواجهها هي تشغيل ملفات midi المستخدمة لتمثيل "نقرات" بندول الإيقاع.

لقد وجدت بعض المقالات عبر الإنترنت حول اللعب MIDI في .NET، ولكن يبدو أن معظمها يعتمد على مكتبات مخصصة قام شخص ما بتجميعها وإتاحتها.أنا لا أكره استخدام هذه الأشياء، لكنني أفضل أن أفهم بنفسي كيف يتم ذلك، لأنه يبدو كذلك يجب تكون ممارسة تافهة في الغالب.

إذن، هل أفتقد شيئًا ما؟أم أنه من الصعب استخدام MIDI داخل تطبيق .NET؟

هل كانت مفيدة؟

المحلول

أعتقد أنك ستحتاج إلى p/استدعاء واجهة برمجة تطبيقات Windows لتتمكن من تشغيل ملفات midi من .net.

تقوم مقالة مشروع الكود هذه بعمل جيد في شرح كيفية القيام بذلك:مقالة vb.net لتشغيل ملفات midi

لإعادة كتابة هذا في c#، ستحتاج إلى عبارة الاستيراد التالية لـ mciSendString:

[DllImport("winmm.dll")] 
static extern Int32 mciSendString(String command, StringBuilder buffer, 
                                  Int32 bufferSize, IntPtr hwndCallback);

آمل أن يساعد هذا - حظا سعيدا!

نصائح أخرى

أنا أعمل على تطبيق C# MIDI في الوقت الحالي، والآخرون على حق - تحتاج إلى استخدام p/invocation لهذا الغرض.أنا أقوم بطرح خاصيتي لأن ذلك يبدو أكثر ملاءمة للتطبيق (أحتاج فقط إلى مجموعة فرعية صغيرة من وظائف MIDI)، ولكن لأغراضك مجموعة أدوات C# MIDI قد يكون مناسبا بشكل أفضل.إنها على الأقل أفضل مكتبة .NET MIDI وجدتها، وقد بحثت فيها بشكل مكثف قبل بدء المشروع.

ميدي دوت نت جعلني جاهزًا للعمل في دقائق - خفيف الوزن وحجم مناسب لمشروع منزلي.إنه متاح أيضًا على جيثب.(لا ينبغي الخلط بينه وبين ما سبق ذكره MIDI.NET, ، والذي يبدو أيضًا واعدًا، لكنني لم أتمكن من ذلك مطلقًا.)

بالطبع ناوديو (المذكور أعلاه أيضًا) لديه الكثير من الإمكانات، ولكن مثل الملصق الأصلي، أردت فقط تشغيل بعض الملاحظات وقراءة كود المصدر وفهمه بسرعة.

لا أستطيع أن أدعي أنني أعرف الكثير عن ذلك، لكنني لا أعتقد أن الأمر بهذه البساطة. - كارل فرانكلين من دوت نت روكس لقد فعلت الشهرة الكثير معها - هل رأيت ذلك؟ DNRTV الخاص به?

يمكنك استخدام مشغل الوسائط:

using WMPLib;
//...
WindowsMediaPlayer wmp = new WindowsMediaPlayer();
wmp.URL = Path.Combine(Application.StartupPath ,"Resources/mymidi1.mid");
wmp.controls.play();

بالنسبة لمعالجة MIDI والموجة واسعة النطاق في .NET، أعتقد ذلك ناوديو هو الحل (متوفر أيضًا عبر نوجيت).

إضافة حديثة هي MIDI.NET يدعم منافذ Midi وملفات Midi وSysEx.

System.Media.مشغل الصوت هي طريقة جيدة وبسيطة لتشغيل ملفات WAV.تتمتع ملفات WAV ببعض المزايا مقارنة بملفات MIDI، أحدها هو أنه يمكنك التحكم بدقة في صوت كل أداة (بدلاً من الاعتماد على آلة النطق المدمجة في الكمبيوتر).

آسف، هذا السؤال قديم بعض الشيء الآن، ولكن ما يلي كان مفيدًا بالنسبة لي (تم نسخه إلى حد ما من Win32 - حلقات Midi باستخدام MCISendString):

[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());
}

يتم إعطاء قائمة كاملة بسلاسل الأوامر هنا.الجزء الرائع في هذا هو أنه يمكنك فقط استخدام أشياء مختلفة إلى جانب جهاز التسلسل للعب أشياء مختلفة, ، قل waveaudio لتشغيل ملفات wav.لا أستطيع معرفة كيفية تشغيله بصيغة mp3 بالرغم من ذلك.

لاحظ أيضًا أنه يجب إرسال أمر الإيقاف والإغلاق على نفس الموضوع الذي تم إرسال أمري الفتح والتشغيل عليه، وإلا فلن يكون لهما أي تأثير وسيظل الملف مفتوحًا.على سبيل المثال:

[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/atsushieno/managed-midi

https://www.nuget.org/packages/managed-midi/

ليس هناك الكثير من التوثيق، ولكن أحد محاور هذه المكتبة هو الدعم عبر الأنظمة الأساسية.

أعتقد أنه من الأفضل استخدام بعض المكتبات التي تحتوي على ميزات متقدمة لتشغيل بيانات MIDI بدلاً من تنفيذها بنفسك.على سبيل المثال، مع جافرطبMIDI لتشغيل ملف MIDI عبر المُركِّب الافتراضي (مايكروسوفت GS Wavetable المركب):

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();
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top