// When we have no pending input data and exactly as much input // as output data, we don't need to copy it into the internal buffer // and can directly forward it to the callback. void * in_buf = input_buffer; unsignedlong pop_input_count = 0u; if (input_buffer && !output_buffer) {
output_frames = *input_frames_count;
} elseif (input_buffer) { if (internal_input_buffer.length() != 0 ||
*input_frames_count < output_frames) { // If we have pending input data left and have to first append the input // so we can pass it as one pointer to the callback. Or this is a glitch. // It can happen when system's performance is poor. Audible silence is // being pushed at the end of the short input buffer. An improvement for // the future is to resample to the output number of frames, when that // happens.
internal_input_buffer.push(static_cast<T *>(input_buffer),
frames_to_samples(*input_frames_count)); if (internal_input_buffer.length() < frames_to_samples(output_frames)) { // This is unxpected but it can happen when a glitch occurs. Fill the // buffer with silence. First keep the actual number of input samples // used without the silence.
pop_input_count = internal_input_buffer.length();
internal_input_buffer.push_silence(frames_to_samples(output_frames) -
internal_input_buffer.length());
} else {
pop_input_count = frames_to_samples(output_frames);
}
in_buf = internal_input_buffer.data();
} elseif (*input_frames_count > output_frames) { // In this case we have more input that we need output and // fill the overflowing input into internal_input_buffer // Since we have no other pending data, we can nonetheless // pass the current input data directly to the callback
assert(pop_input_count == 0); unsignedlong samples_off = frames_to_samples(output_frames);
internal_input_buffer.push( static_cast<T *>(input_buffer) + samples_off,
frames_to_samples(*input_frames_count - output_frames));
}
}
long rv =
data_callback(stream, user_ptr, in_buf, output_buffer, output_frames);
if (input_buffer) { if (pop_input_count) {
internal_input_buffer.pop(nullptr, pop_input_count);
*input_frames_count = samples_to_frames(pop_input_count);
} else {
*input_frames_count = output_frames;
}
drop_audio_if_needed();
}
return rv;
}
// Explicit instantiation of template class. templateclass passthrough_resampler<float>; templateclass passthrough_resampler<short>;
template <typename T, typename InputProcessor, typename OutputProcessor> long
cubeb_resampler_speex<T, InputProcessor, OutputProcessor>::fill( void * input_buffer, long * input_frames_count, void * output_buffer, long output_frames_needed)
{ /* Input and output buffers, typed */
T * in_buffer = reinterpret_cast<T *>(input_buffer);
T * out_buffer = reinterpret_cast<T *>(output_buffer); return (this->*fill_internal)(in_buffer, input_frames_count, out_buffer,
output_frames_needed);
}
template <typename T, typename InputProcessor, typename OutputProcessor> long
cubeb_resampler_speex<T, InputProcessor, OutputProcessor>::fill_internal_output(
T * input_buffer, long * input_frames_count, T * output_buffer, long output_frames_needed)
{
assert(!input_buffer && (!input_frames_count || *input_frames_count == 0) &&
output_buffer && output_frames_needed);
if (!draining) { long got = 0;
T * out_unprocessed = nullptr; long output_frames_before_processing = 0;
/* fill directly the input buffer of the output processor to save a copy */
output_frames_before_processing =
output_processor->input_needed_for_output(output_frames_needed);
if (got < output_frames_before_processing) {
draining = true;
if (got < 0) { return got;
}
}
output_processor->written(got);
}
/* Process the output. If not enough frames have been returned from the
* callback, drain the processors. */ return output_processor->output(output_buffer, output_frames_needed);
}
template <typename T, typename InputProcessor, typename OutputProcessor> long
cubeb_resampler_speex<T, InputProcessor, OutputProcessor>::fill_internal_input(
T * input_buffer, long * input_frames_count, T * output_buffer, long/*output_frames_needed*/)
{
assert(input_buffer && input_frames_count && *input_frames_count &&
!output_buffer);
/* The input data, after eventual resampling. This is passed to the callback.
*/
T * resampled_input = nullptr;
uint32_t resampled_frame_count =
input_processor->output_for_input(*input_frames_count);
/* process the input, and present exactly `output_frames_needed` in the
* callback. */
input_processor->input(input_buffer, *input_frames_count);
/* resampled_frame_count == 0 happens if the resampler
* doesn't have enough input frames buffered to produce 1 resampled frame. */ if (resampled_frame_count == 0) { return *input_frames_count;
}
long got = data_callback(stream, user_ptr, resampled_input, nullptr,
resampled_frame_count);
/* Return the number of initial input frames or part of it. * Since output_frames_needed == 0 in input scenario, the only
* available number outside resampler is the initial number of frames. */ return (*input_frames_count) * (got / resampled_frame_count);
}
template <typename T, typename InputProcessor, typename OutputProcessor> long
cubeb_resampler_speex<T, InputProcessor, OutputProcessor>::fill_internal_duplex(
T * in_buffer, long * input_frames_count, T * out_buffer, long output_frames_needed)
{ if (draining) { // discard input and drain any signal remaining in the resampler. return output_processor->output(out_buffer, output_frames_needed);
}
/* The input data, after eventual resampling. This is passed to the callback.
*/
T * resampled_input = nullptr; /* The output buffer passed down in the callback, that might be resampled. */
T * out_unprocessed = nullptr; long output_frames_before_processing = 0; /* The number of frames returned from the callback. */ long got = 0;
/* We need to determine how much frames to present to the consumer. * - If we have a two way stream, but we're only resampling input, we resample * the input to the number of output frames. * - If we have a two way stream, but we're only resampling the output, we * resize the input buffer of the output resampler to the number of input * frames, and we resample it afterwards. * - If we resample both ways, we resample the input to the number of frames * we would need to pass down to the consumer (before resampling the output), * get the output data, and resample it to the number of frames needed by the
* caller. */
output_frames_before_processing =
output_processor->input_needed_for_output(output_frames_needed); /* fill directly the input buffer of the output processor to save a copy */
out_unprocessed =
output_processor->input_buffer(output_frames_before_processing);
if (in_buffer) { /* process the input, and present exactly `output_frames_needed` in the
* callback. */
input_processor->input(in_buffer, *input_frames_count);
if (got < output_frames_before_processing) {
draining = true;
if (got < 0) { return got;
}
}
output_processor->written(got);
input_processor->drop_audio_if_needed();
/* Process the output. If not enough frames have been returned from the
* callback, drain the processors. */
got = output_processor->output(out_buffer, output_frames_needed);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.