diff options
-rw-r--r-- | include/cubeb/cubeb.h | 21 | ||||
-rw-r--r-- | src/cubeb-internal.h | 4 | ||||
-rw-r--r-- | src/cubeb.c | 41 | ||||
-rw-r--r-- | src/cubeb_alsa.c | 14 | ||||
-rw-r--r-- | src/cubeb_audiotrack.c | 17 | ||||
-rw-r--r-- | src/cubeb_audiounit.c | 14 | ||||
-rw-r--r-- | src/cubeb_opensl.c | 27 | ||||
-rw-r--r-- | src/cubeb_pulse.c | 13 | ||||
-rw-r--r-- | src/cubeb_resampler.cpp | 22 | ||||
-rw-r--r-- | src/cubeb_resampler.h | 3 | ||||
-rw-r--r-- | src/cubeb_sndio.c | 12 | ||||
-rw-r--r-- | src/cubeb_wasapi.cpp | 12 | ||||
-rw-r--r-- | src/cubeb_winmm.c | 20 | ||||
-rw-r--r-- | test/test_audio.cpp | 12 | ||||
-rw-r--r-- | test/test_sanity.cpp | 31 | ||||
-rw-r--r-- | test/test_tone.cpp | 8 |
16 files changed, 167 insertions, 104 deletions
diff --git a/include/cubeb/cubeb.h b/include/cubeb/cubeb.h index 4c016e0..4a716a7 100644 --- a/include/cubeb/cubeb.h +++ b/include/cubeb/cubeb.h @@ -221,17 +221,21 @@ typedef struct { } cubeb_device_collection; /** User supplied data callback. - @param stream - @param user_ptr - @param buffer - @param nframes - @retval Number of frames written to buffer, which must equal nframes except - at end of stream. + @param stream The stream for which this callback fired + @param user_ptr The pointer passed to cubeb_stream_create + @param input_buffer A pointer containing the input data, or nullptr + if this is an output-only stream. + @param output_buffer A pointer containing the output data, or nullptr + if this is an input -only stream. + @param nframes The number of frames of the two buffer. + @retval Number of frames written to the output buffer, which must equal + nframes except at end of stream. @retval CUBEB_ERROR on error, in which case the data callback will stop and the stream will enter a shutdown state. */ typedef long (* cubeb_data_callback)(cubeb_stream * stream, void * user_ptr, - void * buffer, + void * input_buffer, + void * output_buffer, long nframes); /** User supplied state callback. @@ -319,7 +323,8 @@ void cubeb_destroy(cubeb * context); int cubeb_stream_init(cubeb * context, cubeb_stream ** stream, char const * stream_name, - cubeb_stream_params stream_params, + cubeb_stream_params * input_stream_params, + cubeb_stream_params * output_stream_params, unsigned int latency, cubeb_data_callback data_callback, cubeb_state_callback state_callback, diff --git a/src/cubeb-internal.h b/src/cubeb-internal.h index 3235107..15d3b47 100644 --- a/src/cubeb-internal.h +++ b/src/cubeb-internal.h @@ -23,7 +23,9 @@ struct cubeb_ops { cubeb_device_collection ** collection); void (* destroy)(cubeb * context); int (* stream_init)(cubeb * context, cubeb_stream ** stream, char const * stream_name, - cubeb_stream_params stream_params, unsigned int latency, + cubeb_stream_params * input_stream_params, + cubeb_stream_params * output_stream_params, + unsigned int latency, cubeb_data_callback data_callback, cubeb_state_callback state_callback, void * user_ptr); diff --git a/src/cubeb.c b/src/cubeb.c index f22e8a9..9fc3196 100644 --- a/src/cubeb.c +++ b/src/cubeb.c @@ -61,15 +61,36 @@ int audiotrack_init(cubeb ** context, char const * context_name); int kai_init(cubeb ** context, char const * context_name); #endif + int -validate_stream_params(cubeb_stream_params stream_params) +validate_stream_params(cubeb_stream_params * input_stream_params, + cubeb_stream_params * output_stream_params) { - if (stream_params.rate < 1000 || stream_params.rate > 192000 || - stream_params.channels < 1 || stream_params.channels > 8) { - return CUBEB_ERROR_INVALID_FORMAT; + if (output_stream_params) { + if (output_stream_params->rate < 1000 || output_stream_params->rate > 192000 || + output_stream_params->channels < 1 || output_stream_params->channels > 8) { + return CUBEB_ERROR_INVALID_FORMAT; + } } + if (input_stream_params) { + if (input_stream_params->rate < 1000 || input_stream_params->rate > 192000 || + input_stream_params->channels < 1 || input_stream_params->channels > 8) { + return CUBEB_ERROR_INVALID_FORMAT; + } + } + // Rate and sample format must be the same for input and output, if using a + // duplex stream + if (input_stream_params && output_stream_params) { + if (input_stream_params->rate != output_stream_params->rate || + input_stream_params->format != output_stream_params->format) { + return CUBEB_ERROR_INVALID_FORMAT; + } + } + + cubeb_stream_params * params = input_stream_params ? + input_stream_params : output_stream_params; - switch (stream_params.format) { + switch (params->format) { case CUBEB_SAMPLE_S16LE: case CUBEB_SAMPLE_S16BE: case CUBEB_SAMPLE_FLOAT32LE: @@ -80,6 +101,8 @@ validate_stream_params(cubeb_stream_params stream_params) return CUBEB_ERROR_INVALID_FORMAT; } + + int validate_latency(int latency) { @@ -218,7 +241,9 @@ cubeb_destroy(cubeb * context) int cubeb_stream_init(cubeb * context, cubeb_stream ** stream, char const * stream_name, - cubeb_stream_params stream_params, unsigned int latency, + cubeb_stream_params * input_stream_params, + cubeb_stream_params * output_stream_params, + unsigned int latency, cubeb_data_callback data_callback, cubeb_state_callback state_callback, void * user_ptr) @@ -229,13 +254,13 @@ cubeb_stream_init(cubeb * context, cubeb_stream ** stream, char const * stream_n return CUBEB_ERROR_INVALID_PARAMETER; } - if ((r = validate_stream_params(stream_params)) != CUBEB_OK || + if ((r = validate_stream_params(input_stream_params, output_stream_params)) != CUBEB_OK || (r = validate_latency(latency)) != CUBEB_OK) { return r; } return context->ops->stream_init(context, stream, stream_name, - stream_params, latency, + input_stream_params, output_stream_params, latency, data_callback, state_callback, user_ptr); diff --git a/src/cubeb_alsa.c b/src/cubeb_alsa.c index 5e8dab0..5482769 100644 --- a/src/cubeb_alsa.c +++ b/src/cubeb_alsa.c @@ -306,7 +306,7 @@ alsa_refill_stream(cubeb_stream * stm) assert(p); pthread_mutex_unlock(&stm->mutex); - got = stm->data_callback(stm, stm->user_ptr, p, avail); + got = stm->data_callback(stm, stm->user_ptr, NULL, p, avail); pthread_mutex_lock(&stm->mutex); if (got < 0) { pthread_mutex_unlock(&stm->mutex); @@ -781,7 +781,9 @@ static void alsa_stream_destroy(cubeb_stream * stm); static int alsa_stream_init(cubeb * ctx, cubeb_stream ** stream, char const * stream_name, - cubeb_stream_params stream_params, unsigned int latency, + cubeb_stream_params * input_stream_params, + cubeb_stream_params * output_stream_params, + unsigned int latency, cubeb_data_callback data_callback, cubeb_state_callback state_callback, void * user_ptr) { @@ -792,9 +794,11 @@ alsa_stream_init(cubeb * ctx, cubeb_stream ** stream, char const * stream_name, assert(ctx && stream); + assert(!input_stream_params && "not supported."); + *stream = NULL; - switch (stream_params.format) { + switch (output_stream_params->format) { case CUBEB_SAMPLE_S16LE: format = SND_PCM_FORMAT_S16_LE; break; @@ -826,7 +830,7 @@ alsa_stream_init(cubeb * ctx, cubeb_stream ** stream, char const * stream_name, stm->data_callback = data_callback; stm->state_callback = state_callback; stm->user_ptr = user_ptr; - stm->params = stream_params; + stm->params = *output_stream_params; stm->state = INACTIVE; stm->volume = 1.0; @@ -933,7 +937,7 @@ alsa_get_max_channel_count(cubeb * ctx, uint32_t * max_channels) assert(ctx); - r = alsa_stream_init(ctx, &stm, "", params, 100, NULL, NULL, NULL); + r = alsa_stream_init(ctx, &stm, "", NULL, ¶ms, 100, NULL, NULL, NULL); if (r != CUBEB_OK) { return CUBEB_ERROR; } diff --git a/src/cubeb_audiotrack.c b/src/cubeb_audiotrack.c index bf85bb8..07851c2 100644 --- a/src/cubeb_audiotrack.c +++ b/src/cubeb_audiotrack.c @@ -99,12 +99,11 @@ audiotrack_refill(int event, void* user, void* info) return; } - got = stream->data_callback(stream, stream->user_ptr, b->raw, b->frameCount); + got = stream->data_callback(stream, stream->user_ptr, NULL, b->raw, b->frameCount); stream->written += got; if (got != (long)b->frameCount) { - uint32_t p; stream->draining = 1; /* set a marker so we are notified when the are done draining, that is, * when every frame has been played by android. */ @@ -279,7 +278,9 @@ audiotrack_destroy(cubeb * context) int audiotrack_stream_init(cubeb * ctx, cubeb_stream ** stream, char const * stream_name, - cubeb_stream_params stream_params, unsigned int latency, + cubeb_stream_params * input_stream_params, + cubeb_stream_params * output_stream_params, + unsigned int latency, cubeb_data_callback data_callback, cubeb_state_callback state_callback, void * user_ptr) @@ -290,12 +291,14 @@ audiotrack_stream_init(cubeb * ctx, cubeb_stream ** stream, char const * stream_ assert(ctx && stream); - if (stream_params.format == CUBEB_SAMPLE_FLOAT32LE || - stream_params.format == CUBEB_SAMPLE_FLOAT32BE) { + assert(!input_stream_params && "not supported"); + + if (output_stream_params->format == CUBEB_SAMPLE_FLOAT32LE || + output_stream_params->format == CUBEB_SAMPLE_FLOAT32BE) { return CUBEB_ERROR_INVALID_FORMAT; } - if (audiotrack_get_min_frame_count(ctx, &stream_params, (int *)&min_frame_count)) { + if (audiotrack_get_min_frame_count(ctx, output_stream_params, (int *)&min_frame_count)) { return CUBEB_ERROR; } @@ -306,7 +309,7 @@ audiotrack_stream_init(cubeb * ctx, cubeb_stream ** stream, char const * stream_ stm->data_callback = data_callback; stm->state_callback = state_callback; stm->user_ptr = user_ptr; - stm->params = stream_params; + stm->params = *output_stream_params; stm->instance = calloc(SIZE_AUDIOTRACK_INSTANCE, 1); (*(uint32_t*)((intptr_t)stm->instance + SIZE_AUDIOTRACK_INSTANCE - 4)) = 0xbaadbaad; diff --git a/src/cubeb_audiounit.c b/src/cubeb_audiounit.c index 7506107..4d59637 100644 --- a/src/cubeb_audiounit.c +++ b/src/cubeb_audiounit.c @@ -136,7 +136,7 @@ audiounit_output_callback(void * user_ptr, AudioUnitRenderActionFlags * flags, } pthread_mutex_unlock(&stm->mutex); - got = stm->data_callback(stm, stm->user_ptr, buf, nframes); + got = stm->data_callback(stm, stm->user_ptr, NULL, buf, nframes); pthread_mutex_lock(&stm->mutex); if (got < 0) { /* XXX handle this case. */ @@ -539,7 +539,9 @@ static void audiounit_stream_destroy(cubeb_stream * stm); static int audiounit_stream_init(cubeb * context, cubeb_stream ** stream, char const * stream_name, - cubeb_stream_params stream_params, unsigned int latency, + cubeb_stream_params * input_stream_params, + cubeb_stream_params * output_stream_params, + unsigned int latency, cubeb_data_callback data_callback, cubeb_state_callback state_callback, void * user_ptr) { @@ -558,13 +560,15 @@ audiounit_stream_init(cubeb * context, cubeb_stream ** stream, char const * stre UInt32 size; AudioValueRange latency_range; + assert(!input_stream_params && "not supported"); + assert(context); *stream = NULL; memset(&ss, 0, sizeof(ss)); ss.mFormatFlags = 0; - switch (stream_params.format) { + switch (output_stream_params->format) { case CUBEB_SAMPLE_S16LE: ss.mBitsPerChannel = 16; ss.mFormatFlags |= kAudioFormatFlagIsSignedInteger; @@ -589,8 +593,8 @@ audiounit_stream_init(cubeb * context, cubeb_stream ** stream, char const * stre ss.mFormatID = kAudioFormatLinearPCM; ss.mFormatFlags |= kLinearPCMFormatFlagIsPacked; - ss.mSampleRate = stream_params.rate; - ss.mChannelsPerFrame = stream_params.channels; + ss.mSampleRate = output_stream_params->rate; + ss.mChannelsPerFrame = output_stream_params->channels; ss.mBytesPerFrame = (ss.mBitsPerChannel / 8) * ss.mChannelsPerFrame; ss.mFramesPerPacket = 1; diff --git a/src/cubeb_opensl.c b/src/cubeb_opensl.c index 526aef0..cf721f6 100644 --- a/src/cubeb_opensl.c +++ b/src/cubeb_opensl.c @@ -120,7 +120,7 @@ bufferqueue_callback(SLBufferQueueItf caller, void * user_ptr) pthread_mutex_unlock(&stm->mutex); if (!draining) { - written = cubeb_resampler_fill(stm->resampler, buf, + written = cubeb_resampler_fill(stm->resampler, NULL, buf, stm->queuebuf_len / stm->framesize); if (written < 0 || written * stm->framesize > stm->queuebuf_len) { (*stm->play)->SetPlayState(stm->play, SL_PLAYSTATE_PAUSED); @@ -465,17 +465,20 @@ static void opensl_stream_destroy(cubeb_stream * stm); static int opensl_stream_init(cubeb * ctx, cubeb_stream ** stream, char const * stream_name, - cubeb_stream_params stream_params, unsigned int latency, + cubeb_stream_params * input_stream_params, + cubeb_stream_params * output_stream_params, + unsigned int latency, cubeb_data_callback data_callback, cubeb_state_callback state_callback, void * user_ptr) { cubeb_stream * stm; assert(ctx); + assert(!input_stream_params && "not supported"); *stream = NULL; - if (stream_params.channels < 1 || stream_params.channels > 32 || + if (output_stream_params->channels < 1 || output_stream_params->channels > 32 || latency < 1 || latency > 2000) { return CUBEB_ERROR_INVALID_FORMAT; } @@ -483,16 +486,16 @@ opensl_stream_init(cubeb * ctx, cubeb_stream ** stream, char const * stream_name SLDataFormat_PCM format; format.formatType = SL_DATAFORMAT_PCM; - format.numChannels = stream_params.channels; + format.numChannels = output_stream_params->channels; // samplesPerSec is in milliHertz - format.samplesPerSec = stream_params.rate * 1000; + format.samplesPerSec = output_stream_params->rate * 1000; format.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16; format.containerSize = SL_PCMSAMPLEFORMAT_FIXED_16; - format.channelMask = stream_params.channels == 1 ? + format.channelMask = output_stream_params->channels == 1 ? SL_SPEAKER_FRONT_CENTER : SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; - switch (stream_params.format) { + switch (output_stream_params->format) { case CUBEB_SAMPLE_S16LE: format.endianness = SL_BYTEORDER_LITTLEENDIAN; break; @@ -511,10 +514,10 @@ opensl_stream_init(cubeb * ctx, cubeb_stream ** stream, char const * stream_name stm->state_callback = state_callback; stm->user_ptr = user_ptr; - stm->inputrate = stream_params.rate; + stm->inputrate = output_stream_params->rate; stm->latency = latency; - stm->stream_type = stream_params.stream_type; - stm->framesize = stream_params.channels * sizeof(int16_t); + stm->stream_type = output_stream_params->stream_type; + stm->framesize = output_stream_params->channels * sizeof(int16_t); stm->lastPosition = -1; stm->lastPositionTimeStamp = 0; stm->lastCompensativePosition = -1; @@ -575,7 +578,7 @@ opensl_stream_init(cubeb * ctx, cubeb_stream ** stream, char const * stream_name stm->queuebuf_len += stm->framesize - (stm->queuebuf_len % stm->framesize); } - stm->resampler = cubeb_resampler_create(stm, stream_params, + stm->resampler = cubeb_resampler_create(stm, *output_stream_params, preferred_sampling_rate, data_callback, stm->queuebuf_len / stm->framesize, @@ -594,7 +597,7 @@ opensl_stream_init(cubeb * ctx, cubeb_stream ** stream, char const * stream_name } #if defined(__ANDROID__) - SLuint32 stream_type = convert_stream_type_to_sl_stream(stream_params.stream_type); + SLuint32 stream_type = convert_stream_type_to_sl_stream(output_stream_params->stream_type); if (stream_type != 0xFFFFFFFF) { SLAndroidConfigurationItf playerConfig; res = (*stm->playerObj)->GetInterface(stm->playerObj, diff --git a/src/cubeb_pulse.c b/src/cubeb_pulse.c index ef35661..1fd997e 100644 --- a/src/cubeb_pulse.c +++ b/src/cubeb_pulse.c @@ -198,7 +198,7 @@ stream_request_callback(pa_stream * s, size_t nbytes, void * u) assert(size > 0); assert(size % frame_size == 0); - got = stm->data_callback(stm, stm->user_ptr, buffer, size / frame_size); + got = stm->data_callback(stm, stm->user_ptr, NULL, buffer, size / frame_size); if (got < 0) { WRAP(pa_stream_cancel_write)(s); stm->shutdown = 1; @@ -487,7 +487,9 @@ static void pulse_stream_destroy(cubeb_stream * stm); static int pulse_stream_init(cubeb * context, cubeb_stream ** stream, char const * stream_name, - cubeb_stream_params stream_params, unsigned int latency, + cubeb_stream_params * input_stream_params, + cubeb_stream_params * output_stream_params, + unsigned int latency, cubeb_data_callback data_callback, cubeb_state_callback state_callback, void * user_ptr) { @@ -498,10 +500,11 @@ pulse_stream_init(cubeb * context, cubeb_stream ** stream, char const * stream_n int r; assert(context); + assert(!input_stream_params && "not supported."); *stream = NULL; - switch (stream_params.format) { + switch (output_stream_params->format) { case CUBEB_SAMPLE_S16LE: ss.format = PA_SAMPLE_S16LE; break; @@ -523,8 +526,8 @@ pulse_stream_init(cubeb * context, cubeb_stream ** stream, char const * stream_n return CUBEB_ERROR; } - ss.rate = stream_params.rate; - ss.channels = stream_params.channels; + ss.rate = output_stream_params->rate; + ss.channels = output_stream_params->channels; stm = calloc(1, sizeof(*stm)); assert(stm); diff --git a/src/cubeb_resampler.cpp b/src/cubeb_resampler.cpp index 682650a..e8fd7a1 100644 --- a/src/cubeb_resampler.cpp +++ b/src/cubeb_resampler.cpp @@ -72,7 +72,7 @@ to_speex_quality(cubeb_resampler_quality q) } // end of anonymous namespace struct cubeb_resampler { - virtual long fill(void * buffer, long frames_needed) = 0; + virtual long fill(void * input_buffer, void * output_buffer, long frames_needed) = 0; virtual ~cubeb_resampler() {} }; @@ -87,9 +87,9 @@ public: { } - virtual long fill(void * buffer, long frames_needed) + virtual long fill(void * input_buffer, void * output_buffer, long frames_needed) { - long got = data_callback(stream, user_ptr, buffer, frames_needed); + long got = data_callback(stream, user_ptr, input_buffer, output_buffer, frames_needed); assert(got <= frames_needed); return got; } @@ -109,7 +109,7 @@ public: virtual ~cubeb_resampler_speex(); - virtual long fill(void * buffer, long frames_needed); + virtual long fill(void * input_buffer, void * output_buffer, long frames_needed); private: SpeexResamplerState * const speex_resampler; @@ -164,7 +164,7 @@ cubeb_resampler_speex::~cubeb_resampler_speex() } long -cubeb_resampler_speex::fill(void * buffer, long frames_needed) +cubeb_resampler_speex::fill(void * input_buffer, void * output_buffer, long frames_needed) { // Use more input frames than strictly necessary, so in the worst case, // we have leftover unresampled frames at the end, that we can use @@ -178,7 +178,7 @@ cubeb_resampler_speex::fill(void * buffer, long frames_needed) memcpy(resampling_src_buffer.get(), leftover_frames_buffer.get(), leftover_bytes); uint8_t * buffer_start = resampling_src_buffer.get() + leftover_bytes; - long got = data_callback(stream, user_ptr, buffer_start, frames_requested); + long got = data_callback(stream, user_ptr, NULL, buffer_start, frames_requested); assert(got <= frames_requested); if (got < 0) { @@ -191,12 +191,12 @@ cubeb_resampler_speex::fill(void * buffer, long frames_needed) if (stream_params.format == CUBEB_SAMPLE_FLOAT32NE) { float * in_buffer = reinterpret_cast<float *>(resampling_src_buffer.get()); - float * out_buffer = reinterpret_cast<float *>(buffer); + float * out_buffer = reinterpret_cast<float *>(output_buffer); speex_resampler_process_interleaved_float(speex_resampler, in_buffer, &in_frames, out_buffer, &out_frames); } else { short * in_buffer = reinterpret_cast<short *>(resampling_src_buffer.get()); - short * out_buffer = reinterpret_cast<short *>(buffer); + short * out_buffer = reinterpret_cast<short *>(output_buffer); speex_resampler_process_interleaved_int(speex_resampler, in_buffer, &in_frames, out_buffer, &out_frames); } @@ -242,9 +242,11 @@ cubeb_resampler_create(cubeb_stream * stream, long cubeb_resampler_fill(cubeb_resampler * resampler, - void * buffer, long frames_needed) + void * input_buffer, + void * output_buffer, + long frames_needed) { - return resampler->fill(buffer, frames_needed); + return resampler->fill(input_buffer, output_buffer, frames_needed); } void diff --git a/src/cubeb_resampler.h b/src/cubeb_resampler.h index e63c2c1..64f5d58 100644 --- a/src/cubeb_resampler.h +++ b/src/cubeb_resampler.h @@ -53,7 +53,8 @@ cubeb_resampler * cubeb_resampler_create(cubeb_stream * stream, * @retval CUBEB_ERROR on error. */ long cubeb_resampler_fill(cubeb_resampler * resampler, - void * buffer, long frames_needed); + void * input_buffer, + void * output_buffer, long frames_needed); /** * Destroy a cubeb_resampler. diff --git a/src/cubeb_sndio.c b/src/cubeb_sndio.c index 94f9961..c0e3427 100644 --- a/src/cubeb_sndio.c +++ b/src/cubeb_sndio.c @@ -173,7 +173,9 @@ static int sndio_stream_init(cubeb *context, cubeb_stream **stream, char const *stream_name, - cubeb_stream_params stream_params, unsigned int latency, + cubeb_stream_params * input_stream_params, + cubeb_stream_params * output_stream_params, + unsigned int latency, cubeb_data_callback data_callback, cubeb_state_callback state_callback, void *user_ptr) @@ -196,7 +198,7 @@ sndio_stream_init(cubeb *context, sio_initpar(&wpar); wpar.sig = 1; wpar.bits = 16; - switch (stream_params.format) { + switch (output_stream_params->format) { case CUBEB_SAMPLE_S16LE: wpar.le = 1; break; @@ -210,8 +212,8 @@ sndio_stream_init(cubeb *context, DPR("sndio_stream_init() unsupported format\n"); return CUBEB_ERROR_INVALID_FORMAT; } - wpar.rate = stream_params.rate; - wpar.pchan = stream_params.channels; + wpar.rate = output_stream_params->rate; + wpar.pchan = output_stream_params->channels; wpar.appbufsz = latency * wpar.rate / 1000; if (!sio_setpar(s->hdl, &wpar) || !sio_getpar(s->hdl, &rpar)) { sio_close(s->hdl); @@ -237,7 +239,7 @@ sndio_stream_init(cubeb *context, s->arg = user_ptr; s->mtx = PTHREAD_MUTEX_INITIALIZER; s->rdpos = s->wrpos = 0; - if (stream_params.format == CUBEB_SAMPLE_FLOAT32LE) { + if (output_stream_params->format == CUBEB_SAMPLE_FLOAT32LE) { s->conv = 1; size = rpar.round * rpar.pchan * sizeof(float); } else { diff --git a/src/cubeb_wasapi.cpp b/src/cubeb_wasapi.cpp index 3c780e6..d81343c 100644 --- a/src/cubeb_wasapi.cpp +++ b/src/cubeb_wasapi.cpp @@ -472,7 +472,7 @@ refill(cubeb_stream * stm, float * data, long frames_needed) dest = data; } - long out_frames = cubeb_resampler_fill(stm->resampler, dest, frames_needed); + long out_frames = cubeb_resampler_fill(stm->resampler, NULL, dest, frames_needed); /* TODO: Report out_frames < 0 as an error via the API. */ XASSERT(out_frames >= 0); @@ -1201,7 +1201,9 @@ int setup_wasapi_stream(cubeb_stream * stm) int wasapi_stream_init(cubeb * context, cubeb_stream ** stream, - char const * stream_name, cubeb_stream_params stream_params, + char const * stream_name, + cubeb_stream_params * input_stream_params, + cubeb_stream_params * output_stream_params, unsigned int latency, cubeb_data_callback data_callback, cubeb_state_callback state_callback, void * user_ptr) { @@ -1212,9 +1214,11 @@ wasapi_stream_init(cubeb * context, cubeb_stream ** stream, return CUBEB_ERROR; } + XASSERT(!input_stream_params && "not supported."); + XASSERT(context && stream); - if (stream_params.format != CUBEB_SAMPLE_FLOAT32NE) { + if (output_stream_params->format != CUBEB_SAMPLE_FLOAT32NE) { return CUBEB_ERROR_INVALID_FORMAT; } @@ -1226,7 +1230,7 @@ wasapi_stream_init(cubeb * context, cubeb_stream ** stream, stm->data_callback = data_callback; stm->state_callback = state_callback; stm->user_ptr = user_ptr; - stm->stream_params = stream_params; + stm->stream_params = *output_stream_params; stm->draining = false; stm->latency = latency; stm->volume = 1.0; diff --git a/src/cubeb_winmm.c b/src/cubeb_winmm.c index da5828f..8fe73fb 100644 --- a/src/cubeb_winmm.c +++ b/src/cubeb_winmm.c @@ -179,7 +179,7 @@ winmm_refill_stream(cubeb_stream * stm) /* It is assumed that the caller is holding this lock. It must be dropped during the callback to avoid deadlocks. */ LeaveCriticalSection(&stm->lock); - got = stm->data_callback(stm, stm->user_ptr, hdr->lpData, wanted); + got = stm->data_callback(stm, stm->user_ptr, NULL, NULL, hdr->lpData, wanted); EnterCriticalSection(&stm->lock); if (got < 0) { LeaveCriticalSection(&stm->lock); @@ -380,7 +380,9 @@ static void winmm_stream_destroy(cubeb_stream * stm); static int winmm_stream_init(cubeb * context, cubeb_stream ** stream, char const * stream_name, - cubeb_stream_params stream_params, unsigned int latency, + cubeb_stream_params * input_stream_params, + cubeb_stream_params * output_stream_params, + unsigned int latency, cubeb_data_callback data_callback, cubeb_state_callback state_callback, void * user_ptr) @@ -394,26 +396,28 @@ winmm_stream_init(cubeb * context, cubeb_stream ** stream, char const * stream_n XASSERT(context); XASSERT(stream); + XASSERT(input_stream_params && "not supported."); + *stream = NULL; memset(&wfx, 0, sizeof(wfx)); - if (stream_params.channels > 2) { + if (output_stream_params->channels > 2) { wfx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; wfx.Format.cbSize = sizeof(wfx) - sizeof(wfx.Format); } else { wfx.Format.wFormatTag = WAVE_FORMAT_PCM; - if (stream_params.format == CUBEB_SAMPLE_FLOAT32LE) { + if (output_stream_params->format == CUBEB_SAMPLE_FLOAT32LE) { wfx.Format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT; } wfx.Format.cbSize = 0; } - wfx.Format.nChannels = stream_params.channels; - wfx.Format.nSamplesPerSec = stream_params.rate; + wfx.Format.nChannels = output_stream_params->channels; + wfx.Format.nSamplesPerSec = output_stream_params->rate; /* XXX fix channel mappings */ wfx.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT; - switch (stream_params.format) { + switch (output_stream_params->format) { case CUBEB_SAMPLE_S16LE: wfx.Format.wBitsPerSample = 16; wfx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; @@ -446,7 +450,7 @@ winmm_stream_init(cubeb * context, cubeb_stream ** stream, char const * stream_n stm->context = context; - stm->params = stream_params; + stm->params = *output_stream_params; stm->data_callback = data_callback; stm->state_callback = state_callback; diff --git a/test/test_audio.cpp b/test/test_audio.cpp index 6a6ebf5..c6b143f 100644 --- a/test/test_audio.cpp +++ b/test/test_audio.cpp @@ -73,10 +73,10 @@ void synth_run_float(synth_state* synth, float* audiobuffer, long nframes) } } -long data_cb_float(cubeb_stream *stream, void *user, void *buffer, long nframes) +long data_cb_float(cubeb_stream *stream, void *user, void * inputbuffer, void *outputbuffer, long nframes) { synth_state *synth = (synth_state *)user; - synth_run_float(synth, (float*)buffer, nframes); + synth_run_float(synth, (float*)outputbuffer, nframes); return nframes; } @@ -92,10 +92,10 @@ void synth_run_16bit(synth_state* synth, short* audiobuffer, long nframes) } } -long data_cb_short(cubeb_stream *stream, void *user, void *buffer, long nframes) +long data_cb_short(cubeb_stream *stream, void *user, void * inputbuffer, void *outputbuffer, long nframes) { synth_state *synth = (synth_state *)user; - synth_run_16bit(synth, (short*)buffer, nframes); + synth_run_16bit(synth, (short*)outputbuffer, nframes); return nframes; } @@ -160,7 +160,7 @@ int run_test(int num_channels, int sampling_rate, int is_float) goto cleanup; } - r = cubeb_stream_init(ctx, &stream, "test tone", params, + r = cubeb_stream_init(ctx, &stream, "test tone", nullptr, ¶ms, 100, is_float ? data_cb_float : data_cb_short, state_cb, synth); if (r != CUBEB_OK) { fprintf(stderr, "Error initializing cubeb stream: %d\n", r); @@ -212,7 +212,7 @@ int run_panning_volume_test(int is_float) goto cleanup; } - r = cubeb_stream_init(ctx, &stream, "test tone", params, + r = cubeb_stream_init(ctx, &stream, "test tone", NULL, ¶ms, 100, is_float ? data_cb_float : data_cb_short, state_cb, synth); if (r != CUBEB_OK) { fprintf(stderr, "Error initializing cubeb stream: %d\n", r); diff --git a/test/test_sanity.cpp b/test/test_sanity.cpp index ca9ca1b..f04be32 100644 --- a/test/test_sanity.cpp +++ b/test/test_sanity.cpp @@ -40,13 +40,14 @@ static uint64_t total_frames_written; static int delay_callback; static long -test_data_callback(cubeb_stream * stm, void * user_ptr, void * p, long nframes) +test_data_callback(cubeb_stream * stm, void * user_ptr, void * inputbuffer, void * outputbuffer, long nframes) { - assert(stm && user_ptr == &dummy && p && nframes > 0); + assert(stm && user_ptr == &dummy && outputbuffer && nframes > 0); + memset(outputbuffer, 0, nframes * sizeof(short)); #if (defined(_WIN32) || defined(__WIN32__)) - memset(p, 0, nframes * sizeof(float)); + memset(outputbuffer, 0, nframes * sizeof(float)); #else - memset(p, 0, nframes * sizeof(short)); + memset(outputbuffer, 0, nframes * sizeof(short)); #endif total_frames_written += nframes; @@ -158,7 +159,7 @@ test_init_destroy_stream(void) params.rate = STREAM_RATE; params.channels = STREAM_CHANNELS; - r = cubeb_stream_init(ctx, &stream, "test", params, STREAM_LATENCY, + r = cubeb_stream_init(ctx, &stream, "test", nullptr, ¶ms, STREAM_LATENCY, test_data_callback, test_state_callback, &dummy); assert(r == 0 && stream); @@ -187,7 +188,7 @@ test_init_destroy_multiple_streams(void) params.channels = STREAM_CHANNELS; for (i = 0; i < ARRAY_LENGTH(stream); ++i) { - r = cubeb_stream_init(ctx, &stream[i], "test", params, STREAM_LATENCY, + r = cubeb_stream_init(ctx, &stream[i], "test", NULL, ¶ms, STREAM_LATENCY, test_data_callback, test_state_callback, &dummy); assert(r == 0); assert(stream[i]); @@ -219,7 +220,7 @@ test_configure_stream(void) params.rate = STREAM_RATE; params.channels = 2; // panning - r = cubeb_stream_init(ctx, &stream, "test", params, STREAM_LATENCY, + r = cubeb_stream_init(ctx, &stream, "test", NULL, ¶ms, STREAM_LATENCY, test_data_callback, test_state_callback, &dummy); assert(r == 0 && stream); @@ -253,7 +254,7 @@ test_init_start_stop_destroy_multiple_streams(int early, int delay_ms) params.channels = STREAM_CHANNELS; for (i = 0; i < ARRAY_LENGTH(stream); ++i) { - r = cubeb_stream_init(ctx, &stream[i], "test", params, STREAM_LATENCY, + r = cubeb_stream_init(ctx, &stream[i], "test", NULL, ¶ms, STREAM_LATENCY, test_data_callback, test_state_callback, &dummy); assert(r == 0); assert(stream[i]); @@ -317,7 +318,7 @@ test_init_destroy_multiple_contexts_and_streams(void) assert(r == 0 && ctx[i]); for (j = 0; j < streams_per_ctx; ++j) { - r = cubeb_stream_init(ctx[i], &stream[i * streams_per_ctx + j], "test", params, STREAM_LATENCY, + r = cubeb_stream_init(ctx[i], &stream[i * streams_per_ctx + j], "test", NULL, ¶ms, STREAM_LATENCY, test_data_callback, test_state_callback, &dummy); assert(r == 0); assert(stream[i * streams_per_ctx + j]); @@ -352,7 +353,7 @@ test_basic_stream_operations(void) params.rate = STREAM_RATE; params.channels = STREAM_CHANNELS; - r = cubeb_stream_init(ctx, &stream, "test", params, STREAM_LATENCY, + r = cubeb_stream_init(ctx, &stream, "test", NULL, ¶ms, STREAM_LATENCY, test_data_callback, test_state_callback, &dummy); assert(r == 0 && stream); @@ -401,7 +402,7 @@ test_stream_position(void) params.rate = STREAM_RATE; params.channels = STREAM_CHANNELS; - r = cubeb_stream_init(ctx, &stream, "test", params, STREAM_LATENCY, + r = cubeb_stream_init(ctx, &stream, "test", NULL, ¶ms, STREAM_LATENCY, test_data_callback, test_state_callback, &dummy); assert(r == 0 && stream); @@ -474,16 +475,16 @@ static int do_drain; static int got_drain; static long -test_drain_data_callback(cubeb_stream * stm, void * user_ptr, void * p, long nframes) +test_drain_data_callback(cubeb_stream * stm, void * user_ptr, void * inputbuffer, void * outputbuffer, long nframes) { - assert(stm && user_ptr == &dummy && p && nframes > 0); + assert(stm && user_ptr == &dummy && outputbuffer && nframes > 0); if (do_drain == 1) { do_drain = 2; return 0; } /* once drain has started, callback must never be called again */ assert(do_drain != 2); - memset(p, 0, nframes * sizeof(short)); + memset(outputbuffer, 0, nframes * sizeof(short)); total_frames_written += nframes; return nframes; } @@ -517,7 +518,7 @@ test_drain(void) params.rate = STREAM_RATE; params.channels = STREAM_CHANNELS; - r = cubeb_stream_init(ctx, &stream, "test", params, STREAM_LATENCY, + r = cubeb_stream_init(ctx, &stream, "test", NULL, ¶ms, STREAM_LATENCY, test_drain_data_callback, test_drain_state_callback, &dummy); assert(r == 0 && stream); diff --git a/test/test_tone.cpp b/test/test_tone.cpp index d0cee22..59362f6 100644 --- a/test/test_tone.cpp +++ b/test/test_tone.cpp @@ -34,13 +34,13 @@ struct cb_user_data { long position; }; -long data_cb(cubeb_stream *stream, void *user, void *buffer, long nframes) +long data_cb(cubeb_stream *stream, void *user, void* inputbuffer, void *outputbuffer, long nframes) { struct cb_user_data *u = (struct cb_user_data *)user; #if (defined(_WIN32) || defined(__WIN32__)) - float *b = (float *)buffer; + float *b = (float *)outputbuffer; #else - short *b = (short *)buffer; + short *b = (short *)outputbuffer; #endif float t1, t2; int i; @@ -127,7 +127,7 @@ int main(int argc, char *argv[]) } user_data->position = 0; - r = cubeb_stream_init(ctx, &stream, "Cubeb tone (mono)", params, + r = cubeb_stream_init(ctx, &stream, "Cubeb tone (mono)", nullptr, ¶ms, 250, data_cb, state_cb, user_data); if (r != CUBEB_OK) { fprintf(stderr, "Error initializing cubeb stream\n"); |