Issue using Oboe library to generate sound in Android Studio

167 Views Asked by At

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;
}
1

There are 1 best solutions below

0
mortalis On

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.