Programación Secuanciador midi sencillo

synthetistjv
#1 por synthetistjv el 11/10/2011
Hola,

me gustaría realizar un mini proyecto de programación de un secuenciador de lo más sencillo
con el que poder realizar un proyecto de 16 pistas de instrumentos general midi.

Me gustaría saber que entorno es mejor para diseñar el software y que librerias son las que se
recomientan para poder realizar este tipo de tareas (Conexión de teclado maestro midi, control del volumen de cada pista, crear un piano roll).

Ojala me pudierais orientar :)

saludos.
Subir
synthetistjv
#2 por synthetistjv el 20/05/2013
Alguien sabe algo al respecto ? o.O gracias !
Subir
vagar
#3 por vagar el 21/05/2013
¿Qué quieres hacer exactamente? ¿Bajo qué sistema operativo quieres que funcione? Ten en cuenta que la programación multimedia es bastante complicada. Échale un vistazo al código fuente de proyectos opensource como seq24 o rosegarden.

http://www.filter24.org/seq24/
http://www.rosegardenmusic.com/
Subir
plastamix
#4 por plastamix el 02/06/2013
¿Secuenciador midi?

#include "stdafx.h"
#include "mmsystem.h"

struct evento
{
int momento;
char status;
char data1;
char data2;
}eventos[100] ;

HMIDIOUT outHandle;
int contador;
int n_evento;

LPTIMECALLBACK _stdcall timerProc(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
{
contador++;
if (contador==eventos[n_evento].momento)
{
midiOutShortMsg(outHandle, eventos[n_evento].data2 << 16 | eventos[n_evento].data1 << 8 | eventos[n_evento].status);
n_evento++;
}
return 0;
}

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
midiOutOpen(&outHandle, -1, 0, 0, CALLBACK_WINDOW);
timeSetEvent(1, 1, (LPTIMECALLBACK)timerProc, 0, TIME_PERIODIC);

return 0;
}

Eso es un secuenciador midi, para windows.
El volúmen de la nota midi está en data2. Los datos midi de un teclado entran usando la función midiInOpen.
Subir
oasys
#5 por oasys el 26/06/2013
En C se puede usar la librería multimedia para programar mediante mensajes básicos, en verdad es tan sencillo el protocolo que no se necesita de una librería especial que te lo dé mascado, aunque imagino que las habrá, pero así te enteras mejor de cómo funciona todo y tienes mayor control.

Desde luego necesitas conocer la especificación midi, porque cada mensaje lleva un comando, normalmente será un valor hexadecimal 0xB0, donde el valor más bajo es el canal, luego el número de comando, y el valor, así que si por ejemplo tendrás una función que mande mensajes como esta.

//---------------------------------------------------------------------------
// MENSAJES MIDI
//---------------------------------------------------------------------------
void EnviarEventoMidi(HMIDIOUT out, BYTE bStatus, BYTE bData1, BYTE bData2)
{
union { DWORD dwData;BYTE bData[4]; } u;
u.bData[0] = bStatus; // MIDI status byte
u.bData[1] = bData1; // first MIDI data byte
u.bData[2] = bData2; // second MIDI data byte
u.bData[3] = 0;
midiOutShortMsg(out, u.dwData);
}

Imagen no disponible

Segun la tabla para el volumen es el comando 7, y el parámetro para ajustarlo a la mitad sería 63 (la mitad de 128 - 1)

EnviarEventoMidi(puertoOut,(BYTE)(0xB0+canal), 7, 63);

las pistas no tendrán volumen sino el canal, y cada canal puede estar asignado a una pista o varias.

otro mensaje, por ejemplo para tocar una nota (para liberarla hará falta otro comando con su número correspondiente).
EnviarEventoMidi(puertoOut,(BYTE)(0x90+canal), nota, 0x64);

Eso para los mensajes simples donde se le pasa un canal, un comando, y un parámetro, pero luego puede haber mensajes más complejos que necesiten pasar más datos, ahí entran los RPN y los NRPN, te paso las funciones.

//---------------------------------------------------------------------------
// Mensaje NRPN
//---------------------------------------------------------------------------
void mensaje_NRPN(HMIDIOUT out, BYTE CanalSelec, BYTE msb, BYTE lsb, DATASB data)
{
EnviarEventoMidi(out,(BYTE)(0xB0+CanalSelec),99,msb);
EnviarEventoMidi(out,(BYTE)(0xB0+CanalSelec),98,lsb);
EnviarEventoMidi(out,(BYTE)(0xB0+CanalSelec),6,data.msb);
EnviarEventoMidi(out,(BYTE)(0xB0+CanalSelec),38,data.msb);
}
//---------------------------------------------------------------------------
// Mensaje RPN
//---------------------------------------------------------------------------
void mensaje_RPN(HMIDIOUT out, BYTE CanalSelec, BYTE msb, BYTE lsb, DATASB data)
{
EnviarEventoMidi(out,(BYTE)(0xB0+CanalSelec),101,msb);
EnviarEventoMidi(out,(BYTE)(0xB0+CanalSelec),100,lsb);
EnviarEventoMidi(out,(BYTE)(0xB0+CanalSelec),6,data.msb);
EnviarEventoMidi(out,(BYTE)(0xB0+CanalSelec),38,data.lsb);
}

Pero de momento empezaría con los mensajes simples, elegir instrumento para el canal, fijar volumen, panorama, tocar notas, y para cada cosa crear funciones que contengan sus mensajes, por ejemplo para elegir programa y banco, crear las funciones correspondiente con los dos mensajes.

//---------------------------------------------------------------------------
// Cambio de Programa y banco
//---------------------------------------------------------------------------
void SeleccionarInstrumento(BYTE canal, BYTE programa, BYTE banco)
{
EnviarEventoMidi(puertoOut,(BYTE)(0xB0+canal),0,0);
EnviarEventoMidi(puertoOut,(BYTE)(0xB0+canal),32,banco);
}


Lo difícil y pesado es lo del piano roll y todo el tema gráfico y de la interfaz. Eso ya depende del entorno que uses.

(igual puede haber un fallo en el código que te he puesto, lo he picado de por ahí que lo tenía, que sepas que es a modo de orientación y para que puedas arrancar con algo).
Subir
synthetistjv
#6 por synthetistjv el 26/06/2013
Muchas gracias por la información, haber si tengo algún día un rato libre para mirarlo más detenidamente, gracias ! :D
Subir
Hilos similares
Nuevo post

Regístrate o para poder postear en este hilo