Exemplo n.º 1
0
static void
cbjack_deinterleave_playback_refill_s16ne(cubeb_stream * stream, short ** in, float ** bufs_out, jack_nframes_t nframes)
{
  float * out_interleaved_buffer = nullptr;

  short * inptr = (in != NULL) ? *in : nullptr;
  float * outptr = (bufs_out != NULL) ? *bufs_out : nullptr;

  long needed_frames = (bufs_out != NULL) ? nframes : 0;
  long done_frames = 0;
  long input_frames_count = (in != NULL) ? nframes : 0;

  done_frames = cubeb_resampler_fill(stream->resampler,
                                     inptr,
                                     &input_frames_count,
                                     (bufs_out != NULL) ? stream->context->out_resampled_interleaved_buffer_s16ne : NULL,
                                     needed_frames);

  s16ne_to_float(stream->context->out_resampled_interleaved_buffer_float, stream->context->out_resampled_interleaved_buffer_s16ne, done_frames * stream->out_params.channels);

  out_interleaved_buffer = stream->context->out_resampled_interleaved_buffer_float;

  if (outptr) {
    // convert interleaved output buffers to contiguous buffers
    for (unsigned int c = 0; c < stream->out_params.channels; c++) {
      float* buffer = bufs_out[c];
      for (long f = 0; f < done_frames; f++) {
        buffer[f] = out_interleaved_buffer[(f * stream->out_params.channels) + c] * stream->volume;
      }
      if (done_frames < needed_frames) {
        // draining
        for (long f = done_frames; f < needed_frames; f++) {
          buffer[f] = 0.f;
        }
      }
      if (done_frames == 0) {
        // stop, but first zero out the existing buffer
        for (long f = 0; f < needed_frames; f++) {
          buffer[f] = 0.f;
        }
      }
    }
  }

  if (done_frames >= 0 && done_frames < needed_frames) {
    // set drained
    stream->state_callback(stream, stream->user_ptr, CUBEB_STATE_DRAINED);
    // stop stream
    cbjack_stream_stop(stream);
  }
  if (done_frames > 0 && done_frames <= needed_frames) {
    // advance stream position
    stream->position += done_frames * stream->ratio;
  }
  if (done_frames < 0 || done_frames > needed_frames) {
    // stream error
    stream->state_callback(stream, stream->user_ptr, CUBEB_STATE_ERROR);
  }
}
Exemplo n.º 2
0
static void
cbjack_stream_refill(cubeb_stream * stream)
{
  unsigned int max_bytes = cbjack_stream_data_space(stream);
  long const max_num_output_frames = max_bytes / sizeof(float); // we're outputing floats
  long const max_num_frames = (max_num_output_frames * stream->params.rate) / stream->context->jack_sample_rate;

  long num_frames = stream->data_callback(stream,
                                          stream->user_ptr,
                                          NULL,
                                          stream->context->input_buffer,
                                          max_num_frames);

  // check for drain
  if (num_frames < max_num_frames)
    stream->state = STATE_DRAINING;

  float *interleaved_buffer;

  // convert 16-bit to float if needed
  if (stream->params.format == CUBEB_SAMPLE_S16NE) {
    s16ne_to_float(stream->context->float_interleaved_buffer, (short*)stream->context->input_buffer, num_frames * stream->params.channels);
    interleaved_buffer = stream->context->float_interleaved_buffer;
  } else if (stream->params.format == CUBEB_SAMPLE_FLOAT32NE) {
    interleaved_buffer = (float *)stream->context->input_buffer;
  }
  else {
    assert(0); // should not occur, checked by cbjack_stream_init
  }

  if (stream->resampler != NULL) {
    uint32_t resampler_consumed_frames = num_frames;
    uint32_t resampler_output_frames = (FIFO_SIZE / sizeof(float)) * MAX_CHANNELS * 3;

    int resampler_error = speex_resampler_process_interleaved_float(stream->resampler,
                                                                    interleaved_buffer,
                                                                    &resampler_consumed_frames,
                                                                    stream->context->resampled_interleaved_buffer,
                                                                    &resampler_output_frames);
    assert(resampler_error == 0);
    assert(resampler_consumed_frames == num_frames);
    num_frames = resampler_output_frames;
    interleaved_buffer = stream->context->resampled_interleaved_buffer;
  }

  // convert interleaved buffers to contigous buffers
  for (unsigned int c = 0; c < stream->params.channels; c++) {
    float* buffer = stream->context->buffer[c];
    for (long f = 0; f < num_frames; f++) {
      buffer[f] = interleaved_buffer[(f * stream->params.channels) + c] * stream->volume;
    }
  }

  // send contigous buffers to ring buffers
  for (unsigned int c = 0; c < stream->params.channels; c++) {
    size_t bytes_to_write = num_frames * sizeof(float);
    char* buffer = (char*)stream->context->buffer[c];
    while(bytes_to_write > 0) {
      size_t nwritten = api_jack_ringbuffer_write(stream->ringbuffer[c], buffer, bytes_to_write);
      bytes_to_write -= nwritten;
      buffer += nwritten;
      if (nwritten == 0) {
        assert(bytes_to_write == 0);
        break;
      }
    }
  }
}