void RKR::miramidi () { if (snd_seq_event_input_pending (midi_in, 1)) { do { midievents (); } while (snd_seq_event_input_pending (midi_in, 0)); } };
/* 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 run() { snd_seq_t *seq = m_sampl->alsa_seq(); if (seq == NULL) return; m_running = true; int nfds; struct pollfd *pfds; nfds = snd_seq_poll_descriptors_count(seq, POLLIN); pfds = (struct pollfd *) alloca(nfds * sizeof(struct pollfd)); snd_seq_poll_descriptors(seq, pfds, nfds, POLLIN); int poll_rc = 0; while (m_running && poll_rc >= 0) { poll_rc = ::poll(pfds, nfds, 200); while (poll_rc > 0) { snd_seq_event_t *ev = NULL; snd_seq_event_input(seq, &ev); m_sampl->alsa_capture(ev); // snd_seq_free_event(ev); poll_rc = snd_seq_event_input_pending(seq, 0); } } m_running = false; }
/* 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 SeqDriver::procEvents() { int l1; snd_seq_event_t *evIn, evOut; bool outOfRange = false; bool unmatched = false; MidiMap* mm; do { snd_seq_event_input(seq_handle, &evIn); emit midiEvent(evIn); unmatched = true; for(l1 = 0; l1 < midiMapList->count(); l1++) { mm = midiMapList->at(l1); if (mm->isMap(evIn)) { unmatched = false; mm->doMap(evIn, &evOut, &outOfRange); if (!outOfRange) { snd_seq_ev_set_subs(&evOut); snd_seq_ev_set_direct(&evOut); snd_seq_ev_set_source(&evOut, portid_out[mm->portOut]); snd_seq_event_output_direct(seq_handle, &evOut); } } } if (!discardUnmatched && unmatched) { snd_seq_ev_set_subs(evIn); snd_seq_ev_set_direct(evIn); snd_seq_ev_set_source(evIn, portid_out[portUnmatched]); snd_seq_event_output_direct(seq_handle, evIn); } } while (snd_seq_event_input_pending(seq_handle, 0) > 0); }
int AlsaSeqMidiInDriver::read(unsigned char* buf, int max) { if (!this->is_open()) throw std::logic_error("Device not open"); int bytes_read= 0; int err; snd_seq_event_t *ev; do { if (snd_seq_event_input(m_impl->seq, &ev) > 0 ) { err = snd_midi_event_decode (m_impl->decoder, buf, max, ev); //snd_seq_free_event( ev ); if (err > 0) { buf += err; bytes_read += err; max -= err; } else { // error or buffer full -> drop midi event } } } while (snd_seq_event_input_pending(m_impl->seq, 0) > 0); return bytes_read; }
bool mastermidibus::is_more_input () { #ifdef SEQ64_HAVE_LIBASOUND automutex locker(m_mutex); return snd_seq_event_input_pending(m_alsa_seq, 0) > 0; #else return false; #endif }
static PyObject * alsaseq_inputpending(PyObject *self, PyObject *args) { int res; if (!PyArg_ParseTuple(args, "" )) return NULL; res = snd_seq_event_input_pending( seq_handle, 1 ); /* fetch_sequencer */ return PyInt_FromLong( res ); }
bool mastermidibus::is_more_input () { #ifdef HAVE_LIBASOUND automutex locker(m_mutex); int size = snd_seq_event_input_pending(m_alsa_seq, 0); #else int size = 0; #endif return size > 0; }
bool mastermidibus::is_more_input( ){ lock(); int size = snd_seq_event_input_pending(m_alsa_seq, 0); unlock(); return ( size > 0 ); }
static PyObject *get_event_nb(PyObject *self, PyObject *args) { if (!PyArg_ParseTuple(args, "")) /* no args */ return NULL; int n_events = snd_seq_event_input_pending(seq, 1); if (n_events > 0) return get_event(self, args); Py_INCREF(Py_None); return Py_None; }
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); } };
static PyObject * alsaseq_inputpending(PyObject *self, PyObject *args) { int res; if (!PyArg_ParseTuple(args, "" )) return NULL; if (!seq_handle) { PyErr_SetString(PyExc_RuntimeError, "Must initialize module with alsaseq.client() before using it"); return NULL; } res = snd_seq_event_input_pending( seq_handle, 1 ); /* fetch_sequencer */ return PyInt_FromLong( res ); }
static ssize_t snd_rawmidi_virtual_read(snd_rawmidi_t *rmidi, void *buffer, size_t size) { snd_rawmidi_virtual_t *virt = rmidi->private_data; ssize_t result = 0; int size1, err; while (size > 0) { if (! virt->in_buf_ofs) { err = snd_seq_event_input_pending(virt->handle, 1); if (err <= 0 && result > 0) return result; err = snd_seq_event_input(virt->handle, &virt->in_event); if (err < 0) return result > 0 ? result : err; if (virt->in_event->type == SND_SEQ_EVENT_SYSEX) { virt->in_buf_ptr = virt->in_event->data.ext.ptr; virt->in_buf_size = virt->in_event->data.ext.len; } else { virt->in_buf_ptr = virt->in_tmp_buf; virt->in_buf_size = snd_midi_event_decode(virt->midi_event, (unsigned char *)virt->in_tmp_buf, sizeof(virt->in_tmp_buf), virt->in_event); } if (virt->in_buf_size <= 0) continue; } size1 = virt->in_buf_size - virt->in_buf_ofs; if ((size_t)size1 > size) { memcpy(buffer, virt->in_buf_ptr + virt->in_buf_ofs, size); virt->in_buf_ofs += size; result += size; break; } memcpy(buffer, virt->in_buf_ptr + virt->in_buf_ofs, size1); size -= size1; result += size1; buffer += size1; virt->in_buf_ofs = 0; } return result; }
/* 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); }
// The main thread executive. void run() { snd_seq_t *pAlsaSeq = m_pMidiDevice->alsaSeq(); if (pAlsaSeq == NULL) return; int nfds; struct pollfd *pfds; nfds = snd_seq_poll_descriptors_count(pAlsaSeq, POLLIN); pfds = (struct pollfd *) alloca(nfds * sizeof(struct pollfd)); snd_seq_poll_descriptors(pAlsaSeq, pfds, nfds, POLLIN); qxgeditMidiInputRpn xrpn; m_bRunState = true; int iPoll = 0; while (m_bRunState && iPoll >= 0) { // Wait for events... iPoll = poll(pfds, nfds, 200); // Timeout? if (iPoll == 0) xrpn.flush(); while (iPoll > 0) { snd_seq_event_t *pEv = NULL; snd_seq_event_input(pAlsaSeq, &pEv); // Process input event - ... // - enqueue to input track mapping; if (!xrpn.process(pEv)) m_pMidiDevice->capture(pEv); // snd_seq_free_event(pEv); iPoll = snd_seq_event_input_pending(pAlsaSeq, 0); } // Process pending events... while (xrpn.isPending()) { snd_seq_event_t ev; if (xrpn.dequeue(&ev)) m_pMidiDevice->capture(&ev); } } }
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); }
/* this version uses the asynchronous "read()" ... */ void sys_alsa_poll_midi(void) { unsigned char buf[ALSA_MAX_EVENT_SIZE]; int count, alsa_source; int i; snd_seq_event_t *midievent = NULL; if (alsa_nmidiout == 0 && alsa_nmidiin == 0) return; snd_midi_event_init(midiev); if (!alsa_nmidiout && !alsa_nmidiin) return; count = snd_seq_event_input_pending(midi_handle,1); if (count != 0) count = snd_seq_event_input(midi_handle,&midievent); if (midievent != NULL) { count = snd_midi_event_decode(midiev,buf,sizeof(buf),midievent); alsa_source = midievent->dest.port; for(i=0;i<count;i++) sys_midibytein(alsa_source, (buf[i] & 0xff)); //post("received %d midi bytes\n",count); } }
static gboolean data_pending (void) { return snd_seq_event_input_pending (seq, TRUE) != 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; }
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; }
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 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); }
void MidiAlsaSeq::run() { // watch the pipe and sequencer input events int pollfd_count = snd_seq_poll_descriptors_count( m_seqHandle, POLLIN ); struct pollfd * pollfd_set = new struct pollfd[pollfd_count + 1]; snd_seq_poll_descriptors( m_seqHandle, pollfd_set + 1, pollfd_count, POLLIN ); pollfd_set[0].fd = m_pipe[0]; pollfd_set[0].events = POLLIN; ++pollfd_count; while( m_quit == false ) { int pollRet = poll( pollfd_set, pollfd_count, EventPollTimeOut ); if( pollRet == 0 ) { continue; } else if( pollRet == -1 ) { // gdb may interrupt the poll if( errno == EINTR ) { continue; } qCritical( "error while polling ALSA sequencer handle" ); break; } // shutdown? if( m_quit ) { break; } m_seqMutex.lock(); // while event queue is not empty while( snd_seq_event_input_pending( m_seqHandle, true ) > 0 ) { snd_seq_event_t * ev; if( snd_seq_event_input( m_seqHandle, &ev ) < 0 ) { m_seqMutex.unlock(); qCritical( "error while fetching MIDI event from sequencer" ); break; } m_seqMutex.unlock(); snd_seq_addr_t * source = NULL; MidiPort * dest = NULL; for( int i = 0; i < m_portIDs.size(); ++i ) { if( m_portIDs.values()[i][0] == ev->dest.port ) { dest = m_portIDs.keys()[i]; } if( ( m_portIDs.values()[i][1] != -1 && m_portIDs.values()[i][1] == ev->source.port ) || m_portIDs.values()[i][0] == ev->source.port ) { source = &ev->source; } } if( dest == NULL ) { continue; } switch( ev->type ) { case SND_SEQ_EVENT_NOTEON: dest->processInEvent( MidiEvent( MidiNoteOn, ev->data.note.channel, ev->data.note.note - KeysPerOctave, ev->data.note.velocity, source ), MidiTime( ev->time.tick ) ); break; case SND_SEQ_EVENT_NOTEOFF: dest->processInEvent( MidiEvent( MidiNoteOff, ev->data.note.channel, ev->data.note.note - KeysPerOctave, ev->data.note.velocity, source ), MidiTime( ev->time.tick) ); break; case SND_SEQ_EVENT_KEYPRESS: dest->processInEvent( MidiEvent( MidiKeyPressure, ev->data.note.channel, ev->data.note.note - KeysPerOctave, ev->data.note.velocity, source ), MidiTime() ); break; case SND_SEQ_EVENT_CONTROLLER: dest->processInEvent( MidiEvent( MidiControlChange, ev->data.control.channel, ev->data.control.param, ev->data.control.value, source ), MidiTime() ); break; case SND_SEQ_EVENT_PGMCHANGE: dest->processInEvent( MidiEvent( MidiProgramChange, ev->data.control.channel, ev->data.control.param, ev->data.control.value, source ), MidiTime() ); break; case SND_SEQ_EVENT_CHANPRESS: dest->processInEvent( MidiEvent( MidiChannelPressure, ev->data.control.channel, ev->data.control.param, ev->data.control.value, source ), MidiTime() ); break; case SND_SEQ_EVENT_PITCHBEND: dest->processInEvent( MidiEvent( MidiPitchBend, ev->data.control.channel, ev->data.control.value + 8192, 0, source ), MidiTime() ); break; case SND_SEQ_EVENT_SENSING: case SND_SEQ_EVENT_CLOCK: break; default: fprintf( stderr, "ALSA-sequencer: unhandled input " "event %d\n", ev->type ); break; } // end switch m_seqMutex.lock(); } // end while m_seqMutex.unlock(); } delete[] pollfd_set; }
void * midi_thread_function(void *arg) { int rc; struct sched_param rtparam; snd_seq_event_t *ev = 0; /* try to get low-priority real-time scheduling */ memset (&rtparam, 0, sizeof (rtparam)); rtparam.sched_priority = 1; /* just above SCHED_OTHER */ if ((rc = pthread_setschedparam (pthread_self(), SCHED_FIFO, &rtparam)) != 0) { if (rc == EPERM) { ghss_debug_rt(GDB_MIDI, " midi thread: no permission for SCHED_FIFO, continuing..."); } else { ghss_debug_rt(GDB_MIDI, " midi thread: error getting SCHED_FIFO, continuing..."); } } midi_thread_running = 1; do { /* while(!host_exiting) */ rc = poll(alsaClient_pfd, alsaClient_npfd, 500); if (rc <= 0) { if (rc < 0 && rc != EINTR) { ghss_debug_rt(GDB_MIDI, " midi thread: poll error: %s", strerror(errno)); usleep(500); } continue; } pthread_mutex_lock(&midiEventBufferMutex); do { if (snd_seq_event_input(alsaClient, &ev) > 0) { if (midiEventReadIndex == midiEventWriteIndex + 1) { ghss_debug_rt(GDB_MIDI, " midi thread: MIDI event buffer overflow!"); continue; } midiEventBuffer[midiEventWriteIndex] = *ev; ev = &midiEventBuffer[midiEventWriteIndex]; /* We don't need to handle EVENT_NOTE here, because ALSA won't ever deliver them on the sequencer queue -- it unbundles them into NOTE_ON and NOTE_OFF when they're dispatched. We would only need worry about them when retrieving MIDI events from some other source. */ if (ev->type == SND_SEQ_EVENT_NOTEON && ev->data.note.velocity == 0) { ev->type = SND_SEQ_EVENT_NOTEOFF; } /* fprintf(stderr, "midi: flags %02x, tick %u, sec %u nsec %u\n", * ev->flags, ev->time.tick, ev->time.time.tv_sec, ev->time.time.tv_nsec); * fflush(stderr); */ /* -FIX- Ideally, we would use ev->time to figure out how long ago * this event was generated, and adjust accordingly. Instead, we * take the easy-and-fast route of just restamping the event with * the JACK rolling frame time at its arrival, which seems to work * pretty well.... */ /* -FIX- Rosegarden has example of setting up input queue, see * /t/src/example/rosegarden-CVS-20050109/sound/AlsaDriver.cpp */ /* -FIX- snd_seq_ioctl_get_queue_status, aka snd_seq_MUMBLE_get_queue_status() * should return current queue time, subtract event time from that to get offset * into past that event arrived? */ ev->time.tick = jack_frame_time(jackClient); /* fprintf(stderr, "midi: %u\n", ev->time.tick); fflush(stderr); */ ev->dest.client = 0; /* flag as from MIDI thread */ midiEventWriteIndex = (midiEventWriteIndex + 1) % EVENT_BUFFER_SIZE; } } while (snd_seq_event_input_pending(alsaClient, 0) > 0); pthread_mutex_unlock(&midiEventBufferMutex); } while(!host_exiting); midi_thread_running = 0; return NULL; }