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 GetCurrentBackend(nsAString& aBackend) { cubeb* cubebContext = GetCubebContext(); if (cubebContext) { const char* backend = cubeb_get_backend_id(cubebContext); if (backend) { aBackend.AssignASCII(backend); return; } } aBackend.AssignLiteral("unknown"); }
long AudioStream::DataCallback(void* aBuffer, long aFrames) { MonitorAutoLock mon(mMonitor); MOZ_ASSERT(mState != SHUTDOWN, "No data callback after shutdown"); auto writer = AudioBufferWriter( reinterpret_cast<AudioDataValue*>(aBuffer), mOutChannels, aFrames); if (!strcmp(cubeb_get_backend_id(CubebUtils::GetCubebContext()), "winmm")) { // Don't consume audio data until Start() is called. // Expected only with cubeb winmm backend. if (mState == INITIALIZED) { NS_WARNING("data callback fires before cubeb_stream_start() is called"); mAudioClock.UpdateFrameHistory(0, aFrames); return writer.WriteZeros(aFrames); } } else { MOZ_ASSERT(mState != INITIALIZED); } // NOTE: wasapi (others?) can call us back *after* stop()/Shutdown() (mState == SHUTDOWN) // Bug 996162 if (mAudioClock.GetInputRate() == mAudioClock.GetOutputRate()) { GetUnprocessed(writer); } else { GetTimeStretched(writer); } // Always send audible frames first, and silent frames later. // Otherwise it will break the assumption of FrameHistory. if (!mDataSource.Ended()) { mAudioClock.UpdateFrameHistory(aFrames - writer.Available(), writer.Available()); if (writer.Available() > 0) { LOGW("lost %d frames", writer.Available()); writer.WriteZeros(writer.Available()); } } else { // No more new data in the data source. Don't send silent frames so the // cubeb stream can start draining. mAudioClock.UpdateFrameHistory(aFrames - writer.Available(), 0); } WriteDumpFile(mDumpFile, this, aFrames, aBuffer); return aFrames - writer.Available(); }
TEST(cubeb, init_destroy_context) { int r; cubeb * ctx; char const* backend_id; r = common_init(&ctx, "test_sanity"); ASSERT_EQ(r, CUBEB_OK); ASSERT_NE(ctx, nullptr); backend_id = cubeb_get_backend_id(ctx); ASSERT_TRUE(backend_id); fprintf(stderr, "Backend: %s\n", backend_id); cubeb_destroy(ctx); }
void ReportCubebBackendUsed() { StaticMutexAutoLock lock(sMutex); sAudioStreamInitEverSucceeded = true; bool foundBackend = false; for (uint32_t i = 0; i < ArrayLength(AUDIOSTREAM_BACKEND_ID_STR); i++) { if (!strcmp(cubeb_get_backend_id(sCubebContext), AUDIOSTREAM_BACKEND_ID_STR[i])) { Telemetry::Accumulate(Telemetry::AUDIOSTREAM_BACKEND_USED, i); foundBackend = true; } } if (!foundBackend) { Telemetry::Accumulate(Telemetry::AUDIOSTREAM_BACKEND_USED, CUBEB_BACKEND_UNKNOWN); } }
static void test_init_destroy_context(void) { int r; cubeb * ctx; char const* backend_id; BEGIN_TEST; r = cubeb_init(&ctx, "test_sanity"); assert(r == 0 && ctx); backend_id = cubeb_get_backend_id(ctx); assert(backend_id); fprintf(stderr, "Backend: %s\n", backend_id); cubeb_destroy(ctx); END_TEST; }
nsresult AudioStream::Init(uint32_t aNumChannels, AudioConfig::ChannelLayout::ChannelMap aChannelMap, uint32_t aRate, AudioDeviceInfo* aSinkInfo) { auto startTime = TimeStamp::Now(); LOG("%s channels: %d, rate: %d", __FUNCTION__, aNumChannels, aRate); mChannels = aNumChannels; mOutChannels = aNumChannels; mDumpFile = OpenDumpFile(aNumChannels, aRate); mSinkInfo = aSinkInfo; cubeb_stream_params params; params.rate = aRate; params.channels = mOutChannels; params.layout = static_cast<uint32_t>(aChannelMap); params.format = ToCubebFormat<AUDIO_OUTPUT_FORMAT>::value; params.prefs = CubebUtils::GetDefaultStreamPrefs(); mAudioClock.Init(aRate); cubeb* cubebContext = CubebUtils::GetCubebContext(); if (!cubebContext) { LOGE("Can't get cubeb context!"); CubebUtils::ReportCubebStreamInitFailure(true); return NS_ERROR_DOM_MEDIA_CUBEB_INITIALIZATION_ERR; } // cubeb's winmm backend prefills buffers on init rather than stream start. // See https://github.com/kinetiknz/cubeb/issues/150 mPrefillQuirk = !strcmp(cubeb_get_backend_id(cubebContext), "winmm"); return OpenCubeb(cubebContext, params, startTime, CubebUtils::GetFirstStream()); }
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 }
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; }