void run() { const int maxEventSize = 16 * 1024; snd_midi_event_t* midiParser; if (snd_midi_event_new (maxEventSize, &midiParser) >= 0) { HeapBlock <uint8> buffer (maxEventSize); const int numPfds = snd_seq_poll_descriptors_count (seqHandle, POLLIN); struct pollfd* const pfd = (struct pollfd*) alloca (numPfds * sizeof (struct pollfd)); snd_seq_poll_descriptors (seqHandle, pfd, numPfds, POLLIN); while (! threadShouldExit()) { if (poll (pfd, numPfds, 500) > 0) { snd_seq_event_t* inputEvent = nullptr; snd_seq_nonblock (seqHandle, 1); do { if (snd_seq_event_input (seqHandle, &inputEvent) >= 0) { // xxx what about SYSEXes that are too big for the buffer? const int numBytes = snd_midi_event_decode (midiParser, buffer, maxEventSize, inputEvent); snd_midi_event_reset_decode (midiParser); if (numBytes > 0) { const MidiMessage message ((const uint8*) buffer, numBytes, Time::getMillisecondCounter() * 0.001); callback->handleIncomingMidiMessage (midiInput, message); } snd_seq_free_event (inputEvent); } } while (snd_seq_event_input_pending (seqHandle, 0) > 0); snd_seq_free_event (inputEvent); } } snd_midi_event_free (midiParser); } };
// This splits the Midi events from one channel to another two channels void Spliter::midievents(){ snd_seq_event_t *midievent; midievent=NULL; snd_seq_event_input(midi_in,&midievent); if (midievent==NULL) return; if ((midievent->type==SND_SEQ_EVENT_NOTEON)||(midievent->type==SND_SEQ_EVENT_NOTEOFF)){ int cmdchan=midievent->data.note.channel; if (cmdchan==Pchin){ snd_seq_ev_set_subs(midievent); snd_seq_ev_set_direct(midievent); if (midievent->data.note.note<Psplitpoint) { midievent->data.note.channel=Pchout1; int tmp=midievent->data.note.note; tmp+=Poct1*12;if (tmp>127) tmp=127;if (tmp<0) tmp=0; midievent->data.note.note=tmp; } else { midievent->data.note.channel=Pchout2; int tmp=midievent->data.note.note; tmp+=Poct2*12;if (tmp>127) tmp=127;if (tmp<0) tmp=0; midievent->data.note.note=tmp; }; snd_seq_event_output_direct(midi_out,midievent); } else { snd_seq_ev_set_subs(midievent); snd_seq_ev_set_direct(midievent); snd_seq_event_output_direct(midi_out,midievent); }; }; snd_seq_free_event(midievent); };
/* handles all the midi calls */ void midi_action(snd_seq_t *seq_handle) { snd_seq_event_t *ev; do { snd_seq_event_input(seq_handle, &ev); printf( "%i \n", ev->data.control.channel, ev->data.control.value); switch (ev->type) { case SND_SEQ_EVENT_CONTROLLER: printf("Control event on Channel %2d: %5d \n", ev->data.control.channel, ev->data.control.value); midi_set(ev, 2); pedal_set(ev); break; case SND_SEQ_EVENT_PITCHBEND: printf("Pitchbender event on Channel %2d: %5d \n", ev->data.control.channel, ev->data.control.value); break; case SND_SEQ_EVENT_NOTEON: printf("Note On event on Channel %2d: %5d \n", ev->data.control.channel, ev->data.note.note); break; case SND_SEQ_EVENT_NOTEOFF: printf("Note Off event on Channel %2d: %5d \n", ev->data.control.channel, ev->data.note.note); break; case SND_SEQ_EVENT_PGMCHANGE: printf("PGM event on Channel %2d: %5d \n", ev->data.control.channel, ev->data.control.value); midi_set(ev, 1); break; } snd_seq_free_event(ev); } while (snd_seq_event_input_pending(seq_handle, 0) > 0); }
void* midi2lp(void* nothing) { printf("waiting for midi events\n"); snd_seq_event_t *ev; while (1) { // get a new event. if there aren't any, wait for one snd_seq_event_input(midi_client, &ev); // copy the data to send switch (ev->type) { case SND_SEQ_EVENT_NOTEON: lp_send3(lp, NOTE_ON, ev->data.note.note, ev->data.note.velocity); break; case SND_SEQ_EVENT_NOTEOFF: lp_send3(lp, NOTE_OFF, ev->data.note.note, ev->data.note.velocity); break; case SND_SEQ_EVENT_CONTROLLER: lp_send3(lp, CTRL, ev->data.control.param, ev->data.control.value); break; } // free the midi event snd_seq_free_event(ev); } }
/* TODO: ADD MIDI PANIC/ALL NOTES OFF */ int midi_callback() { snd_seq_event_t *ev; int l1; do { snd_seq_event_input(seq_handle, &ev); switch (ev->type) { case SND_SEQ_EVENT_NOTEON: for (l1 = 0; l1 < POLY; l1++) { if (!note_active[l1]) { note[l1] = ev->data.note.note; printf("Note ON %d FREQ %d\n", note[l1] ,(note[l1])*FREQ_CHANNEL_WIDTH+FREQ_START); velocity[l1] = ev->data.note.velocity / 127.0; env_time[l1] = 0; gate[l1] = 1; note_active[l1] = 1; break; } } break; case SND_SEQ_EVENT_NOTEOFF: for (l1 = 0; l1 < POLY; l1++) { if (gate[l1] && note_active[l1] && (note[l1] == ev->data.note.note)) { printf("Note OFF %d \n", note[l1]); env_time[l1] = 0; gate[l1] = 0; } } break; } snd_seq_free_event(ev); } while (snd_seq_event_input_pending(seq_handle, 0) > 0); return (0); }
int MidiInputDeviceAlsa::Main() { int npfd; struct pollfd* pfd; snd_seq_event_t* ev; npfd = snd_seq_poll_descriptors_count(hAlsaSeq, POLLIN); pfd = (struct pollfd*) alloca(npfd * sizeof(struct pollfd)); snd_seq_poll_descriptors(hAlsaSeq, pfd, npfd, POLLIN); while (true) { if (poll(pfd, npfd, 100000) > 0) { do { snd_seq_event_input(hAlsaSeq, &ev); int port = (int) ev->dest.port; MidiInputPort* pMidiInputPort = Ports[port]; switch (ev->type) { case SND_SEQ_EVENT_CONTROLLER: if (ev->data.control.param == 0) pMidiInputPort->DispatchBankSelectMsb(ev->data.control.value, ev->data.control.channel); else if (ev->data.control.param == 32) pMidiInputPort->DispatchBankSelectLsb(ev->data.control.value, ev->data.control.channel); pMidiInputPort->DispatchControlChange(ev->data.control.param, ev->data.control.value, ev->data.control.channel); break; case SND_SEQ_EVENT_CHANPRESS: pMidiInputPort->DispatchControlChange(128, ev->data.control.value, ev->data.control.channel); break; case SND_SEQ_EVENT_PITCHBEND: pMidiInputPort->DispatchPitchbend(ev->data.control.value, ev->data.control.channel); break; case SND_SEQ_EVENT_NOTEON: if (ev->data.note.velocity != 0) { pMidiInputPort->DispatchNoteOn(ev->data.note.note, ev->data.note.velocity, ev->data.control.channel); } else { pMidiInputPort->DispatchNoteOff(ev->data.note.note, 0, ev->data.control.channel); } break; case SND_SEQ_EVENT_NOTEOFF: pMidiInputPort->DispatchNoteOff(ev->data.note.note, ev->data.note.velocity, ev->data.control.channel); break; case SND_SEQ_EVENT_SYSEX: pMidiInputPort->DispatchSysex(ev->data.ext.ptr, ev->data.ext.len); break; case SND_SEQ_EVENT_PGMCHANGE: pMidiInputPort->DispatchProgramChange(ev->data.control.value, ev->data.control.channel); break; } snd_seq_free_event(ev); } while (snd_seq_event_input_pending(hAlsaSeq, 0) > 0); } } // just to avoid a compiler warning return EXIT_FAILURE; }
void* alsa_input_thread(void * arg) { struct a2j * self = arg; int npfd; struct pollfd * pfd; snd_seq_addr_t addr; snd_seq_client_info_t * client_info; snd_seq_port_info_t * port_info; bool initial; snd_seq_event_t * event; int ret; npfd = snd_seq_poll_descriptors_count(self->seq, POLLIN); pfd = (struct pollfd *)alloca(npfd * sizeof(struct pollfd)); snd_seq_poll_descriptors(self->seq, pfd, npfd, POLLIN); initial = true; while (g_keep_alsa_walking) { if ((ret = poll(pfd, npfd, 1000)) > 0) { while (snd_seq_event_input (self->seq, &event) > 0) { if (initial) { snd_seq_client_info_alloca(&client_info); snd_seq_port_info_alloca(&port_info); snd_seq_client_info_set_client(client_info, -1); while (snd_seq_query_next_client(self->seq, client_info) >= 0) { addr.client = snd_seq_client_info_get_client(client_info); if (addr.client == SND_SEQ_CLIENT_SYSTEM || addr.client == self->client_id) { continue; } snd_seq_port_info_set_client(port_info, addr.client); snd_seq_port_info_set_port(port_info, -1); while (snd_seq_query_next_port(self->seq, port_info) >= 0) { addr.port = snd_seq_port_info_get_port(port_info); a2j_update_port(self, addr, port_info); } } initial = false; } if (event->source.client == SND_SEQ_CLIENT_SYSTEM) { a2j_port_event(self, event); } else { a2j_input_event(self, event); } snd_seq_free_event (event); } } } return (void*) 0; }
void midi_process(snd_seq_event_t *ev) { // If this event is a PGMCHANGE type, it's a request to map a channel to an instrument if (ev->type == SND_SEQ_EVENT_PGMCHANGE) { //printf("PGMCHANGE: channel %2d, %5d, %5d\n", ev->data.control.channel, ev->data.control.param, ev->data.control.value); // Clear pins state, this is probably the beginning of a new song allOff(); } // If the event is SND_SEQ_EVENT_BOUNCE, then maybe this is an interrupt? if (ev->type == SND_SEQ_EVENT_BOUNCE) { allOff(); } if (channelActive == ev->data.control.channel) { // Note on/off event if (ev->type == SND_SEQ_EVENT_NOTEON) { // When pinActive is -1, we're playing the first note if (-1 == pinActive) { pinActive = 0; } else { // First turn off the current pin printf("Turning off pin %d\n", pinActive); pinOff(pinActive); // Increment pinActive printf("Incrementing pinActive\n"); pinActive++; // Reset to zero if we're above the number of pins if (pinActive >= TOTAL_PINS) { printf("Resetting pinActive to zero\n"); pinActive = 0; } } // Turn on the next pin printf("Turning on pin %d\n", pinActive); pinOn(pinActive); } } snd_seq_free_event(ev); }
void midi_process(snd_seq_event_t *ev) { //If this event is a PGMCHANGE type, it's a request to map a channel to an instrument if( ev->type == SND_SEQ_EVENT_PGMCHANGE ) { //Clear pins state, this is probably the beginning of a new song clearPinsState(); setPlayChannel(ev->data.control.channel, 1); } else if ( ((ev->type == SND_SEQ_EVENT_NOTEON)||(ev->type == SND_SEQ_EVENT_NOTEOFF)) ) { //Note on/off event int isOn = 1; //Note velocity == 0 means the same thing as a NOTEOFF type event if( ev->data.note.velocity == 0 || ev->type == SND_SEQ_EVENT_NOTEOFF) { isOn = 0; } //There are 12 different kinds of notes. (I will only use the first 8 for my rig but I need to the modulus. will be 0-11.) int pinIdx = ev->data.note.note % 12; //If pin is set to be turned on if( isOn ) { //If pin is currently available to play a note, or if currently playing channel can be overriden due to higher priority channel if( pinNotes[pinIdx] == -1 || pinChannels[pinIdx] > ev->data.note.channel ) { //Write to the pin, save the note to pinNotes digitalWrite(pinIdx, 1); pinNotes[pinIdx] = ev->data.note.note; pinChannels[pinIdx] = ev->data.note.channel; } } else { //Pin is to be turned off //If this is the note that turned the pin on.. if( pinNotes[pinIdx] == ev->data.note.note && pinChannels[pinIdx] == ev->data.note.channel ) { //Write to the pin, indicate that pin is available digitalWrite(pinIdx, 0); pinNotes[pinIdx] = -1; pinChannels[pinIdx] = INT_MAX; } } } else { printf("Unhandled event %2d\n", ev->type); } snd_seq_free_event(ev); } // end of midi_process
void Midi2UdpThread::run() { QUdpSocket *udpSocket; udpSocket = new QUdpSocket(0); forever { if (abort) { delete udpSocket; return; } if (poll(pfd, npfd, 250) > 0) { // Get MIDI event snd_seq_event_input(seq_handle, &midi_event); long len = snd_midi_event_decode(eventparser, midimsg, MAX_MIDI_MESSAGE_LENGTH, midi_event); if( len < 0 ) { printf("midi2udp: Error decoding midi event!\n"); } else { printf("midi2udp: got midi event: "); for(int i=0; i<len; ++i) { printf("0x%x ", midimsg[i]); } printf("\n"); // Send it over UDP for(set<string>::iterator ip_it = ds_ips.begin(); ip_it != ds_ips.end(); ++ip_it) { QString to_((*ip_it).c_str()); printf("sending to %s\n", (*ip_it).c_str()); QHostAddress to(to_); udpSocket->writeDatagram((char*)midimsg, len, to, DS_PORT); } } snd_seq_free_event(midi_event); snd_midi_event_reset_decode(eventparser); } } }
/* TODO: ADD MIDI PANIC/ALL NOTES OFF */ int midi_callback() { snd_seq_event_t *ev; int l1; do { snd_seq_event_input(seq_handle, &ev); switch (ev->type) { case SND_SEQ_EVENT_NOTEON: for (l1 = 0; l1 < POLY; l1++) { if (!note_active[l1]) { note[l1] = ev->data.note.note; midichannel[l1] = ev->data.note.channel; velocity[l1] = ev->data.note.velocity / 127; attron(COLOR_PAIR(1)); printw("CH %2.0f ", midichannel[l1]+1); printw("Note %3d ", note[l1]); printw("Velocity %3.0f ", velocity[l1] * 127); printw("Frequency %3.1f \n", ((note[l1]*FREQ_CHANNEL_WIDTH)+((128*FREQ_CHANNEL_WIDTH*midichannel[l1])+FREQ_START)) ); refresh(); attroff(COLOR_PAIR(1)); env_time[l1] = 0; gate[l1] = 1; note_active[l1] = 1; break; } } break; case SND_SEQ_EVENT_NOTEOFF: for (l1 = 0; l1 < POLY; l1++) { if (gate[l1] && note_active[l1] && (note[l1] == ev->data.note.note)) { printw("Note OFF %3d \n", note[l1]); env_time[l1] = 0; gate[l1] = 0; } } break; } snd_seq_free_event(ev); } while (snd_seq_event_input_pending(seq_handle, 0) > 0); return (0); }
int midi_action(snd_seq_t *seq_handle) { snd_seq_event_t *ev; int cnt = 0; do { snd_seq_event_input(seq_handle, &ev); switch (ev->type) { case SND_SEQ_EVENT_NOTEON: if (channels && !(channels & (1<<ev->data.note.channel))) break; if (ev->data.note.velocity != 0) { note_on(ev->data.note.note, ev->data.note.velocity); cnt++; } } snd_seq_free_event(ev); } while (snd_seq_event_input_pending(seq_handle, 0) > 0); return cnt; }
int midi_callback() { snd_seq_event_t *ev; int l1; do { snd_seq_event_input(seq_handle, &ev); switch (ev->type) { case SND_SEQ_EVENT_PITCHBEND: pitch = (double)ev->data.control.value / 8192.0; break; case SND_SEQ_EVENT_CONTROLLER: if (ev->data.control.param == 1) { modulation = (double)ev->data.control.value / 10.0; } break; case SND_SEQ_EVENT_NOTEON: for (l1 = 0; l1 < POLY; l1++) { if (!note_active[l1]) { note[l1] = ev->data.note.note; velocity[l1] = ev->data.note.velocity / 127.0; env_time[l1] = 0; gate[l1] = 1; note_active[l1] = 1; break; } } break; case SND_SEQ_EVENT_NOTEOFF: for (l1 = 0; l1 < POLY; l1++) { if (gate[l1] && note_active[l1] && (note[l1] == ev->data.note.note)) { env_time[l1] = 0; gate[l1] = 0; } } break; } snd_seq_free_event(ev); } while (snd_seq_event_input_pending(seq_handle, 0) > 0); return (0); }
int midi_read() { snd_seq_event_t *ev; int channel,value,note,velocity,param; do { snd_seq_event_input(seq_handle, &ev); switch (ev->type) { case SND_SEQ_EVENT_NOTEON: channel = ev->data.note.channel; note = ev->data.note.note & 0x7f; velocity = ev->data.note.velocity; note_on_action(channel,note,velocity); break; case SND_SEQ_EVENT_NOTEOFF: channel = ev->data.note.channel; note = ev->data.note.note; velocity = ev->data.note.velocity; note_off_action(channel,note,velocity); break; case SND_SEQ_EVENT_PGMCHANGE: channel = ev->data.control.channel; value = ev->data.control.value; program_change_action(channel,value); break; case SND_SEQ_EVENT_CONTROLLER: channel = ev->data.control.channel; param = ev->data.control.param; value = ev->data.control.value; control_change_action(channel,param,value); break; } snd_seq_free_event(ev); } while (snd_seq_event_input_pending(seq_handle, 0) > 0); return (0); }
void midi_action(snd_seq_t *seq_handle) { snd_seq_event_t *ev; do { snd_seq_event_input(seq_handle, &ev); switch (ev->type) { case SND_SEQ_EVENT_CONTROLLER: printf(MIDI_FORMAT, MIDI_CONTROL, ev->data.control.channel, ev->data.control.value); break; case SND_SEQ_EVENT_PITCHBEND: printf(MIDI_FORMAT, MIDI_PITCH_BEND, ev->data.control.channel, ev->data.control.value); break; case SND_SEQ_EVENT_NOTEON: printf(MIDI_FORMAT, MIDI_NOTE_ON, ev->data.control.channel, ev->data.note.note); break; case SND_SEQ_EVENT_NOTEOFF: printf(MIDI_FORMAT, MIDI_NOTE_OFF, ev->data.control.channel, ev->data.note.note); break; } fflush(stdout); fflush(stderr); snd_seq_free_event(ev); } while (snd_seq_event_input_pending(seq_handle, 0) > 0); }
int main( int argc, char *argv[] ) { jack_client_t *jackClient; snd_seq_t *seqport; struct pollfd *pfd; int npfd; snd_seq_event_t *midievent; int channel, midiport; int note, length, i, j, minpos; double freq, avg, vol, scale, min; double *tempstring; puts( "SO-KL5 v.1.2 by 50m30n3 2009-2011" ); if( argc > 1 ) channel = atoi( argv[1] ); else channel = 0; signal( SIGINT, sig_exit ); signal( SIGTERM, sig_exit ); puts( "Connecting to Jack Audio Server" ); jackClient = jack_client_open( "SO-KL5", JackNoStartServer, NULL ); if( jackClient == NULL ) { fputs( "Cannot connect to Jack Server\n", stderr ); return 1; } jack_on_shutdown( jackClient, jack_shutdown, 0 ); outport = jack_port_register( jackClient, "output", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput | JackPortIsTerminal, 0 ); jack_set_process_callback( jackClient, process, 0 ); samplerate = jack_get_sample_rate( jackClient ); puts( "Initializing synth parameters" ); sustain = 0; cutoff = 64; resonance = 100; attack = 64; volume = 100; fcutoff = (cutoff+5.0)/400.0; sattack = (attack+5.0)/800.0; freso = (resonance/160.0)*(1.0-fcutoff); ssustain = 0.6+pow( sustain/127.0, 0.4)*0.4; for( note=0; note<NUMNOTES; note++ ) { freq = 440.0*pow( 2.0, (note+BASENOTE-69) / 12.0 ); stringcutoff[note] = 0.5 + pow( (double)note / (double)NUMNOTES, 0.5 ) * 0.45; length = round( (double)samplerate / freq ); stringlength[note] = length; strings[note] = malloc( length * sizeof( double ) ); if( strings[note] == NULL ) { fputs( "Error allocating memory\n", stderr ); return 1; } for( i=0; i<length; i++ ) { strings[note][i] = 0.0; } stringpos[note] = 0; status[note] = 0; } freq = 440.0*pow( 2.0, (BASENOTE-69) / 12.0 ); length = (double)samplerate / freq; tempstring = malloc( length * sizeof( double ) ); if( tempstring == NULL ) { fputs( "Error allocating memory\n", stderr ); return 1; } lpval = lplast = 0.0; jack_activate( jackClient ); printf( "Listening on MIDI channel %i\n", channel ); if( snd_seq_open( &seqport, "default", SND_SEQ_OPEN_INPUT, 0 ) < 0 ) { fputs( "Cannot connect to ALSA sequencer\n", stderr ); return 1; } snd_seq_set_client_name( seqport, "SO-KL5" ); midiport = snd_seq_create_simple_port( seqport, "input", SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, SND_SEQ_PORT_TYPE_APPLICATION ); if( midiport < 0 ) { fputs( "Cannot create ALSA sequencer port\n", stderr ); return 1; } npfd = snd_seq_poll_descriptors_count( seqport, POLLIN ); pfd = (struct pollfd *)malloc( npfd * sizeof( struct pollfd ) ); snd_seq_poll_descriptors( seqport, pfd, npfd, POLLIN ); done = 0; while( ! done ) { if( poll( pfd, npfd, 100000 ) > 0 ) { do { snd_seq_event_input( seqport, &midievent ); if( ( midievent->type == SND_SEQ_EVENT_NOTEON ) && ( midievent->data.note.channel == channel ) ) { note = midievent->data.note.note; if( ( note >= BASENOTE ) && ( note < BASENOTE+NUMNOTES ) ) { note -= BASENOTE; status[note] = 1; for( i=0; i<stringlength[note]; i++ ) { tempstring[i] = ((double)rand()/(double)RAND_MAX)*2.0-1.0; } freq = stringcutoff[note] * 0.25 + midievent->data.note.velocity/127.0 * 0.2 + sattack + 0.1; for( j=0; j<30; j++ ) { tempstring[0] = tempstring[0]*freq + tempstring[stringlength[note]-1]*(1.0-freq); for( i=1; i<stringlength[note]; i++ ) { tempstring[i] = tempstring[i]*freq + tempstring[(i-1)%stringlength[note]]*(1.0-freq); } } avg = 0.0; for( i=0; i<stringlength[note]; i++ ) { avg += tempstring[i]; } avg /= stringlength[note]; scale = 0.0; for( i=0; i<stringlength[note]; i++ ) { tempstring[i] -= avg; if( fabs( tempstring[i] ) > scale ) scale = fabs( tempstring[i] ); } min = 10.0; minpos = 0; for( i=0; i<stringlength[note]; i++ ) { tempstring[i] /= scale; if( fabs( tempstring[i] ) + fabs( tempstring[i] - tempstring[i-1] ) * 5.0 < min ) { min = fabs( tempstring[i] ) + fabs( tempstring[i] - tempstring[i-1] ) * 5.0; minpos = i; } } vol = midievent->data.note.velocity/256.0; for( i=0; i<stringlength[note]; i++ ) { strings[note][(stringpos[note]+i)%stringlength[note]] += tempstring[(i+minpos)%stringlength[note]]*vol; } } } else if( ( midievent->type == SND_SEQ_EVENT_NOTEOFF ) && ( midievent->data.note.channel == channel ) ) { note = midievent->data.note.note; if( ( note >= BASENOTE ) && ( note < BASENOTE+NUMNOTES ) ) { note -= BASENOTE; status[note] = 0; } } else if( ( midievent->type == SND_SEQ_EVENT_CONTROLLER ) && ( midievent->data.control.channel == channel ) ) { if( midievent->data.control.param == 74 ) { cutoff = midievent->data.control.value; fcutoff = (cutoff+5.0)/400.0; printf( "Cutoff: %i \r", cutoff ); fflush( stdout ); } else if( midievent->data.control.param == 71 ) { resonance = midievent->data.control.value; freso = (resonance/140.0)*(1.0-fcutoff); printf( "Resonance: %i \r", resonance ); fflush( stdout ); } else if( midievent->data.control.param == 73 ) { attack = midievent->data.control.value; sattack = (attack+5.0)/800.0; printf( "Attack: %i \r", attack ); fflush( stdout ); } else if( midievent->data.control.param == 7 ) { volume = midievent->data.control.value; printf( "Volume: %i \r", volume ); fflush( stdout ); } else if( ( midievent->data.control.param == 64 ) || ( midievent->data.control.param == 1 ) ) { sustain = midievent->data.control.value; ssustain = 0.6+pow( sustain/127.0, 0.4)*0.4; printf( "Sustain: %i \r", sustain ); fflush( stdout ); } } snd_seq_free_event( midievent ); } while( snd_seq_event_input_pending( seqport, 0 ) > 0 ); } } free( pfd ); snd_seq_delete_port( seqport, midiport ); snd_seq_close( seqport ); jack_deactivate( jackClient ); puts( "Freeing data" ); for( note=0; note<NUMNOTES; note++ ) { free( strings[note] ); } free( tempstring ); jack_port_unregister( jackClient, outport ); jack_client_close( jackClient ); return 0; }
void midi_process(snd_seq_event_t *ev) { //If this event is a PGMCHANGE type, it's a request to map a channel to an instrument if( ev->type == SND_SEQ_EVENT_PGMCHANGE ) { //printf("PGMCHANGE: channel %2d, %5d, %5d\n", ev->data.control.channel, ev->data.control.param, ev->data.control.value); //Clear pins state, this is probably the beginning of a new song clearPinsState(); setChannelInstrument(ev->data.control.channel, ev->data.control.value); } //Note on/off event else if ( ((ev->type == SND_SEQ_EVENT_NOTEON)||(ev->type == SND_SEQ_EVENT_NOTEOFF)) ) { //choose the output pin based on the pitch of the note int pinIdx = choosePinIdx(ev->data.note.note, ev->data.note.channel); if(!isPercussionChannel(ev->data.note.channel) ) { int isOn = 1; //Note velocity == 0 means the same thing as a NOTEOFF type event if( ev->data.note.velocity == 0 || ev->type == SND_SEQ_EVENT_NOTEOFF) { isOn = 0; } //If pin is set to be turned on if( isOn ) { //If pin is currently available to play a note, or if currently playing channel can be overriden due to higher priority channel if( pinNotes[pinIdx] == -1 || pinChannels[pinIdx] > ev->data.note.channel ) { if( (pinChannels[pinIdx] > ev->data.note.channel ) && pinNotes[pinIdx] != -1) { //printf("OVERRIDING CHANNEL %i for %i\n", pinChannels[pinIdx], ev->data.note.channel); } //Write to the pin, save the note to pinNotes //printf("Pin %i - %s %i %i \n", pinIdx, isOn ? "on" : "off", ev->data.note.note, ev->data.note.channel); digitalWrite(pinIdx, 1); pinNotes[pinIdx] = ev->data.note.note; pinChannels[pinIdx] = ev->data.note.channel; } } //Pin is to be turned off else { //If this is the note that turned the pin on.. if( pinNotes[pinIdx] == ev->data.note.note && pinChannels[pinIdx] == ev->data.note.channel ) { //Write to the pin, indicate that pin is available //printf("Pin %i - %s %i %i \n", pinIdx, isOn ? "on" : "off", ev->data.note.note, ev->data.note.channel); digitalWrite(pinIdx, 0); pinNotes[pinIdx] = -1; pinChannels[pinIdx] = INT_MAX; } } } else { //This is the percussion channel, flip the value static int percussionOn = 0; if( PERCUSSION_PIN_IDX != -1 ) { if( percussionOn) { digitalWrite(pinIdx, 0); percussionOn = 0; } else { digitalWrite(pinIdx, 1); percussionOn = 1; } } } } else { printf("Unhandled event %2d\n", ev->type); } snd_seq_free_event(ev); }
bool mastermidibus::get_midi_event( event *a_in ) { lock(); snd_seq_event_t *ev; bool sysex = false; /* temp for midi data */ unsigned char buffer[0x1000]; snd_seq_event_input(m_alsa_seq, &ev); bool ret = false; if (! global_manual_alsa_ports ) { switch( ev->type ){ case SND_SEQ_EVENT_PORT_START: { //printf("SND_SEQ_EVENT_PORT_START: addr[%d:%d]\n", // ev->data.addr.client, ev->data.addr.port ); port_start( ev->data.addr.client, ev->data.addr.port ); ret = true; break; } case SND_SEQ_EVENT_PORT_EXIT: { //printf("SND_SEQ_EVENT_PORT_EXIT: addr[%d:%d]\n", // ev->data.addr.client, ev->data.addr.port ); port_exit( ev->data.addr.client, ev->data.addr.port ); ret = true; break; } case SND_SEQ_EVENT_PORT_CHANGE: { //printf("SND_SEQ_EVENT_PORT_CHANGE: addr[%d:%d]\n", // ev->data.addr.client, // ev->data.addr.port ); ret = true; break; } default: break; } } if( ret ){ unlock(); return false; } /* alsa midi parser */ snd_midi_event_t *midi_ev; snd_midi_event_new( 0x1000, &midi_ev ); long bytes = snd_midi_event_decode( midi_ev, buffer, 0x1000, ev ); a_in->set_timestamp( ev->time.tick ); a_in->set_status( buffer[0] ); a_in->set_size( bytes ); /* we will only get EVENT_SYSEX on the first packet of midi data, the rest we have to poll for */ //if ( buffer[0] == EVENT_SYSEX ){ if ( 0 ){ /* set up for sysex if needed */ a_in->start_sysex( ); sysex = a_in->append_sysex( buffer, bytes ); } else { a_in->set_data( buffer[1], buffer[2] ); // some keyboards send on's with vel 0 for off if ( a_in->get_status() == EVENT_NOTE_ON && a_in->get_note_velocity() == 0x00 ){ a_in->set_status( EVENT_NOTE_OFF ); } sysex = false; } /* sysex messages might be more than one message */ while ( sysex ){ snd_seq_event_input(m_alsa_seq, &ev); bytes = snd_midi_event_decode( midi_ev, buffer, 0x1000, ev ); sysex = a_in->append_sysex( buffer, bytes ); } snd_seq_free_event( ev ); snd_midi_event_free( midi_ev ); unlock(); return true; }
void AlsaMidiInputThread::readEvent() { m_mutex.lock(); /* Wait for input data */ do { AlsaMidiInputDevice* device = NULL; snd_seq_event_t* ev = NULL; /* Receive an event */ snd_seq_event_input(m_alsa, &ev); // Find a device matching the event's address. If one isn't // found, skip this event, since we're not interested in it. uint uid = AlsaMidiUtil::addressToVariant(&ev->source).toUInt(); if (m_devices.contains(uid) == true) device = m_devices[uid]; else continue; Q_ASSERT(device != NULL); uchar cmd = 0; uchar data1 = 0; uchar data2 = 0; //qDebug() << "ALSA MIDI event received !" << ev->type; if (snd_seq_ev_is_control_type(ev)) { switch (ev->type) { case SND_SEQ_EVENT_PGMCHANGE: cmd = MIDI_PROGRAM_CHANGE; data1 = ev->data.control.value; data2 = 127; break; case SND_SEQ_EVENT_CONTROLLER: cmd = MIDI_CONTROL_CHANGE | ev->data.control.channel; data1 = ev->data.control.param; data2 = ev->data.control.value; break; case SND_SEQ_EVENT_PITCHBEND: cmd = MIDI_PITCH_WHEEL | ev->data.control.channel; data1 = (ev->data.control.value + 8192) & 0x7f; data2 = (ev->data.control.value + 8192) >> 7; break; case SND_SEQ_EVENT_KEYPRESS: cmd = MIDI_NOTE_AFTERTOUCH | ev->data.note.channel; data1 = ev->data.note.note; data2 = ev->data.note.velocity; break; case SND_SEQ_EVENT_CHANPRESS: cmd = MIDI_CHANNEL_AFTERTOUCH | ev->data.control.channel; data1 = ev->data.control.value; break; default: break; } } else if (snd_seq_ev_is_note_type(ev)) { if (ev->type == SND_SEQ_EVENT_NOTEOFF) cmd = MIDI_NOTE_OFF | ev->data.note.channel; else if (ev->data.note.velocity == 0 && ev->data.note.off_velocity == 0) cmd = MIDI_NOTE_OFF | ev->data.note.channel; else cmd = MIDI_NOTE_ON | ev->data.note.channel; data1 = ev->data.note.note; data2 = ev->data.note.velocity; } else if (snd_seq_ev_is_queue_type(ev)) { if (device->processMBC(ev->type) == false) continue; if (ev->type == SND_SEQ_EVENT_START) cmd = MIDI_BEAT_START; else if(ev->type == SND_SEQ_EVENT_STOP) cmd = MIDI_BEAT_STOP; else if(ev->type == SND_SEQ_EVENT_CONTINUE) cmd = MIDI_BEAT_CONTINUE; else if(ev->type == SND_SEQ_EVENT_CLOCK) cmd = MIDI_BEAT_CLOCK; qDebug() << "MIDI clock: " << cmd; } // ALSA API is a bit controversial on this. snd_seq_event_input() says // it ALLOCATES the event but snd_seq_free_event() says this is not // needed because the event IS NOT allocated. No crashes observed // either way, so I guess freeing nevertheless is a bit safer. snd_seq_free_event(ev); uint channel = 0; uchar value = 0; if (QLCMIDIProtocol::midiToInput(cmd, data1, data2, device->midiChannel(), &channel, &value) == true) { device->emitValueChanged(channel, value); // for MIDI beat clock signals, // generate a synthetic release event if (cmd >= MIDI_BEAT_CLOCK && cmd <= MIDI_BEAT_STOP) device->emitValueChanged(channel, 0); } } while (snd_seq_event_input_pending(m_alsa, 0) > 0);
static void midi_in_cb (gpointer data, int fd, GdkInputCondition condition) { snd_seq_t *handle = (snd_seq_t *)data; snd_seq_event_t *pev; int rc; /* Perform sanity checks. */ if ((int)condition != GDK_INPUT_READ) { g_print( "wrong condition (%d). %d was expected\n", condition, GDK_INPUT_READ); return; } if (handle == NULL) { g_print( "NULL handle detected\n"); return; } /* Process MIDI event. Don't forget to free the event after usage. */ rc = snd_seq_event_input( handle, &pev); if (rc < 0) { g_print("unable to get event"); return; } switch (pev->type) { case SND_SEQ_EVENT_NOTEOFF: /* Simulate a note on event. */ pev->data.note.velocity = 0; /* no break here. Go to next case...*/ case SND_SEQ_EVENT_NOTE: case SND_SEQ_EVENT_NOTEON: if (IS_MIDI_DEBUG_ON) { midi_print_event(pev); } midi_process_note_on( &(pev->data.note)); break; case SND_SEQ_EVENT_CONTROLLER: if (IS_MIDI_DEBUG_ON) { midi_print_event(pev); } midi_process_controller( &(pev->data.control)); break; case SND_SEQ_EVENT_PGMCHANGE: if (IS_MIDI_DEBUG_ON) { midi_print_event(pev); } midi_process_program_change( &(pev->data.control)); break; default: if (IS_MIDI_DEBUG_ON) { /* Some events (like SND_SEQ_EVENT_SENSING) are not printed by the print_event routine. */ midi_print_event(pev); } break; } rc = snd_seq_free_event( pev); if (rc < 0) { g_print("unable to free event"); return; } return; } /* midi_in_cb() */
void Udp2MidiThread::run() { QUdpSocket *udpSocket = new QUdpSocket(); bool bres = udpSocket->bind(PC_PORT); if( bres == false ) { printf("Could not bind to port %d!\n", PC_PORT); return; } forever { if (abort) { delete udpSocket; return; } if( udpSocket->waitForReadyRead(250) == true ) { // Receive from UDP QHostAddress from_address; int len = udpSocket->readDatagram((char*)midimsg, MAX_MIDI_MESSAGE_LENGTH, &from_address); if( len == -1 ) { printf("udp2midi: Error receiving data!\n"); } if( (len == 3) && (midimsg[0] == 0) && (midimsg[1] == 0) && (midimsg[2] == 0) ) { string from_ip = from_address.toString().toStdString(); printf("Keepalive from: %s\n", from_ip.c_str()); midi2udp->add_ip(from_ip); } else { // Send to MIDI printf("udp2midi: Sending event: "); for(int i=0; i<len; ++i) { printf("0x%x ", midimsg[i]); } printf("\n"); long res = snd_midi_event_encode(eventparser, midimsg, len, midi_event); if( res < 0) { printf("Error encoding midi event!\n"); } snd_midi_event_reset_encode(eventparser); if(midi_event->type == SND_SEQ_EVENT_NOTEON) { printf("udp2midi: Note on: %d, channel %d\n", midi_event->data.note.note, midi_event->data.control.channel); } else if(midi_event->type == SND_SEQ_EVENT_NOTEOFF){ printf("udp2midi: Note off: %d, channel %d\n", midi_event->data.note.note, midi_event->data.control.channel); } snd_seq_ev_set_subs(midi_event); snd_seq_ev_set_direct(midi_event); snd_seq_ev_set_source(midi_event, midi_out_port); snd_seq_event_output_direct(seq_handle, midi_event); snd_seq_free_event(midi_event); } } } }
void midi_process(snd_seq_event_t *ev) { //If this event is a PGMCHANGE type, it's a request to map a channel to an instrument if( ev->type == SND_SEQ_EVENT_PGMCHANGE ) { printf("PGMCHANGE: channel %2d, %5d, %5d\n", ev->data.control.channel, ev->data.control.param, ev->data.control.value); //Clear pins state, this is probably the beginning of a new song clearPinsState(); //Filter out this channel if it's a base, percussion, or synth instrument if( (ev->data.control.value >= 8 && ev->data.control.value <= 15) || //Percussion (ev->data.control.value >= 32 && ev->data.control.value <= 39) || //Base (ev->data.control.value >= 88 && ev->data.control.value <= 103) //Synth ) { setPlayChannel(ev->data.control.channel, 0); } else { setPlayChannel(ev->data.control.channel, 1); } } //Note on/off event else if ( ((ev->type == SND_SEQ_EVENT_NOTEON)||(ev->type == SND_SEQ_EVENT_NOTEOFF)) ) { //If it's on a channel I care about if( isPlayChannel(ev->data.note.channel) ) { int isOn = 1; //Note velocity == 0 means the same thing as a NOTEOFF type event if( ev->data.note.velocity == 0 || ev->type == SND_SEQ_EVENT_NOTEOFF) { isOn = 0; } //There are 12 different kinds of notes. int noteMod = ev->data.note.note % 12; //Cast to double double noteModDouble = noteMod; //The pin to use is determined by: // ( pitch / ( Total number of notes / Total Number of Pins) ) double noteBin = noteModDouble / (12.0 / MY_NUM_PINS); //Cast back to int int pinIdx = (int)noteBin; //If pin is set to be turned on if( isOn ) { //If pin is currently available to play a note, or if currently playing channel can be overriden due to higher priority channel if( pinNotes[pinIdx] == -1 || pinChannels[pinIdx] > ev->data.note.channel ) { if( (pinChannels[pinIdx] > ev->data.note.channel ) && pinNotes[pinIdx] != -1) { printf("OVERRIDING CHANNEL %i for %i\n", pinChannels[pinIdx], ev->data.note.channel); } //Write to the pin, save the note to pinNotes //printf("Pin %i - %s %i %i \n", pinIdx, isOn ? "on" : "off", ev->data.note.note, ev->data.note.channel); digitalWrite(pinIdx, 1); pinNotes[pinIdx] = ev->data.note.note; pinChannels[pinIdx] = ev->data.note.channel; } } //Pin is to be turned off else { //If this is the note that turned the pin on.. if( pinNotes[pinIdx] == ev->data.note.note && pinChannels[pinIdx] == ev->data.note.channel ) { //Write to the pin, indicate that pin is available //printf("Pin %i - %s %i %i \n", pinIdx, isOn ? "on" : "off", ev->data.note.note, ev->data.note.channel); digitalWrite(pinIdx, 0); pinNotes[pinIdx] = -1; pinChannels[pinIdx] = INT_MAX; } } } } else { printf("Unhandled event %2d\n", ev->type); } snd_seq_free_event(ev); }
int main( int argc, char *argv[] ) { jack_client_t *jackClient; snd_seq_t *seqport; struct pollfd *pfd; int npfd; snd_seq_event_t *midievent; int channel, midiport; int note, length, i; double freq; puts( "SO-666 v.1.01 by 50m30n3 2009-2010" ); if( argc > 1 ) channel = atoi( argv[1] ); else channel = 0; signal( SIGINT, sig_exit ); signal( SIGTERM, sig_exit ); puts( "Connecting to Jack Audio Server" ); jackClient = jack_client_open( "SO-666", JackNoStartServer, NULL ); if( jackClient == NULL ) { fputs( "Cannot connect to Jack Server\n", stderr ); return 1; } jack_on_shutdown( jackClient, jack_shutdown, 0 ); outport = jack_port_register( jackClient, "output", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput | JackPortIsTerminal, 0 ); jack_set_process_callback( jackClient, process, 0 ); samplerate = jack_get_sample_rate( jackClient ); puts( "Initializing synth parameters" ); feedback = 32; cutoff = 64; resonance = 64; volume = 100; fcutoff = pow( (cutoff+50.0)/200.0, 5.0 ); freso = resonance/127.0; ffeedback = 0.01+pow( feedback/127.0, 4.0)*0.9; for( note=0; note<NUMNOTES; note++ ) { freq = 440.0*pow( 2.0, (note+BASENOTE-69) / 12.0 ); //stringcutoff[note] = ( freq * 16.0 ) / (double)samplerate; stringcutoff[note] = 0.9; length = (double)samplerate / freq; stringlength[note] = length; strings[note] = malloc( length * sizeof( double ) ); if( strings[note] == NULL ) { fputs( "Error allocating memory\n", stderr ); return 1; } for( i=0; i<length; i++ ) { strings[note][i] = 0.0; } stringpos[note] = 0; status[note] = 0; } lpval = lplast = 0.0; hpval = hplast = 0.0; jack_activate( jackClient ); printf( "Listening on MIDI channel %i\n", channel ); if( snd_seq_open( &seqport, "default", SND_SEQ_OPEN_INPUT, 0 ) < 0 ) { fputs( "Cannot connect to ALSA sequencer\n", stderr ); return 1; } snd_seq_set_client_name( seqport, "SO-666" ); midiport = snd_seq_create_simple_port( seqport, "input", SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, SND_SEQ_PORT_TYPE_APPLICATION ); if( midiport < 0 ) { fputs( "Cannot create ALSA sequencer port\n", stderr ); return 1; } npfd = snd_seq_poll_descriptors_count( seqport, POLLIN ); pfd = (struct pollfd *)malloc( npfd * sizeof( struct pollfd ) ); snd_seq_poll_descriptors( seqport, pfd, npfd, POLLIN ); done = 0; while( ! done ) { if( poll( pfd, npfd, 100000 ) > 0 ) { do { snd_seq_event_input( seqport, &midievent ); if( ( midievent->type == SND_SEQ_EVENT_NOTEON ) && ( midievent->data.note.channel == channel ) ) { note = midievent->data.note.note; if( ( note >= BASENOTE ) && ( note < BASENOTE+NUMNOTES ) ) { note -= BASENOTE; status[note] = 1; } } else if( ( midievent->type == SND_SEQ_EVENT_NOTEOFF ) && ( midievent->data.note.channel == channel ) ) { note = midievent->data.note.note; if( ( note >= BASENOTE ) && ( note < BASENOTE+NUMNOTES ) ) { note -= BASENOTE; status[note] = 0; } } else if( ( midievent->type == SND_SEQ_EVENT_CONTROLLER ) && ( midievent->data.control.channel == channel ) ) { if( midievent->data.control.param == 74 ) { cutoff = midievent->data.control.value; fcutoff = pow( (cutoff+50.0)/200.0, 5.0 ); printf( "Cutoff: %i \r", cutoff ); fflush( stdout ); } else if( midievent->data.control.param == 71 ) { resonance = midievent->data.control.value; freso = resonance/127.0; printf( "Resonance: %i \r", resonance ); fflush( stdout ); } else if( midievent->data.control.param == 7 ) { volume = midievent->data.control.value; printf( "Volume: %i \r", volume ); fflush( stdout ); } else if( midievent->data.control.param == 1 ) { feedback = midievent->data.control.value; ffeedback = 0.01+pow( feedback/127.0, 4.0)*0.9; printf( "Feedback: %i \r", feedback ); fflush( stdout ); } } snd_seq_free_event( midievent ); } while( snd_seq_event_input_pending( seqport, 0 ) > 0 ); } } free( pfd ); snd_seq_delete_port( seqport, midiport ); snd_seq_close( seqport ); jack_deactivate( jackClient ); puts( "Freeing data" ); for( note=0; note<NUMNOTES; note++ ) { free( strings[note] ); } jack_port_unregister( jackClient, outport ); jack_client_close( jackClient ); return 0; }
static DWORD WINAPI midRecThread(LPVOID arg) { int npfd; struct pollfd *pfd; TRACE("Thread startup\n"); while(!end_thread) { TRACE("Thread loop\n"); npfd = snd_seq_poll_descriptors_count(midiSeq, POLLIN); pfd = HeapAlloc(GetProcessHeap(), 0, npfd * sizeof(struct pollfd)); snd_seq_poll_descriptors(midiSeq, pfd, npfd, POLLIN); /* Check if an event is present */ if (poll(pfd, npfd, 250) < 0) { HeapFree(GetProcessHeap(), 0, pfd); continue; } /* Note: This definitely does not work. * while(snd_seq_event_input_pending(midiSeq, 0) > 0) { snd_seq_event_t* ev; snd_seq_event_input(midiSeq, &ev); .................... snd_seq_free_event(ev); }*/ do { WORD wDevID; snd_seq_event_t* ev; snd_seq_event_input(midiSeq, &ev); /* Find the target device */ for (wDevID = 0; wDevID < MIDM_NumDevs; wDevID++) if ( (ev->source.client == MidiInDev[wDevID].addr.client) && (ev->source.port == MidiInDev[wDevID].addr.port) ) break; if ((wDevID == MIDM_NumDevs) || (MidiInDev[wDevID].state != 1)) FIXME("Unexpected event received, type = %x from %d:%d\n", ev->type, ev->source.client, ev->source.port); else { DWORD dwTime, toSend = 0; /* FIXME: Should use ev->time instead for better accuracy */ dwTime = GetTickCount() - MidiInDev[wDevID].startTime; TRACE("Event received, type = %x, device = %d\n", ev->type, wDevID); switch(ev->type) { case SND_SEQ_EVENT_NOTEOFF: toSend = (ev->data.note.velocity << 16) | (ev->data.note.note << 8) | MIDI_CMD_NOTE_OFF | ev->data.control.channel; break; case SND_SEQ_EVENT_NOTEON: toSend = (ev->data.note.velocity << 16) | (ev->data.note.note << 8) | MIDI_CMD_NOTE_ON | ev->data.control.channel; break; case SND_SEQ_EVENT_KEYPRESS: toSend = (ev->data.note.velocity << 16) | (ev->data.note.note << 8) | MIDI_CMD_NOTE_PRESSURE | ev->data.control.channel; break; case SND_SEQ_EVENT_CONTROLLER: toSend = (ev->data.control.value << 16) | (ev->data.control.param << 8) | MIDI_CMD_CONTROL | ev->data.control.channel; break; case SND_SEQ_EVENT_PITCHBEND: toSend = (ev->data.control.value << 16) | (ev->data.control.param << 8) | MIDI_CMD_BENDER | ev->data.control.channel; break; case SND_SEQ_EVENT_PGMCHANGE: toSend = (ev->data.control.value << 16) | (ev->data.control.param << 8) | MIDI_CMD_PGM_CHANGE | ev->data.control.channel; break; case SND_SEQ_EVENT_CHANPRESS: toSend = (ev->data.control.value << 16) | (ev->data.control.param << 8) | MIDI_CMD_CHANNEL_PRESSURE | ev->data.control.channel; break; case SND_SEQ_EVENT_SYSEX: { int len = ev->data.ext.len; LPBYTE ptr = (BYTE*) ev->data.ext.ptr; LPMIDIHDR lpMidiHdr; /* FIXME: Should handle sysex greater that a single buffer */ EnterCriticalSection(&crit_sect); if ((lpMidiHdr = MidiInDev[wDevID].lpQueueHdr) != NULL) { if (len <= lpMidiHdr->dwBufferLength) { lpMidiHdr->dwBytesRecorded = len; memcpy(lpMidiHdr->lpData, ptr, len); lpMidiHdr->dwFlags &= ~MHDR_INQUEUE; lpMidiHdr->dwFlags |= MHDR_DONE; MidiInDev[wDevID].lpQueueHdr = (LPMIDIHDR)lpMidiHdr->lpNext; if (MIDI_NotifyClient(wDevID, MIM_LONGDATA, (DWORD)lpMidiHdr, dwTime) != MMSYSERR_NOERROR) WARN("Couldn't notify client\n"); } else FIXME("No enough space in the buffer to store sysex!\n"); } else FIXME("Sysex received but no buffer to store it!\n"); LeaveCriticalSection(&crit_sect); } break; case SND_SEQ_EVENT_SENSING: /* Noting to do */ break; default: FIXME("Unhandled event received, type = %x\n", ev->type); break; } if (toSend != 0) { TRACE("Sending event %08lx (from %d %d)\n", toSend, ev->source.client, ev->source.port); if (MIDI_NotifyClient(wDevID, MIM_DATA, toSend, dwTime) != MMSYSERR_NOERROR) { WARN("Couldn't notify client\n"); } } } snd_seq_free_event(ev); } while(snd_seq_event_input_pending(midiSeq, 0) > 0); HeapFree(GetProcessHeap(), 0, pfd); } return 0; }
void event_decoder(snd_seq_t *handle, int argc, char *argv[]) { snd_seq_event_t *ev; snd_seq_port_info_t *pinfo; snd_seq_port_subscribe_t *sub; snd_seq_addr_t addr; int client, port, queue, max, err, v1, v2; char *ptr; struct pollfd *pfds; if ((client = snd_seq_client_id(handle))<0) { fprintf(stderr, "Cannot determine client number: %s\n", snd_strerror(client)); return; } printf("Client ID = %i\n", client); if ((queue = snd_seq_alloc_queue(handle))<0) { fprintf(stderr, "Cannot allocate queue: %s\n", snd_strerror(queue)); return; } printf("Queue ID = %i\n", queue); if ((err = snd_seq_nonblock(handle, 1))<0) fprintf(stderr, "Cannot set nonblock mode: %s\n", snd_strerror(err)); snd_seq_port_info_alloca(&pinfo); snd_seq_port_info_set_name(pinfo, "Input"); snd_seq_port_info_set_type(pinfo, SND_SEQ_PORT_TYPE_MIDI_GENERIC); snd_seq_port_info_set_capability(pinfo, SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_WRITE); /* Enable timestamping for events sent by external subscribers. */ snd_seq_port_info_set_timestamping(pinfo, 1); snd_seq_port_info_set_timestamp_real(pinfo, 1); snd_seq_port_info_set_timestamp_queue(pinfo, queue); if ((err = snd_seq_create_port(handle, pinfo)) < 0) { fprintf(stderr, "Cannot create input port: %s\n", snd_strerror(err)); return; } port = snd_seq_port_info_get_port(pinfo); event_decoder_start_timer(handle, queue, client, port); snd_seq_port_subscribe_alloca(&sub); addr.client = SND_SEQ_CLIENT_SYSTEM; addr.port = SND_SEQ_PORT_SYSTEM_ANNOUNCE; snd_seq_port_subscribe_set_sender(sub, &addr); addr.client = client; addr.port = port; snd_seq_port_subscribe_set_dest(sub, &addr); snd_seq_port_subscribe_set_queue(sub, queue); snd_seq_port_subscribe_set_time_update(sub, 1); snd_seq_port_subscribe_set_time_real(sub, 1); if ((err = snd_seq_subscribe_port(handle, sub))<0) { fprintf(stderr, "Cannot subscribe announce port: %s\n", snd_strerror(err)); return; } addr.client = SND_SEQ_CLIENT_SYSTEM; addr.port = SND_SEQ_PORT_SYSTEM_TIMER; snd_seq_port_subscribe_set_sender(sub, &addr); if ((err = snd_seq_subscribe_port(handle, sub))<0) { fprintf(stderr, "Cannot subscribe timer port: %s\n", snd_strerror(err)); return; } for (max = 0; max < argc; max++) { ptr = argv[max]; if (!ptr) continue; snd_seq_port_subscribe_set_time_real(sub, 0); if (tolower(*ptr) == 'r') { snd_seq_port_subscribe_set_time_real(sub, 1); ptr++; } if (sscanf(ptr, "%i.%i", &v1, &v2) != 2) { fprintf(stderr, "Wrong argument '%s'...\n", argv[max]); return; } addr.client = v1; addr.port = v2; snd_seq_port_subscribe_set_sender(sub, &addr); if ((err = snd_seq_subscribe_port(handle, sub))<0) { fprintf(stderr, "Cannot subscribe port %i from client %i: %s\n", v2, v1, snd_strerror(err)); return; } } max = snd_seq_poll_descriptors_count(handle, POLLIN); pfds = alloca(sizeof(*pfds) * max); while (1) { snd_seq_poll_descriptors(handle, pfds, max, POLLIN); if (poll(pfds, max, -1) < 0) break; do { if ((err = snd_seq_event_input(handle, &ev))<0) break; if (!ev) continue; decode_event(ev); snd_seq_free_event(ev); } while (err > 0); } }
static int vj_dequeue_midi_event( vmidi_t *v ) { int ret = 0; int err = 0; while( snd_seq_event_input_pending( v->sequencer, 1 ) > 0 ) { int data[4] = { 0,0,0,0}; int isvalid = 1; snd_seq_event_t *ev = NULL; err = snd_seq_event_input( v->sequencer, &ev ); if( err == -ENOSPC || err == -EAGAIN ) return ret; data[0] = ev->type; switch( ev->type ) { /* controller: channel <0-N>, <modwheel 0-127> */ case SND_SEQ_EVENT_CONTROLLER: data[1] = ev->data.control.channel*256+ev->data.control.param; // OB: added chan+param as identifier data[2] = ev->data.control.value; break; case SND_SEQ_EVENT_PITCHBEND: data[1] = ev->data.control.channel; data[2] = ev->data.control.value; break; case SND_SEQ_EVENT_NOTE: data[1] = ev->data.control.channel; data[2] = ev->data.note.note; break; case SND_SEQ_EVENT_NOTEON: data[2] = ev->data.control.channel; data[1] = ev->data.note.note; break; case SND_SEQ_EVENT_NOTEOFF: data[2] = ev->data.control.channel; data[1] = ev->data.note.note; break; case SND_SEQ_EVENT_KEYPRESS: data[1] = ev->data.control.channel; data[2] = ev->data.note.velocity; break; case SND_SEQ_EVENT_PGMCHANGE: data[1] = ev->data.control.param; data[2] = ev->data.control.value; break; default: data[1] = -1; data[2] = -1; isvalid = 0; veejay_msg(VEEJAY_MSG_WARNING, "unknown midi event received: %d %x %x",ev->type,data[1],data[2],data[2]); break; } if( isvalid == 1 ) { vj_midi_send_vims_now( v, data ); } if( ev ) { snd_seq_free_event( ev ); ret ++; } } return ret; }
void PrintMidiIn() { snd_seq_event_t* t_event; char bytes[] = {0x00, 0x00, 0xFF}; do { snd_seq_event_input(t_seq, &t_event); //printf("t_event->source.port: %u\n", t_event->source.port); //printf("t_event->source.client: %u\n", t_event->source.client); if (t_event->data.addr.port == nIdPortInA) printf("PORTA AA\n"); else if(t_event->data.addr.port == nIdPortInB) printf("PORTA BB\n"); else if(t_event->data.addr.port == nIdPortInC) printf("PORTA CC\n"); else printf("ev->data.addr.port: %u\n", t_event->data.addr.port); //printf("ev->data.addr.client: %u\n", t_event->data.addr.client); if (t_event->dest.port == nIdPortInA) printf("PORTA A\n"); else if(t_event->dest.port == nIdPortInB) printf("PORTA B\n"); else if(t_event->dest.port == nIdPortInC) printf("PORTA C\n"); else printf("t_event->dest.port: %u\n", t_event->data.addr.port); switch (t_event->type) { case SND_SEQ_EVENT_NOTEOFF: bytes[0] = 0x80 + t_event->data.control.channel; bytes[1] = t_event->data.note.note; bytes[2] = t_event->data.note.velocity; printf("IN ==> 0x%x Note off 0x%x 0x%x 0x%x\n", bytes[0]&0xF0, bytes[0]&0xF, bytes[1], bytes[2]); break; case SND_SEQ_EVENT_NOTEON: bytes[0] = 0x90 + t_event->data.control.channel; bytes[1] = t_event->data.note.note; bytes[2] = t_event->data.note.velocity; printf("IN ==> 0x%x Note on 0x%x 0x%x 0x%x\n", bytes[0]&0xF0, bytes[0]&0xF, bytes[1], bytes[2]); break; case SND_SEQ_EVENT_KEYPRESS: bytes[0] = 0x90 + t_event->data.control.channel; bytes[1] = t_event->data.note.note; bytes[2] = t_event->data.note.velocity; printf("IN ==> 0x%x Pressure change 0x%x 0x%x 0x%x\n", bytes[0]&0xF0, bytes[0]&0xF, bytes[1], bytes[2]); break; case SND_SEQ_EVENT_CONTROLLER: bytes[0] = 0xB0 + t_event->data.control.channel; bytes[1] = t_event->data.control.param; bytes[2] = t_event->data.control.value; printf("IN ==> 0x%x Controller change 0x%x 0x%x 0x%x\n", bytes[0]&0xF0, bytes[0]&0xF, bytes[1], bytes[2]); break; case SND_SEQ_EVENT_PGMCHANGE: bytes[0] = 0xC0 + t_event->data.control.channel; bytes[1] = t_event->data.control.value; printf("IN ==> 0x%x Program change 0x%x 0x%x 0x%x\n", bytes[0]&0xF0, bytes[0]&0xF, bytes[1], bytes[2]); break; case SND_SEQ_EVENT_CHANPRESS: bytes[0] = 0xD0 + t_event->data.control.channel; bytes[1] = t_event->data.control.value; printf("IN ==> 0x%x Channel change 0x%x 0x%x 0x%x\n", bytes[0]&0xF0, bytes[0]&0xF, bytes[1], bytes[2]); break; case SND_SEQ_EVENT_PITCHBEND: bytes[0] = 0xE0 + t_event->data.control.channel; t_event->data.control.value += 8192; bytes[1] = (int)t_event->data.control.value & 0x7F; bytes[2] = (int)t_event->data.control.value >> 7; printf("IN ==> 0x%x Pitch bend %03u %5d\n", bytes[0]&0xF0, bytes[0]&0xF, t_event->data.control.value); break; default: break; } snd_seq_free_event(t_event); } while (snd_seq_event_input_pending(t_seq, 0) > 0); }
int main(int argc, char *argv[]){ int note = -1; /* MIDI note we are currently playing. */ int note_update = 1; /* If 1, the note has changed; * re-send the output voltage. */ int pitchbend = 8192; /* Current pitchbend value. 8192 = no bend. */ snd_seq_t *seqhandle; /* ALSA Sequencer handle */ snd_seq_event_t *ev; /* Sequencer event for handling MIDI messages. */ int npfd; /* Number of pollfds */ struct pollfd *pfd; /* Storage for array of struct pollfd, used for * polling for MIDI messages. */ if(argc != 2){ fputs(usage, stderr); return -1; } if(serialcv_init(argv[1], VREF)){ fputs("monotron: could not open serial port\n", stderr); return -2; } if(alsa_init(&seqhandle)){ fputs("monotron: coudle not open ALSA sequencer\n", stderr); serialcv_shutdown(); return -3; } npfd = snd_seq_poll_descriptors_count(seqhandle, POLLIN); pfd = malloc(npfd * sizeof(struct pollfd)); if(NULL == pfd){ fputs("monotron: malloc failure\n", stderr); serialcv_shutdown(); alsa_shutdown(seqhandle); } snd_seq_poll_descriptors(seqhandle, pfd, npfd, POLLIN); signal(SIGINT, terminate_loop); signal(SIGTERM, terminate_loop); while(!gotsignal){ if(note_update){ if(note >= 0){ serialcv_voltage(note_voltage(note) + pitchbend_voltage(pitchbend)); } else { serialcv_voltage(note_voltage(-1)); } note_update = 0; } if(poll(pfd, npfd, 1000) > 0){ /* MIDI Message received */ do{ snd_seq_event_input(seqhandle, &ev); if(MIDI_CH == ev->data.control.channel){ switch(ev->type){ case SND_SEQ_EVENT_PITCHBEND: pitchbend = ev->data.control.value; note_update = 1; break; case SND_SEQ_EVENT_NOTEON: if(0 == ev->data.note.velocity){ if(ev->data.note.note == note){ note = -1; note_update = 1; } } else { note = ev->data.note.note; /* Briefly output the idle voltage to * re-trigger the synth's EG */ serialcv_voltage(IDLE_VOLTS); note_update = 1; } break; case SND_SEQ_EVENT_NOTEOFF: if(ev->data.note.note == note){ note = -1; note_update = 1; } break; } } snd_seq_free_event(ev); }while(snd_seq_event_input_pending(seqhandle, 0)); } } serialcv_shutdown(); alsa_shutdown(seqhandle); free(pfd); return 0; }