visual - La mejor manera de reproducir sonidos MIDI usando C#
reproducir sonidos en c (9)
Estoy trabajando en una aplicación C # MIDI en este momento, y los demás tienen razón, necesita usar p / invoke para esto. Estoy rodando el mío, ya que parecía más apropiado para la aplicación (solo necesito un pequeño subconjunto de la funcionalidad MIDI), pero para tus propósitos, C # MIDI Toolkit podría ser una mejor opción. Es al menos la mejor biblioteca .NET MIDI que encontré, y busqué extensamente antes de comenzar el proyecto.
Estoy intentando reconstruir una aplicación antigua de metrónomo que se escribió originalmente usando MFC
en C ++ para que se escriba en .NET
usando C#
. Uno de los problemas con los que me estoy enfrentando es reproducir los archivos midi que se utilizan para representar los "clics" del metrónomo.
He encontrado algunos artículos en línea sobre la reproducción de MIDI
en .NET, pero la mayoría de ellos parecen depender de bibliotecas personalizadas que alguien ha improvisado y puesto a disposición. No soy reacio a usar estos, pero prefiero entender por mí mismo cómo se hace esto, ya que parece que debería ser un ejercicio en su mayoría trivial.
Entonces, ¿me estoy perdiendo algo? ¿O es simplemente difícil usar MIDI dentro de una aplicación .NET?
No puedo afirmar que sé mucho al respecto, pero no creo que sea tan sencillo: a Carl Franklin de la fama de DotNetRocks le ha ido bien, ¿has visto su DNRTV ?
System.Media. SoundPlayer es una buena y sencilla forma de reproducir archivos WAV. Los archivos WAV tienen algunas ventajas sobre MIDI, uno de ellos es que puedes controlar con precisión cómo suena cada instrumento (en lugar de confiar en el sintetizador incorporado de la computadora).
Puedes usar el reproductor multimedia:
using WMPLib;
//...
WindowsMediaPlayer wmp = new WindowsMediaPlayer();
wmp.URL = Path.Combine(Application.StartupPath ,"Resources/mymidi1.mid");
wmp.controls.play();
Una adición reciente es MIDI.NET que admite Midi Ports, Midi Files y SysEx.
Creo que deberás invocar p / invoke a la API de Windows para poder reproducir archivos midi de .net.
Este artículo del proyecto de código hace un buen trabajo al explicar cómo hacer esto: artículo de vb.net para reproducir archivos midi
Para volver a escribir esto es c # necesitaría la siguiente instrucción de importación para mciSendString:
[DllImport("winmm.dll")]
static extern Int32 mciSendString(String command, StringBuilder buffer,
Int32 bufferSize, IntPtr hwndCallback);
¡Espero que esto ayude, buena suerte!
midi-dot-net me puso en funcionamiento en minutos, liviano y del tamaño adecuado para mi proyecto hogareño. También está disponible en GitHub . (No debe confundirse con el MIDI.NET mencionado anteriormente, que también parece prometedor, pero nunca lo hice).
Por supuesto, NAudio (también mencionado anteriormente) tiene toneladas de capacidad, pero al igual que el póster original solo quería tocar algunas notas y leer y entender rápidamente el código fuente.
Lo siento, esta pregunta ya es un poco vieja, pero lo siguiente funcionó para mí (algo copiado de Win32 - Midi looping with 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());
}
Aquí se proporciona una lista completa de las cadenas de comandos. Lo bueno de esto es que puedes usar diferentes cosas además del secuenciador para tocar cosas diferentes , por ejemplo, waveaudio para reproducir archivos .wav. Sin embargo, no puedo imaginar cómo hacer que funcione .mp3.
Además, tenga en cuenta que los comandos de detención y cierre deben enviarse en el mismo subproceso en el que se enviaron los comandos abrir y reproducir; de lo contrario, no tendrán efecto y el archivo permanecerá abierto. Por ejemplo:
[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);
}