int run_test(int num_channels, int sampling_rate, int is_float) { int r = CUBEB_OK; cubeb *ctx = NULL; synth_state* synth = NULL; cubeb_stream *stream = NULL; const char * backend_id = NULL; r = cubeb_init(&ctx, "Cubeb audio test: channels"); if (r != CUBEB_OK) { fprintf(stderr, "Error initializing cubeb library\n"); goto cleanup; } backend_id = cubeb_get_backend_id(ctx); if ((is_float && !supports_float32(backend_id)) || (!is_float && !supports_int16(backend_id)) || !supports_channel_count(backend_id, num_channels)) { /* don't treat this as a test failure. */ goto cleanup; } fprintf(stderr, "Testing %d channel(s), %d Hz, %s (%s)\n", num_channels, sampling_rate, is_float ? "float" : "short", cubeb_get_backend_id(ctx)); cubeb_stream_params params; params.format = is_float ? CUBEB_SAMPLE_FLOAT32NE : CUBEB_SAMPLE_S16NE; params.rate = sampling_rate; params.channels = num_channels; synth = synth_create(params.channels, params.rate); if (synth == NULL) { fprintf(stderr, "Out of memory\n"); goto cleanup; } r = cubeb_stream_init(ctx, &stream, "test tone", NULL, NULL, NULL, ¶ms, 4096, is_float ? data_cb_float : data_cb_short, state_cb_audio, synth); if (r != CUBEB_OK) { fprintf(stderr, "Error initializing cubeb stream: %d\n", r); goto cleanup; } cubeb_stream_start(stream); delay(200); cubeb_stream_stop(stream); cleanup: cubeb_stream_destroy(stream); cubeb_destroy(ctx); synth_destroy(synth); return r; }
void AudioCallbackDriver::StartStream() { if (cubeb_stream_start(mAudioStream) != CUBEB_OK) { MOZ_CRASH("Could not start cubeb stream for MSG."); } { MonitorAutoLock mon(mGraphImpl->GetMonitor()); mStarted = true; mWaitState = WAITSTATE_RUNNING; } }
TEST(cubeb, record) { if (cubeb_set_log_callback(CUBEB_LOG_DISABLED, nullptr /*print_log*/) != CUBEB_OK) { printf("Set log callback failed\n"); } cubeb *ctx; cubeb_stream *stream; cubeb_stream_params params; int r; user_state_record stream_state = { false }; r = cubeb_init(&ctx, "Cubeb record example"); if (r != CUBEB_OK) { fprintf(stderr, "Error initializing cubeb library\n"); ASSERT_EQ(r, CUBEB_OK); } /* This test needs an available input device, skip it if this host does not * have one. */ if (!has_available_input_device(ctx)) { return; } params.format = STREAM_FORMAT; params.rate = SAMPLE_FREQUENCY; params.channels = 1; params.layout = CUBEB_LAYOUT_MONO; r = cubeb_stream_init(ctx, &stream, "Cubeb record (mono)", NULL, ¶ms, NULL, nullptr, 4096, data_cb_record, state_cb_record, &stream_state); if (r != CUBEB_OK) { fprintf(stderr, "Error initializing cubeb stream\n"); ASSERT_EQ(r, CUBEB_OK); } cubeb_stream_start(stream); delay(500); cubeb_stream_stop(stream); cubeb_stream_destroy(stream); cubeb_destroy(ctx); #ifdef __linux__ // user callback does not arrive in Linux, silence the error printf("Check is disabled in Linux\n"); #else ASSERT_TRUE(stream_state.seen_audio); #endif }
TEST(cubeb, duplex) { cubeb *ctx; cubeb_stream *stream; cubeb_stream_params input_params; cubeb_stream_params output_params; int r; user_state_duplex stream_state = { false }; uint32_t latency_frames = 0; r = cubeb_init(&ctx, "Cubeb duplex example", NULL); ASSERT_EQ(r, CUBEB_OK) << "Error initializing cubeb library"; std::unique_ptr<cubeb, decltype(&cubeb_destroy)> cleanup_cubeb_at_exit(ctx, cubeb_destroy); /* This test needs an available input device, skip it if this host does not * have one. */ if (!has_available_input_device(ctx)) { return; } /* typical user-case: mono input, stereo output, low latency. */ input_params.format = STREAM_FORMAT; input_params.rate = 48000; input_params.channels = 1; input_params.layout = CUBEB_LAYOUT_MONO; output_params.format = STREAM_FORMAT; output_params.rate = 48000; output_params.channels = 2; output_params.layout = CUBEB_LAYOUT_STEREO; r = cubeb_get_min_latency(ctx, output_params, &latency_frames); ASSERT_EQ(r, CUBEB_OK) << "Could not get minimal latency"; r = cubeb_stream_init(ctx, &stream, "Cubeb duplex", NULL, &input_params, NULL, &output_params, latency_frames, data_cb_duplex, state_cb_duplex, &stream_state); ASSERT_EQ(r, CUBEB_OK) << "Error initializing cubeb stream"; std::unique_ptr<cubeb_stream, decltype(&cubeb_stream_destroy)> cleanup_stream_at_exit(stream, cubeb_stream_destroy); cubeb_stream_start(stream); delay(500); cubeb_stream_stop(stream); ASSERT_TRUE(stream_state.seen_audio); }
void AudioStream::StartUnlocked() { mMonitor.AssertCurrentThreadOwns(); if (!mCubebStream) { mNeedsStart = true; return; } MonitorAutoUnlock mon(mMonitor); if (mState == INITIALIZED) { int r = cubeb_stream_start(mCubebStream); mState = r == CUBEB_OK ? STARTED : ERRORED; LOG(("AudioStream: started %p, state %s", this, mState == STARTED ? "STARTED" : "ERRORED")); } }
void AudioStream::Resume() { MonitorAutoLock mon(mMonitor); if (!mCubebStream || mState != STOPPED) { return; } int r; { MonitorAutoUnlock mon(mMonitor); r = cubeb_stream_start(mCubebStream.get()); } if (mState != ERRORED && r == CUBEB_OK) { mState = STARTED; } }
int main(int argc, char *argv[]) { #ifdef CUBEB_GECKO_BUILD ScopedXPCOM xpcom("test_record"); #endif cubeb *ctx; cubeb_stream *stream; cubeb_stream_params params; int r; user_state stream_state = { false }; r = cubeb_init(&ctx, "Cubeb record example"); if (r != CUBEB_OK) { fprintf(stderr, "Error initializing cubeb library\n"); return r; } /* This test needs an available input device, skip it if this host does not * have one. */ if (!has_available_input_device(ctx)) { return 0; } params.format = STREAM_FORMAT; params.rate = SAMPLE_FREQUENCY; params.channels = 1; r = cubeb_stream_init(ctx, &stream, "Cubeb record (mono)", NULL, ¶ms, NULL, nullptr, 250, data_cb, state_cb, &stream_state); if (r != CUBEB_OK) { fprintf(stderr, "Error initializing cubeb stream\n"); return r; } cubeb_stream_start(stream); delay(500); cubeb_stream_stop(stream); cubeb_stream_destroy(stream); cubeb_destroy(ctx); assert(stream_state.seen_noise); return CUBEB_OK; }
static void test_basic_stream_operations(void) { int r; cubeb * ctx; cubeb_stream * stream; cubeb_stream_params params; uint64_t position; BEGIN_TEST r = cubeb_init(&ctx, "test_sanity"); assert(r == 0 && ctx); params.format = STREAM_FORMAT; params.rate = STREAM_RATE; params.channels = STREAM_CHANNELS; r = cubeb_stream_init(ctx, &stream, "test", params, STREAM_LATENCY, test_data_callback, test_state_callback, &dummy); assert(r == 0 && stream); /* position and volume before stream has started */ r = cubeb_stream_get_position(stream, &position); assert(r == 0 && position == 0); r = cubeb_stream_start(stream); assert(r == 0); /* position and volume after while stream running */ r = cubeb_stream_get_position(stream, &position); assert(r == 0); r = cubeb_stream_stop(stream); assert(r == 0); /* position and volume after stream has stopped */ r = cubeb_stream_get_position(stream, &position); assert(r == 0); cubeb_stream_destroy(stream); cubeb_destroy(ctx); END_TEST }
void BufferedAudioStream::StartUnlocked() { mMonitor.AssertCurrentThreadOwns(); if (!mCubebStream || mState != INITIALIZED) { return; } if (mState != STARTED) { int r; { MonitorAutoUnlock mon(mMonitor); r = cubeb_stream_start(mCubebStream); } if (mState != ERRORED) { mState = r == CUBEB_OK ? STARTED : ERRORED; } } }
TEST(cubeb, basic_stream_operations) { int r; cubeb * ctx; cubeb_stream * stream; cubeb_stream_params params; uint64_t position; r = common_init(&ctx, "test_sanity"); ASSERT_EQ(r, CUBEB_OK); ASSERT_NE(ctx, nullptr); params.format = STREAM_FORMAT; params.rate = STREAM_RATE; params.channels = STREAM_CHANNELS; params.layout = STREAM_LAYOUT; r = cubeb_stream_init(ctx, &stream, "test", NULL, NULL, NULL, ¶ms, STREAM_LATENCY, test_data_callback, test_state_callback, &dummy); ASSERT_EQ(r, CUBEB_OK); ASSERT_NE(stream, nullptr); /* position and volume before stream has started */ r = cubeb_stream_get_position(stream, &position); ASSERT_EQ(r, CUBEB_OK); ASSERT_EQ(position, 0u); r = cubeb_stream_start(stream); ASSERT_EQ(r, CUBEB_OK); /* position and volume after while stream running */ r = cubeb_stream_get_position(stream, &position); ASSERT_EQ(r, CUBEB_OK); r = cubeb_stream_stop(stream); ASSERT_EQ(r, CUBEB_OK); /* position and volume after stream has stopped */ r = cubeb_stream_get_position(stream, &position); ASSERT_EQ(r, CUBEB_OK); cubeb_stream_destroy(stream); cubeb_destroy(ctx); }
void AudioStream::StartUnlocked() { mMonitor.AssertCurrentThreadOwns(); if (!mCubebStream) { mNeedsStart = true; return; } if (mState == INITIALIZED) { int r; { MonitorAutoUnlock mon(mMonitor); r = cubeb_stream_start(mCubebStream.get()); PanOutputIfNeeded(mMicrophoneActive); } mState = r == CUBEB_OK ? STARTED : ERRORED; LOG(("AudioStream: started %p, state %s", this, mState == STARTED ? "STARTED" : "ERRORED")); } }
TEST(cubeb, record) { cubeb *ctx; cubeb_stream *stream; cubeb_stream_params params; int r; user_state_record stream_state = { false }; r = cubeb_init(&ctx, "Cubeb record example"); if (r != CUBEB_OK) { fprintf(stderr, "Error initializing cubeb library\n"); ASSERT_EQ(r, CUBEB_OK); } /* This test needs an available input device, skip it if this host does not * have one. */ if (!has_available_input_device(ctx)) { return; } params.format = STREAM_FORMAT; params.rate = SAMPLE_FREQUENCY; params.channels = 1; r = cubeb_stream_init(ctx, &stream, "Cubeb record (mono)", NULL, ¶ms, NULL, nullptr, 4096, data_cb_record, state_cb_record, &stream_state); if (r != CUBEB_OK) { fprintf(stderr, "Error initializing cubeb stream\n"); ASSERT_EQ(r, CUBEB_OK); } cubeb_stream_start(stream); delay(500); cubeb_stream_stop(stream); cubeb_stream_destroy(stream); cubeb_destroy(ctx); ASSERT_TRUE(stream_state.seen_noise); }
nsresult nsBufferedAudioStream::Write(const AudioDataValue* aBuf, uint32_t aFrames) { MonitorAutoLock mon(mMonitor); if (!mCubebStream || mState == ERRORED) { return NS_ERROR_FAILURE; } NS_ASSERTION(mState == INITIALIZED || mState == STARTED, "Stream write in unexpected state."); const uint8_t* src = reinterpret_cast<const uint8_t*>(aBuf); uint32_t bytesToCopy = aFrames * mBytesPerFrame; while (bytesToCopy > 0) { uint32_t available = NS_MIN(bytesToCopy, mBuffer.Available()); NS_ABORT_IF_FALSE(available % mBytesPerFrame == 0, "Must copy complete frames."); mBuffer.AppendElements(src, available); src += available; bytesToCopy -= available; if (mState != STARTED) { int r; { MonitorAutoUnlock mon(mMonitor); r = cubeb_stream_start(mCubebStream); } mState = r == CUBEB_OK ? STARTED : ERRORED; } if (mState != STARTED) { return NS_ERROR_FAILURE; } if (bytesToCopy > 0) { mon.Wait(); } } return NS_OK; }
void AudioStream::StartUnlocked() { mMonitor.AssertCurrentThreadOwns(); if (!mCubebStream) { return; } if (mState == INITIALIZED) { mState = STARTED; int r; { MonitorAutoUnlock mon(mMonitor); r = cubeb_stream_start(mCubebStream.get()); // DataCallback might be called before we exit this scope // if cubeb_stream_start() succeeds. mState must be set to STARTED // beforehand. } if (r != CUBEB_OK) { mState = ERRORED; } LOG("started, state %s", mState == STARTED ? "STARTED" : "ERRORED"); } }
TEST(cubeb, stream_position) { size_t i; int r; cubeb * ctx; cubeb_stream * stream; cubeb_stream_params params; uint64_t position, last_position; total_frames_written = 0; r = common_init(&ctx, "test_sanity"); ASSERT_EQ(r, CUBEB_OK); ASSERT_NE(ctx, nullptr); params.format = STREAM_FORMAT; params.rate = STREAM_RATE; params.channels = STREAM_CHANNELS; params.layout = STREAM_LAYOUT; r = cubeb_stream_init(ctx, &stream, "test", NULL, NULL, NULL, ¶ms, STREAM_LATENCY, test_data_callback, test_state_callback, &dummy); ASSERT_EQ(r, CUBEB_OK); ASSERT_NE(stream, nullptr); /* stream position should not advance before starting playback */ r = cubeb_stream_get_position(stream, &position); ASSERT_EQ(r, CUBEB_OK); ASSERT_EQ(position, 0u); delay(500); r = cubeb_stream_get_position(stream, &position); ASSERT_EQ(r, CUBEB_OK); ASSERT_EQ(position, 0u); /* stream position should advance during playback */ r = cubeb_stream_start(stream); ASSERT_EQ(r, CUBEB_OK); /* XXX let start happen */ delay(500); /* stream should have prefilled */ ASSERT_TRUE(total_frames_written.load() > 0); r = cubeb_stream_get_position(stream, &position); ASSERT_EQ(r, CUBEB_OK); last_position = position; delay(500); r = cubeb_stream_get_position(stream, &position); ASSERT_EQ(r, CUBEB_OK); ASSERT_GE(position, last_position); last_position = position; /* stream position should not exceed total frames written */ for (i = 0; i < 5; ++i) { r = cubeb_stream_get_position(stream, &position); ASSERT_EQ(r, CUBEB_OK); ASSERT_GE(position, last_position); ASSERT_LE(position, total_frames_written.load()); last_position = position; delay(500); } /* test that the position is valid even when starting and * stopping the stream. */ for (i = 0; i < 5; ++i) { r = cubeb_stream_stop(stream); ASSERT_EQ(r, CUBEB_OK); r = cubeb_stream_get_position(stream, &position); ASSERT_EQ(r, CUBEB_OK); ASSERT_TRUE(last_position < position); last_position = position; delay(500); r = cubeb_stream_start(stream); ASSERT_EQ(r, CUBEB_OK); delay(500); } ASSERT_NE(last_position, 0u); /* stream position should not advance after stopping playback */ r = cubeb_stream_stop(stream); ASSERT_EQ(r, CUBEB_OK); /* XXX allow stream to settle */ delay(500); r = cubeb_stream_get_position(stream, &position); ASSERT_EQ(r, CUBEB_OK); last_position = position; delay(500); r = cubeb_stream_get_position(stream, &position); ASSERT_EQ(r, CUBEB_OK); ASSERT_EQ(position, last_position); cubeb_stream_destroy(stream); cubeb_destroy(ctx); }
int run_panning_volume_test(int is_float) { int r = CUBEB_OK; cubeb *ctx = NULL; synth_state* synth = NULL; cubeb_stream *stream = NULL; const char * backend_id = NULL; r = cubeb_init(&ctx, "Cubeb audio test"); if (r != CUBEB_OK) { fprintf(stderr, "Error initializing cubeb library\n"); goto cleanup; } backend_id = cubeb_get_backend_id(ctx); if ((is_float && !supports_float32(backend_id)) || (!is_float && !supports_int16(backend_id))) { /* don't treat this as a test failure. */ goto cleanup; } cubeb_stream_params params; params.format = is_float ? CUBEB_SAMPLE_FLOAT32NE : CUBEB_SAMPLE_S16NE; params.rate = 44100; params.channels = 2; synth = synth_create(params.channels, params.rate); if (synth == NULL) { fprintf(stderr, "Out of memory\n"); goto cleanup; } r = cubeb_stream_init(ctx, &stream, "test tone", NULL, NULL, NULL, ¶ms, 4096, is_float ? data_cb_float : data_cb_short, state_cb_audio, synth); if (r != CUBEB_OK) { fprintf(stderr, "Error initializing cubeb stream: %d\n", r); goto cleanup; } fprintf(stderr, "Testing: volume\n"); for(int i=0;i <= 4; ++i) { fprintf(stderr, "Volume: %d%%\n", i*25); cubeb_stream_set_volume(stream, i/4.0f); cubeb_stream_start(stream); delay(400); cubeb_stream_stop(stream); delay(100); } fprintf(stderr, "Testing: panning\n"); for(int i=-4;i <= 4; ++i) { fprintf(stderr, "Panning: %.2f%%\n", i/4.0f); cubeb_stream_set_panning(stream, i/4.0f); cubeb_stream_start(stream); delay(400); cubeb_stream_stop(stream); delay(100); } cleanup: cubeb_stream_destroy(stream); cubeb_destroy(ctx); synth_destroy(synth); return r; }
static void test_drain(void) { int r; cubeb * ctx; cubeb_stream * stream; cubeb_stream_params params; uint64_t position; BEGIN_TEST total_frames_written = 0; r = cubeb_init(&ctx, "test_sanity"); assert(r == 0 && ctx); params.format = STREAM_FORMAT; params.rate = STREAM_RATE; params.channels = STREAM_CHANNELS; r = cubeb_stream_init(ctx, &stream, "test", params, STREAM_LATENCY, test_drain_data_callback, test_drain_state_callback, &dummy); assert(r == 0 && stream); r = cubeb_stream_start(stream); assert(r == 0); delay(500); do_drain = 1; for (;;) { r = cubeb_stream_get_position(stream, &position); assert(r == 0); if (got_drain) { break; } else { uint32_t i, skip = 0; /* Latency passed to cubeb_stream_init is not really honored on OSX, win32/winmm and android, skip this test. */ const char * backend_id = cubeb_get_backend_id(ctx); const char * latency_not_honored_bakends[] = { "audiounit", "winmm", "audiotrack", "opensl" }; for (i = 0; i < ARRAY_LENGTH(latency_not_honored_bakends); i++) { if (!strcmp(backend_id, latency_not_honored_bakends[i])) { skip = 1; } } if (!skip) { /* Position should roughly be equal to the number of written frames. We * need to take the latency into account. */ int latency = (STREAM_LATENCY * STREAM_RATE) / 1000; assert(position + latency <= total_frames_written); } } delay(500); } r = cubeb_stream_get_position(stream, &position); assert(r == 0); assert(got_drain); // Disabled due to failures in the ALSA backend. //assert(position == total_frames_written); cubeb_stream_destroy(stream); cubeb_destroy(ctx); END_TEST }
static void test_stream_position(void) { int i; int r; cubeb * ctx; cubeb_stream * stream; cubeb_stream_params params; uint64_t position, last_position; BEGIN_TEST total_frames_written = 0; r = cubeb_init(&ctx, "test_sanity"); assert(r == 0 && ctx); params.format = STREAM_FORMAT; params.rate = STREAM_RATE; params.channels = STREAM_CHANNELS; r = cubeb_stream_init(ctx, &stream, "test", params, STREAM_LATENCY, test_data_callback, test_state_callback, &dummy); assert(r == 0 && stream); /* stream position should not advance before starting playback */ r = cubeb_stream_get_position(stream, &position); assert(r == 0 && position == 0); delay(500); r = cubeb_stream_get_position(stream, &position); assert(r == 0 && position == 0); /* stream position should advance during playback */ r = cubeb_stream_start(stream); assert(r == 0); /* XXX let start happen */ delay(500); /* stream should have prefilled */ assert(total_frames_written > 0); r = cubeb_stream_get_position(stream, &position); assert(r == 0); last_position = position; delay(500); r = cubeb_stream_get_position(stream, &position); assert(r == 0); assert(position >= last_position); last_position = position; /* stream position should not exceed total frames written */ for (i = 0; i < 5; ++i) { r = cubeb_stream_get_position(stream, &position); assert(r == 0); assert(position >= last_position); assert(position <= total_frames_written); last_position = position; delay(500); } assert(last_position != 0); /* stream position should not advance after stopping playback */ r = cubeb_stream_stop(stream); assert(r == 0); /* XXX allow stream to settle */ delay(500); r = cubeb_stream_get_position(stream, &position); assert(r == 0); last_position = position; delay(500); r = cubeb_stream_get_position(stream, &position); assert(r == 0); assert(position == last_position); cubeb_stream_destroy(stream); cubeb_destroy(ctx); END_TEST }