Entra

View Full Version : [c++]Ricezione di program change midi da tastiera musicale a pc


gokuss4
02-02-2013, 07:45
Ciao.
Mi addentro in un discorso un po' particolare in quanto io sono programmatore ma per hobby sono anche musicista (suono tastiere elettroniche).
Ora io ho una tastiera che può essere collegata al pc via usb e viene vista come una periferica midi.
La tastiera quando si fanno certe operazioni invia dei messaggi midi di program change agli altri dispositi collegati alle sue porte midi.
Ora immaginiamo che al posto di collegare un altro strumento midi alla tastiera , io collego le uscite midi della mia tastiera agli ingressi midi di una scheda audio usb esterna (m-audio audiophile usb).
Ecco la domanda. Come faccio tramite linguaggio C++ (uso c++ builder 6) a scrivere un programma che acceda alla periferica midi vista da windows e si metta in ascolto dei messaggi midi che arrivano (program change), e mi scriva tutti questi messaggi (normalmente codici alfanumerici) in un file? è possibile?
Grazie!

sottovento
02-02-2013, 08:41
Hai gia' controllato

http://stackoverflow.com/questions/5612358/audio-midi-c-library-for-a-real-time-application

e

http://stackoverflow.com/questions/3231/c-c-library-for-reading-midi-signals-from-a-usb-midi-device

Sembrano proprio fare al caso tuo

misterx
02-02-2013, 08:49
dai un occhio qui http://code.msdn.microsoft.com/windowshardware/site/search?query=midi&f%5B0%5D.Value=midi&f%5B0%5D.Type=SearchText&ac=8

gokuss4
02-02-2013, 10:15
non sono molto pratico di programmazioni con periferiche windows usb e midi mi date un example code?:D

misterx
02-02-2013, 11:28
anch'io suonicchio un D50 ed uso borland builder 6 :D , conviene iniziare a postare qualche link utile http://msdn.microsoft.com/en-us/library/ms712058.aspx

gokuss4
02-02-2013, 14:20
devo importare qualche libreria particolare in c++ builder?
Mi puoi dare una mano a scrivere il codice?
La tastiera quando premo il tasto incrimato manda un messaggio di program change (penso sulla porta midi keyboard). leggendo il manuale questo messaggio dovrebbe contenere anche un numero che è quello che mi interessa recuperare da programma...
Come procedo?
Considerato che collego la tastiera nei midi della scheda audio esterna audiophile usb come faccio a eccedervi da programma?
come richiamo da pc la periferica audiophile usb sezione midi da c++?
qualcuno ha già fatto di queste prove?
ho bisogno di qualcuno che mi aiuti non so da che parte cominciare.

misterx
02-02-2013, 15:35
il seguente codice si compila tranquillamente con BCB6, non avendo collegato una tastiera MIDI non posso testarlo: fammi sapere


#include <conio.h> /* include for kbhit() and getch() functions */
#include <stdio.h> /* for printf() function */

#include <windows.h> /* required before including mmsystem.h */
#include <mmsystem.h> /* multimedia functions (such as MIDI) for Windows */

int main(int argc, char** argv) {
int ckey; // storage for the current keyboard key being pressed
int notestate = 0; // keeping track of when the note is on or off
int velocity = 100; // MIDI note velocity parameter value
int midiport; // select which MIDI output port to open
int flag; // monitor the status of returning functions
HMIDIOUT device; // MIDI device interface for sending MIDI output

// variable which is both an integer and an array of characters:
union { unsigned long word; unsigned char data[4]; } message;
// message.data[0] = command byte of the MIDI message, for example: 0x90
// message.data[1] = first data byte of the MIDI message, for example: 60
// message.data[2] = second data byte of the MIDI message, for example 100
// message.data[3] = not used for any MIDI messages, so set to 0
message.data[0] = 0x90; // MIDI note-on message (requires to data bytes)
message.data[1] = 60; // MIDI note-on message: Key number (60 = middle C)
message.data[2] = 100; // MIDI note-on message: Key velocity (100 = loud)
message.data[3] = 0; // Unused parameter

// Assign the MIDI output port number (from input or default to 0)
if (argc < 2) {
midiport = 0;
} else {
midiport = atoi(argv[1]);
}
printf("MIDI output port set to %d.\n", midiport);

// Open the MIDI output port
flag = midiOutOpen(&device, midiport, 0, 0, CALLBACK_NULL);
if (flag != MMSYSERR_NOERROR) {
printf("Error opening MIDI Output.\n");
return 1;
}

// Main event loop
printf("Press \"q\" to quit.\n");
while (1) { // event loop
if (kbhit()) { // If a key on the computer keyboard has been pressed
ckey = getch();
if (notestate == 0) {
// Note is currently off, turn on note.
message.data[2] = velocity;
notestate = 1;
printf("Note turned ON.\n");
} else {
// Note is currently on, turn off note.
message.data[2] = 0; // 0 velocity = note off
notestate = 0;
printf("Note turned OFF.\n");
}
flag = midiOutShortMsg(device, message.word);
if (flag != MMSYSERR_NOERROR) {
printf("Warning: MIDI Output is not open.\n");
}
if (ckey == 'q') break;
}
}

// turn any MIDI notes currently playing:
midiOutReset(device);

// Remove any data in MIDI device and close the MIDI Output port
midiOutClose(device);

return 0;
}

gokuss4
02-02-2013, 17:50
devo ancora testarlo però mi domando una cosa
1. Come faccio nel codice a sciegliere la scheda audio esterna?
2. Come faccio a leggere se è stato inviato un program change e cosa contiene quel messaggio? Grazie!
penso dovrei leggere il message data che mi invia la tastiera , non modificarlo.
A me interessa leggere i messaggi che arrivano di program change

misterx
02-02-2013, 18:41
devi provare il codice e vedere cosa ti ritornano le varie funzioni. Io non ho sottomano una interfaccia MIDI con la quale fare delle prove ma credo che col codice che ti ho postato e con un minimo sforzo da parte tua, si riesca ad ottenere ciò che chiedi.

Dovrebbe essere la midiOutOpen() a fare tutto il lavoro ma devi approfondire il suo funzionamento.

gokuss4
02-02-2013, 21:29
ho installato un midi device di prova.
Ho provato con midi-ox per vedere se riceveva segnali e qui tutto ok
Penso di essere riuscito a capire come aprire la periferica midi corretta.
Ma ora non capisco come stampare a video all'infinito lo stream dei messaggi midi che escono dal device e entrano nel pc...
Ho bisogno di aiuto.
Stavo dando un occhiata alle funzioni dispobili.
ma sembra non ce ne sia nessuna che faccia al caso mio.
Poi una volta che sarò riuscito a capire come stampare tutti i messaggi in entrata (come fa midi-ox) resta da capire come distinguere quelli che si riferiscono a un program change.
Grazie per l'aiuto:muro:

gokuss4
03-02-2013, 11:10
help.
Per me fare questa cosa è molto importante
grazie a chi mi darà una mano
Buona domenica

misterx
03-02-2013, 19:17
hai provato a compilare il codice che ti ho postato ed eseguirlo?
Che succede se premi qualche tasto sulla tastiera?

gokuss4
03-02-2013, 19:31
non fa niente.
O per lo meno se premo invio sulla tastiera del pc cambia da note on a note off :D
Ma non è quello deve fare.
Io voglio che si metta in ascolto dei messaggi che arrivano e li stampi a video.
ora come ora non reagisce a input dalla tastiera musicale.
Vorrei ottenere la stampa di tutti i messaggi ... un po come dovrebbe fare midi-ox per esempio.
Grazie mille per l'aiuto che mi stai dando.
per me è molto importante questo programma

misterx
03-02-2013, 19:59
non fa niente.
O per lo meno se premo invio sulla tastiera del pc cambia da note on a note off :D
Ma non è quello deve fare.
Io voglio che si metta in ascolto dei messaggi che arrivano e li stampi a video.
ora come ora non reagisce a input dalla tastiera musicale.
Vorrei ottenere la stampa di tutti i messaggi ... un po come dovrebbe fare midi-ox per esempio.
Grazie mille per l'aiuto che mi stai dando.
per me è molto importante questo programma

chi cambia da note ON a note OFF la tastiera?


flag = midiOutShortMsg(device, message.word);

gokuss4
03-02-2013, 20:42
nessuno ho solo detto che se premo invio sulla tastiera del pc si alternano i due messaggi....
dalla tastiera musicale se schiaccio non succede niente...
un altra cosa:
"The midiOutShortMsg function sends a short MIDI message to the specified MIDI output device."
a quanto pare invia un messaggio su un output device giusto?
Io però devo fare il contrario , ricevere un messaggio che arriva dall'output ...

misterx
03-02-2013, 20:46
certo, però inizia prima a vedere se PC e tastiera comunicano tra lloro, magari cambiando il tipo di messaggio e poi usi la funzione complementare per leggere messaggi che a naso dovrebbe essere una cosa del tipo midiInShortMsg()

gokuss4
03-02-2013, 21:15
per cambiare tipo di messaggio come faccio'
perchè guardando il codice lui mette message.word.
che vuol dire .WORD?
si riferisce al vettore message?
io i vettori li chiamo message[0],message[1]... per accedere ai dati

misterx
04-02-2013, 11:01
http://msdn.microsoft.com/en-us/library/windows/desktop/dd798481(v=vs.85).aspx

se guaradi la spiegazione i 4 data da 8 bit vengono trasformati in una parola lunga 32 bit.

message.data[0] = 0x90;
message.data[1] = 60;
message.data[2] = 100;
message.data[3] = 0;


High e Low in decimale vengono ordinati in questo modo0
0 -- 100 -- 60 -- 144 = 11001000011110010010000

ed inviati quindi alla periferica midi

p.s.
però questa trattazione tecnica non ci serve per inviare comandi alla tastiera

gokuss4
04-02-2013, 21:06
ho provato ma non ottengo nessun risultato.
Sto cominciando a non capirci più nulla...
Non c'è qualche metodo più semplice?
Magari appoggiandosi a midi-ox o un altro linguaggio?
Pensavo fosse semplice recuperare il messaggio di program change invece :cry:

misterx
04-02-2013, 21:29
Ti assicuro che a questo livello è ancora semplice. Hai provato a lanciare l'eseguibile passando come argomento 1 ?

gokuss4
04-02-2013, 21:37
no come si fa?
scusa ma non sono molto pratico di queste cose...

gokuss4
04-02-2013, 22:20
non riesci a darmi una mano tu a scrivelo?
Poi io lo testo.
Veramente sono negato, ma ci tenevo a scrivere questo codice...
Ti prego per me è molto importante.
Devo ascoltare all'infinito e recuperare tutti i program e control change....
grazie

misterx
05-02-2013, 06:13
nel menu Run di Borland Builder esiste la voce Parameters, basta scrivere 1 ed eseguire

gokuss4
05-02-2013, 07:08
ciao!
Ho provato ma non funziona ancora nulla.
Ma la modifica che mi hai fatto fare sui parametri a casa serviva?
Come faccio a essere sicuro che stia dialogando effettivamente con la scheda audio usb e non con altre?
Per capire se il programma funziona cosa dovrei ottenere quando premo i tasti da tastiera?
E' possibile che magari programma e tastiera stiano inviando su canali midi 1 2 3 ... differenti?
Come faccio a verificare i canali utilizzati.
Grazie mille per l'aiuto!

misterx
05-02-2013, 13:51
di che tipo di scheda audio si tratta?

Se guardi il codice il numero passato come argomento si riferisce al numero di porta

gokuss4
05-02-2013, 16:24
la scheda è la m-audio audiophile usb.
Il numero passato come argomento intenti quello che poi vado a modificare da run->parameters?
Grazie!

misterx
05-02-2013, 18:54
non avendo un ascheda a disposizione è un pò caotica la cosa, comunque per enumerare le schede prova questo breve programma, forse la scheda non viene vista.
Prendi nota dell'ID di questo codice ed usalo per l'altro programma.


#include <conio.h>
#include <stdio.h>
#include <windows.h>
#include <mmsystem.h>

int main(int argc, char** argv) {

MIDIOUTCAPS moc;
unsigned long iNumDevs, i;

/* Get the number of MIDI Out devices in this computer */
iNumDevs = midiOutGetNumDevs();

/* Go through all of those devices, displaying their names */
for (i = 0; i < iNumDevs; i++)
{
/* Get info about the next device */
if (!midiOutGetDevCaps(i, &moc, sizeof(MIDIOUTCAPS)))
{
/* Display its Device ID and name */
printf("Device ID #%u: %s\r\n", i, moc.szPname);
}
}

return 0;
}



fonte: http://web.tiscalinet.it/giordy/midi-tech/lowmidi.htm