static void cbjack_stream_silence_out(cubeb_stream * stream, jack_nframes_t nframes) { for (unsigned int c = 0; c < stream->params.channels; c++) { float *samples = (float*)api_jack_port_get_buffer(stream->output_ports[c], nframes); for (jack_nframes_t s = 0; s < nframes; s++) { samples[s] = 0.0f; } } }
static void cbjack_stream_data_out(cubeb_stream * stream, jack_nframes_t nframes) { for (unsigned int c = 0; c < stream->params.channels; c++) { float* samples = (float*)api_jack_port_get_buffer(stream->output_ports[c], nframes); size_t needed_bytes = nframes * sizeof(float); size_t nread = api_jack_ringbuffer_read(stream->ringbuffer[c], (char *)samples, needed_bytes); assert(nread == needed_bytes); } stream->position += nframes; }
static int cbjack_process(jack_nframes_t nframes, void * arg) { cubeb * ctx = (cubeb *)arg; int t_jack_xruns = ctx->jack_xruns; int i; for (int j = 0; j < MAX_STREAMS; j++) { cubeb_stream *stm = &ctx->streams[j]; float *bufs_out[stm->out_params.channels]; float *bufs_in[stm->in_params.channels]; if (!stm->in_use) continue; // handle xruns by skipping audio that should have been played for (i = 0; i < t_jack_xruns; i++) { stm->position += ctx->fragment_size * stm->ratio; } ctx->jack_xruns -= t_jack_xruns; if (!stm->ports_ready) continue; if (stm->devs & OUT_ONLY) { // get jack output buffers for (i = 0; i < (int)stm->out_params.channels; i++) bufs_out[i] = (float*)api_jack_port_get_buffer(stm->output_ports[i], nframes); } if (stm->devs & IN_ONLY) { // get jack input buffers for (i = 0; i < (int)stm->in_params.channels; i++) bufs_in[i] = (float*)api_jack_port_get_buffer(stm->input_ports[i], nframes); } if (stm->pause) { // paused, play silence on output if (stm->devs & OUT_ONLY) { for (unsigned int c = 0; c < stm->out_params.channels; c++) { float* buffer_out = bufs_out[c]; for (long f = 0; f < nframes; f++) { buffer_out[f] = 0.f; } } } if (stm->devs & IN_ONLY) { // paused, capture silence for (unsigned int c = 0; c < stm->in_params.channels; c++) { float* buffer_in = bufs_in[c]; for (long f = 0; f < nframes; f++) { buffer_in[f] = 0.f; } } } } else { // try to lock stream mutex if (pthread_mutex_trylock(&stm->mutex) == 0) { int16_t *in_s16ne = stm->context->in_resampled_interleaved_buffer_s16ne; float *in_float = stm->context->in_resampled_interleaved_buffer_float; // unpaused, play audio if (stm->devs == DUPLEX) { if (stm->out_params.format == CUBEB_SAMPLE_S16NE) { cbjack_interleave_capture(stm, bufs_in, nframes, true); cbjack_deinterleave_playback_refill_s16ne(stm, &in_s16ne, bufs_out, nframes); } else if (stm->out_params.format == CUBEB_SAMPLE_FLOAT32NE) { cbjack_interleave_capture(stm, bufs_in, nframes, false); cbjack_deinterleave_playback_refill_float(stm, &in_float, bufs_out, nframes); } } else if (stm->devs == IN_ONLY) { if (stm->in_params.format == CUBEB_SAMPLE_S16NE) { cbjack_interleave_capture(stm, bufs_in, nframes, true); cbjack_deinterleave_playback_refill_s16ne(stm, &in_s16ne, nullptr, nframes); } else if (stm->in_params.format == CUBEB_SAMPLE_FLOAT32NE) { cbjack_interleave_capture(stm, bufs_in, nframes, false); cbjack_deinterleave_playback_refill_float(stm, &in_float, nullptr, nframes); } } else if (stm->devs == OUT_ONLY) { if (stm->out_params.format == CUBEB_SAMPLE_S16NE) { cbjack_deinterleave_playback_refill_s16ne(stm, nullptr, bufs_out, nframes); } else if (stm->out_params.format == CUBEB_SAMPLE_FLOAT32NE) { cbjack_deinterleave_playback_refill_float(stm, nullptr, bufs_out, nframes); } } // unlock stream mutex pthread_mutex_unlock(&stm->mutex); } else { // could not lock mutex // output silence if (stm->devs & OUT_ONLY) { for (unsigned int c = 0; c < stm->out_params.channels; c++) { float* buffer_out = bufs_out[c]; for (long f = 0; f < nframes; f++) { buffer_out[f] = 0.f; } } } if (stm->devs & IN_ONLY) { // capture silence for (unsigned int c = 0; c < stm->in_params.channels; c++) { float* buffer_in = bufs_in[c]; for (long f = 0; f < nframes; f++) { buffer_in[f] = 0.f; } } } } } } return 0; }