Suara midi-dot-net diputar dua kali

Pertama, saya bukan seorang programmer PRO tetapi hanya seorang pelajar yang memiliki sedikit masalah dengan perpustakaan Midi-Dot-Net yang unggul.

Saya menggunakan perpustakaan Midi-Dot-Net untuk menulis aplikasi sederhana di Visual Studio dalam bahasa C#. Tapi saya terjebak pada masalah yang sangat membingungkan.

Saya menempatkan sedikit kode ke dalam Form1.cs

public void NoteOn(NoteOnMessage msg) {
    if (InvokeRequired) {
        BeginInvoke(noteOnHandler, msg);
        return;
    }

     inputStatusLabel.Text = String.Format("{0}", msg.Pitch);
     String nutka = inputStatusLabel.Text;

    if (nutka == "A0") {
        clock.Schedule(new NoteOnMessage(outputDevice, Channel.Channel1, Pitch.A0, 80, 2));
    }
}

Jadi, saya menempatkan String baru dan menamainya nutka, dan nutka akan menerima nama not yang ditekan di Keyboard USB MIDI saya. Kemudian saya menempatkan pernyataan IF, dan membandingkan nutka dengan "A0" (not pertama di keyboard).

Lalu jika "A0" saya menekan outputDevice saya memainkan nada tertentu. Dan itu diputar tetapi diputar dua kali, satu - saat saya menekan tombol (dengan catatan A0) pada keyboard dan kedua kalinya - saat saya melepaskan tombol itu.

Saya melakukan breakpoint pada public void NoteOn(NoteOnMessage msg) dan memperhatikan bahwa aplikasi kembali ke sini dua kali dan memutar nada itu dua kali, masih tidak tahu alasannya.

Satu lagi, ada metode public void NoteOff(NoteOffMessage message), tapi sepertinya tidak berhasil.

Saya benar-benar tidak dapat memahaminya, dan saya sedang mencari bantuan.

PEMBARUAN ... PERBARUI ... PEMBARUAN

Masalah lain muncul (bagian pertama terselesaikan berkat saran CL dan Chris Dunaway serta penjelasan Justin langkah demi langkah).

Terima kasih Justin :) saya melihat hidup tanpa masalah tidak mungkin :)

Dengan clock.Schedule saya hanya dapat memainkan suara MIDI tetapi saya ingin memainkan contoh not piano (format file wav) dan dalam 4-5 minggu kampus saya akan membantu saya merekam suara piano saya sendiri untuk setiap not. Saya juga ingin memainkannya secara bersamaan.

Saya pikir semuanya akan baik-baik saja dan sekarang... ada masalah dengan bermain secara bersamaan. Saya mencoba memeriksa tiga kemungkinan:

1) Saya mencoba memainkan suara piano dari perpustakaan nada dasar yang saya miliki dan menggunakan SoundPlayer untuk itu:

SoundPlayer noteA0 = new SoundPlayer(Properties.Resources.A0);
noteA0.Play();

saya menggunakannya untuk setiap pernyataan nada dengan nama SoundPlayer yang berbeda (tergantung pada nama nada) dan yang saya perhatikan adalah - saya tidak dapat memutar nada secara bersamaan.

2) jadi saya menggunakan perpustakaan WMP dan WindowsMediaPlayer berikutnya:

Misalnya:

var noteA0 = new WMPLib.WindowsMediaPlayer();
noteA0.URL = @"c:\sounds\piano\A0.wav";

Oke... ini diputar secara bersamaan tetapi sepertinya semakin banyak nada yang saya mainkan atau saya hanya memutar sebuah lagu, semakin besar latensi yang saya dapatkan dan akhirnya program saya macet saat memainkan apa pun...

3) saya mencoba menggunakan Microsoft.DirectX.AudioVideoPlayback:

Audio noteA1 = new Audio(@"C:\sounds\piano\A1.wav");
noteA1.Play();

saya memulai program saya, menekan tombol dan boom! mogok dengan pesan kesalahan:

An unhandled exception of type 'System.BadImageFormatException' occurred in Midi.dll
Additional information: Could not load file or assembly 'Microsoft.DirectX.AudioVideoPlayback.dll' or one of its dependencies. 
It is not a valid Win32 application. (Exception from HRESULT: 0x800700C1)

Tentu saja saya tidak lupa menggunakan:

using System.Media;
using Microsoft.DirectX.AudioVideoPlayback;
using Microsoft.DirectX;

Saat ini saya tidak tahu apa yang bisa saya lakukan lagi dan lagi - saya butuh bantuan orang yang berpengalaman :)


person Martin    schedule 19.06.2015    source sumber
comment
Saya tidak mengerti bagian Invoke, bukankah sebaiknya Anda memanggil NoteOn? Apa itu noteOnHandler? Bagaimana cara menelepon NoteOn? Dari mana?   -  person Sinatr    schedule 19.06.2015
comment
Ada sumber lengkap yang saya gunakan: link Saya mengedit form1.cs dan proyeknya bergantung pada folder Midi yang juga ditempatkan di tautan di atas.   -  person Martin    schedule 19.06.2015
comment
Program yang sedang Anda edit mengharapkan pengguna untuk menekan tombol play pada Form windows. Dengan menggunakan keyboard midi, Anda secara efektif memainkan not tersebut tetapi juga mengirimkan acara ke metode NoteOn, yang kemudian memicu not kedua saat Anda memanggil clock.Schedule. Singkatnya, program yang Anda edit mungkin bukan titik awal yang tepat untuk apa yang ingin Anda capai.   -  person Paul    schedule 19.06.2015
comment
Bolehkah saya meminta bantuan Paul dengan kode saat ini? Bisakah Anda menunjukkan kepada saya hubungan antara 1) saya menekan tombol midi eksternal dan 2) playButton_click ? Mencoba memahami kodenya, tetapi tidak dapat menemukan koneksi yang menggandakan suara   -  person Martin    schedule 19.06.2015


Jawaban (2)


Memperluas jawaban CL., berikut adalah urutan peristiwa yang mungkin terjadi:

  1. Anda menekan tombol pada keyboard MIDI Anda yang mengirimkan Note On message, with a Pitch of A0, and a velocity (kecepatan pastinya dapat bervariasi setiap saat).
  2. Kode Anda menerima ini dan, karena cocok dengan pernyataan if Anda, mengirimkan Note On message, with a pitch of A0, and a velocity of 80.

Di sinilah hal itu menjadi rumit. Beberapa perangkat MIDI mengirimkan pesan Note Off yang sesuai dengan Pitch yang sama saat Anda melepaskan kunci. Perangkat lain akan mengirimkan pesan Note On kedua dengan Pitch yang sama, namun dengan Kecepatan 0. Kedua jenis pesan ini (atau seharusnya) secara fungsional setara, dan masing-masing perangkat dapat menghentikan pemutaran not (atau bahkan keduanya) . Jadi,

  1. Anda melepaskan tombol pada keyboard Anda yang mengirimkan Note On message, with a Pitch of A0, and a Velocity of 0.
  2. Kode Anda menerima ini dan, karena juga cocok dengan pernyataan if Anda, mengirimkan Note On message, with a pich of A0, and a velocity of 80.

Karena Note On dengan Kecepatan 0 juga merupakan Note Off, yang terjadi adalah kode Anda mengubah "Note Off" keyboard Anda kembali menjadi Note On, sehingga memutar suaranya dua kali.

Seperti yang Chris Dunaway, Anda perlu menentukan apakah Note On adalah sebenarnya adalah "Note Off" dengan menguji Kecepatan 0.

    if (nutka == "A0" && msg.Velocity != 0) {
        clock.Schedule(new NoteOnMessage(outputDevice, Channel.Channel1, Pitch.A0, 80, 2));
    }
person Justin Ryan    schedule 19.06.2015
comment
Saya ingin mengucapkan terima kasih kepada kalian semua dan CL atas spesifikasinya! Tapi Dear Justin, saya ingin mengucapkan terima kasih yang tulus! Anda menjelaskan kepada saya dengan tepat dan sangat rinci masalah saya dan Anda memperbaikinya dengan luar biasa. Sekarang saya mengerti langkah demi langkah mengapa suara itu diputar dua kali dan terima kasih kepada Anda sekarang saya bisa mengatasinya. Senang sekali ada orang yang memiliki ilmu praktis yang luar biasa dan mereka membaginya dengan pemula seperti saya :) - person Martin; 22.06.2015
comment
Apakah mungkin memutar suara dari Sumber Daya dengan menggunakan jam.Jadwal? - person Martin; 26.06.2015
comment
@Martin Maaf, saya tidak begitu mengerti apa yang ingin Anda lakukan. Silakan kirimkan pertanyaan lain dengan semua detail masalah baru Anda, dan beri tag sebagai [midi]. - person Justin Ryan; 26.06.2015

Spesifikasi Rinci MIDI 1.0 mengatakan:

MIDI menyediakan dua cara yang kira-kira setara untuk mematikan nada (suara). Sebuah not dapat dimatikan dengan mengirimkan pesan Note-Off untuk nomor not dan saluran yang sama, atau dengan mengirimkan pesan Note-On untuk not dan saluran tersebut dengan nilai kecepatan nol. Keuntungan menggunakan "Note-On dengan kecepatan nol" adalah dapat menghindari pengiriman byte status tambahan saat Status Berjalan digunakan.

Karena efisiensi ini, pengiriman pesan Note-On dengan nilai kecepatan nol adalah metode yang paling umum digunakan. Namun, beberapa instrumen keyboard menerapkan kecepatan pelepasan yang menggunakan kode Note-Off (8nH) yang disertai dengan byte "kecepatan mati". Penerima harus mampu mengenali metode mematikan not, dan harus memperlakukannya dengan cara yang sama.

person CL.    schedule 19.06.2015
comment
masih belum bisa memahaminya, sayangnya pikiran saya tidak logis :( butuh bantuan :) - person Martin; 19.06.2015
comment
@Martin - Saya pikir Anda perlu memeriksa msg.Velocity dalam metode NoteOn Anda dan jika Kecepatannya 0 maka itu adalah catatan (jika saya memahami apa yang diposting CL). - person Chris Dunaway; 19.06.2015