Externals: update cubeb to kinetiknz/cubeb@c2bd582

A bunch of changes, looks mainly like bug fixes and code cleanup.

Notable changes:
- `cubeb_get_min_latency`'s signature was changed to take params via
  pointer, requiring Dolphin code to be tweaked in two places.
- A fix for kinetiknz/cubeb#320, as reported by @shuffle2
- Fixed build on FreeBSD (kinetiknz/cubeb#344), as contributed by @endrift
This commit is contained in:
Michael M
2017-10-21 14:28:39 -07:00
parent 774fca4d01
commit aa40c4a7ce
31 changed files with 1058 additions and 601 deletions
+45 -4
View File
@@ -43,9 +43,11 @@ add_library(cubeb
src/cubeb_resampler.cpp
src/cubeb_panner.cpp
src/cubeb_log.cpp
src/cubeb_utils.c
src/cubeb_strings.c
$<TARGET_OBJECTS:speex>)
target_include_directories(cubeb PUBLIC include)
target_include_directories(cubeb
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<INSTALL_INTERFACE:include>
)
target_include_directories(cubeb PRIVATE src)
target_compile_definitions(cubeb PRIVATE OUTSIDE_SPEEX)
target_compile_definitions(cubeb PRIVATE FLOATING_POINT)
@@ -56,7 +58,42 @@ add_sanitizers(cubeb)
include(GenerateExportHeader)
generate_export_header(cubeb EXPORT_FILE_NAME ${CMAKE_BINARY_DIR}/exports/cubeb_export.h)
target_include_directories(cubeb PUBLIC ${CMAKE_BINARY_DIR}/exports)
target_include_directories(cubeb
PUBLIC $<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/exports>
)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/include DESTINATION ${CMAKE_INSTALL_PREFIX})
install(DIRECTORY ${CMAKE_BINARY_DIR}/exports/ DESTINATION ${CMAKE_INSTALL_PREFIX}/include/cubeb)
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
COMPATIBILITY SameMajorVersion
)
configure_package_config_file(
"Config.cmake.in"
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
INSTALL_DESTINATION "lib/cmake/${PROJECT_NAME}"
)
install(TARGETS cubeb
EXPORT "${PROJECT_NAME}Targets"
DESTINATION ${CMAKE_INSTALL_PREFIX}
LIBRARY DESTINATION "lib"
ARCHIVE DESTINATION "lib"
RUNTIME DESTINATION "bin"
INCLUDES DESTINATION "include"
)
install(
FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
DESTINATION "lib/cmake/${PROJECT_NAME}"
)
install(
EXPORT "${PROJECT_NAME}Targets"
NAMESPACE "${PROJECT_NAME}::"
DESTINATION "lib/cmake/${PROJECT_NAME}"
)
add_library(speex OBJECT
src/speex/resample.c)
@@ -82,6 +119,7 @@ if(USE_PULSE)
target_sources(cubeb PRIVATE
src/cubeb_pulse.c)
target_compile_definitions(cubeb PRIVATE USE_PULSE)
target_link_libraries(cubeb PRIVATE pulse)
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
target_link_libraries(cubeb PRIVATE dl)
endif()
@@ -93,6 +131,9 @@ if(USE_ALSA)
src/cubeb_alsa.c)
target_compile_definitions(cubeb PRIVATE USE_ALSA)
target_link_libraries(cubeb PRIVATE asound pthread)
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
target_link_libraries(cubeb PRIVATE dl)
endif()
endif()
check_include_files(jack/jack.h USE_JACK)
@@ -100,10 +141,10 @@ if(USE_JACK)
target_sources(cubeb PRIVATE
src/cubeb_jack.cpp)
target_compile_definitions(cubeb PRIVATE USE_JACK)
target_link_libraries(cubeb PRIVATE jack pthread)
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
target_link_libraries(cubeb PRIVATE dl)
endif()
target_link_libraries(cubeb PRIVATE pthread)
endif()
check_include_files(audioclient.h USE_WASAPI)
+4
View File
@@ -0,0 +1,4 @@
@PACKAGE_INIT@
include("${CMAKE_CURRENT_LIST_DIR}/cubebTargets.cmake")
check_required_components(cubeb)
+22 -39
View File
@@ -33,11 +33,11 @@ extern "C" {
cubeb * app_ctx;
cubeb_init(&app_ctx, "Example Application");
int rv;
int rate;
int latency_frames;
uint32_t rate;
uint32_t latency_frames;
uint64_t ts;
rv = cubeb_get_min_latency(app_ctx, output_params, &latency_frames);
rv = cubeb_get_min_latency(app_ctx, &output_params, &latency_frames);
if (rv != CUBEB_OK) {
fprintf(stderr, "Could not get minimum latency");
return rv;
@@ -144,28 +144,6 @@ typedef enum {
#endif
} cubeb_sample_format;
#if defined(__ANDROID__)
/**
* This maps to the underlying stream types on supported platforms, e.g.
* Android.
*/
typedef enum {
CUBEB_STREAM_TYPE_VOICE_CALL = 0,
CUBEB_STREAM_TYPE_SYSTEM = 1,
CUBEB_STREAM_TYPE_RING = 2,
CUBEB_STREAM_TYPE_MUSIC = 3,
CUBEB_STREAM_TYPE_ALARM = 4,
CUBEB_STREAM_TYPE_NOTIFICATION = 5,
CUBEB_STREAM_TYPE_BLUETOOTH_SCO = 6,
CUBEB_STREAM_TYPE_SYSTEM_ENFORCED = 7,
CUBEB_STREAM_TYPE_DTMF = 8,
CUBEB_STREAM_TYPE_TTS = 9,
CUBEB_STREAM_TYPE_FM = 10,
CUBEB_STREAM_TYPE_MAX
} cubeb_stream_type;
#endif
/** An opaque handle used to refer a particular input or output device
* across calls. */
typedef void const * cubeb_devid;
@@ -239,12 +217,9 @@ typedef enum {
typedef struct {
cubeb_sample_format format; /**< Requested sample format. One of
#cubeb_sample_format. */
unsigned int rate; /**< Requested sample rate. Valid range is [1000, 192000]. */
unsigned int channels; /**< Requested channel count. Valid range is [1, 8]. */
uint32_t rate; /**< Requested sample rate. Valid range is [1000, 192000]. */
uint32_t channels; /**< Requested channel count. Valid range is [1, 8]. */
cubeb_channel_layout layout; /**< Requested channel layout. This must be consistent with the provided channels. */
#if defined(__ANDROID__)
cubeb_stream_type stream_type; /**< Used to map Android audio stream types */
#endif
} cubeb_stream_params;
/** Audio device description */
@@ -348,13 +323,13 @@ typedef struct {
cubeb_device_fmt format; /**< Sample format supported. */
cubeb_device_fmt default_format; /**< The default sample format for this device. */
unsigned int max_channels; /**< Channels. */
unsigned int default_rate; /**< Default/Preferred sample rate. */
unsigned int max_rate; /**< Maximum sample rate supported. */
unsigned int min_rate; /**< Minimum sample rate supported. */
uint32_t max_channels; /**< Channels. */
uint32_t default_rate; /**< Default/Preferred sample rate. */
uint32_t max_rate; /**< Maximum sample rate supported. */
uint32_t min_rate; /**< Minimum sample rate supported. */
unsigned int latency_lo; /**< Lowest possible latency in frames. */
unsigned int latency_hi; /**< Higest possible latency in frames. */
uint32_t latency_lo; /**< Lowest possible latency in frames. */
uint32_t latency_hi; /**< Higest possible latency in frames. */
} cubeb_device_info;
/** Device collection.
@@ -405,7 +380,7 @@ typedef void (* cubeb_device_changed_callback)(void * user_ptr);
/**
* User supplied callback called when the underlying device collection changed.
* @param context A pointer to the cubeb context.
* @param user_ptr The pointer passed to cubeb_stream_init. */
* @param user_ptr The pointer passed to cubeb_register_device_collection_changed. */
typedef void (* cubeb_device_collection_changed_callback)(cubeb * context,
void * user_ptr);
@@ -455,7 +430,7 @@ CUBEB_EXPORT int cubeb_get_max_channel_count(cubeb * context, uint32_t * max_cha
@retval CUBEB_ERROR_INVALID_PARAMETER
@retval CUBEB_ERROR_NOT_SUPPORTED */
CUBEB_EXPORT int cubeb_get_min_latency(cubeb * context,
cubeb_stream_params params,
cubeb_stream_params * params,
uint32_t * latency_frames);
/** Get the preferred sample rate for this backend: this is hardware and
@@ -512,7 +487,7 @@ CUBEB_EXPORT int cubeb_stream_init(cubeb * context,
cubeb_stream_params * input_stream_params,
cubeb_devid output_device,
cubeb_stream_params * output_stream_params,
unsigned int latency_frames,
uint32_t latency_frames,
cubeb_data_callback data_callback,
cubeb_state_callback state_callback,
void * user_ptr);
@@ -534,6 +509,14 @@ CUBEB_EXPORT int cubeb_stream_start(cubeb_stream * stream);
@retval CUBEB_ERROR */
CUBEB_EXPORT int cubeb_stream_stop(cubeb_stream * stream);
/** Reset stream to the default device.
@param stream
@retval CUBEB_OK
@retval CUBEB_ERROR_INVALID_PARAMETER
@retval CUBEB_ERROR_NOT_SUPPORTED
@retval CUBEB_ERROR */
CUBEB_EXPORT int cubeb_stream_reset_default_device(cubeb_stream * stream);
/** Get the current stream playback position.
@param stream
@param position Playback position in frames.
+2 -1
View File
@@ -57,6 +57,7 @@
<ClInclude Include="..\src\cubeb_resampler_internal.h" />
<ClInclude Include="..\src\cubeb_ringbuffer.h" />
<ClInclude Include="..\src\cubeb_ring_array.h" />
<ClInclude Include="..\src\cubeb_strings.h" />
<ClInclude Include="..\src\cubeb_utils.h" />
<ClInclude Include="..\src\cubeb_utils_unix.h" />
<ClInclude Include="..\src\cubeb_utils_win.h" />
@@ -74,7 +75,7 @@
<ClCompile Include="..\src\cubeb_mixer.cpp" />
<ClCompile Include="..\src\cubeb_panner.cpp" />
<ClCompile Include="..\src\cubeb_resampler.cpp" />
<ClCompile Include="..\src\cubeb_utils.c" />
<ClCompile Include="..\src\cubeb_strings.c" />
<ClCompile Include="..\src\cubeb_wasapi.cpp" />
<ClCompile Include="..\src\cubeb_winmm.c" />
<ClCompile Include="..\src\speex\resample.c" />
+3 -2
View File
@@ -11,6 +11,7 @@
<ClInclude Include="..\src\cubeb_resampler_internal.h" />
<ClInclude Include="..\src\cubeb_ring_array.h" />
<ClInclude Include="..\src\cubeb_ringbuffer.h" />
<ClInclude Include="..\src\cubeb_strings.h" />
<ClInclude Include="..\src\cubeb_utils.h" />
<ClInclude Include="..\src\cubeb_utils_unix.h" />
<ClInclude Include="..\src\cubeb_utils_win.h" />
@@ -45,7 +46,7 @@
<ClCompile Include="..\src\cubeb_mixer.cpp" />
<ClCompile Include="..\src\cubeb_panner.cpp" />
<ClCompile Include="..\src\cubeb_resampler.cpp" />
<ClCompile Include="..\src\cubeb_utils.c" />
<ClCompile Include="..\src\cubeb_strings.c" />
<ClCompile Include="..\src\cubeb_wasapi.cpp" />
<ClCompile Include="..\src\cubeb_winmm.c" />
<ClCompile Include="..\src\speex\resample.c">
@@ -57,4 +58,4 @@
<UniqueIdentifier>{caf7c7d0-0918-4299-8423-b287285d6fd0}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>
</Project>
+1
View File
@@ -69,6 +69,7 @@ struct cubeb_ops {
void (* stream_destroy)(cubeb_stream * stream);
int (* stream_start)(cubeb_stream * stream);
int (* stream_stop)(cubeb_stream * stream);
int (* stream_reset_default_device)(cubeb_stream * stream);
int (* stream_get_position)(cubeb_stream * stream, uint64_t * position);
int (* stream_get_latency)(cubeb_stream * stream, uint32_t * latency);
int (* stream_set_volume)(cubeb_stream * stream, float volumes);
+29 -4
View File
@@ -245,9 +245,9 @@ cubeb_get_max_channel_count(cubeb * context, uint32_t * max_channels)
}
int
cubeb_get_min_latency(cubeb * context, cubeb_stream_params params, uint32_t * latency_ms)
cubeb_get_min_latency(cubeb * context, cubeb_stream_params * params, uint32_t * latency_ms)
{
if (!context || !latency_ms) {
if (!context || !params || !latency_ms) {
return CUBEB_ERROR_INVALID_PARAMETER;
}
@@ -255,7 +255,7 @@ cubeb_get_min_latency(cubeb * context, cubeb_stream_params params, uint32_t * la
return CUBEB_ERROR_NOT_SUPPORTED;
}
return context->ops->get_min_latency(context, params, latency_ms);
return context->ops->get_min_latency(context, *params, latency_ms);
}
int
@@ -368,6 +368,20 @@ cubeb_stream_stop(cubeb_stream * stream)
return stream->context->ops->stream_stop(stream);
}
int
cubeb_stream_reset_default_device(cubeb_stream * stream)
{
if (!stream) {
return CUBEB_ERROR_INVALID_PARAMETER;
}
if (!stream->context->ops->stream_reset_default_device) {
return CUBEB_ERROR_NOT_SUPPORTED;
}
return stream->context->ops->stream_reset_default_device(stream);
}
int
cubeb_stream_get_position(cubeb_stream * stream, uint64_t * position)
{
@@ -574,13 +588,24 @@ int cubeb_enumerate_devices(cubeb * context,
int cubeb_device_collection_destroy(cubeb * context,
cubeb_device_collection * collection)
{
int r;
if (context == NULL || collection == NULL)
return CUBEB_ERROR_INVALID_PARAMETER;
if (!context->ops->device_collection_destroy)
return CUBEB_ERROR_NOT_SUPPORTED;
return context->ops->device_collection_destroy(context, collection);
if (!collection->device)
return CUBEB_OK;
r = context->ops->device_collection_destroy(context, collection);
if (r == CUBEB_OK) {
collection->device = NULL;
collection->count = 0;
}
return r;
}
int cubeb_register_device_collection_changed(cubeb * context,
+1 -1
View File
@@ -17,7 +17,6 @@
#include <alsa/asoundlib.h>
#include "cubeb/cubeb.h"
#include "cubeb-internal.h"
#include "cubeb_utils.h"
#define CUBEB_STREAM_MAX 16
#define CUBEB_WATCHDOG_MS 10000
@@ -1361,6 +1360,7 @@ static struct cubeb_ops const alsa_ops = {
.stream_destroy = alsa_stream_destroy,
.stream_start = alsa_stream_start,
.stream_stop = alsa_stream_stop,
.stream_reset_default_device = NULL,
.stream_get_position = alsa_stream_get_position,
.stream_get_latency = alsa_stream_get_latency,
.stream_set_volume = alsa_stream_set_volume,
+4 -3
View File
@@ -145,9 +145,9 @@ audiotrack_get_min_frame_count(cubeb * ctx, cubeb_stream_params * params, int *
status_t status;
/* Recent Android have a getMinFrameCount method. */
if (!audiotrack_version_is_gingerbread(ctx)) {
status = ctx->klass.get_min_frame_count(min_frame_count, params->stream_type, params->rate);
status = ctx->klass.get_min_frame_count(min_frame_count, AUDIO_STREAM_TYPE_MUSIC, params->rate);
} else {
status = ctx->klass.get_min_frame_count_gingerbread(min_frame_count, params->stream_type, params->rate);
status = ctx->klass.get_min_frame_count_gingerbread(min_frame_count, AUDIO_STREAM_TYPE_MUSIC, params->rate);
}
if (status != 0) {
ALOG("error getting the min frame count");
@@ -325,7 +325,7 @@ audiotrack_stream_init(cubeb * ctx, cubeb_stream ** stream, char const * stream_
channels = stm->params.channels == 2 ? AUDIO_CHANNEL_OUT_STEREO_ICS : AUDIO_CHANNEL_OUT_MONO_ICS;
}
ctx->klass.ctor(stm->instance, stm->params.stream_type, stm->params.rate,
ctx->klass.ctor(stm->instance, AUDIO_STREAM_TYPE_MUSIC, stm->params.rate,
AUDIO_FORMAT_PCM_16_BIT, channels, min_frame_count, 0,
audiotrack_refill, stm, 0, 0);
@@ -429,6 +429,7 @@ static struct cubeb_ops const audiotrack_ops = {
.stream_destroy = audiotrack_stream_destroy,
.stream_start = audiotrack_stream_start,
.stream_stop = audiotrack_stream_stop,
.stream_reset_default_device = NULL,
.stream_get_position = audiotrack_stream_get_position,
.stream_get_latency = audiotrack_stream_get_latency,
.stream_set_volume = audiotrack_stream_set_volume,
+309 -292
View File
File diff suppressed because it is too large Load Diff
+27 -12
View File
@@ -96,6 +96,8 @@ static int cbjack_stream_device_destroy(cubeb_stream * stream,
static int cbjack_stream_get_current_device(cubeb_stream * stm, cubeb_device ** const device);
static int cbjack_enumerate_devices(cubeb * context, cubeb_device_type type,
cubeb_device_collection * collection);
static int cbjack_device_collection_destroy(cubeb * context,
cubeb_device_collection * collection);
static int cbjack_stream_init(cubeb * context, cubeb_stream ** stream, char const * stream_name,
cubeb_devid input_device,
cubeb_stream_params * input_stream_params,
@@ -119,12 +121,13 @@ static struct cubeb_ops const cbjack_ops = {
.get_preferred_sample_rate = cbjack_get_preferred_sample_rate,
.get_preferred_channel_layout = NULL,
.enumerate_devices = cbjack_enumerate_devices,
.device_collection_destroy = cubeb_utils_default_device_collection_destroy,
.device_collection_destroy = cbjack_device_collection_destroy,
.destroy = cbjack_destroy,
.stream_init = cbjack_stream_init,
.stream_destroy = cbjack_stream_destroy,
.stream_start = cbjack_stream_start,
.stream_stop = cbjack_stream_stop,
.stream_reset_default_device = NULL,
.stream_get_position = cbjack_stream_get_position,
.stream_get_latency = cbjack_get_latency,
.stream_set_volume = cbjack_stream_set_volume,
@@ -973,6 +976,9 @@ cbjack_stream_device_destroy(cubeb_stream * /*stream*/,
return CUBEB_OK;
}
#define JACK_DEFAULT_IN "JACK capture"
#define JACK_DEFAULT_OUT "JACK playback"
static int
cbjack_enumerate_devices(cubeb * context, cubeb_device_type type,
cubeb_device_collection * collection)
@@ -982,20 +988,20 @@ cbjack_enumerate_devices(cubeb * context, cubeb_device_type type,
uint32_t rate;
cbjack_get_preferred_sample_rate(context, &rate);
const char * j_in = "JACK capture";
const char * j_out = "JACK playback";
cubeb_device_info * devices = new cubeb_device_info[2];
reinterpret_cast<cubeb_device_info *>(calloc(2, sizeof(cubeb_device_info)));
if (!devices)
return CUBEB_ERROR;
PodZero(devices, 2);
collection->count = 0;
if (type & CUBEB_DEVICE_TYPE_OUTPUT) {
cubeb_device_info * cur = &devices[collection->count];
cur->device_id = strdup(j_out);
cur->device_id = JACK_DEFAULT_OUT;
cur->devid = (cubeb_devid) cur->device_id;
cur->friendly_name = strdup(j_out);
cur->group_id = strdup(j_out);
cur->vendor_name = strdup(j_out);
cur->friendly_name = JACK_DEFAULT_OUT;
cur->group_id = JACK_DEFAULT_OUT;
cur->vendor_name = JACK_DEFAULT_OUT;
cur->type = CUBEB_DEVICE_TYPE_OUTPUT;
cur->state = CUBEB_DEVICE_STATE_ENABLED;
cur->preferred = CUBEB_DEVICE_PREF_ALL;
@@ -1012,11 +1018,11 @@ cbjack_enumerate_devices(cubeb * context, cubeb_device_type type,
if (type & CUBEB_DEVICE_TYPE_INPUT) {
cubeb_device_info * cur = &devices[collection->count];
cur->device_id = strdup(j_in);
cur->device_id = JACK_DEFAULT_IN;
cur->devid = (cubeb_devid) cur->device_id;
cur->friendly_name = strdup(j_in);
cur->group_id = strdup(j_in);
cur->vendor_name = strdup(j_in);
cur->friendly_name = JACK_DEFAULT_IN;
cur->group_id = JACK_DEFAULT_IN;
cur->vendor_name = JACK_DEFAULT_IN;
cur->type = CUBEB_DEVICE_TYPE_INPUT;
cur->state = CUBEB_DEVICE_STATE_ENABLED;
cur->preferred = CUBEB_DEVICE_PREF_ALL;
@@ -1035,3 +1041,12 @@ cbjack_enumerate_devices(cubeb * context, cubeb_device_type type,
return CUBEB_OK;
}
static int
cbjack_device_collection_destroy(cubeb * /*ctx*/,
cubeb_device_collection * collection)
{
XASSERT(collection);
delete [] collection->device;
return CUBEB_OK;
}
+1
View File
@@ -351,6 +351,7 @@ static struct cubeb_ops const kai_ops = {
/*.stream_destroy =*/ kai_stream_destroy,
/*.stream_start =*/ kai_stream_start,
/*.stream_stop =*/ kai_stream_stop,
/*.stream_reset_default_device =*/ NULL,
/*.stream_get_position =*/ kai_stream_get_position,
/*.stream_get_latency = */ kai_stream_get_latency,
/*.stream_set_volume =*/ kai_stream_set_volume,
+14
View File
@@ -95,6 +95,12 @@ public:
}
}).detach();
}
// Tell the underlying queue the producer thread has changed, so it does not
// assert in debug. This should be called with the thread stopped.
void reset_producer_thread()
{
msg_queue.reset_thread_ids();
}
private:
#ifndef _WIN32
const struct timespec sleep_for = {
@@ -128,3 +134,11 @@ void cubeb_async_log(char const * fmt, ...)
cubeb_async_logger::get().push(msg);
va_end(args);
}
void cubeb_async_log_reset_threads()
{
if (!g_cubeb_log_callback) {
return;
}
cubeb_async_logger::get().reset_producer_thread();
}
+1
View File
@@ -23,6 +23,7 @@ extern "C" {
extern cubeb_log_level g_cubeb_log_level;
extern cubeb_log_callback g_cubeb_log_callback PRINTF_FORMAT(1, 2);
void cubeb_async_log(const char * fmt, ...);
void cubeb_async_log_reset_threads();
#ifdef __cplusplus
}
+12 -10
View File
@@ -299,7 +299,7 @@ mix_remap(long inframes,
T * out, unsigned long out_len,
cubeb_channel_layout in_layout, cubeb_channel_layout out_layout)
{
assert(in_layout != out_layout);
assert(in_layout != out_layout && inframes >= 0);
// We might overwrite the data before we copied them to the mapped index
// (e.g. upmixing from stereo to 2F1 or mapping [L, R] to [R, L])
@@ -325,15 +325,16 @@ mix_remap(long inframes,
return false;
}
for (unsigned long i = 0, out_index = 0; i < inframes * in_channels; i += in_channels, out_index += out_channels) {
for (unsigned long i = 0, out_index = 0; i < (unsigned long)inframes * in_channels; i += in_channels, out_index += out_channels) {
for (unsigned int j = 0; j < out_channels; ++j) {
cubeb_channel channel = CHANNEL_INDEX_TO_ORDER[out_layout][j];
uint32_t channel_mask = 1 << channel;
int channel_index = CHANNEL_ORDER_TO_INDEX[in_layout][channel];
assert(channel_index >= -1);
assert(out_index + j < out_len);
if (in_layout_mask & channel_mask) {
assert(i + channel_index < in_len);
assert(channel_index != -1);
assert(i + channel_index < in_len);
out[out_index + j] = in[i + channel_index];
} else {
assert(channel_index == -1);
@@ -353,13 +354,13 @@ downmix_fallback(long inframes,
T * out, unsigned long out_len,
unsigned int in_channels, unsigned int out_channels)
{
assert(in_channels >= out_channels);
assert(in_channels >= out_channels && inframes >= 0);
if (in_channels == out_channels && in == out) {
return;
}
for (unsigned long i = 0, out_index = 0; i < inframes * in_channels; i += in_channels, out_index += out_channels) {
for (unsigned long i = 0, out_index = 0; i < (unsigned long)inframes * in_channels; i += in_channels, out_index += out_channels) {
for (unsigned int j = 0; j < out_channels; ++j) {
assert(i + j < in_len && out_index + j < out_len);
out[out_index + j] = in[i + j];
@@ -416,7 +417,7 @@ mono_to_stereo(long insamples, T const * in, unsigned long in_len,
T * out, unsigned long out_len, unsigned int out_channels)
{
for (long i = 0, j = 0; i < insamples; ++i, j += out_channels) {
assert(i < in_len && j + 1 < out_len);
assert((unsigned long)i < in_len && (unsigned long)j + 1 < out_len);
out[j] = out[j + 1] = in[i];
}
}
@@ -460,7 +461,7 @@ cubeb_upmix(long inframes,
/* Put silence in remaining channels. */
for (long i = 0, o = 0; i < inframes; ++i, o += out_channels) {
for (unsigned int j = 2; j < out_channels; ++j) {
assert(o + j < out_len);
assert((unsigned long)o + j < out_len);
out[o + j] = 0.0;
}
}
@@ -490,7 +491,8 @@ cubeb_should_downmix(cubeb_stream_params const * stream, cubeb_stream_params con
bool
cubeb_should_mix(cubeb_stream_params const * stream, cubeb_stream_params const * mixer)
{
return cubeb_should_upmix(stream, mixer) || cubeb_should_downmix(stream, mixer);
return stream->layout != CUBEB_LAYOUT_UNDEFINED &&
(cubeb_should_upmix(stream, mixer) || cubeb_should_downmix(stream, mixer));
}
struct cubeb_mixer {
@@ -559,11 +561,11 @@ void cubeb_mixer_destroy(cubeb_mixer * mixer)
void cubeb_mixer_mix(cubeb_mixer * mixer, long frames,
void * input_buffer, unsigned long input_buffer_length,
void * output_buffer, unsigned long outputput_buffer_length,
void * output_buffer, unsigned long output_buffer_length,
cubeb_stream_params const * stream_params,
cubeb_stream_params const * mixer_params)
{
assert(mixer);
mixer->mix(frames, input_buffer, input_buffer_length, output_buffer, outputput_buffer_length,
mixer->mix(frames, input_buffer, input_buffer_length, output_buffer, output_buffer_length,
stream_params, mixer_params);
}
+1 -1
View File
@@ -79,7 +79,7 @@ cubeb_mixer * cubeb_mixer_create(cubeb_sample_format format,
void cubeb_mixer_destroy(cubeb_mixer * mixer);
void cubeb_mixer_mix(cubeb_mixer * mixer, long frames,
void * input_buffer, unsigned long input_buffer_length,
void * output_buffer, unsigned long outputput_buffer_length,
void * output_buffer, unsigned long output_buffer_length,
cubeb_stream_params const * stream_params,
cubeb_stream_params const * mixer_params);
+38 -74
View File
@@ -105,7 +105,6 @@ struct cubeb_stream {
/* Flag indicating draining. Synchronized
* by stream::mutex lock. */
int draining;
cubeb_stream_type stream_type;
/* Flags to determine in/out.*/
uint32_t input_enabled;
uint32_t output_enabled;
@@ -187,6 +186,29 @@ opensl_set_draining(cubeb_stream * stm, int value)
stm->draining = value;
}
static void
opensl_notify_drained(cubeb_stream * stm)
{
assert(stm);
int r = pthread_mutex_lock(&stm->mutex);
assert(r == 0);
int draining = opensl_get_draining(stm);
r = pthread_mutex_unlock(&stm->mutex);
assert(r == 0);
if (draining) {
stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_DRAINED);
if (stm->play) {
LOG("stop player in play_callback");
r = opensl_stop_player(stm);
assert(r == CUBEB_OK);
}
if (stm->recorderItf) {
r = opensl_stop_recorder(stm);
assert(r == CUBEB_OK);
}
}
}
static uint32_t
opensl_get_shutdown(cubeb_stream * stm)
{
@@ -217,24 +239,7 @@ play_callback(SLPlayItf caller, void * user_ptr, SLuint32 event)
assert(stm);
switch (event) {
case SL_PLAYEVENT_HEADATMARKER:
{
int r = pthread_mutex_lock(&stm->mutex);
assert(r == 0);
draining = opensl_get_draining(stm);
r = pthread_mutex_unlock(&stm->mutex);
assert(r == 0);
if (draining) {
stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_DRAINED);
if (stm->play) {
r = opensl_stop_player(stm);
assert(r == CUBEB_OK);
}
if (stm->recorderItf) {
r = opensl_stop_recorder(stm);
assert(r == CUBEB_OK);
}
}
}
opensl_notify_drained(stm);
break;
default:
break;
@@ -330,9 +335,16 @@ bufferqueue_callback(SLBufferQueueItf caller, void * user_ptr)
opensl_set_draining(stm, 1);
r = pthread_mutex_unlock(&stm->mutex);
assert(r == 0);
// Use SL_PLAYEVENT_HEADATMARKER event from slPlayCallback of SLPlayItf
// to make sure all the data has been processed.
(*stm->play)->SetMarkerPosition(stm->play, (SLmillisecond)written_duration);
if (written_duration == 0) {
// since we didn't write any sample, it's not possible to reach the marker
// time and trigger the callback. We should initiative notify drained.
opensl_notify_drained(stm);
} else {
// Use SL_PLAYEVENT_HEADATMARKER event from slPlayCallback of SLPlayItf
// to make sure all the data has been processed.
(*stm->play)->SetMarkerPosition(stm->play, (SLmillisecond)written_duration);
}
return;
}
}
@@ -586,31 +598,6 @@ player_fullduplex_callback(SLBufferQueueItf caller, void * user_ptr)
TIMESTAMP("EXIT");
}
#if defined(__ANDROID__)
static SLuint32
convert_stream_type_to_sl_stream(cubeb_stream_type stream_type)
{
switch(stream_type) {
case CUBEB_STREAM_TYPE_SYSTEM:
return SL_ANDROID_STREAM_SYSTEM;
case CUBEB_STREAM_TYPE_MUSIC:
return SL_ANDROID_STREAM_MEDIA;
case CUBEB_STREAM_TYPE_NOTIFICATION:
return SL_ANDROID_STREAM_NOTIFICATION;
case CUBEB_STREAM_TYPE_ALARM:
return SL_ANDROID_STREAM_ALARM;
case CUBEB_STREAM_TYPE_VOICE_CALL:
return SL_ANDROID_STREAM_VOICE;
case CUBEB_STREAM_TYPE_RING:
return SL_ANDROID_STREAM_RING;
case CUBEB_STREAM_TYPE_SYSTEM_ENFORCED:
return SL_ANDROID_STREAM_SYSTEM_ENFORCED;
default:
return 0xFFFFFFFF;
}
}
#endif
static void opensl_destroy(cubeb * ctx);
#if defined(__ANDROID__)
@@ -899,7 +886,7 @@ opensl_get_min_latency(cubeb * ctx, cubeb_stream_params params, uint32_t * laten
if (get_primary_output_frame_count) {
primary_buffer_size = get_primary_output_frame_count();
} else {
if (get_output_frame_count(&primary_buffer_size, params.stream_type) != 0) {
if (get_output_frame_count(&primary_buffer_size, AUDIO_STREAM_TYPE_MUSIC) != 0) {
return CUBEB_ERROR;
}
}
@@ -1127,7 +1114,6 @@ opensl_configure_playback(cubeb_stream * stm, cubeb_stream_params * params) {
assert(params);
stm->inputrate = params->rate;
stm->stream_type = params->stream_type;
stm->framesize = params->channels * sizeof(int16_t);
stm->lastPosition = -1;
stm->lastPositionTimeStamp = 0;
@@ -1228,29 +1214,6 @@ opensl_configure_playback(cubeb_stream * stm, cubeb_stream_params * params) {
assert(stm->queuebuf[i]);
}
#if defined(__ANDROID__)
SLuint32 stream_type = convert_stream_type_to_sl_stream(params->stream_type);
if (stream_type != 0xFFFFFFFF) {
SLAndroidConfigurationItf playerConfig;
res = (*stm->playerObj)->GetInterface(stm->playerObj,
stm->context->SL_IID_ANDROIDCONFIGURATION,
&playerConfig);
if (res != SL_RESULT_SUCCESS) {
LOG("Failed to get android configuration interface. Error code: %lu", res);
return CUBEB_ERROR;
}
res = (*playerConfig)->SetConfiguration(playerConfig,
SL_ANDROID_KEY_STREAM_TYPE,
&stream_type,
sizeof(SLint32));
if (res != SL_RESULT_SUCCESS) {
LOG("Failed to set android configuration interface. Error code: %lu", res);
return CUBEB_ERROR;
}
}
#endif
res = (*stm->playerObj)->Realize(stm->playerObj, SL_BOOLEAN_FALSE);
if (res != SL_RESULT_SUCCESS) {
LOG("Failed to realize player object. Error code: %lu", res);
@@ -1654,7 +1617,7 @@ opensl_stream_get_position(cubeb_stream * stm, uint64_t * position)
samplerate = stm->inputrate;
r = stm->context->get_output_latency(&mixer_latency, stm->stream_type);
r = stm->context->get_output_latency(&mixer_latency, AUDIO_STREAM_TYPE_MUSIC);
if (r) {
return CUBEB_ERROR;
}
@@ -1690,7 +1653,7 @@ opensl_stream_get_latency(cubeb_stream * stm, uint32_t * latency)
uint32_t mixer_latency; // The latency returned by AudioFlinger is in ms.
/* audio_stream_type_t is an int, so this is okay. */
r = stm->context->get_output_latency(&mixer_latency, stm->stream_type);
r = stm->context->get_output_latency(&mixer_latency, AUDIO_STREAM_TYPE_MUSIC);
if (r) {
return CUBEB_ERROR;
}
@@ -1746,6 +1709,7 @@ static struct cubeb_ops const opensl_ops = {
.stream_destroy = opensl_stream_destroy,
.stream_start = opensl_stream_start,
.stream_stop = opensl_stream_stop,
.stream_reset_default_device = NULL,
.stream_get_position = opensl_stream_get_position,
.stream_get_latency = opensl_stream_get_latency,
.stream_set_volume = opensl_stream_set_volume,
+95 -20
View File
@@ -13,7 +13,7 @@
#include "cubeb/cubeb.h"
#include "cubeb-internal.h"
#include "cubeb_mixer.h"
#include "cubeb_utils.h"
#include "cubeb_strings.h"
#include <stdio.h>
#ifdef DISABLE_LIBPULSE_DLOPEN
@@ -102,6 +102,7 @@ struct cubeb {
int error;
cubeb_device_collection_changed_callback collection_changed_callback;
void * collection_changed_user_ptr;
cubeb_strings * device_ids;
};
struct cubeb_stream {
@@ -127,6 +128,24 @@ enum cork_state {
NOTIFY = 1 << 1
};
static int
intern_device_id(cubeb * ctx, char const ** id)
{
char const * interned;
assert(ctx);
assert(id);
interned = cubeb_strings_intern(ctx->device_ids, *id);
if (!interned) {
return CUBEB_ERROR;
}
*id = interned;
return CUBEB_OK;
}
static void
sink_info_callback(pa_context * context, const pa_sink_info * info, int eol, void * u)
{
@@ -608,6 +627,10 @@ pulse_init(cubeb ** context, char const * context_name)
ctx->ops = &pulse_ops;
ctx->libpulse = libpulse;
if (cubeb_strings_init(&ctx->device_ids) != CUBEB_OK) {
pulse_destroy(ctx);
return CUBEB_ERROR;
}
ctx->mainloop = WRAP(pa_threaded_mainloop_new)();
ctx->default_sink_info = NULL;
@@ -630,7 +653,6 @@ pulse_init(cubeb ** context, char const * context_name)
WRAP(pa_operation_unref)(o);
}
WRAP(pa_threaded_mainloop_unlock)(ctx->mainloop);
assert(ctx->default_sink_info);
*context = ctx;
@@ -650,6 +672,9 @@ pulse_get_max_channel_count(cubeb * ctx, uint32_t * max_channels)
(void)ctx;
assert(ctx && max_channels);
if (!ctx->default_sink_info)
return CUBEB_ERROR;
*max_channels = ctx->default_sink_info->channel_map.channels;
return CUBEB_OK;
@@ -661,6 +686,9 @@ pulse_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate)
assert(ctx && rate);
(void)ctx;
if (!ctx->default_sink_info)
return CUBEB_ERROR;
*rate = ctx->default_sink_info->sample_spec.rate;
return CUBEB_OK;
@@ -672,6 +700,9 @@ pulse_get_preferred_channel_layout(cubeb * ctx, cubeb_channel_layout * layout)
assert(ctx && layout);
(void)ctx;
if (!ctx->default_sink_info)
return CUBEB_ERROR;
*layout = channel_map_to_layout(&ctx->default_sink_info->channel_map);
return CUBEB_OK;
@@ -717,6 +748,10 @@ pulse_destroy(cubeb * ctx)
WRAP(pa_threaded_mainloop_free)(ctx->mainloop);
}
if (ctx->device_ids) {
cubeb_strings_destroy(ctx->device_ids);
}
if (ctx->libpulse) {
dlclose(ctx->libpulse);
}
@@ -751,8 +786,9 @@ create_pa_stream(cubeb_stream * stm,
{
assert(stm && stream_params);
assert(&stm->input_stream == pa_stm || (&stm->output_stream == pa_stm &&
stream_params->layout != CUBEB_LAYOUT_UNDEFINED &&
CUBEB_CHANNEL_LAYOUT_MAPS[stream_params->layout].channels == stream_params->channels));
(stream_params->layout == CUBEB_LAYOUT_UNDEFINED ||
(stream_params->layout != CUBEB_LAYOUT_UNDEFINED &&
CUBEB_CHANNEL_LAYOUT_MAPS[stream_params->layout].channels == stream_params->channels))));
*pa_stm = NULL;
pa_sample_spec ss;
ss.format = to_pulse_format(stream_params->format);
@@ -1049,6 +1085,7 @@ pulse_stream_set_volume(cubeb_stream * stm, float volume)
pa_volume_t vol;
pa_cvolume cvol;
const pa_sample_spec * ss;
cubeb * ctx;
if (!stm->output_stream) {
return CUBEB_ERROR;
@@ -1058,7 +1095,9 @@ pulse_stream_set_volume(cubeb_stream * stm, float volume)
/* if the pulse daemon is configured to use flat volumes,
* apply our own gain instead of changing the input volume on the sink. */
if (stm->context->default_sink_info->flags & PA_SINK_FLAT_VOLUME) {
ctx = stm->context;
if (ctx->default_sink_info &&
(ctx->default_sink_info->flags & PA_SINK_FLAT_VOLUME)) {
stm->volume = volume;
} else {
ss = WRAP(pa_stream_get_sample_spec)(stm->output_stream);
@@ -1068,16 +1107,16 @@ pulse_stream_set_volume(cubeb_stream * stm, float volume)
index = WRAP(pa_stream_get_index)(stm->output_stream);
op = WRAP(pa_context_set_sink_input_volume)(stm->context->context,
op = WRAP(pa_context_set_sink_input_volume)(ctx->context,
index, &cvol, volume_success,
stm);
if (op) {
operation_wait(stm->context, stm->output_stream, op);
operation_wait(ctx, stm->output_stream, op);
WRAP(pa_operation_unref)(op);
}
}
WRAP(pa_threaded_mainloop_unlock)(stm->context->mainloop);
WRAP(pa_threaded_mainloop_unlock)(ctx->mainloop);
return CUBEB_OK;
}
@@ -1202,18 +1241,30 @@ pulse_sink_info_cb(pa_context * context, const pa_sink_info * info,
{
pulse_dev_list_data * list_data = user_data;
cubeb_device_info * devinfo;
const char * prop;
char const * prop = NULL;
char const * device_id = NULL;
(void)context;
if (eol || info == NULL)
if (eol) {
WRAP(pa_threaded_mainloop_signal)(list_data->context->mainloop, 0);
return;
}
if (info == NULL)
return;
device_id = info->name;
if (intern_device_id(list_data->context, &device_id) != CUBEB_OK) {
assert(false);
return;
}
pulse_ensure_dev_list_data_list_size(list_data);
devinfo = &list_data->devinfo[list_data->count];
memset(devinfo, 0, sizeof(cubeb_device_info));
devinfo->device_id = strdup(info->name);
devinfo->device_id = device_id;
devinfo->devid = (cubeb_devid) devinfo->device_id;
devinfo->friendly_name = strdup(info->description);
prop = WRAP(pa_proplist_gets)(info->proplist, "sysfs.path");
@@ -1239,8 +1290,6 @@ pulse_sink_info_cb(pa_context * context, const pa_sink_info * info,
devinfo->latency_hi = 0;
list_data->count += 1;
WRAP(pa_threaded_mainloop_signal)(list_data->context->mainloop, 0);
}
static cubeb_device_state
@@ -1264,18 +1313,27 @@ pulse_source_info_cb(pa_context * context, const pa_source_info * info,
{
pulse_dev_list_data * list_data = user_data;
cubeb_device_info * devinfo;
const char * prop;
char const * prop = NULL;
char const * device_id = NULL;
(void)context;
if (eol)
if (eol) {
WRAP(pa_threaded_mainloop_signal)(list_data->context->mainloop, 0);
return;
}
device_id = info->name;
if (intern_device_id(list_data->context, &device_id) != CUBEB_OK) {
assert(false);
return;
}
pulse_ensure_dev_list_data_list_size(list_data);
devinfo = &list_data->devinfo[list_data->count];
memset(devinfo, 0, sizeof(cubeb_device_info));
devinfo->device_id = strdup(info->name);
devinfo->device_id = device_id;
devinfo->devid = (cubeb_devid) devinfo->device_id;
devinfo->friendly_name = strdup(info->description);
prop = WRAP(pa_proplist_gets)(info->proplist, "sysfs.path");
@@ -1301,7 +1359,6 @@ pulse_source_info_cb(pa_context * context, const pa_source_info * info,
devinfo->latency_hi = 0;
list_data->count += 1;
WRAP(pa_threaded_mainloop_signal)(list_data->context->mainloop, 0);
}
static void
@@ -1313,8 +1370,10 @@ pulse_server_info_cb(pa_context * c, const pa_server_info * i, void * userdata)
free(list_data->default_sink_name);
free(list_data->default_source_name);
list_data->default_sink_name = strdup(i->default_sink_name);
list_data->default_source_name = strdup(i->default_source_name);
list_data->default_sink_name =
i->default_sink_name ? strdup(i->default_sink_name) : NULL;
list_data->default_source_name =
i->default_source_name ? strdup(i->default_source_name) : NULL;
WRAP(pa_threaded_mainloop_signal)(list_data->context->mainloop, 0);
}
@@ -1363,6 +1422,21 @@ pulse_enumerate_devices(cubeb * context, cubeb_device_type type,
return CUBEB_OK;
}
static int
pulse_device_collection_destroy(cubeb * ctx, cubeb_device_collection * collection)
{
size_t n;
for (n = 0; n < collection->count; n++) {
free((void *) collection->device[n].friendly_name);
free((void *) collection->device[n].vendor_name);
free((void *) collection->device[n].group_id);
}
free(collection->device);
return CUBEB_OK;
}
static int
pulse_stream_get_current_device(cubeb_stream * stm, cubeb_device ** const device)
{
@@ -1492,12 +1566,13 @@ static struct cubeb_ops const pulse_ops = {
.get_preferred_sample_rate = pulse_get_preferred_sample_rate,
.get_preferred_channel_layout = pulse_get_preferred_channel_layout,
.enumerate_devices = pulse_enumerate_devices,
.device_collection_destroy = cubeb_utils_default_device_collection_destroy,
.device_collection_destroy = pulse_device_collection_destroy,
.destroy = pulse_destroy,
.stream_init = pulse_stream_init,
.stream_destroy = pulse_stream_destroy,
.stream_start = pulse_stream_start,
.stream_stop = pulse_stream_stop,
.stream_reset_default_device = NULL,
.stream_get_position = pulse_stream_get_position,
.stream_get_latency = pulse_stream_get_latency,
.stream_set_volume = pulse_stream_set_volume,
+16 -2
View File
@@ -35,15 +35,22 @@ to_speex_quality(cubeb_resampler_quality q)
}
}
uint32_t min_buffered_audio_frame(uint32_t sample_rate)
{
return sample_rate / 20;
}
template<typename T>
passthrough_resampler<T>::passthrough_resampler(cubeb_stream * s,
cubeb_data_callback cb,
void * ptr,
uint32_t input_channels)
uint32_t input_channels,
uint32_t sample_rate)
: processor(input_channels)
, stream(s)
, data_callback(cb)
, user_ptr(ptr)
, sample_rate(sample_rate)
{
}
@@ -73,6 +80,7 @@ long passthrough_resampler<T>::fill(void * input_buffer, long * input_frames_cou
if (input_buffer) {
internal_input_buffer.pop(nullptr, frames_to_samples(output_frames));
*input_frames_count = output_frames;
drop_audio_if_needed();
}
return rv;
@@ -242,9 +250,15 @@ cubeb_resampler_speex<T, InputProcessor, OutputProcessor>
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. */
return output_processor->output(out_buffer, output_frames_needed);
got = output_processor->output(out_buffer, output_frames_needed);
output_processor->drop_audio_if_needed();
return got;
}
/* Resampler C API */
+51 -6
View File
@@ -39,6 +39,13 @@ MOZ_END_STD_NAMESPACE
/* This header file contains the internal C++ API of the resamplers, for testing. */
// When dropping audio input frames to prevent building
// an input delay, this function returns the number of frames
// to keep in the buffer.
// @parameter sample_rate The sample rate of the stream.
// @return A number of frames to keep.
uint32_t min_buffered_audio_frame(uint32_t sample_rate);
int to_speex_quality(cubeb_resampler_quality q);
struct cubeb_resampler {
@@ -75,7 +82,8 @@ public:
passthrough_resampler(cubeb_stream * s,
cubeb_data_callback cb,
void * ptr,
uint32_t input_channels);
uint32_t input_channels,
uint32_t sample_rate);
virtual long fill(void * input_buffer, long * input_frames_count,
void * output_buffer, long output_frames);
@@ -85,6 +93,15 @@ public:
return 0;
}
void drop_audio_if_needed()
{
uint32_t to_keep = min_buffered_audio_frame(sample_rate);
uint32_t available = samples_to_frames(internal_input_buffer.length());
if (available > to_keep) {
internal_input_buffer.pop(nullptr, frames_to_samples(available - to_keep));
}
}
private:
cubeb_stream * const stream;
const cubeb_data_callback data_callback;
@@ -92,6 +109,7 @@ private:
/* This allows to buffer some input to account for the fact that we buffer
* some inputs. */
auto_array<T> internal_input_buffer;
uint32_t sample_rate;
};
/** Bidirectional resampler, can resample an input and an output stream, or just
@@ -164,6 +182,7 @@ public:
int quality)
: processor(channels)
, resampling_ratio(static_cast<float>(source_rate) / target_rate)
, source_rate(source_rate)
, additional_latency(0)
, leftover_samples(0)
{
@@ -296,6 +315,16 @@ public:
resampling_in_buffer.set_length(leftover_samples +
frames_to_samples(written_frames));
}
void drop_audio_if_needed()
{
// Keep at most 100ms buffered.
uint32_t available = samples_to_frames(resampling_in_buffer.length());
uint32_t to_keep = min_buffered_audio_frame(source_rate);
if (available > to_keep) {
resampling_in_buffer.pop(nullptr, frames_to_samples(available - to_keep));
}
}
private:
/** Wrapper for the speex resampling functions to have a typed
* interface. */
@@ -332,6 +361,7 @@ private:
SpeexResamplerState * speex_resampler;
/** Source rate / target rate. */
const float resampling_ratio;
const uint32_t source_rate;
/** Storage for the input frames, to be resampled. Also contains
* any unresampled frames after resampling. */
auto_array<T> resampling_in_buffer;
@@ -350,11 +380,13 @@ class delay_line : public processor {
public:
/** Constructor
* @parameter frames the number of frames of delay.
* @parameter channels the number of channels of this delay line. */
delay_line(uint32_t frames, uint32_t channels)
* @parameter channels the number of channels of this delay line.
* @parameter sample_rate sample-rate of the audio going through this delay line */
delay_line(uint32_t frames, uint32_t channels, uint32_t sample_rate)
: processor(channels)
, length(frames)
, leftover_samples(0)
, sample_rate(sample_rate)
{
/* Fill the delay line with some silent frames to add latency. */
delay_input_buffer.push_silence(frames * channels);
@@ -444,6 +476,15 @@ public:
{
return length;
}
void drop_audio_if_needed()
{
size_t available = samples_to_frames(delay_input_buffer.length());
uint32_t to_keep = min_buffered_audio_frame(sample_rate);
if (available > to_keep) {
delay_input_buffer.pop(nullptr, frames_to_samples(available - to_keep));
}
}
private:
/** The length, in frames, of this delay line */
uint32_t length;
@@ -455,6 +496,7 @@ private:
/** The output buffer. This is only ever used if using the ::output with a
* single argument. */
auto_array<T> delay_output_buffer;
uint32_t sample_rate;
};
/** This sits behind the C API and is more typed. */
@@ -485,7 +527,8 @@ cubeb_resampler_create_internal(cubeb_stream * stream,
(output_params && !input_params && (output_params->rate == target_rate))) {
return new passthrough_resampler<T>(stream, callback,
user_ptr,
input_params ? input_params->channels : 0);
input_params ? input_params->channels : 0,
target_rate);
}
/* Determine if we need to resampler one or both directions, and create the
@@ -517,13 +560,15 @@ cubeb_resampler_create_internal(cubeb_stream * stream,
* other direction so that the streams are synchronized. */
if (input_resampler && !output_resampler && input_params && output_params) {
output_delay.reset(new delay_line<T>(input_resampler->latency(),
output_params->channels));
output_params->channels,
output_params->rate));
if (!output_delay) {
return NULL;
}
} else if (output_resampler && !input_resampler && input_params && output_params) {
input_delay.reset(new delay_line<T>(output_resampler->latency(),
input_params->channels));
input_params->channels,
output_params->rate));
if (!input_delay) {
return NULL;
}

Some files were not shown because too many files have changed in this diff Show More