View Full Version : [c++]Ricezione di program change midi da tastiera musicale a pc
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
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
non sono molto pratico di programmazioni con periferiche windows usb e midi mi date un example code?:D
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
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.
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;
}
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
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.
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:
help.
Per me fare questa cosa è molto importante
grazie a chi mi darà una mano
Buona domenica
hai provato a compilare il codice che ti ho postato ed eseguirlo?
Che succede se premi qualche tasto sulla tastiera?
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
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);
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 ...
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()
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
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
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:
Ti assicuro che a questo livello è ancora semplice. Hai provato a lanciare l'eseguibile passando come argomento 1 ?
no come si fa?
scusa ma non sono molto pratico di queste cose...
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
nel menu Run di Borland Builder esiste la voce Parameters, basta scrivere 1 ed eseguire
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!
di che tipo di scheda audio si tratta?
Se guardi il codice il numero passato come argomento si riferisce al numero di porta
la scheda è la m-audio audiophile usb.
Il numero passato come argomento intenti quello che poi vado a modificare da run->parameters?
Grazie!
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
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.