Ejemplo n.º 1
0
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, &params,
                        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;
}
Ejemplo n.º 2
0
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");
}
Ejemplo n.º 3
0
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();
}
Ejemplo n.º 4
0
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);
}
Ejemplo n.º 5
0
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);
  }
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
0
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());
}
Ejemplo n.º 8
0
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
}
Ejemplo n.º 9
0
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, &params,
                        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;
}