void decode_midi_buffer (uint32_t *buffer_uint32, unsigned int buffer_size_uint32, jack_default_audio_sample_t* buf) { int i; jack_midi_clear_buffer (buf); for (i = 0; i < buffer_size_uint32 - 3;) { uint32_t payload_size; payload_size = buffer_uint32[i]; payload_size = ntohl (payload_size); if (payload_size) { jack_midi_event_t event; event.time = ntohl (buffer_uint32[i+1]); event.size = ntohl (buffer_uint32[i+2]); event.buffer = (jack_midi_data_t*) (&(buffer_uint32[i+3])); jack_midi_event_write (buf, event.time, event.buffer, event.size); // skip to the next event unsigned int nb_data_quads = (((event.size-1) & ~0x3) >> 2)+1; i += 3+nb_data_quads; } else break; // no events can follow an empty event, we're done }
void MidiBuffer::clearEventBuffer() { if(!isValid()) { return; } jack_midi_clear_buffer(_jackBuffer); }
static void jack_process(alsa_seqmidi_t *self, struct process_info *info) { stream_t *str = &self->stream[info->dir]; port_jack_func process = port_type[info->dir].jack_func; int i, del=0; add_ports(str); // process ports for (i=0; i<PORT_HASH_SIZE; ++i) { port_t **pport = &str->ports[i]; while (*pport) { port_t *port = *pport; port->jack_buf = jack_port_get_buffer(port->jack_port, info->nframes); if (info->dir == PORT_INPUT) jack_midi_clear_buffer(port->jack_buf); if (!port->is_dead) (*process)(self, port, info); else if (jack_ringbuffer_write_space(self->port_del) >= sizeof(port)) { debug_log("jack: removed port %s", port->name); *pport = port->next; jack_ringbuffer_write(self->port_del, (char*)&port, sizeof(port)); del++; continue; } pport = &port->next; } } if (del) sem_post(&self->port_sem); }
static int process(jack_nframes_t nframes, void *arg) { int i,j; void* port_buf = jack_port_get_buffer(output_port, nframes); unsigned char* buffer; jack_midi_clear_buffer(port_buf); /*memset(buffer, 0, nframes*sizeof(jack_default_audio_sample_t));*/ for(i=0; i<nframes; i++) { for(j=0; j<num_notes; j++) { if(note_starts[j] == loop_index) { buffer = jack_midi_event_reserve(port_buf, i, 3); /* printf("wrote a note on, port buffer = 0x%x, event buffer = 0x%x\n", port_buf, buffer);*/ buffer[2] = 64; /* velocity */ buffer[1] = note_frqs[j]; buffer[0] = 0x90; /* note on */ } else if(note_starts[j] + note_lengths[j] == loop_index) { buffer = jack_midi_event_reserve(port_buf, i, 3); /* printf("wrote a note off, port buffer = 0x%x, event buffer = 0x%x\n", port_buf, buffer);*/ buffer[2] = 64; /* velocity */ buffer[1] = note_frqs[j]; buffer[0] = 0x80; /* note off */ } } loop_index = loop_index+1 >= loop_nsamp ? 0 : loop_index+1; } return 0; }
int process(jack_nframes_t nframes, void *arg) { sample_t *in = jack_port_get_buffer(input_port, nframes); void *midi_out = jack_port_get_buffer(output_port, nframes); jack_midi_clear_buffer(midi_out); for (unsigned int i = 0; i < nframes; i++) { sample_t cur = in[i]; last_idx = wrap(last_idx + 1, LAST_WIDTH); last[last_idx] = fabs(cur); for (unsigned int j = 0; j < LAST_WIDTH; j++) { fft_in[j] = last[wrap(last_idx + j, LAST_WIDTH)]; } fftwf_execute(fft_plan); power = 0; for (unsigned int j = 0; j < FFT_SIZE; j++) { power += fabs(fft_out[j]); } power /= FFT_SIZE; if (!hit && (power > 2)) { hit = true; DEBUG("HIT power = %.3f \n", power); send_note(midi_out, i, 0.5); } else if (hit && (power < 0.9)) { hit = false; DEBUG("UNHIT power = %.3f \n", power); } static float minp; static float maxp; if (delay == 0) { DEBUG("power ∈ [%+2.3f, %+2.3f] \r", minp, maxp); /* unsigned int star = power; */ /* for (unsigned int j = 0; j < star; j++) DEBUG(" "); */ /* DEBUG("*\r"); */ delay = 30000; minp = 1e9; maxp = -1e9; } else { if (power < minp) minp = power; if (power > maxp) maxp = power; --delay; } } return 0; }
static void jack_process(midi_stream_t *str, jack_nframes_t nframes) { int r, w; process_jack_t proc; jack_nframes_t cur_frames; if (!str->owner->keep_walking) return; proc.midi = str->owner; proc.nframes = nframes; proc.frame_time = jack_last_frame_time(proc.midi->client); cur_frames = jack_frame_time(proc.midi->client); int periods_diff = cur_frames - proc.frame_time; if (periods_diff < proc.nframes) { int periods_lost = periods_diff / proc.nframes; proc.frame_time += periods_lost * proc.nframes; debug_log("xrun detected: %d periods lost", periods_lost); } // process existing ports for (r=0, w=0; r<str->jack.nports; ++r) { midi_port_t *port = str->jack.ports[r]; proc.port = port; assert (port->state > PORT_ADDED_TO_JACK && port->state < PORT_REMOVED_FROM_JACK); proc.buffer = jack_port_get_buffer(port->jack, nframes); if (str->mode == POLLIN) jack_midi_clear_buffer(proc.buffer); if (port->state == PORT_REMOVED_FROM_MIDI) { port->state = PORT_REMOVED_FROM_JACK; // this signals to scan thread continue; // this effectively removes port from the midi->in.jack.ports[] } (str->process_jack)(&proc); if (r != w) str->jack.ports[w] = port; ++w; } if (str->jack.nports != w) debug_log("jack_%s: nports %d -> %d", str->name, str->jack.nports, w); str->jack.nports = w; jack_add_ports(str); // it makes no sense to add them earlier since they have no data yet // wake midi thread write(str->wake_pipe[1], &r, 1); }
void PlayerHandler::process(const jack_nframes_t nframes) { void* outPortBuf = jack_port_get_buffer(m_outputPort, nframes); jack_midi_clear_buffer(outPortBuf); jack_position_t pos; const jack_transport_state_t state = jack_transport_query(m_client, &pos); switch (state) { case JackTransportStopped: { if (m_previousState != state) { // stop them all now allNotesOff(outPortBuf, 0); // reset position m_position = 0; } break; } case JackTransportRolling: { const jack_nframes_t framesAtStart = jack_last_frame_time(m_client); const jack_nframes_t lastFrame = framesAtStart + nframes; const jack_nframes_t startFrame = framesAtStart - pos.frame; while (m_position < m_master.size() && startFrame + m_master[m_position].m_time >= framesAtStart && startFrame + m_master[m_position].m_time < lastFrame) { const MidiEvent & event = m_master[m_position]; const jack_nframes_t newOffset = event.m_time - pos.frame; jack_midi_event_write(outPortBuf, newOffset, event.m_data, event.m_size); noteChange(event.m_data); ++m_position; } break; } default: { break; } } m_previousState = state; }
static int _process(jack_nframes_t nframes, void *arg) { // process input events _t *data = (_t *)arg; framework_midi_event_init(&data->fw, NULL, nframes); /* for all frames in the buffer */ for(int i = 0; i < nframes; i++) { /* process all midi events at this sample time */ jack_midi_event_t event; int port; while (framework_midi_event_get(&data->fw, i, &event, &port)) { if (data->started && _writeable(data, event.size)) _write(data, sdrkit_last_frame_time(arg)+i, event.size, event.buffer); } } // process output events _t *dp = (_t *)arg; void* midi_out = jack_port_get_buffer(framework_midi_output(dp,0), nframes); jack_midi_event_t event; // find out what there is to do framework_midi_event_init(&dp->fw, &dp->midi, nframes); // clear the jack output buffer jack_midi_clear_buffer(midi_out); // for each frame in this callback for(int i = 0; i < nframes; i += 1) { // process all midi output events at this sample frame int port; while (framework_midi_event_get(&dp->fw, i, &event, &port)) { if (event.size != 0) { unsigned char* buffer = jack_midi_event_reserve(midi_out, i, event.size); if (buffer == NULL) { fprintf(stderr, "%s:%d: jack won't buffer %ld midi bytes!\n", __FILE__, __LINE__, (long)event.size); } else { memcpy(buffer, event.buffer, event.size); //fprintf(stderr, "midi_insert sent %x %x %x\n", buffer[0], buffer[1], buffer[2]); } } } } return 0; }
// Jack process callback int jackProcessOut( jack_nframes_t nframes, void *arg ) { JackMidiData *data = (JackMidiData *) arg; jack_midi_data_t *midiData; int space; // Is port created? if ( data->port == NULL ) return 0; void *buff = jack_port_get_buffer( data->port, nframes ); jack_midi_clear_buffer( buff ); while ( jack_ringbuffer_read_space( data->buffSize ) > 0 ) { jack_ringbuffer_read( data->buffSize, (char *) &space, (size_t) sizeof(space) ); midiData = jack_midi_event_reserve( buff, 0, space ); jack_ringbuffer_read( data->buffMessage, (char *) midiData, (size_t) space ); } return 0; }
int process(jack_nframes_t nframes, void *arg) { int j; data *par = (data *) arg; jack_midi_event_t *event = (jack_midi_event_t *) jack_port_get_buffer(par->inPort, nframes); int eCount = jack_midi_get_event_count(event); void *buffer = jack_port_get_buffer(par->outPort, nframes); jack_midi_clear_buffer(buffer); for (eCount, j = 0; eCount > 0; eCount--, j++) { jack_midi_event_t nextE; jack_midi_event_get(&nextE, event, j); // Filtering by channel char ch = nextE.buffer[0] & 0x0F; if (par->channelFilter >= 0) { if (ch != par->channelFilter) return 0; } if (nextE.buffer[0] & 0x80 || nextE.buffer[0] & 0x90) { if (nextE.buffer[1] >= par->currentNote) { nextE.buffer[0] &= 0xF0; nextE.buffer[0] += par->ch2Num; nextE.buffer[1] += par->ch2Shift; } else { nextE.buffer[0] &= 0xF0; nextE.buffer[0] += par->ch1Num; nextE.buffer[1] += par->ch1Shift; } } jack_midi_event_write(buffer, nextE.time, nextE.buffer, nextE.size); } return 0; }
void* luajack_get_buffer(luajack_t *port) /* Wrapper of jack_port_get_buffer() */ { #define cud ((pud)->cud) pud_t *pud; if(!(pud = get_pud(port))) return NULL; if(!IsProcessCallback(cud)) { luajack_error("function available only in process callback"); return NULL; } if(pud->buf) { luajack_error("buffer already retrieved"); return NULL; } pud->nframes = cud->nframes; pud->buf = jack_port_get_buffer(pud->port, pud->nframes); if(!pud->buf) { luajack_error("cannot get port buffer"); return NULL; } pud->bufp = 0; if(PortIsMidi(pud)) { if(PortIsOutput(pud)) jack_midi_clear_buffer(pud->buf); } return pud->buf; #undef cud }
void midiSendLong(unsigned char *buf, unsigned long len) { /*int err = snd_rawmidi_write(handle_out, buf, len); if (err != len) { fprintf(stderr, "could not write %ld byte to output, return: %d\n", len, err); exit(1); }*/ if (jack_midi_output_port == NULL) { fprintf(stderr, "midiSendLong failed: output port closed\n"); exit(1); } void* output_buf = jack_port_get_buffer (jack_midi_output_port, 1); jack_midi_clear_buffer(output_buf); printhex("send:", buf, len); int err = jack_midi_event_write(output_buf, 0, buf, len); if (err != 0) { if (err == ENOBUFS) { // if there's not enough space in buffer for event } fprintf(stderr, "could not write %ld byte to output, return: %d\n", len, err); exit(1); } }
int process(jack_nframes_t nframes, void *arg) { jack_default_audio_sample_t *in = (jack_default_audio_sample_t *)jack_port_get_buffer(input_port, nframes); void *out = jack_port_get_buffer(output_port, nframes); jack_midi_clear_buffer(out); static int count = -1; int is_on; float volume; int frame; for(frame = 0; frame < nframes; frame++) { if((is_on = (volume = fabs(in[frame])) > threshold)) count = 0; else if(count++ == min_time_between_hits) count = -1; if(is_on != midi_event.playing && -midi_event.playing == count) toggle_midi_event(out, frame, &midi_event, volume); } return 0; }
int process(jack_nframes_t nframes, void* arg) { TimerProcess.Start(); static uint64_t frametime = 0; TJackSynth* synth = static_cast<TJackSynth*>(arg); /* Process MIDI input */ void* inbuf = jack_port_get_buffer(MidiIn, nframes); jack_nframes_t event_count = jack_midi_get_event_count(inbuf); for (jack_nframes_t i = 0; i < event_count; i++) { jack_midi_event_t event; jack_midi_event_get(&event, inbuf, i); std::vector<uint8_t> data(event.buffer, event.buffer + event.size); synth->HandleMidi(data, frametime + event.time); } /* Send MIDI */ void* outbuf = jack_port_get_buffer(MidiOut, nframes); jack_midi_clear_buffer(outbuf); while (!MidiOutQueue.empty()) { const std::vector<uint8_t>& data = MidiOutQueue.front(); int ret = jack_midi_event_write(outbuf, 0, data.data(), data.size()); MidiOutQueue.pop(); if (ret != 0) { fprintf(stderr, "MIDI send error\n"); } } synth->Process(nframes); frametime += nframes; TimerProcess.Stop(); return 0; }
static int a2j_process (jack_nframes_t nframes, void * arg) { struct a2j* self = (struct a2j *) arg; struct a2j_stream * stream_ptr; int i; struct a2j_port ** port_ptr; struct a2j_port * port; if (g_freewheeling) { return 0; } self->cycle_start = jack_last_frame_time (self->jack_client); stream_ptr = &self->stream; a2j_add_ports (stream_ptr); // process ports for (i = 0 ; i < PORT_HASH_SIZE ; i++) { port_ptr = &stream_ptr->port_hash[i]; while (*port_ptr != NULL) { struct a2j_alsa_midi_event ev; jack_nframes_t now; jack_nframes_t one_period; char *ev_buf; port = *port_ptr; if (port->is_dead) { if (jack_ringbuffer_write_space (self->port_del) >= sizeof(port_ptr)) { a2j_debug("jack: removed port %s", port->name); *port_ptr = port->next; jack_ringbuffer_write (self->port_del, (char*)&port, sizeof(port)); } else { a2j_error ("port deletion lost - no space in event buffer!"); } port_ptr = &port->next; continue; } port->jack_buf = jack_port_get_buffer(port->jack_port, nframes); /* grab data queued by the ALSA input thread and write it into the JACK port buffer. it will delivered during the JACK period that this function is called from. */ /* first clear the JACK port buffer in preparation for new data */ // a2j_debug ("PORT: %s process input", jack_port_name (port->jack_port)); jack_midi_clear_buffer (port->jack_buf); now = jack_frame_time (self->jack_client); one_period = jack_get_buffer_size (self->jack_client); while (jack_ringbuffer_peek (port->inbound_events, (char*)&ev, sizeof(ev) ) == sizeof(ev) ) { jack_midi_data_t* buf; jack_nframes_t offset; if (ev.time >= self->cycle_start) { break; } //jack_ringbuffer_read_advance (port->inbound_events, sizeof (ev)); ev_buf = (char *) alloca( sizeof(ev) + ev.size ); if (jack_ringbuffer_peek (port->inbound_events, ev_buf, sizeof(ev) + ev.size ) != sizeof(ev) + ev.size) break; offset = self->cycle_start - ev.time; if (offset > one_period) { /* from a previous cycle, somehow. cram it in at the front */ offset = 0; } else { /* offset from start of the current cycle */ offset = one_period - offset; } a2j_debug ("event at %d offset %d", ev.time, offset); /* make sure there is space for it */ buf = jack_midi_event_reserve (port->jack_buf, offset, ev.size); if (buf) { /* grab the event */ memcpy( buf, ev_buf + sizeof(ev), ev.size ); } else { /* throw it away (no space) */ a2j_error ("threw away MIDI event - not reserved at time %d", ev.time); } jack_ringbuffer_read_advance (port->inbound_events, sizeof(ev) + ev.size); a2j_debug("input on %s: sucked %d bytes from inbound at %d", jack_port_name (port->jack_port), ev.size, ev.time); } port_ptr = &port->next; } } return 0; }
static int process_callback(jack_nframes_t nframes, void *arg) { int i, ax, axis_note, axis_velocity; void* port_buffer = jack_port_get_buffer(output_port, nframes); unsigned char* buffer; unsigned char axis_playing[24]; jack_midi_clear_buffer(port_buffer); for (i=0; i<nframes; i++) { for (ax=0; ax<20; ax++) { if (!isPoly) { buffer = jack_midi_event_reserve(port_buffer, i, 3); buffer[2] = 0x00; //as much poly as the host can get buffer[1] = 0x7F; //enable poly buffer[0] = 0xB0; //control mode isPoly = 1; if (debug) printf("Polyphonic mode enabled\n"); } if (black_keys) { if (ax==0) axis_note = -2; //dummy else if (ax==1) axis_note = 0x02; //leftY (Modulation) else if (ax==2) axis_note = 0x0A; //rightH (Pan) else if (ax==3) axis_note = -2; //dummy else if (ax==4) axis_note = 0x10; //Acc X (Misc 1) 0x10 else if (ax==5) axis_note = 0x11; //Acc Y (Misc 2) 0x11 else if (ax==6) axis_note = 0x12; //Acc Z (Misc 3) 0x12 else if (ax==7) axis_note = -2; //gyro (doesn't work) else if (ax==8) axis_note = 61+(12*oct); //up else if (ax==9) axis_note = 62+(12*oct); //right else if (ax==10) axis_note = 63+(12*oct); //down else if (ax==11) axis_note = 60+(12*oct); //left else if (ax==12) axis_note = 65+(12*oct); //l2 else if (ax==13) axis_note = 66+(12*oct); //r2 else if (ax==14) axis_note = 64+(12*oct); //l1 else if (ax==15) axis_note = 67+(12*oct); //r1 else if (ax==16) axis_note = 69+(12*oct); //triangle else if (ax==17) axis_note = 70+(12*oct); //circle else if (ax==18) axis_note = 71+(12*oct); //cross else if (ax==19) axis_note = 68+(12*oct); //square } else { if (ax==0) axis_note = -2; //dummy else if (ax==1) axis_note = 0x02; //leftY (Modulation) else if (ax==2) axis_note = 0x0A; //rightH (Pan) else if (ax==3) axis_note = -2; //dummy else if (ax==4) axis_note = 0x10; //Acc X (Misc 1) 0x10 else if (ax==5) axis_note = 0x11; //Acc Y (Misc 2) 0x11 else if (ax==6) axis_note = 0x12; //Acc Z (Misc 3) 0x12 else if (ax==7) axis_note = -2; //gyro (doesn't work) else if (ax==8) axis_note = 62+(12*oct); //up else if (ax==9) axis_note = 64+(12*oct); //right else if (ax==10) axis_note = 65+(12*oct); //down else if (ax==11) axis_note = 60+(12*oct); //left else if (ax==12) axis_note = 69+(12*oct); //l2 else if (ax==13) axis_note = 71+(12*oct); //r2 else if (ax==14) axis_note = 67+(12*oct); //l1 else if (ax==15) axis_note = 72+(12*oct); //r1 else if (ax==16) axis_note = 76+(12*oct); //triangle else if (ax==17) axis_note = 77+(12*oct); //circle else if (ax==18) axis_note = 79+(12*oct); //cross else if (ax==19) axis_note = 74+(12*oct); //square } if (ax==1) axis_velocity = abs(axis[ax]/0xff) - 1; // modulation else if (ax==2) axis_velocity = ((axis[ax]/0xff)/2) + 63; // pan else if (ax<7) axis_velocity = ((axis[ax]/0xff)/2) + 63; // other controls else if (ax>=8 && ax<=19) { // keys axis_velocity = (axis[ax]/0xff) - 1; if (axis_velocity > 0) { axis_velocity = axis_velocity*(6.0-logf(axis_velocity)); if (axis_velocity < 0) axis_velocity = 0; else if (axis_velocity > 127) axis_velocity = 127; } } else axis_velocity = (axis[ax]/0xff) - 1; // all the others if (axis_velocity == -1) axis_velocity = 0; if (axis[ax]) axis_playing[ax] = 1; else axis_playing[ax] = 0; if (axis_prev_action[ax] != axis_playing[ax]) { axis_is_checked[ax] = 0; } if (!axis_is_checked[ax]) { if (axis_playing[ax]) { buffer = jack_midi_event_reserve(port_buffer, i, 3); buffer[2] = axis_velocity; buffer[1] = axis_note; if (ax>7) buffer[0] = 0x90; //note-on else buffer[0] = 0xB0; //control/mode axis_prev_action[ax] = 1; if (debug && (ax<4 || ax>7) && axis_note>0) printf("PLAY: axis %02i; velocity is %03i; playing ? %i\n", ax, axis_velocity, axis_playing[ax]); } else { buffer = jack_midi_event_reserve(port_buffer, i, 3); buffer[2] = axis_velocity; buffer[1] = axis_note; if (ax>7) buffer[0] = 0x80;//note-off else buffer[0] = 0xB0; //control/mode axis_prev_action[ax] = 0; if (debug && (ax<4 || ax>7) && axis_note>0) printf("STOP: axis %02i; velocity is %03i; playing ? %i\n", ax, axis_velocity, axis_playing[ax]); } axis_is_checked[ax] = 1; } else if (axis_prev_velocity[ax] != axis[ax]) { buffer = jack_midi_event_reserve(port_buffer, i, 3); buffer[2] = axis_velocity; buffer[1] = axis_note; if (ax>7) buffer[0] = 0xA0; //aftertouch else buffer[0] = 0xB0; //control/mode if (debug && (ax<4 || ax>7) && axis_note>0) printf("CTRL: axis %02i; velocity is %03i; playing ? %i\n", ax, axis_velocity, axis_playing[ax]); } axis_prev_velocity[ax] = axis[ax]; } } return 0; }
static int process_cb(jack_nframes_t nframes, void *arg) { struct cbox_jack_io_impl *jii = arg; struct cbox_io *io = jii->ioi.pio; struct cbox_io_callbacks *cb = io->cb; io->io_env.buffer_size = nframes; for (int i = 0; i < io->io_env.input_count; i++) io->input_buffers[i] = jack_port_get_buffer(jii->inputs[i], nframes); for (int i = 0; i < io->io_env.output_count; i++) { io->output_buffers[i] = jack_port_get_buffer(jii->outputs[i], nframes); if (!io->output_buffers[i]) continue; for (int j = 0; j < nframes; j ++) io->output_buffers[i][j] = 0.f; } for (GSList *p = io->midi_inputs; p; p = p->next) { struct cbox_jack_midi_input *input = p->data; if (input->hdr.output_set || input->hdr.enable_appsink) { copy_midi_data_to_buffer(input->port, io->io_env.buffer_size, &input->hdr.buffer); if (input->hdr.enable_appsink) cbox_midi_appsink_supply(&input->hdr.appsink, &input->hdr.buffer); } else cbox_midi_buffer_clear(&input->hdr.buffer); } if (cb->on_transport_sync) { jack_transport_state_t state = jack_transport_query(jii->client, NULL); if (state != jii->last_transport_state) { jack_position_t pos; jack_transport_query(jii->client, &pos); if (jii->debug_transport) g_message("JACK transport: incoming state change, state = %s, last state = %s, pos = %d\n", transport_state_names[state], transport_state_names[(int)jii->last_transport_state], (int)pos.frame); if (state == JackTransportStopped) { if (cb->on_transport_sync(cb->user_data, ts_stopping, pos.frame)) jii->last_transport_state = state; } else if (state == JackTransportRolling && jii->last_transport_state == JackTransportStarting) { if (cb->on_transport_sync(cb->user_data, ts_rolling, pos.frame)) jii->last_transport_state = state; } else jii->last_transport_state = state; } } cb->process(cb->user_data, io, nframes); for (int i = 0; i < io->io_env.input_count; i++) io->input_buffers[i] = NULL; for (int i = 0; i < io->io_env.output_count; i++) io->output_buffers[i] = NULL; for (GSList *p = io->midi_outputs; p; p = g_slist_next(p)) { struct cbox_jack_midi_output *midiout = p->data; void *pbuf = jack_port_get_buffer(midiout->port, nframes); jack_midi_clear_buffer(pbuf); cbox_midi_merger_render(&midiout->hdr.merger); if (midiout->hdr.buffer.count) { uint8_t tmp_data[4]; for (int i = 0; i < midiout->hdr.buffer.count; i++) { const struct cbox_midi_event *event = cbox_midi_buffer_get_event(&midiout->hdr.buffer, i); const uint8_t *pdata = cbox_midi_event_get_data(event); if ((pdata[0] & 0xF0) == 0x90 && !pdata[2] && event->size == 3) { tmp_data[0] = pdata[0] & ~0x10; tmp_data[1] = pdata[1]; tmp_data[2] = pdata[2]; pdata = tmp_data; } if (jack_midi_event_write(pbuf, event->time, pdata, event->size)) { g_warning("MIDI buffer overflow on JACK output port '%s'", midiout->hdr.name); break; } } } } return 0; }
static void process_midi_output(jack_nframes_t nframes) { int i, t, bytes_remaining, track_number; unsigned char *buffer, tmp_status; void *port_buffers[MAX_NUMBER_OF_TRACKS]; jack_nframes_t last_frame_time; jack_transport_state_t transport_state; static jack_transport_state_t previous_transport_state = JackTransportStopped; static int previous_playback_started = -1; static int previous_playback_paused = 0; for (i = 0; i <= smf->number_of_tracks; i++) { port_buffers[i] = jack_port_get_buffer(output_ports[i], nframes); if (port_buffers[i] == NULL) { warn_from_jack_thread_context("jack_port_get_buffer failed, cannot send anything."); return; } #ifdef JACK_MIDI_NEEDS_NFRAMES jack_midi_clear_buffer(port_buffers[i], nframes); #else jack_midi_clear_buffer(port_buffers[i]); #endif if (just_one_output) break; } if (ctrl_c_pressed) { send_all_sound_off(port_buffers, nframes); /* The idea here is to exit at the second time process_midi_output gets called. Otherwise, All Sound Off won't be delivered. */ ctrl_c_pressed++; if (ctrl_c_pressed >= 3) exit(0); return; } // g_debug("PROCESS CALLBACK!!!"); if (playback_paused) { if (!previous_playback_paused) { send_all_sound_off(port_buffers, nframes); } previous_playback_paused = playback_paused; return; } previous_playback_paused = playback_paused; if (use_transport) { // if (!ready_to_roll) return; transport_state = jack_transport_query(jack_client, NULL); if (transport_state == JackTransportStopped) { if (previous_transport_state == JackTransportRolling) { send_all_sound_off(port_buffers, nframes); } playback_started = -1; } if (transport_state == JackTransportStarting) { playback_started = -1; } if (transport_state == JackTransportRolling) { if (previous_transport_state != JackTransportRolling) { jack_position_t position; jack_transport_query(jack_client, &position); song_position = position.frame; playback_started = jack_last_frame_time(jack_client); } } previous_transport_state = transport_state; } else { if (playback_started == -1) { if (previous_playback_started >= 0) { send_all_sound_off(port_buffers, nframes); send_sond_end(); } } previous_playback_started = playback_started; } /* End of song already? */ if (playback_started < 0) return; last_frame_time = jack_last_frame_time(jack_client); /* We may push at most one byte per 0.32ms to stay below 31.25 Kbaud limit. */ bytes_remaining = nframes_to_ms(nframes) * rate_limit; double loop_offset = loop_song(smf); for (;;) { smf_event_t *event = smf_peek_next_event(smf); int end_of_song = 0; int is_meta_event = 0; if (event == NULL) { end_of_song = 1; } else if (smf_event_is_metadata(event)) { is_meta_event = 1; char *decoded = smf_event_decode(event); if (decoded) { if (!be_quiet) g_debug("Metadata: %s", decoded); end_of_song = process_meta_event(decoded); free(decoded); } } if (end_of_song) { if (!be_quiet) g_debug("End of song."); playback_started = -1; if (!use_transport) ctrl_c_pressed = 1; break; } if (is_meta_event) { smf_event_t *ret = smf_get_next_event(smf); assert(ret != 0); continue; } bytes_remaining -= event->midi_buffer_length; if (rate_limit > 0.0 && bytes_remaining <= 0) { warn_from_jack_thread_context("Rate limiting in effect."); break; } // t = seconds_to_nframes(event->time_seconds) + playback_started - song_position + nframes - last_frame_time; t = seconds_to_nframes(event->time_seconds + loop_offset) + playback_started - song_position - last_frame_time; /* If computed time is too much into the future, we'll need to send it later. */ if (t >= (int)nframes) break; /* If computed time is < 0, we missed a cycle because of xrun. */ if (t < 0) t = 0; assert(event->track->track_number >= 0 && event->track->track_number <= MAX_NUMBER_OF_TRACKS); /* We will send this event; remove it from the queue. */ smf_event_t *ret = smf_get_next_event(smf); assert(ret != 0); /* First, send it via midi_out. */ track_number = 0; #ifdef JACK_MIDI_NEEDS_NFRAMES buffer = jack_midi_event_reserve(port_buffers[track_number], t, event->midi_buffer_length, nframes); #else buffer = jack_midi_event_reserve(port_buffers[track_number], t, event->midi_buffer_length); #endif if (buffer == NULL) { warn_from_jack_thread_context("jack_midi_event_reserve failed, NOTE LOST."); break; } memcpy(buffer, event->midi_buffer, event->midi_buffer_length); /* Ignore per-track outputs? */ if (just_one_output) continue; /* Send it via proper output port. */ track_number = event->track->track_number; #ifdef JACK_MIDI_NEEDS_NFRAMES buffer = jack_midi_event_reserve(port_buffers[track_number], t, event->midi_buffer_length, nframes); #else buffer = jack_midi_event_reserve(port_buffers[track_number], t, event->midi_buffer_length); #endif if (buffer == NULL) { warn_from_jack_thread_context("jack_midi_event_reserve failed, NOTE LOST."); break; } /* Before sending, reset channel to 0. XXX: Not very pretty. */ assert(event->midi_buffer_length >= 1); tmp_status = event->midi_buffer[0]; if (event->midi_buffer[0] >= 0x80 && event->midi_buffer[0] <= 0xEF) event->midi_buffer[0] &= 0xF0; memcpy(buffer, event->midi_buffer, event->midi_buffer_length); event->midi_buffer[0] = tmp_status; } }
// rt static int _process(jack_nframes_t nsamples, void *data) { prog_t *handle = data; bin_t *bin = &handle->bin; sp_app_t *app = bin->app; #if defined(JACK_HAS_CYCLE_TIMES) clock_gettime(CLOCK_REALTIME, &handle->ntp); handle->ntp.tv_sec += JAN_1970; // convert NTP to OSC time jack_nframes_t offset = jack_frames_since_cycle_start(handle->client); float T; jack_get_cycle_times(handle->client, &handle->cycle.cur_frames, &handle->cycle.cur_usecs, &handle->cycle.nxt_usecs, &T); (void)T; handle->cycle.ref_frames = handle->cycle.cur_frames + offset; // calculate apparent period double diff = 1e-6 * (handle->cycle.nxt_usecs - handle->cycle.cur_usecs); // calculate apparent samples per period handle->cycle.dT = nsamples / diff; handle->cycle.dTm1 = 1.0 / handle->cycle.dT; #endif // get transport position jack_position_t pos; jack_transport_state_t rolling = jack_transport_query(handle->client, &pos) == JackTransportRolling; int trans_changed = (rolling != handle->trans.rolling) || (pos.frame != handle->trans.frame) || (pos.beats_per_bar != handle->trans.beats_per_bar) || (pos.beat_type != handle->trans.beat_type) || (pos.ticks_per_beat != handle->trans.ticks_per_beat) || (pos.beats_per_minute != handle->trans.beats_per_minute); const size_t sample_buf_size = sizeof(float) * nsamples; const sp_app_system_source_t *sources = sp_app_get_system_sources(app); const sp_app_system_sink_t *sinks = sp_app_get_system_sinks(app); if(sp_app_bypassed(app)) // aka loading state { //fprintf(stderr, "app is bypassed\n"); // clear output buffers for(const sp_app_system_sink_t *sink=sinks; sink->type != SYSTEM_PORT_NONE; sink++) { switch(sink->type) { case SYSTEM_PORT_NONE: case SYSTEM_PORT_CONTROL: case SYSTEM_PORT_COM: break; case SYSTEM_PORT_AUDIO: case SYSTEM_PORT_CV: { void *out_buf = jack_port_get_buffer(sink->sys_port, nsamples); memset(out_buf, 0x0, sample_buf_size); break; } case SYSTEM_PORT_MIDI: case SYSTEM_PORT_OSC: { void *out_buf = jack_port_get_buffer(sink->sys_port, nsamples); jack_midi_clear_buffer(out_buf); break; } } } bin_process_pre(bin, nsamples, true); bin_process_post(bin); return 0; } //TODO use __builtin_assume_aligned // fill input buffers for(const sp_app_system_source_t *source=sources; source->type != SYSTEM_PORT_NONE; source++) { switch(source->type) { case SYSTEM_PORT_NONE: case SYSTEM_PORT_CONTROL: break; case SYSTEM_PORT_AUDIO: case SYSTEM_PORT_CV: { const void *in_buf = jack_port_get_buffer(source->sys_port, nsamples); memcpy(source->buf, in_buf, sample_buf_size); break; } case SYSTEM_PORT_MIDI: { void *in_buf = jack_port_get_buffer(source->sys_port, nsamples); void *seq_in = source->buf; LV2_Atom_Forge *forge = &handle->forge; LV2_Atom_Forge_Frame frame; lv2_atom_forge_set_buffer(forge, seq_in, SEQ_SIZE); LV2_Atom_Forge_Ref ref = lv2_atom_forge_sequence_head(forge, &frame, 0); if(ref && trans_changed) ref = _trans_event(handle, forge, rolling, &pos); int n = jack_midi_get_event_count(in_buf); for(int i=0; i<n; i++) { jack_midi_event_t mev; jack_midi_event_get(&mev, in_buf, i); //add jack midi event to in_buf if(ref) ref = lv2_atom_forge_frame_time(forge, mev.time); if(ref) ref = lv2_atom_forge_atom(forge, mev.size, handle->midi_MidiEvent); if(ref) ref = lv2_atom_forge_raw(forge, mev.buffer, mev.size); if(ref) lv2_atom_forge_pad(forge, mev.size); } if(ref) lv2_atom_forge_pop(forge, &frame); else lv2_atom_sequence_clear(seq_in); break; } case SYSTEM_PORT_OSC: { void *in_buf = jack_port_get_buffer(source->sys_port, nsamples); void *seq_in = source->buf; LV2_Atom_Forge *forge = &handle->forge; LV2_Atom_Forge_Frame frame; lv2_atom_forge_set_buffer(forge, seq_in, SEQ_SIZE); LV2_Atom_Forge_Ref ref = lv2_atom_forge_sequence_head(forge, &frame, 0); if(ref && trans_changed) ref = _trans_event(handle, forge, rolling, &pos); int n = jack_midi_get_event_count(in_buf); for(int i=0; i<n; i++) { jack_midi_event_t mev; jack_midi_event_get(&mev, (void *)in_buf, i); //add jack osc event to in_buf if(osc_check_packet(mev.buffer, mev.size)) { if(ref) ref = lv2_atom_forge_frame_time(forge, mev.time); handle->ref = ref; osc_dispatch_method(mev.buffer, mev.size, methods, _bundle_in, _bundle_out, handle); ref = handle->ref; } } if(ref) lv2_atom_forge_pop(forge, &frame); else lv2_atom_sequence_clear(seq_in); break; } case SYSTEM_PORT_COM: { void *seq_in = source->buf; LV2_Atom_Forge *forge = &handle->forge; LV2_Atom_Forge_Frame frame; lv2_atom_forge_set_buffer(forge, seq_in, SEQ_SIZE); LV2_Atom_Forge_Ref ref = lv2_atom_forge_sequence_head(forge, &frame, 0); const LV2_Atom_Object *obj; size_t size; while((obj = varchunk_read_request(bin->app_from_com, &size))) { if(ref) ref = lv2_atom_forge_frame_time(forge, 0); if(ref) ref = lv2_atom_forge_raw(forge, obj, size); if(ref) lv2_atom_forge_pad(forge, size); varchunk_read_advance(bin->app_from_com); } if(ref) lv2_atom_forge_pop(forge, &frame); else lv2_atom_sequence_clear(seq_in); break; } } } // update transport state handle->trans.rolling = rolling; handle->trans.frame = rolling ? handle->trans.frame + nsamples : pos.frame; handle->trans.beats_per_bar = pos.beats_per_bar; handle->trans.beat_type = pos.beat_type; handle->trans.ticks_per_beat = pos.ticks_per_beat; handle->trans.beats_per_minute = pos.beats_per_minute; bin_process_pre(bin, nsamples, false); // fill output buffers for(const sp_app_system_sink_t *sink=sinks; sink->type != SYSTEM_PORT_NONE; sink++) { switch(sink->type) { case SYSTEM_PORT_NONE: case SYSTEM_PORT_CONTROL: break; case SYSTEM_PORT_AUDIO: case SYSTEM_PORT_CV: { void *out_buf = jack_port_get_buffer(sink->sys_port, nsamples); memcpy(out_buf, sink->buf, sample_buf_size); break; } case SYSTEM_PORT_MIDI: { void *out_buf = jack_port_get_buffer(sink->sys_port, nsamples); const LV2_Atom_Sequence *seq_out = sink->buf; // fill midi output buffer jack_midi_clear_buffer(out_buf); if(seq_out) { LV2_ATOM_SEQUENCE_FOREACH(seq_out, ev) { const LV2_Atom *atom = &ev->body; if(atom->type != handle->midi_MidiEvent) continue; // ignore non-MIDI events jack_midi_event_write(out_buf, ev->time.frames, LV2_ATOM_BODY_CONST(atom), atom->size); } } break; } case SYSTEM_PORT_OSC: { void *out_buf = jack_port_get_buffer(sink->sys_port, nsamples); const LV2_Atom_Sequence *seq_out = sink->buf; // fill midi output buffer jack_midi_clear_buffer(out_buf); if(seq_out) { LV2_ATOM_SEQUENCE_FOREACH(seq_out, ev) { const LV2_Atom_Object *obj = (const LV2_Atom_Object *)&ev->body; handle->osc_ptr = handle->osc_buf; handle->osc_end = handle->osc_buf + OSC_SIZE; osc_atom_event_unroll(&handle->oforge, obj, _bundle_push_cb, _bundle_pop_cb, _message_cb, handle); size_t size = handle->osc_ptr ? handle->osc_ptr - handle->osc_buf : 0; if(size) { jack_midi_event_write(out_buf, ev->time.frames, handle->osc_buf, size); } } } break; } case SYSTEM_PORT_COM: { const LV2_Atom_Sequence *seq_out = sink->buf; LV2_ATOM_SEQUENCE_FOREACH(seq_out, ev) { const LV2_Atom *atom = (const LV2_Atom *)&ev->body; // try do process events directly bin->advance_ui = sp_app_from_ui(bin->app, atom); if(!bin->advance_ui) // queue event in ringbuffer instead { //fprintf(stderr, "plugin ui direct is blocked\n"); void *ptr; size_t size = lv2_atom_total_size(atom); if((ptr = varchunk_write_request(bin->app_from_app, size))) { memcpy(ptr, atom, size); varchunk_write_advance(bin->app_from_app, size); } else { //fprintf(stderr, "app_from_ui ringbuffer full\n"); //FIXME } } } break; } } } bin_process_post(bin); return 0; }
// JACK specifics. int qmidinetJackMidiDevice::process ( jack_nframes_t nframes ) { jack_nframes_t buffer_size = jack_get_buffer_size(m_pJackClient); m_last_frame_time = jack_last_frame_time(m_pJackClient); // Enqueue/dequeue events // to/from ring-buffers... for (int i = 0; i < m_nports; ++i) { if (m_ppJackPortIn && m_ppJackPortIn[i] && m_pJackBufferIn) { void *pvBufferIn = jack_port_get_buffer(m_ppJackPortIn[i], nframes); const int nevents = jack_midi_get_event_count(pvBufferIn); const unsigned int nlimit = jack_ringbuffer_write_space(m_pJackBufferIn); unsigned char achBuffer[nlimit]; unsigned char *pchBuffer = &achBuffer[0]; unsigned int nwrite = 0; for (int n = 0; n < nevents; ++n) { if (nwrite + sizeof(qmidinetJackMidiEvent) >= nlimit) break; qmidinetJackMidiEvent *pJackEventIn = (struct qmidinetJackMidiEvent *) pchBuffer; jack_midi_event_get(&pJackEventIn->event, pvBufferIn, n); if (nwrite + sizeof(qmidinetJackMidiEvent) + pJackEventIn->event.size >= nlimit) break; pJackEventIn->port = i; pchBuffer += sizeof(qmidinetJackMidiEvent); nwrite += sizeof(qmidinetJackMidiEvent); ::memcpy(pchBuffer, pJackEventIn->event.buffer, pJackEventIn->event.size); pchBuffer += pJackEventIn->event.size; nwrite += pJackEventIn->event.size; } if (nwrite > 0) { jack_ringbuffer_write(m_pJackBufferIn, (const char *) achBuffer, nwrite); } } if (m_ppJackPortOut && m_ppJackPortOut[i] && m_pJackBufferOut) { void *pvBufferOut = jack_port_get_buffer(m_ppJackPortOut[i], nframes); jack_midi_clear_buffer(pvBufferOut); const unsigned int nlimit = jack_midi_max_event_size(pvBufferOut); unsigned int nread = 0; qmidinetJackMidiEvent ev; while (jack_ringbuffer_peek(m_pJackBufferOut, (char *) &ev, sizeof(ev)) == sizeof(ev) && nread < nlimit) { if (ev.port != i) break; if (ev.event.time > m_last_frame_time) break; jack_nframes_t offset = m_last_frame_time - ev.event.time; if (offset > buffer_size) offset = 0; else offset = buffer_size - offset; jack_ringbuffer_read_advance(m_pJackBufferOut, sizeof(ev)); jack_midi_data_t *pMidiData = jack_midi_event_reserve(pvBufferOut, offset, ev.event.size); if (pMidiData) jack_ringbuffer_read(m_pJackBufferOut, (char *) pMidiData, ev.event.size); else jack_ringbuffer_read_advance(m_pJackBufferOut, ev.event.size); nread += ev.event.size; } } } if (m_pJackBufferIn && jack_ringbuffer_read_space(m_pJackBufferIn) > 0) m_pRecvThread->sync(); return 0; }
int process(jack_nframes_t nframes, void *arg) { struct guitarseq *guitarseq = arg; if(!guitarseq) { fprintf(stderr, "No guitarseq instance!\n"); return 1; } void* port_buf; jack_nframes_t now = jack_frame_time (guitarseq->jack_client); //Output port_buf = jack_port_get_buffer(guitarseq->out_port, nframes); jack_midi_clear_buffer(port_buf); while (1) { jack_nframes_t time; //TODO: Do a safer read, in case only part of the message is here if (!jack_ringbuffer_read (guitarseq->out_buffer, (char *)&time, sizeof(time))) { break; } // from the future? if (time >= now) { break; } // time it right jack_nframes_t offset = time - now + nframes - 1; // get the size of the event size_t size; jack_ringbuffer_read(guitarseq->out_buffer, (char *)&size, sizeof(size)); INFO("out event at %u%+d size %zu\n", now, offset, size); if (offset > nframes) // from the past, somehow. cram it in at the front offset = 0; // proceed to giving it to jack jack_midi_data_t *buffer = jack_midi_event_reserve (port_buf, offset, size); if(buffer) { jack_ringbuffer_read(guitarseq->out_buffer, (char *)buffer, size); } else { // throw it away :( TODO: find more jack_ringbuffer_read_advance (guitarseq->out_buffer, size); ERROR("threw away MIDI event - no space reserved at time %u offset %d\n",time,offset); } } // Input port_buf = jack_port_get_buffer(guitarseq->in_port, nframes); jack_nframes_t event_count = jack_midi_get_event_count(port_buf); for(jack_nframes_t i=0; i<event_count; i++) { jack_midi_event_t in_event; jack_midi_event_get(&in_event, port_buf, i); //adds a note to the ringbuffer if (jack_ringbuffer_write_space(guitarseq->in_buffer) >= sizeof(in_event.time)+sizeof(in_event.size)+in_event.size) { jack_ringbuffer_write(guitarseq->in_buffer, (char *)&in_event.time, sizeof(in_event.time)); jack_ringbuffer_write(guitarseq->in_buffer, (char *)&in_event.size, sizeof(in_event.size)); jack_ringbuffer_write(guitarseq->in_buffer, (char *)in_event.buffer, in_event.size); } else { ERROR("Couldn't write to ringbuffer at %u, %zu midi data bytes lost\n", in_event.time, in_event.size); } } return 0; }
void ModeHandler::process(const jack_nframes_t nframes) { void* inPortBuf = jack_port_get_buffer(m_inputPort, nframes); void* outPortBuf = jack_port_get_buffer(m_outputPort, nframes); jack_midi_clear_buffer(outPortBuf); const jack_transport_state_t state = jack_transport_query(m_client, nullptr); const jack_nframes_t eventCount = jack_midi_get_event_count(inPortBuf); for (size_t i = 0; i < eventCount; ++i) { jack_midi_event_t inEvent; jack_midi_event_get(&inEvent, inPortBuf, i); const jack_midi_data_t cmd = inEvent.buffer[0] & 0xf0; switch (cmd) { case MIDI_NOTEON: case MIDI_NOTEOFF: { const jack_midi_data_t note = inEvent.buffer[1]; const jack_midi_data_t velocity = inEvent.buffer[2]; int noteToUse = note; // we only map on a note on // on a note off we use the previously mapped note // and only is transport is rolling if (cmd == MIDI_NOTEON && velocity > 0) { if (state == JackTransportRolling) { const int newNote = transpose(m_offset, m_quirkOffset, note); m_mappedNotes[note] = newNote; noteToUse = newNote; } } else { // NOTEOFF if (m_mappedNotes[note] != NOT_MAPPED) { noteToUse = m_mappedNotes[note]; m_mappedNotes[note] = NOT_MAPPED; } } if (noteToUse != SKIP) { jack_midi_data_t data[3]; data[0] = inEvent.buffer[0]; data[1] = noteToUse;; data[2] = inEvent.buffer[2]; jack_midi_event_write(outPortBuf, inEvent.time, data, 3); } break; } default: { // just forward everything else jack_midi_event_write(outPortBuf, inEvent.time, inEvent.buffer, inEvent.size); } } } }
int process(jack_nframes_t nframes, void *arg) { int i,j; void* port_buf = jack_port_get_buffer(output_port, nframes); unsigned char* buffer; jack_midi_clear_buffer(port_buf); for(i = 0; i < nframes; i++) { while(queued_notes.size > 0) { note_on(queued_notes.note[queued_notes.size - 1], port_buf, i); queued_notes.size--; } if (strummer_action != STRUMMER_ACTION_NONE) { if (strummer_action == STRUMMER_ACTION_MID_DOWN || strummer_action == STRUMMER_ACTION_MID_UP) { strum_chord(chord[chord_state], port_buf, i); strummer_action = STRUMMER_ACTION_NONE; } else { if (strummer_state != STRUMMER_STATE_SUSTAINED) { mute(port_buf, i); strummer_action = STRUMMER_ACTION_NONE; } } } if (whammy_action != WHAMMY_ACTION_NONE) { buffer = jack_midi_event_reserve(port_buf, i, 3); unsigned int pitch_shift = (MIDI_PITCH_CENTER * whammy_state) / CWIID_GUITAR_WHAMMY_MAX ; unsigned int pitch_value = MIDI_PITCH_CENTER - pitch_shift; buffer[2] = (pitch_value & 0x3F80) >> 7; // most significant bits buffer[1] = pitch_value & 0x007f; // least significant bits buffer[0] = MIDI_PITCH_WHEEL + midi_channel; // pitch wheel change printf("whammy! %x, %x, %x, desimalt: %d\n", buffer[0], buffer[2], buffer[1], pitch_value); whammy_action = WHAMMY_ACTION_NONE; } if (touchbar_action != TOUCHBAR_ACTION_NONE) { buffer = jack_midi_event_reserve(port_buf, i, 3); // scale input to output values (5th represents maximum possible input value) unsigned int modulation = (MIDI_MODULATION_MAX * touchbar_state) / CWIID_GUITAR_TOUCHBAR_5TH ; printf("touchbar action! %d, %x, sent %x\n", touchbar_action, touchbar_state, modulation); buffer[2] = modulation; buffer[1] = 0x1; // modulation buffer[0] = MIDI_CONTROL_CHANGE + midi_channel; // control change touchbar_action = TOUCHBAR_ACTION_NONE; } if (stick_action != STICK_ACTION_NONE) { printf("stick_action!\n"); unsigned int volume = last_sent_volume_value; if (stick_action == STICK_ACTION_ROTATE_COUNTER_CLOCKWISE) { volume += stick_zone_average_value / 2 ; if (volume > 127) { volume = 127; } } else if (stick_action == STICK_ACTION_ROTATE_CLOCKWISE) { if (volume >= stick_zone_average_value / 2) { volume -= stick_zone_average_value / 2; } else { volume = 0; } } if (volume != last_sent_volume_value) { printf("volume: %d\n", volume); buffer = jack_midi_event_reserve(port_buf, i, 3); buffer[2] = volume; buffer[1] = 0x7; // volume buffer[0] = MIDI_CONTROL_CHANGE + midi_channel; // control change last_sent_volume_value = volume; } stick_action = STICK_ACTION_NONE; } while (drums_action != 0) { uint8_t send_note_off = 0; buffer = jack_midi_event_reserve(port_buf, i, 3); buffer[2] = 0x7F; /* velocity */ if ((drums_action & RED) == RED) { /* if ((drums_state & RED) == RED) { send_note_off = 1; } drums_state ^= RED; */ buffer[1] = 38; /* note number */ drums_action &= ~RED; } else if ((drums_action & YELLOW) == YELLOW) { /* if ((drums_state & YELLOW) == YELLOW) { send_note_off = 1; } drums_state ^= YELLOW; */ buffer[1] = 42; /* note number */ drums_action &= ~YELLOW; } else if ((drums_action & BLUE) == BLUE) { /* if ((drums_state & BLUE) == BLUE) { send_note_off = 1; } drums_state ^= BLUE; */ buffer[1] = 48; /* note number */ drums_action &= ~BLUE; } else if ((drums_action & ORANGE) == ORANGE) { /* if ((drums_state & ORANGE) == ORANGE) { send_note_off = 1; } drums_state ^= ORANGE; */ buffer[1] = 51; /* note number */ drums_action &= ~ORANGE; } else if ((drums_action & GREEN) == GREEN) { /* if ((drums_state & GREEN) == GREEN) { send_note_off = 1; } drums_state ^= GREEN; */ buffer[1] = 45; /* note number */ drums_action &= ~GREEN; } else if ((drums_action & PEDAL) == PEDAL) { /* if ((drums_state & PEDAL) == PEDAL) { send_note_off = 1; } drums_state ^= PEDAL; */ buffer[1] = 36; /* note number */ drums_action &= ~PEDAL; } if (send_note_off) { buffer[0] = MIDI_NOTE_OFF + 9; // note off } else { buffer[0] = MIDI_NOTE_ON + 9; // note on } } if (crossfader_action != CROSSFADER_ACTION_NONE) { buffer = jack_midi_event_reserve(port_buf, i, 3); uint8_t crossfader_midi_value = current_turntables_state.crossfader * 127 / CWIID_TURNTABLES_CROSSFADER_MAX; buffer[2] = crossfader_midi_value; buffer[1] = MIDI_BALANCE_MSB; buffer[0] = MIDI_CONTROL_CHANGE + midi_channel; // control change crossfader_action = CROSSFADER_ACTION_NONE; } if (effect_dial_action != EFFECT_DIAL_ACTION_NONE) { buffer = jack_midi_event_reserve(port_buf, i, 3); buffer[0] = MIDI_CONTROL_CHANGE + midi_channel; // control change buffer[1] = MIDI_EFFECT_CTL_1_MSB; int16_t signed_value; switch (effect_dial_action) { case EFFECT_DIAL_ACTION_ROTATE_CLOCKWISE: effect_dial_state.value += effect_dial_state.change; if (effect_dial_state.value > effect_dial_state.max_value) { effect_dial_state.value = effect_dial_state.max_value; } break; case EFFECT_DIAL_ACTION_ROTATE_COUNTER_CLOCKWISE: signed_value = effect_dial_state.value + effect_dial_state.change; effect_dial_state.value += effect_dial_state.change; if (signed_value < effect_dial_state.min_value) { effect_dial_state.value = effect_dial_state.min_value; } break; case EFFECT_DIAL_ACTION_INITIALIZE: printf("initialize\n"); current_turntables_state.effect_dial = effect_dial_state.initial_value; break; } buffer[2] = effect_dial_state.value; effect_dial_action = EFFECT_DIAL_ACTION_NONE; } }
/* ** jack process callback */ static int _process(jack_nframes_t nframes, void *arg) { _t *dp = (_t *)arg; void *midi_out = jack_port_get_buffer(framework_midi_output(dp,0), nframes); jack_midi_event_t event; // initialize input event queue framework_midi_event_init(&dp->fw, &dp->midi, nframes); // recompute timings if necessary _update(dp); /* this is important, very strange if omitted */ jack_midi_clear_buffer(midi_out); /* for all frames in the buffer */ for (int i = 0; i < nframes; i++) { /* read all events for this frame */ int port; while (framework_midi_event_get(&dp->fw, i, &event, &port)) { if (port < dp->fw.n_midi_inputs) { /* it is a midi_input event */ if (event.size == 3) { const unsigned char channel = (event.buffer[0]&0xF)+1; const unsigned char command = event.buffer[0]&0xF0; const unsigned char note = event.buffer[1]; if (channel == dp->opts.chan && note == dp->opts.note) { if (command == MIDI_NOTE_ON) { if ( ! dp->ptt_on) { dp->ptt_on = 1; _send(dp, midi_out, i, command, dp->opts.note+1); } dp->key_on = 1; if (i+dp->ptt_delay_samples < nframes) { _send(dp, midi_out, i+dp->ptt_delay_samples, command, dp->opts.note); } else { midi_buffer_write_delay(&dp->midi, i+dp->ptt_delay_samples-nframes); midi_buffer_write_note_on(&dp->midi, 0, channel, note, 0); } } else if (command == MIDI_NOTE_OFF) { if (i+dp->ptt_delay_samples < nframes) { dp->key_on = 0; dp->ptt_hang_count = dp->ptt_hang_samples+dp->ptt_delay_samples; _send(dp, midi_out, i+dp->ptt_delay_samples, command, dp->opts.note); } else { midi_buffer_write_delay(&dp->midi, i+dp->ptt_delay_samples-nframes); midi_buffer_write_note_off(&dp->midi, 0, channel, note, 0); } } } } } else { /* it is a midi buffer event */ if (event.size != 0) { const unsigned char command = event.buffer[0]&0xF0; if (command == MIDI_NOTE_ON) { dp->key_on = 1; } else if (command == MIDI_NOTE_OFF) { dp->key_on = 0; dp->ptt_hang_count = dp->ptt_hang_samples; } _send(dp, midi_out, i, command, dp->opts.note); } } } /* clock the ptt hang time counter */ if (dp->key_on == 0 && dp->ptt_on != 0 && --dp->ptt_hang_count <= 0) { dp->ptt_on = 0; _send(dp, midi_out, i, MIDI_NOTE_OFF, dp->opts.note+1); } } return 0; }
static int handle_process(jack_nframes_t frames, void *arg) { jack_midi_data_t *buffer; jack_midi_event_t event; jack_nframes_t event_count; jack_nframes_t event_time; jack_nframes_t frame; size_t i; jack_nframes_t last_frame_time; jack_midi_data_t *message; jack_time_t microseconds; void *port_buffer; jack_time_t time; jack_midi_clear_buffer(jack_port_get_buffer(out_port, frames)); switch (process_state) { case 0: /* State: initializing */ switch (wait_semaphore(init_semaphore, 0)) { case -1: set_process_error(SOURCE_WAIT_SEMAPHORE, get_semaphore_error()); /* Fallthrough on purpose */ case 0: return 0; } highest_latency = 0; lowest_latency = 0; messages_received = 0; messages_sent = 0; process_state = 1; total_latency = 0; total_latency_time = 0; unexpected_messages = 0; xrun_count = 0; jack_port_get_latency_range(remote_in_port, JackCaptureLatency, &in_latency_range); jack_port_get_latency_range(remote_out_port, JackPlaybackLatency, &out_latency_range); goto send_message; case 1: /* State: processing */ port_buffer = jack_port_get_buffer(in_port, frames); event_count = jack_midi_get_event_count(port_buffer); last_frame_time = jack_last_frame_time(client); for (i = 0; i < event_count; i++) { jack_midi_event_get(&event, port_buffer, i); message = (messages_received % 2) ? message_2 : message_1; if ((event.size == message_size) && (! memcmp(message, event.buffer, message_size * sizeof(jack_midi_data_t)))) { goto found_message; } unexpected_messages++; } microseconds = jack_frames_to_time(client, last_frame_time) - last_activity_time; if ((microseconds / 1000000) >= timeout) { set_process_error(SOURCE_PROCESS, ERROR_MSG_TIMEOUT); } break; found_message: event_time = last_frame_time + event.time; frame = event_time - last_activity; time = jack_frames_to_time(client, event_time) - last_activity_time; if ((! highest_latency) || (frame > highest_latency)) { highest_latency = frame; highest_latency_time = time; } if ((! lowest_latency) || (frame < lowest_latency)) { lowest_latency = frame; lowest_latency_time = time; } latency_time_values[messages_received] = time; latency_values[messages_received] = frame; total_latency += frame; total_latency_time += time; messages_received++; if (messages_received == samples) { process_state = 2; if (! signal_semaphore(process_semaphore)) { /* Sigh ... */ die(SOURCE_SIGNAL_SEMAPHORE, get_semaphore_error()); } break; } send_message: frame = (jack_nframes_t) ((((double) rand()) / RAND_MAX) * frames); if (frame >= frames) { frame = frames - 1; } port_buffer = jack_port_get_buffer(out_port, frames); buffer = jack_midi_event_reserve(port_buffer, frame, message_size); if (buffer == NULL) { set_process_error(SOURCE_EVENT_RESERVE, ERROR_RESERVE); break; } message = (messages_sent % 2) ? message_2 : message_1; memcpy(buffer, message, message_size * sizeof(jack_midi_data_t)); last_activity = jack_last_frame_time(client) + frame; last_activity_time = jack_frames_to_time(client, last_activity); messages_sent++; case 2: /* State: finished - do nothing */ case -1: /* State: error - do nothing */ case -2: /* State: signalled - do nothing */ ; } return 0; }
/** * The process callback for this JACK application. * It is called by JACK at the appropriate times. */ int process (jack_nframes_t nframes, void *arg) { jack_nframes_t net_period; int rx_bufsize, tx_bufsize; jack_default_audio_sample_t *buf; jack_port_t *port; JSList *node; int chn; int size, i; const char *porttype; int input_fd; jack_position_t local_trans_pos; uint32_t *packet_buf_tx, *packet_bufX; uint32_t *rx_packet_ptr; jack_time_t packet_recv_timestamp; if( bitdepth == 1000 || bitdepth == 999) net_period = (factor * jack_get_buffer_size(client) * 1024 / jack_get_sample_rate(client) / 8) & (~1) ; else net_period = (float) nframes / (float) factor; rx_bufsize = get_sample_size (bitdepth) * capture_channels * net_period + sizeof (jacknet_packet_header); tx_bufsize = get_sample_size (bitdepth) * playback_channels * net_period + sizeof (jacknet_packet_header); /* Allocate a buffer where both In and Out Buffer will fit */ packet_buf_tx = alloca (tx_bufsize); jacknet_packet_header *pkthdr_tx = (jacknet_packet_header *) packet_buf_tx; /* * for latency==0 we need to send out the packet before we wait on the reply. * but this introduces a cycle of latency, when netsource is connected to itself. * so we send out before read only in zero latency mode. * */ if( latency == 0 ) { /* reset packet_bufX... */ packet_bufX = packet_buf_tx + sizeof (jacknet_packet_header) / sizeof (jack_default_audio_sample_t); /* ---------- Send ---------- */ render_jack_ports_to_payload (bitdepth, playback_ports, playback_srcs, nframes, packet_bufX, net_period, dont_htonl_floats); /* fill in packet hdr */ pkthdr_tx->transport_state = jack_transport_query (client, &local_trans_pos); pkthdr_tx->transport_frame = local_trans_pos.frame; pkthdr_tx->framecnt = framecnt; pkthdr_tx->latency = latency; pkthdr_tx->reply_port = reply_port; pkthdr_tx->sample_rate = jack_get_sample_rate (client); pkthdr_tx->period_size = nframes; /* playback for us is capture on the other side */ pkthdr_tx->capture_channels_audio = playback_channels_audio; pkthdr_tx->playback_channels_audio = capture_channels_audio; pkthdr_tx->capture_channels_midi = playback_channels_midi; pkthdr_tx->playback_channels_midi = capture_channels_midi; pkthdr_tx->mtu = mtu; if( freewheeling != 0 ) pkthdr_tx->sync_state = (jack_nframes_t)MASTER_FREEWHEELS; else pkthdr_tx->sync_state = (jack_nframes_t)deadline_goodness; //printf("goodness=%d\n", deadline_goodness ); packet_header_hton (pkthdr_tx); if (cont_miss < 3 * latency + 5) { int r; for( r = 0; r < redundancy; r++ ) netjack_sendto (outsockfd, (char *) packet_buf_tx, tx_bufsize, 0, &destaddr, sizeof (destaddr), mtu); } else if (cont_miss > 50 + 5 * latency) { state_connected = 0; packet_cache_reset_master_address( packcache ); //printf ("Frame %d \tRealy too many packets missed (%d). Let's reset the counter\n", framecnt, cont_miss); cont_miss = 0; } } /* * ok... now the RECEIVE code. * */ if( reply_port ) input_fd = insockfd; else input_fd = outsockfd; // for latency == 0 we can poll. if( (latency == 0) || (freewheeling != 0) ) { jack_time_t deadline = jack_get_time() + 1000000 * jack_get_buffer_size(client) / jack_get_sample_rate(client); // Now loop until we get the right packet. while(1) { jack_nframes_t got_frame; if ( ! netjack_poll_deadline( input_fd, deadline ) ) break; packet_cache_drain_socket(packcache, input_fd); if (packet_cache_get_next_available_framecnt( packcache, framecnt - latency, &got_frame )) if( got_frame == (framecnt - latency) ) break; } } else { // normally: // only drain socket. packet_cache_drain_socket(packcache, input_fd); } size = packet_cache_retreive_packet_pointer( packcache, framecnt - latency, (char**)&rx_packet_ptr, rx_bufsize, &packet_recv_timestamp ); /* First alternative : we received what we expected. Render the data * to the JACK ports so it can be played. */ if (size == rx_bufsize) { uint32_t *packet_buf_rx = rx_packet_ptr; jacknet_packet_header *pkthdr_rx = (jacknet_packet_header *) packet_buf_rx; packet_bufX = packet_buf_rx + sizeof (jacknet_packet_header) / sizeof (jack_default_audio_sample_t); // calculate how much time there would have been, if this packet was sent at the deadline. int recv_time_offset = (int) (jack_get_time() - packet_recv_timestamp); packet_header_ntoh (pkthdr_rx); deadline_goodness = recv_time_offset - (int)pkthdr_rx->latency; //printf( "deadline goodness = %d ---> off: %d\n", deadline_goodness, recv_time_offset ); if (cont_miss) { //printf("Frame %d \tRecovered from dropouts\n", framecnt); cont_miss = 0; } render_payload_to_jack_ports (bitdepth, packet_bufX, net_period, capture_ports, capture_srcs, nframes, dont_htonl_floats); state_currentframe = framecnt; state_recv_packet_queue_time = recv_time_offset; state_connected = 1; sync_state = pkthdr_rx->sync_state; packet_cache_release_packet( packcache, framecnt - latency ); } /* Second alternative : we've received something that's not * as big as expected or we missed a packet. We render silence * to the ouput ports */ else { jack_nframes_t latency_estimate; if( packet_cache_find_latency( packcache, framecnt, &latency_estimate ) ) //if( (state_latency == 0) || (latency_estimate < state_latency) ) state_latency = latency_estimate; // Set the counters up. state_currentframe = framecnt; //state_latency = framecnt - pkthdr->framecnt; state_netxruns += 1; //printf ("Frame %d \tPacket missed or incomplete (expected: %d bytes, got: %d bytes)\n", framecnt, rx_bufsize, size); //printf ("Frame %d \tPacket missed or incomplete\n", framecnt); cont_miss += 1; chn = 0; node = capture_ports; while (node != NULL) { port = (jack_port_t *) node->data; buf = jack_port_get_buffer (port, nframes); porttype = jack_port_type (port); if (strncmp (porttype, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size ()) == 0) for (i = 0; i < nframes; i++) buf[i] = 0.0; else if (strncmp (porttype, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size ()) == 0) jack_midi_clear_buffer (buf); node = jack_slist_next (node); chn++; } } if (latency != 0) { /* reset packet_bufX... */ packet_bufX = packet_buf_tx + sizeof (jacknet_packet_header) / sizeof (jack_default_audio_sample_t); /* ---------- Send ---------- */ render_jack_ports_to_payload (bitdepth, playback_ports, playback_srcs, nframes, packet_bufX, net_period, dont_htonl_floats); /* fill in packet hdr */ pkthdr_tx->transport_state = jack_transport_query (client, &local_trans_pos); pkthdr_tx->transport_frame = local_trans_pos.frame; pkthdr_tx->framecnt = framecnt; pkthdr_tx->latency = latency; pkthdr_tx->reply_port = reply_port; pkthdr_tx->sample_rate = jack_get_sample_rate (client); pkthdr_tx->period_size = nframes; /* playback for us is capture on the other side */ pkthdr_tx->capture_channels_audio = playback_channels_audio; pkthdr_tx->playback_channels_audio = capture_channels_audio; pkthdr_tx->capture_channels_midi = playback_channels_midi; pkthdr_tx->playback_channels_midi = capture_channels_midi; pkthdr_tx->mtu = mtu; if( freewheeling != 0 ) pkthdr_tx->sync_state = (jack_nframes_t)MASTER_FREEWHEELS; else pkthdr_tx->sync_state = (jack_nframes_t)deadline_goodness; //printf("goodness=%d\n", deadline_goodness ); packet_header_hton (pkthdr_tx); if (cont_miss < 3 * latency + 5) { int r; for( r = 0; r < redundancy; r++ ) netjack_sendto (outsockfd, (char *) packet_buf_tx, tx_bufsize, 0, &destaddr, sizeof (destaddr), mtu); } else if (cont_miss > 50 + 5 * latency) { state_connected = 0; packet_cache_reset_master_address( packcache ); //printf ("Frame %d \tRealy too many packets missed (%d). Let's reset the counter\n", framecnt, cont_miss); cont_miss = 0; } } framecnt++; return 0; }
CARLA_EXPORT void jack_midi_reset_buffer(void* buf) { jack_midi_clear_buffer(buf); }