int ringbuffer_cread(jack_ringbuffer_t *rbuf, void *buf, size_t bufsz, int advance, uint32_t *tag, size_t *len) /* C version: returns 1 on success and 0 on error */ { jack_ringbuffer_data_t vec[2]; hdr_t hdr; uint32_t len0; size_t cnt; /* peek for header */ cnt = jack_ringbuffer_peek(rbuf, (char*)&hdr, sizeof(hdr)); if(cnt != sizeof(hdr)) return 0; /* see if there are 'len' bytes of data available */ cnt = jack_ringbuffer_read_space(rbuf); if( cnt < (sizeof(hdr) + hdr.len) ) return 0; /* check if data fits in the user provided buffer */ if(hdr.len > bufsz ) return luajack_error("not enough space for ringbuffer_read() " "(at least %u bytes needed)", hdr.len); *tag = hdr.tag; *len = hdr.len; if(hdr.len == 0) /* tag only */ { if(advance) jack_ringbuffer_read_advance(rbuf, sizeof(hdr)); if(bufsz>0) ((char*)buf)[0]='\0'; return 1; } /* get the read vector */ jack_ringbuffer_get_read_vector(rbuf, vec); /* copy the data part in the user provided buffer */ if(vec[0].len >= (sizeof(hdr) + hdr.len)) /* all the data are in vec[0] */ memcpy(buf, vec[0].buf + sizeof(hdr), hdr.len); else if(vec[0].len > sizeof(hdr)) /* part of the data are in vec[0] */ { len0 = vec[0].len - sizeof(hdr); memcpy(buf, vec[0].buf + sizeof(hdr), len0); memcpy((char*)buf + len0, vec[1].buf, hdr.len - len0); } else /* part of the header and all of the data are in vec[1] */ { len0 = sizeof(hdr) - vec[0].len; /* bytes oh header in vec[1] */ memcpy((char*)buf, vec[1].buf + len0, hdr.len); } if(advance) jack_ringbuffer_read_advance(rbuf, sizeof(hdr) + hdr.len); return 1; }
int ringbuffer_luaread(jack_ringbuffer_t *rbuf, lua_State *L, int advance) /* tag, data = read() * returns tag=nil if there is not a complete message (header+data) in * the ringbuffer * if the header.len is 0, data is returned as an empty string ("") */ { jack_ringbuffer_data_t vec[2]; hdr_t hdr; uint32_t len; size_t cnt; /* peek for header */ cnt = jack_ringbuffer_peek(rbuf, (char*)&hdr, sizeof(hdr)); if(cnt != sizeof(hdr)) { lua_pushnil(L); return 1; } /* see if there are 'len' bytes of data available */ cnt = jack_ringbuffer_read_space(rbuf); if( cnt < (sizeof(hdr) + hdr.len) ) { lua_pushnil(L); return 1; } lua_pushinteger(L, hdr.tag); if(hdr.len == 0) /* header only */ { if(advance) jack_ringbuffer_read_advance(rbuf, sizeof(hdr)); lua_pushstring(L, ""); return 2; } /* get the read vector */ jack_ringbuffer_get_read_vector(rbuf, vec); //printf("vec[0].len=%u, vec[1].len=%u hdr.len=%u\n",vec[0].len,vec[1].len,hdr.len); if(vec[0].len >= (sizeof(hdr) + hdr.len)) /* data fits in vec[0] */ lua_pushlstring(L, vec[0].buf + sizeof(hdr), hdr.len); else if(vec[0].len > sizeof(hdr)) { len = vec[0].len - sizeof(hdr); lua_pushlstring(L, vec[0].buf + sizeof(hdr), len); lua_pushlstring(L, vec[1].buf, hdr.len - len); lua_concat(L, 2); } else /* vec[0] contains only the header or part of it (data is all in vec[1]) */ { len = sizeof(hdr) - vec[0].len; /* the first len bytes in vec1 are part of the header */ lua_pushlstring(L, vec[1].buf + len, hdr.len); } if(advance) jack_ringbuffer_read_advance(rbuf, sizeof(hdr) + hdr.len); return 2; }
// MIDI events capture method. void qmidinetJackMidiDevice::capture (void) { if (m_pJackBufferIn == NULL) return; char *pchBuffer; qmidinetJackMidiEvent ev; while (jack_ringbuffer_peek(m_pJackBufferIn, (char *) &ev, sizeof(ev)) == sizeof(ev)) { jack_ringbuffer_read_advance(m_pJackBufferIn, sizeof(ev)); pchBuffer = m_pQueueIn->push(ev.port, ev.event.time, ev.event.size); if (pchBuffer) jack_ringbuffer_read(m_pJackBufferIn, pchBuffer, ev.event.size); else jack_ringbuffer_read_advance(m_pJackBufferIn, ev.event.size); } float sample_rate = jack_get_sample_rate(m_pJackClient); jack_nframes_t frame_time = jack_frame_time(m_pJackClient); while ((pchBuffer = m_pQueueIn->pop( &ev.port, &ev.event.time, &ev.event.size)) != NULL) { ev.event.time += m_last_frame_time; if (ev.event.time > frame_time) { unsigned long sleep_time = ev.event.time - frame_time; float secs = float(sleep_time) / sample_rate; if (secs > 0.0001f) { #if 0 // defined(__GNUC__) && defined(Q_OS_LINUX) struct timespec ts; ts.tv_sec = time_t(secs); ts.tv_nsec = long(1E+9f * (secs - ts.tv_sec)); ::nanosleep(&ts, NULL); #else m_pRecvThread->usleep(long(1E+6f * secs)); #endif } frame_time = ev.event.time; } #ifdef CONFIG_DEBUG // - show (input) event for debug purposes... fprintf(stderr, "JACK MIDI In Port %d: (%d)", ev.port, int(ev.event.size)); for (unsigned int i = 0; i < ev.event.size; ++i) fprintf(stderr, " 0x%02x", (unsigned char) pchBuffer[i]); fprintf(stderr, "\n"); #endif recvData((unsigned char *) pchBuffer, ev.event.size, ev.port); } }
/** @brief Read into an array Read from the buffer into an array. \param dest an array to be read into \param cnt the number of elements to read into this array */ void read(Type *dest, unsigned cnt){ jack_ringbuffer_data_t readVec[2]; unsigned int read_size = sizeof(Type) * cnt; if(getReadSpace() <= 0){ //throw error!!!! return; } //get the readvector jack_ringbuffer_get_read_vector(mRingBufferPtr, readVec); //if the first vector has enough data then just read from there if(readVec[0].len >= read_size){ memcpy(dest, readVec[0].buf, read_size); } else { //if the first vector is zero length then read from the second if(readVec[0].len == 0){ memcpy(dest, readVec[1].buf, read_size); } else { //this gets tricky char * byterep = (char *)dest; //first read the data out of the first vector memcpy(byterep, readVec[0].buf, readVec[0].len); //then read the rest out of the second memcpy(byterep + readVec[0].len, readVec[1].buf, read_size - readVec[0].len); } } //advance the read pointer jack_ringbuffer_read_advance(mRingBufferPtr, read_size); }
/** flush buffers and reset. Must only be called from the RT thread. */ void Disk_Stream::base_flush ( bool is_output ) { THREAD_ASSERT( RT ); /* flush buffers */ for ( int i = _rb.size(); i--; ) jack_ringbuffer_read_advance( _rb[ i ], jack_ringbuffer_read_space( _rb[ i ] ) ); /* sem_destroy( &_blocks ); */ /* if ( is_output ) */ /* sem_init( &_blocks, 0, _total_blocks ); */ /* else */ /* sem_init( &_blocks, 0, 0 ); */ if ( is_output ) { int n; sem_getvalue( &_blocks, &n ); n = _total_blocks - n; while ( n-- ) sem_post( &_blocks ); } else { sem_destroy( &_blocks ); sem_init( &_blocks, 0, 0 ); } }
int ringbuffer_cread_advance(jack_ringbuffer_t *rbuf) /* C version: returns 1 or 0 */ { hdr_t hdr; /* peek for header */ size_t cnt = jack_ringbuffer_peek(rbuf, (char*)&hdr, sizeof(hdr)); if(cnt == sizeof(hdr)) { /* see if there are 'len' bytes of data available */ cnt = jack_ringbuffer_read_space(rbuf); if( cnt >= (sizeof(hdr) + hdr.len) ) { jack_ringbuffer_read_advance(rbuf, sizeof(hdr) + hdr.len); return 1; } } return 0; }
/* * ============================ Input ============================== */ static void do_jack_input(alsa_seqmidi_t *self, port_t *port, struct process_info *info) { // process port->early_events alsa_midi_event_t ev; while (jack_ringbuffer_read(port->early_events, (char*)&ev, sizeof(ev))) { jack_midi_data_t* buf; int64_t time = ev.time - info->period_start; if (time < 0) time = 0; else if (time >= info->nframes) time = info->nframes - 1; buf = jack_midi_event_reserve(port->jack_buf, (jack_nframes_t)time, ev.size); if (buf) jack_ringbuffer_read(port->early_events, (char*)buf, ev.size); else jack_ringbuffer_read_advance(port->early_events, ev.size); debug_log("input: it's time for %d bytes at %lld", ev.size, time); } }
int ringbuffer_luaread_advance(jack_ringbuffer_t *rbuf, lua_State *L) /* call this after a peek to just advance the read pointer */ { hdr_t hdr; /* peek for header */ size_t cnt = jack_ringbuffer_peek(rbuf, (char*)&hdr, sizeof(hdr)); if(cnt == sizeof(hdr)) { cnt = jack_ringbuffer_read_space(rbuf); if( cnt >= (sizeof(hdr) + hdr.len)) { jack_ringbuffer_read_advance(rbuf, sizeof(hdr) + hdr.len); lua_pushboolean(L, 1); return 1; } } lua_pushboolean(L, 0); return 1; }
static void do_jack_input(process_jack_t *p) { input_port_t *port = (input_port_t*) p->port; event_head_t event; while (jack_ringbuffer_read_space(port->base.event_ring) >= sizeof(event)) { jack_ringbuffer_data_t vec[2]; jack_nframes_t time; int i, todo; jack_ringbuffer_read(port->base.event_ring, (char*)&event, sizeof(event)); // TODO: take into account possible warping if ((event.time + p->nframes) < p->frame_time) time = 0; else if (event.time >= p->frame_time) time = p->nframes -1; else time = event.time + p->nframes - p->frame_time; jack_ringbuffer_get_read_vector(port->base.data_ring, vec); assert ((vec[0].len + vec[1].len) >= event.size); if (event.overruns) midi_unpack_reset(&port->unpack); todo = event.size; for (i=0; i<2 && todo>0; ++i) { int avail = todo < vec[i].len ? todo : vec[i].len; int done = midi_unpack_buf(&port->unpack, (unsigned char*)vec[i].buf, avail, p->buffer, time); if (done != avail) { debug_log("jack_in: buffer overflow in port %s", port->base.name); break; } todo -= done; } jack_ringbuffer_read_advance(port->base.data_ring, event.size); } }
int JackWinMMEDriver::Read() { size_t size; for (int chan = 0; chan < fCaptureChannels; chan++) { if (fGraphManager->GetConnectionsNum(fCapturePortList[chan]) > 0) { JackMidiBuffer* midi_buffer = GetInputBuffer(chan); if (jack_ringbuffer_read_space (fRingBuffer[chan]) == 0) { // Reset buffer midi_buffer->Reset(midi_buffer->nframes); } else { while ((size = jack_ringbuffer_read_space (fRingBuffer[chan])) > 0) { //jack_info("jack_ringbuffer_read_space %d", size); int ev_count = 0; jack_ringbuffer_read(fRingBuffer[chan], (char*)&ev_count, sizeof(int)); if (ev_count > 0) { for (int j = 0; j < ev_count; j++) { unsigned int event_len = 3; // Read event actual data jack_midi_data_t* dest = midi_buffer->ReserveEvent(0, event_len); jack_ringbuffer_read(fRingBuffer[chan], (char*)dest, event_len); } } } } } else { //jack_info("Consume ring buffer"); jack_ringbuffer_read_advance(fRingBuffer[chan], jack_ringbuffer_read_space(fRingBuffer[chan])); } } return 0; }
void JackRingbuffer::advanceRead(size_t cnt) { jack_ringbuffer_read_advance(ringbuffer_, cnt); }
static int do_midi_output(process_midi_t *proc) { int worked = 0; output_port_t *port = (output_port_t*) proc->port; if (!midi_is_ready(proc)) return 0; // eat events while (port->next_event.time <= proc->cur_time) { port->todo += port->next_event.size; if (jack_ringbuffer_read(port->base.event_ring, (char*)&port->next_event, sizeof(port->next_event))!=sizeof(port->next_event)) { port->next_event.time = 0; port->next_event.size = 0; break; } else debug_log("midi_out: at %ld got %d bytes for %ld", (long)proc->cur_time, (int)port->next_event.size, (long)port->next_event.time); } if (port->todo) debug_log("midi_out: todo = %d at %ld", (int)port->todo, (long)proc->cur_time); // calc next wakeup time if (!port->todo && port->next_event.time && port->next_event.time < proc->next_time) { proc->next_time = port->next_event.time; debug_log("midi_out: next_time = %ld", (long)proc->next_time); } if (port->todo && port->base.is_ready) { // write data int size = port->todo; int res; jack_ringbuffer_data_t vec[2]; jack_ringbuffer_get_read_vector(port->base.data_ring, vec); if (size > vec[0].len) { size = vec[0].len; assert (size > 0); } res = snd_rawmidi_write(port->base.rawmidi, vec[0].buf, size); if (res > 0) { jack_ringbuffer_read_advance(port->base.data_ring, res); debug_log("midi_out: written %d bytes to %s", res, port->base.name); port->todo -= res; worked = 1; } else if (res == -EWOULDBLOCK) { port->base.is_ready = 0; debug_log("midi_out: -EWOULDBLOCK on %s", port->base.name); return 1; } else { error_log("midi_out: writing to port %s failed: %s", port->base.name, snd_strerror(res)); return 0; } snd_rawmidi_drain(port->base.rawmidi); } // update pfds for this port if (!midi_update_pfds(proc)) return 0; if (!port->todo) { int i; if (worked) debug_log("midi_out: relaxing on %s", port->base.name); for (i=0; i<port->base.npfds; ++i) proc->wpfds[i].events &= ~POLLOUT; } else { int i; for (i=0; i<port->base.npfds; ++i) proc->wpfds[i].events |= POLLOUT; } return 1; }
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 Record_DS::disk_thread ( void ) { _thread.name( "Capture" ); DMESSAGE( "capture thread running..." ); track()->record( _capture, _frame ); const nframes_t nframes = _nframes * _disk_io_blocks; /* buffer to hold the interleaved data returned by the track reader */ sample_t *buf = new sample_t[ nframes * channels() ]; #ifndef AVOID_UNNECESSARY_COPYING sample_t *cbuf = new sample_t[ nframes ]; #endif const size_t block_size = nframes * sizeof( sample_t ); int blocks_ready = 0; while ( wait_for_block() ) { if ( ++blocks_ready < _disk_io_blocks ) continue; else blocks_ready = 0; /* pull data from the per-channel ringbuffers and interlace it */ for ( int i = channels(); i--; ) { #ifdef AVOID_UNNECESSARY_COPYING /* interleave direcectly from the ringbuffer to avoid * unnecessary copying */ jack_ringbuffer_data_t rbd[2]; memset( rbd, 0, sizeof( rbd ) ); jack_ringbuffer_get_read_vector( _rb[ i ], rbd ); if ( rbd[ 0 ].len >= block_size ) { /* it'll all fit in one go */ buffer_interleave_one_channel( buf, (sample_t*)rbd[ 0 ].buf, i, channels(), nframes ); } else if ( rbd[ 0 ].len + rbd[ 1 ].len >= block_size ) { /* there's enough space in the ringbuffer, but it's not contiguous */ assert( ! ( rbd[ 0 ].len % sizeof( sample_t ) ) ); const nframes_t f = rbd[ 0 ].len / sizeof( sample_t ); /* do the first half */ buffer_deinterleave_one_channel( (sample_t*)rbd[ 0 ].buf, buf, i, channels(), f ); buffer_interleave_one_channel( buf, (sample_t*)rbd[ 0 ].buf, i, channels(), f ); assert( rbd[ 1 ].len >= ( nframes - f ) * sizeof( sample_t ) ); /* do the second half */ buffer_interleave_one_channel( buf + f, (sample_t*)rbd[ 0 ].buf, i, channels(), nframes - f ); } else ++_xruns; jack_ringbuffer_read_advance( _rb[ i ], block_size ); #else if ( jack_ringbuffer_read( _rb[ i ], (char*)cbuf, block_size ) < block_size ) ++_xruns; buffer_interleave_one_channel( buf, cbuf, i, channels(), nframes ); #endif } write_block( buf, nframes ); } DMESSAGE( "capture thread terminating" ); /* flush what remains in the buffer out to disk */ { /* use JACk sized blocks for this last bit */ const nframes_t nframes = _nframes; const size_t block_size = _nframes * sizeof( sample_t ); #ifdef AVOID_UNNECESSARY_COPYING sample_t *cbuf = new sample_t[ nframes ]; #endif while ( blocks_ready-- > 0 || ( ! sem_trywait( &_blocks ) && errno != EAGAIN ) ) { for ( int i = channels(); i--; ) { jack_ringbuffer_read( _rb[ i ], (char*)cbuf, block_size ); buffer_interleave_one_channel( buf, cbuf, i, channels(), nframes ); } const nframes_t frames_remaining = (_stop_frame - _frame ) - _frames_written; if ( frames_remaining < nframes ) { /* this is the last block, might be partial */ write_block( buf, frames_remaining ); break; } else write_block( buf, nframes ); } #ifdef AVOID_UNNECESSARY_COPYING delete[] cbuf; #endif } delete[] buf; #ifndef AVOID_UNNECESSARY_COPYING delete[] cbuf; #endif DMESSAGE( "finalzing capture" ); Track::Capture *c = _capture; _capture = NULL; /* now finalize the recording */ track()->finalize( c, _stop_frame ); delete c; _terminate = false; DMESSAGE( "capture thread gone" ); _thread.exit(); }
JackResampler::JackResampler() :fRatio(1),fRingBufferSize(DEFAULT_RB_SIZE) { fRingBuffer = jack_ringbuffer_create(sizeof(jack_default_audio_sample_t) * fRingBufferSize); jack_ringbuffer_read_advance(fRingBuffer, (sizeof(jack_default_audio_sample_t) * fRingBufferSize) / 2); }
//================================================================ int process(jack_nframes_t nframes, void *arg) { //fprintf(stderr,"."); //return 0; //if shutting down fill buffers with 0 and return if(shutdown_in_progress==1) { int i; for(i=0; i < output_port_count; i++) { sample_t *o1; o1=(sample_t*)jack_port_get_buffer(ioPortArray[i], nframes); //memset(o1, 0, bytes_per_sample*nframes); //always 4 bytes, 32 bit float memset(o1, 0, 4*nframes); } return 0; } if(process_enabled==1) { //if no data for this cycle(all channels) //is available(!), fill buffers with 0 or re-use old buffers and return if(jack_ringbuffer_read_space(rb) < port_count * bytes_per_sample*nframes) { int i; for(i=0; i < output_port_count; i++) { if(shutdown_in_progress==1 || process_enabled!=1) { return 0; } if(zero_on_underflow==1) { sample_t *o1; o1=(sample_t*)jack_port_get_buffer(ioPortArray[i], nframes); //memset(o1, 0, bytes_per_sample*nframes); //always 4 bytes, 32 bit float memset(o1, 0, 4*nframes); } print_info(); } multi_channel_drop_counter++; if(rebuffer_on_underflow==1) { pre_buffer_counter=0; process_enabled=0; } //reset avg calculation time_interval_avg=0; msg_received_counter=0; fscs_avg_counter=0; return 0; }//end not enough data available in ringbuffer process_cycle_counter++; if(process_cycle_counter>receive_max-1 && test_mode==1) { last_test_cycle=1; } //init to 0. increment before use fscs_avg_counter++; frames_since_cycle_start_sum+=frames_since_cycle_start; frames_since_cycle_start_avg=frames_since_cycle_start_sum/fscs_avg_counter; //check and reset after use if(fscs_avg_calc_interval>=fscs_avg_counter) { fscs_avg_counter=0; frames_since_cycle_start_sum=0; } //if sender sends more channels than we have output channels, ignore them int i; for(i=0; i<port_count; i++) { if(shutdown_in_progress==1 || process_enabled!=1) { return 0; } sample_t *o1; o1=(sample_t*)jack_port_get_buffer(ioPortArray[i], nframes); int16_t *o1_16; if(bytes_per_sample==2) { o1_16=malloc(bytes_per_sample*nframes); } //32 bit float if(bytes_per_sample==4) { jack_ringbuffer_read(rb, (char*)o1, bytes_per_sample*nframes); } //16 bit pcm else { jack_ringbuffer_read(rb, (char*)o1_16, bytes_per_sample*nframes); int x; for(x=0;x<nframes;x++) { o1[x]=(float)MIN_(MAX_((float)o1_16[x]/32760,-1.0f),1.0f); } free(o1_16); } /* fprintf(stderr,"\rreceiving from %s:%s", sender_host,sender_port ); */ print_info(); }//end for i < port_count //requested via /buffer, for test purposes (make buffer "tight") if(requested_drop_count>0) { uint64_t drop_bytes_count=requested_drop_count *port_count*period_size*bytes_per_sample; jack_ringbuffer_read_advance(rb,drop_bytes_count); requested_drop_count=0; multi_channel_drop_counter=0; } }//end if process_enabled==1 else //if process_enabled==0 { int i; for(i=0; i<port_count; i++) { if(shutdown_in_progress==1 || process_enabled!=1) { return 0; } sample_t *o1; o1=(sample_t*)jack_port_get_buffer(ioPortArray[i], nframes); //this is per channel, not per cycle. *port_count if(relaxed_display_counter>=update_display_every_nth_cycle*port_count || last_test_cycle==1 ) { //only for init if((int)message_number<=0 && starting_transmission==0) { if(shutup==0 && quiet==0) { fprintf(stderr,"\rwaiting for audio input data..."); } io_simple("/wait_for_input"); } else { if(shutup==0 && quiet==0) { fprintf(stderr,"\r# %" PRId64 " buffering... mc periods to go: %" PRId64 "%s", message_number, pre_buffer_size-pre_buffer_counter, "\033[0J" ); } if(io_()) { lo_message msgio=lo_message_new(); lo_message_add_int64(msgio,message_number); lo_message_add_int64(msgio,pre_buffer_size-pre_buffer_counter); lo_send_message(loio, "/buffering", msgio); lo_message_free(msgio); } } fflush(stderr); relaxed_display_counter=0; } relaxed_display_counter++; //set output buffer silent //memset(o1, 0, port_count*bytes_per_sample*nframes); //always 4 bytes, 32 bit float memset(o1, 0, port_count*4*nframes); }//end for i < port_count }//end process_enabled==0 //tasks independent of process_enabled 0/1 //if sender sends less channels than we have output channels, wee need to fill them with 0 if(input_port_count < output_port_count) { int i; for(i=0;i < (output_port_count-input_port_count);i++) { //sample_t *o1; //o1=(sample_t*) /////? jack_port_get_buffer(ioPortArray[input_port_count+i], nframes); } } if(last_test_cycle==1) { if(shutup==0) { fprintf(stderr,"\ntest finished after %" PRId64 " process cycles\n",process_cycle_counter); fprintf(stderr,"(waiting and buffering cycles not included)\n"); } io_simple_long("/test_finished",process_cycle_counter); shutdown_in_progress=1; } //simulate long cycle process duration //usleep(1000); frames_since_cycle_start=jack_frames_since_cycle_start(client); return 0; } //end process()
void ringbuffer_read_advance(jack_ringbuffer_t *rb, size_t cnt) { jack_ringbuffer_read_advance(rb, cnt * sizeof(float)); }
void *jack_player_thread(void *unused){ WfAudioInfo* nfo = &myplayer->info; const int nframes = 1024; float *tmpbuf = (float*) calloc(nframes * nfo->channels, sizeof(float)); float *bufptr = tmpbuf; #ifdef ENABLE_RESAMPLING size_t maxbufsiz = nframes; int err = 0; SRC_STATE* src_state = src_new(SRC_QUALITY, nfo->channels, NULL); SRC_DATA src_data; int nframes_r = floorf((float) nframes*m_fResampleRatio); ///< # of frames after resampling #ifdef VARISPEED maxbufsiz = (2+nframes_r) * 2; #else maxbufsiz = (1+nframes_r); #endif float *smpbuf = (float*) calloc(maxbufsiz * nfo->channels, sizeof(float)); src_data.input_frames = nframes; src_data.output_frames = nframes_r; src_data.end_of_input = 0; src_data.src_ratio = m_fResampleRatio; src_data.input_frames_used = 0; src_data.output_frames_gen = 0; src_data.data_in = tmpbuf; src_data.data_out = smpbuf; #else int nframes_r = nframes; // no resampling #endif int ladspaerr = 0; #if (defined ENABLE_LADSPA) if (m_use_effect && play->enable_effect) { int i; for(i=0;i<nfo->channels;i++) { ladspaerr |= ladspah_init(myplugin[i], m_use_effect, m_effectno, jack_get_sample_rate(j_client) /* m_samplerate */, maxbufsiz); } if (ladspaerr) { dbg(0, "error setting up LADSPA plugin - effect disabled.\n"); } } else { ladspaerr = 1; } play->effect_enabled = ladspaerr ? false : true; // read-only for GUI #endif size_t rbchunk = nframes_r * nfo->channels * sizeof(float); play_position = 0; int64_t decoder_position = 0; pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); pthread_mutex_lock(&player_thread_lock); /** ALL SYSTEMS GO **/ player_active = 1; while(thread_run) { int rv = ad_read(myplayer, tmpbuf, nframes * nfo->channels); if (rv > 0) decoder_position += rv / nfo->channels; #ifdef JACK_MIDI const float pp[3] = {play->effect_param[0], play->effect_param[1] + midi_note, play->effect_param[2] + midi_octave}; #else const float pp[3] = {play->effect_param[0], play->effect_param[1], play->effect_param[2]}; #endif #if (defined ENABLE_RESAMPLING) && (defined VARISPEED) const float varispeed = play->playback_speed; #if 0 /* note: libsamplerate slowly approaches a new sample-rate slowly * src_set_ratio() allow for immediate updates at loss of quality */ static float oldspd = -1; if (oldspd != varispeed) { if ((err = src_set_ratio(src_state, m_fResampleRatio * varispeed))) dbg(0, "SRC ERROR: %s", src_strerror(err)); // instant change. oldspd = varispeed; } #endif nframes_r = floorf((float) nframes * m_fResampleRatio * varispeed); ///< # of frames after resampling src_data.input_frames = nframes; src_data.output_frames = nframes_r; src_data.src_ratio = m_fResampleRatio * varispeed; src_data.end_of_input = 0; #endif if (rv != nframes * nfo->channels) { dbg(1, "end of file."); if (rv > 0) { #ifdef ENABLE_RESAMPLING # ifdef VARISPEED if (1) # else if(m_fResampleRatio != 1.0) # endif { src_data.input_frames = rv / nfo->channels; #ifdef VARISPEED src_data.output_frames = floorf((float)(rv / nfo->channels) * m_fResampleRatio * varispeed); #else src_data.output_frames = floorf((float)(rv / nfo->channels) * m_fResampleRatio); #endif src_data.end_of_input = play->config.loop ? 0 : 1; src_process(src_state, &src_data); bufptr = smpbuf; rv = src_data.output_frames_gen * nfo->channels; } #endif if (!ladspaerr) { ladspah_set_param(myplugin, nfo->channels, 0 /*cents */, pp[0]); /* -100 .. 100 */ ladspah_set_param(myplugin, nfo->channels, 1 /*semitones */, pp[1]); /* -12 .. 12 */ ladspah_set_param(myplugin, nfo->channels, 2 /*octave */, pp[2]); /* -3 .. 3 */ ladspah_process_nch(myplugin, nfo->channels, bufptr, rv / nfo->channels); } jack_ringbuffer_write(rb, (char *) bufptr, rv * sizeof(float)); } if (play->config.loop) { ad_seek(myplayer, 0); decoder_position = 0; #ifdef ENABLE_RESAMPLING //src_reset (src_state); // XXX causes click # ifdef VARISPEED if (1) # else if(m_fResampleRatio != 1.0) # endif { src_data.end_of_input = 0; src_data.input_frames = nframes; src_data.output_frames = nframes_r; } #endif #if (defined ENABLE_RESAMPLING) && (defined VARISPEED) while(thread_run && jack_ringbuffer_write_space(rb) <= maxbufsiz*nfo->channels*sizeof(float)) #else while(thread_run && jack_ringbuffer_write_space(rb) <= rbchunk) #endif { pthread_cond_wait(&buffer_ready, &player_thread_lock); } continue; } else break; } /* end EOF handling */ #ifdef ENABLE_RESAMPLING #ifdef VARISPEED if(1) // m_fResampleRatio*varispeed != 1.0) #else if(m_fResampleRatio != 1.0) #endif { if ((err=src_process(src_state, &src_data))) { dbg(0, "SRC PROCESS ERROR: %s", src_strerror(err)); } bufptr = smpbuf; rbchunk = src_data.output_frames_gen * nfo->channels * sizeof(float); } #endif if (!ladspaerr) { ladspah_set_param(myplugin, nfo->channels, 0 /*cent */, pp[0]); /* -100 .. 100 */ ladspah_set_param(myplugin, nfo->channels, 1 /*semitones */, pp[1]); /* -12 .. 12 */ ladspah_set_param(myplugin, nfo->channels, 2 /*octave */, pp[2]); /* -3 .. 3 */ ladspah_process_nch(myplugin, nfo->channels, bufptr, rbchunk/ nfo->channels / sizeof(float)); } jack_ringbuffer_write(rb, (char *) bufptr, rbchunk); #if (defined ENABLE_RESAMPLING) && (defined VARISPEED) while(thread_run && jack_ringbuffer_write_space(rb) <= maxbufsiz*nfo->channels*sizeof(float)) #else while(thread_run && jack_ringbuffer_write_space(rb) <= rbchunk) #endif { #if 1 // flush_ringbuffer on seek if (playpause && seek_request != -1) break; #endif pthread_cond_wait(&buffer_ready, &player_thread_lock); } /* Handle SEEKs */ while (seek_request>=0 && seek_request<=1) { double csr = seek_request; decoder_position = floor(m_frames * seek_request); ad_seek(myplayer, decoder_position); if (csr == seek_request) { seek_request = -1; #if 1 // flush_ringbuffer ! size_t rs=jack_ringbuffer_read_space(rb); jack_ringbuffer_read_advance(rb,rs); #endif break; } } #if (defined ENABLE_RESAMPLING) && (defined VARISPEED) update_playposition (decoder_position, varispeed); #else update_playposition (decoder_position, 1.0); #endif } /** END OF PLAYBACK **/ #if (defined ENABLE_RESAMPLING) && (defined VARISPEED) const float varispeed = play->playback_speed; #else const float varispeed = 1.0; #endif pthread_mutex_unlock(&player_thread_lock); if (thread_run) { // wait for ringbuffer to empty. while (!silent && !playpause) { usleep(20); update_playposition (decoder_position, varispeed); } thread_run = 0; player_active = 0; play->effect_enabled = false; int i; for(i=0;i<nfo->channels;i++) { ladspah_deinit(myplugin[i]); } JACKclose(); } free(tmpbuf); #ifdef ENABLE_RESAMPLING src_delete(src_state); free(smpbuf); #endif player_active = 0; if(play->status != PLAY_PLAY_PENDING){ play->next(); } return NULL; }
// 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; }
void JackResampler::Reset(unsigned int new_size) { fRingBufferSize = new_size; jack_ringbuffer_reset_size(fRingBuffer, sizeof(jack_default_audio_sample_t) * fRingBufferSize); jack_ringbuffer_read_advance(fRingBuffer, (sizeof(jack_default_audio_sample_t) * fRingBufferSize / 2)); }
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; }
int32 ad_read(ad_rec_t * handle, int16 * buf, int32 max) { #ifdef HAVE_SAMPLERATE_H int resample_error; #endif if (!handle->recording) return AD_EOF; size_t length = sample_size * max; #ifdef HAVE_SAMPLERATE_H // Resample the data from the sample rate set in the jack server to that required // by sphinx length = jack_ringbuffer_peek (handle->rbuffer, (char*) handle->sample_buffer, length); size_t length_in_samples = length / sample_size; if(handle->resample_state == NULL) return AD_EOF; // We will try to downsample if jackd is running at a higher sample rate jack_nframes_t jack_samplerate = jack_get_sample_rate(handle->client); SRC_DATA data; data.data_in = handle->sample_buffer; data.input_frames = length_in_samples; data.data_out = handle->resample_buffer; data.output_frames = BUFFER_SIZE / sample_size; data.src_ratio = (float) handle->sps / jack_samplerate; data.end_of_input = 0; if ((resample_error = src_process(handle->resample_state, &data)) != 0) { fprintf (stderr, "resample error %s\n", src_strerror (resample_error)); return 1; } for(int i=0; i<data.output_frames_gen; i++) { buf[i] = (int16) (int16_range_over_two * (handle->resample_buffer[i] + 1.0) + SHRT_MIN); } jack_ringbuffer_read_advance(handle->rbuffer, data.input_frames_used * sample_size); if(length == 0 && (!handle->recording)) { return AD_EOF; } return data.output_frames_gen; #else length = jack_ringbuffer_read (handle->rbuffer, (char*) handle->sample_buffer, length); size_t length_in_samples = length / sample_size; for(int i=0; i<length_in_samples; i++) { buf[i] = (int16) (int16_range_over_two * (handle->sample_buffer[i] + 1.0) + SHRT_MIN); } if(length == 0 && (!handle->recording)) { return AD_EOF; } return length_in_samples; #endif }