0

I'm trying to use the Oboe library to generate sound in my Android Studio project, but I'm having some issues.

I followed this documentation https://github.com/google/oboe/blob/main/docs/FullGuide.md and I wrote this code that supposed to play a sound but when I execute it I only hear a noise that lasts less than a second.

I have increased the size of the buffer and number of frames and still I get the same result.
The expected result should be the sound lasts for more than 1 second.
Exactly 80096/22000 = ~3.64 seconds.

#include "createStream.h"
int main() {
    oboe::AudioStreamBuilder streamBuilder;
    streamBuilder.setSampleRate(22000);

    std::shared_ptr<oboe::AudioStream> mStream;

    oboe::Result result = streamBuilder.openStream(mStream);
    if (result != oboe::Result::OK) {
        return 10;
    }

    result = mStream->requestStart();
    int16_t buffer[80096];
    int numFrames = sizeof(buffer) / sizeof(buffer[0]);
    
    for (int i = 0; i < 80096; i++) {
        int a = rand() % 65536;
        buffer[i] = a;
    }

    mStream->write(buffer, numFrames, -1);
    
    if (result != oboe::Result::OK) {
        return 9;
    }
    mStream->requestStop();
    mStream->close();
    return 150;
}
mortalis
  • 2,060
  • 24
  • 34
cs_guy98
  • 3
  • 2
  • No idea, never used this API. But just a quick read of the documentation (which seems excellent) makes me suspicious of your code. Firstly it seems that you should only write data to the audio stream from a callback function, This guarantees that data is written only when the device is ready to receive it. Secondly the valid values for the timeout parameter when writing are zero (for non-blocking) or positive (for blocking), you provided a value of `-1`. – john Mar 31 '23 at 05:46
  • `requestStart()` is asynchronous, so you cannot write data right after it, as the immendiate state is `Starting`, not `Started` required to be able to write/read data. Check the `waitForStateChange()` from that doc page if it helps to sync the stream state. – mortalis May 01 '23 at 19:15

1 Answers1

0

Problems I notices in this code:

  • numFrames is probably calculated incorrectly, as it's not clear what sample format the stream is using. In my test the default is Float, but I understand it can vary if not specified. Same for stream channels.
    So if the stream is opened with 2 channels by default and is using float samples, the number of frames to be written is sizeof(buffer) / sizeof(float) / 2, since each sample is sizeof(float) bytes long and each frame in the terms of the Oboe stream has 2 samples, 1 for each channel
  • passing -1 as the last argument in write() makes the call async, so the stream is stopped and closed immediately

Here's a working example I've tested:

#include "oboe/Oboe.h"

void testAudio() {
  int channels = 2;
  int sample_rate = 22000;
  int duration = 2;
  
  shared_ptr<oboe::AudioStream> stream;
  
  oboe::AudioStreamBuilder builder;
  builder.setFormat(AudioFormat::Float);
  builder.setChannelCount(channels);
  builder.setSampleRate(sample_rate);
  
  builder.openStream(stream);
  stream->requestStart();
  
  int size = duration * sample_rate * channels * sizeof(float);
  uint8_t buffer[size];
  
  for (int i = 0; i < size; i++) {
    buffer[i] = rand() % 255;
  }

  int numFrames = size / sizeof(float) / channels;
  stream->write(buffer, numFrames, 100);
  
  stream->requestStop();
  stream->close();
}

I omit error checking for simplicity.
Here I specify the format and channels explicitly, though it's better to also check them from the stream instance after it started.

Using a byte array just for simpler arithmetics, so I know 4 elements would make a sample (or sizeof(float)).

Not sure if 100 is a good timeout value, but for this experiment it served.

mortalis
  • 2,060
  • 24
  • 34