diff options
author | Steve Haynal <softerhardware@gmail.com> | 2013-12-09 17:01:00 -0800 |
---|---|---|
committer | Steve Haynal <softerhardware@gmail.com> | 2013-12-09 17:01:00 -0800 |
commit | 95a88be60209a04d37b062cc5548e3d123d9a595 (patch) | |
tree | ffd0f0205de0d603e2f7441bbfae8b4b0134e36c /gr-audio/lib | |
parent | 317cd569beeeb7259671f0a84f09818fe6d7f825 (diff) |
Support for >1 jack port, various sizes of jack buffers
Diffstat (limited to 'gr-audio/lib')
-rw-r--r-- | gr-audio/lib/jack/jack_sink.cc | 111 | ||||
-rw-r--r-- | gr-audio/lib/jack/jack_sink.h | 6 | ||||
-rw-r--r-- | gr-audio/lib/jack/jack_source.cc | 112 | ||||
-rw-r--r-- | gr-audio/lib/jack/jack_source.h | 6 |
4 files changed, 145 insertions, 90 deletions
diff --git a/gr-audio/lib/jack/jack_sink.cc b/gr-audio/lib/jack/jack_sink.cc index c47c37a301..ed3f63b81f 100644 --- a/gr-audio/lib/jack/jack_sink.cc +++ b/gr-audio/lib/jack/jack_sink.cc @@ -67,16 +67,19 @@ namespace gr { jack_sink *self = (jack_sink *)arg; unsigned int read_size = nframes*sizeof(sample_t); - if(jack_ringbuffer_read_space(self->d_ringbuffer) < read_size) { - self->d_nunderuns++; - // FIXME: move this fputs out, we shouldn't use blocking calls in process() - fputs("jU", stderr); - return 0; - } + for(int i = 0; i < self->d_portcount; i++) { - char *buffer = (char *)jack_port_get_buffer(self->d_jack_output_port, nframes); + if(jack_ringbuffer_read_space(self->d_ringbuffer[i]) < read_size) { + self->d_nunderuns++; + // FIXME: move this fputs out, we shouldn't use blocking calls in process() + fputs("jU", stderr); + return 0; + } - jack_ringbuffer_read(self->d_ringbuffer, buffer, read_size); + char *buffer = (char *)jack_port_get_buffer(self->d_jack_output_port[i], nframes); + + jack_ringbuffer_read(self->d_ringbuffer[i], buffer, read_size); + } #ifndef NO_PTHREAD // Tell the sink thread there is room in the ringbuffer. @@ -105,7 +108,9 @@ namespace gr { d_device_name(device_name.empty() ? default_device_name() : device_name), d_ok_to_block(ok_to_block), d_jack_client(0), - d_ringbuffer(0), + d_portcount(0), + d_jack_output_port(), + d_ringbuffer(), d_nunderuns(0) { #ifndef NO_PTHREAD @@ -135,22 +140,15 @@ namespace gr { //jack_on_shutdown (d_jack_client, &jack_shutdown, (void*)this); - d_jack_output_port = - jack_port_register(d_jack_client, "out", - JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); - d_jack_buffer_size = jack_get_buffer_size(d_jack_client); set_output_multiple(d_jack_buffer_size); - d_ringbuffer = - jack_ringbuffer_create(N_BUFFERS*d_jack_buffer_size*sizeof(sample_t)); - if(d_ringbuffer == NULL) - bail("jack_ringbuffer_create failed", 0); assert(sizeof(float)==sizeof(sample_t)); - set_input_signature(io_signature::make(1, 1, sizeof(sample_t))); + // Real number of outputs is set in check_topology + set_input_signature(io_signature::make(1, MAX_PORTS, sizeof(sample_t))); jack_nframes_t sample_rate = jack_get_sample_rate(d_jack_client); @@ -164,9 +162,25 @@ namespace gr { bool jack_sink::check_topology (int ninputs, int noutputs) { - if(ninputs != 1) + if(ninputs > MAX_PORTS) return false; + d_portcount = ninputs; // # of channels we're really using + + // Create ports and ringbuffers + for(int i = 0; i < d_portcount; i++) { + std::string portname("out" + boost::to_string(i)); + + d_jack_output_port[i] = + jack_port_register(d_jack_client, portname.c_str(), + JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); + + d_ringbuffer[i] = + jack_ringbuffer_create(N_BUFFERS*d_jack_buffer_size*sizeof(sample_t)); + if(d_ringbuffer[i] == NULL) + bail("jack_ringbuffer_create failed", 0); + } + // tell the JACK server that we are ready to roll if(jack_activate (d_jack_client)) throw std::runtime_error("audio_jack_sink"); @@ -177,7 +191,9 @@ namespace gr { jack_sink::~jack_sink() { jack_client_close(d_jack_client); - jack_ringbuffer_free(d_ringbuffer); + + for(int i = 0; i < d_portcount; i++) + jack_ringbuffer_free(d_ringbuffer[i]); } int @@ -185,39 +201,48 @@ namespace gr { gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { - // write_size and work_size are in bytes - int work_size = noutput_items*sizeof(sample_t); - unsigned int write_size; - while(work_size > 0) { - unsigned int write_space; // bytes + const float **in = (const float **)&input_items[0]; + + for(int i = 0; i < d_portcount; i++) { + + int k = 0; + + // write_size and work_size are in bytes + int work_size = noutput_items*sizeof(sample_t); + unsigned int write_size; + + while(work_size > 0) { + unsigned int write_space; // bytes #ifdef NO_PTHREAD - while((write_space=jack_ringbuffer_write_space(d_ringbuffer)) < - d_jack_buffer_size*sizeof(sample_t)) { - usleep(1000000*((d_jack_buffer_size-write_space/sizeof(sample_t))/d_sampling_rate)); - } + while((write_space=jack_ringbuffer_write_space(d_ringbuffer[i])) < + d_jack_buffer_size*sizeof(sample_t)) { + usleep(1000000*((d_jack_buffer_size-write_space/sizeof(sample_t))/d_sampling_rate)); + } #else - // JACK actually requires POSIX + // JACK actually requires POSIX - pthread_mutex_lock(&d_jack_process_lock); - while((write_space = jack_ringbuffer_write_space(d_ringbuffer)) < - d_jack_buffer_size*sizeof(sample_t)) { + pthread_mutex_lock(&d_jack_process_lock); + while((write_space = jack_ringbuffer_write_space(d_ringbuffer[i])) < + d_jack_buffer_size*sizeof(sample_t)) { - // wait until jack_sink_process() signals more room - pthread_cond_wait(&d_ringbuffer_ready, &d_jack_process_lock); - } - pthread_mutex_unlock(&d_jack_process_lock); + // wait until jack_sink_process() signals more room + pthread_cond_wait(&d_ringbuffer_ready, &d_jack_process_lock); + } + pthread_mutex_unlock(&d_jack_process_lock); #endif - write_space -= write_space%(d_jack_buffer_size*sizeof(sample_t)); - write_size = std::min(write_space, (unsigned int)work_size); + write_space -= write_space%(d_jack_buffer_size*sizeof(sample_t)); + write_size = std::min(write_space, (unsigned int)work_size); - if(jack_ringbuffer_write(d_ringbuffer, (char *) input_items[0], - write_size) < write_size) { - bail("jack_ringbuffer_write failed", 0); + if(jack_ringbuffer_write(d_ringbuffer[i], (char *) &(in[i][k]), + write_size) < write_size) { + bail("jack_ringbuffer_write failed", 0); + } + work_size -= write_size; + k += write_size/sizeof(sample_t); } - work_size -= write_size; } return noutput_items; diff --git a/gr-audio/lib/jack/jack_sink.h b/gr-audio/lib/jack/jack_sink.h index de34120055..9c97b34f96 100644 --- a/gr-audio/lib/jack/jack_sink.h +++ b/gr-audio/lib/jack/jack_sink.h @@ -55,8 +55,10 @@ namespace gr { bool d_ok_to_block; jack_client_t *d_jack_client; - jack_port_t *d_jack_output_port; - jack_ringbuffer_t *d_ringbuffer; + static const int MAX_PORTS = 10; + int d_portcount; + jack_port_t *d_jack_output_port[MAX_PORTS]; + jack_ringbuffer_t *d_ringbuffer[MAX_PORTS]; jack_nframes_t d_jack_buffer_size; pthread_cond_t d_ringbuffer_ready; pthread_mutex_t d_jack_process_lock; diff --git a/gr-audio/lib/jack/jack_source.cc b/gr-audio/lib/jack/jack_source.cc index a897785b0e..d2a1698982 100644 --- a/gr-audio/lib/jack/jack_source.cc +++ b/gr-audio/lib/jack/jack_source.cc @@ -67,16 +67,18 @@ namespace gr { jack_source *self = (jack_source *)arg; unsigned int write_size = nframes*sizeof(sample_t); - if(jack_ringbuffer_write_space (self->d_ringbuffer) < write_size) { - self->d_noverruns++; - // FIXME: move this fputs out, we shouldn't use blocking calls in process() - fputs ("jO", stderr); - return 0; - } - - char *buffer = (char *)jack_port_get_buffer(self->d_jack_input_port, nframes); + for(int i = 0; i < self->d_portcount; i++) { + if(jack_ringbuffer_write_space (self->d_ringbuffer[i]) < write_size) { + self->d_noverruns++; + // FIXME: move this fputs out, we shouldn't use blocking calls in process() + fputs ("jO", stderr); + return 0; + } + + char *buffer = (char *)jack_port_get_buffer(self->d_jack_input_port[i], nframes); - jack_ringbuffer_write (self->d_ringbuffer, buffer, write_size); + jack_ringbuffer_write (self->d_ringbuffer[i], buffer, write_size); + } #ifndef NO_PTHREAD // Tell the source thread there is data in the ringbuffer. @@ -106,7 +108,9 @@ namespace gr { d_device_name(device_name.empty() ? default_device_name() : device_name), d_ok_to_block(ok_to_block), d_jack_client(0), - d_ringbuffer(0), + d_portcount(0), + d_jack_input_port(), + d_ringbuffer(), d_noverruns(0) { #ifndef NO_PTHREAD @@ -136,20 +140,12 @@ namespace gr { //jack_on_shutdown (d_jack_client, &jack_shutdown, (void*)this); - d_jack_input_port = jack_port_register(d_jack_client, "in", - JACK_DEFAULT_AUDIO_TYPE, - JackPortIsInput, 0); - d_jack_buffer_size = jack_get_buffer_size(d_jack_client); set_output_multiple(d_jack_buffer_size); - d_ringbuffer = jack_ringbuffer_create(N_BUFFERS*d_jack_buffer_size*sizeof(sample_t)); - if(d_ringbuffer == NULL) - bail("jack_ringbuffer_create failed", 0); - assert(sizeof(float)==sizeof(sample_t)); - set_output_signature(io_signature::make(1, 1, sizeof(sample_t))); + set_output_signature(io_signature::make(1, MAX_PORTS, sizeof(sample_t))); jack_nframes_t sample_rate = jack_get_sample_rate(d_jack_client); @@ -163,6 +159,24 @@ namespace gr { bool jack_source::check_topology(int ninputs, int noutputs) { + + if(noutputs > MAX_PORTS) + return false; + + d_portcount = noutputs; // # of channels we're really using + + // Create ports and ringbuffers + for(int i = 0; i < d_portcount; i++) { + std::string portname("in" + boost::to_string(i)); + + d_jack_input_port[i] = jack_port_register(d_jack_client, portname.c_str(), + JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); + + d_ringbuffer[i] = jack_ringbuffer_create(N_BUFFERS*d_jack_buffer_size*sizeof(sample_t)); + if(d_ringbuffer[i] == NULL) + bail("jack_ringbuffer_create failed", 0); + } + // tell the JACK server that we are ready to roll if(jack_activate (d_jack_client)) throw std::runtime_error("audio_jack_source"); @@ -173,7 +187,10 @@ namespace gr { jack_source::~jack_source() { jack_client_close(d_jack_client); - jack_ringbuffer_free(d_ringbuffer); + + + for(int i = 0; i < d_portcount; i++) + jack_ringbuffer_free(d_ringbuffer[i]); } int @@ -181,42 +198,51 @@ namespace gr { gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { - // read_size and work_size are in bytes - unsigned int read_size; + + const float **out = (const float **)&output_items[0]; // Minimize latency noutput_items = std::min (noutput_items, (int)d_jack_buffer_size); - int work_size = noutput_items*sizeof(sample_t); + for(int i = 0; i < d_portcount; i++) { - while(work_size > 0) { - unsigned int read_space; // bytes + int k = 0; + + // read_size and work_size are in bytes + unsigned int read_size; + + int work_size = noutput_items*sizeof(sample_t); + + while(work_size > 0) { + unsigned int read_space; // bytes #ifdef NO_PTHREAD - while((read_space=jack_ringbuffer_read_space (d_ringbuffer)) < - d_jack_buffer_size*sizeof(sample_t)) { - usleep(1000000*((d_jack_buffer_size-read_space/sizeof(sample_t))/d_sampling_rate)); - } + while((read_space=jack_ringbuffer_read_space (d_ringbuffer[i])) < + d_jack_buffer_size*sizeof(sample_t)) { + usleep(1000000*((d_jack_buffer_size-read_space/sizeof(sample_t))/d_sampling_rate)); + } #else - // JACK actually requires POSIX - pthread_mutex_lock(&d_jack_process_lock); - while((read_space = jack_ringbuffer_read_space(d_ringbuffer)) < - d_jack_buffer_size*sizeof(sample_t)) { - // wait until jack_source_process() signals more data - pthread_cond_wait(&d_ringbuffer_ready, &d_jack_process_lock); - } - pthread_mutex_unlock(&d_jack_process_lock); + // JACK actually requires POSIX + pthread_mutex_lock(&d_jack_process_lock); + while((read_space = jack_ringbuffer_read_space(d_ringbuffer[i])) < + d_jack_buffer_size*sizeof(sample_t)) { + // wait until jack_source_process() signals more data + pthread_cond_wait(&d_ringbuffer_ready, &d_jack_process_lock); + } + pthread_mutex_unlock(&d_jack_process_lock); #endif - read_space -= read_space%(d_jack_buffer_size*sizeof(sample_t)); - read_size = std::min(read_space, (unsigned int)work_size); + read_space -= read_space%(d_jack_buffer_size*sizeof(sample_t)); + read_size = std::min(read_space, (unsigned int)work_size); - if(jack_ringbuffer_read(d_ringbuffer, (char *) output_items[0], - read_size) < read_size) { - bail("jack_ringbuffer_read failed", 0); + if(jack_ringbuffer_read(d_ringbuffer[i], (char *) &(out[i][k]), + read_size) < read_size) { + bail("jack_ringbuffer_read failed", 0); + } + work_size -= read_size; + k += read_size/sizeof(sample_t); } - work_size -= read_size; } return noutput_items; diff --git a/gr-audio/lib/jack/jack_source.h b/gr-audio/lib/jack/jack_source.h index 665139289b..2f7a0163a4 100644 --- a/gr-audio/lib/jack/jack_source.h +++ b/gr-audio/lib/jack/jack_source.h @@ -55,8 +55,10 @@ namespace gr { bool d_ok_to_block; jack_client_t *d_jack_client; - jack_port_t *d_jack_input_port; - jack_ringbuffer_t *d_ringbuffer; + static const int MAX_PORTS = 10; + int d_portcount; + jack_port_t *d_jack_input_port[MAX_PORTS]; + jack_ringbuffer_t *d_ringbuffer[MAX_PORTS]; jack_nframes_t d_jack_buffer_size; pthread_cond_t d_ringbuffer_ready; pthread_mutex_t d_jack_process_lock; |