You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Studio中使用Oboe库生成声音时长不符问题求助

Oboe库生成声音仅播放不到1秒噪音的问题解决

问题描述

在Android Studio项目中使用Oboe库生成声音,按官方文档编写代码后,仅能听到不到1秒的噪音,增大缓冲区和帧数也无法解决。预期声音时长应为约3.64秒(80096样本 ÷ 22000采样率),原代码如下:

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

问题原因

  • 帧数计算错误:Oboe默认创建立体声(2通道)流,每个音频帧包含2个int16_t样本。原代码直接将缓冲区样本数当作帧数传入write(),导致Oboe尝试读取80096帧(160192个样本),远超缓冲区容量,触发越界读取,实际仅播放部分数据就终止。
  • 流过早关闭:write()完成后立即调用requestStop()和close(),此时音频硬件缓冲区仍有未播放数据,直接停止会截断剩余音频。
  • 未检查关键操作结果:requestStart()的启动结果未校验,可能导致后续写入操作无效。

解决方案及修正代码

  1. 显式设置单声道流,简化帧数计算;或根据实际通道数计算正确帧数
  2. 写入完成后等待音频播放完毕再停止流
  3. 校验所有Oboe操作的返回结果

修正后的代码:

#include "createStream.h"
#include <cstdlib>
#include <ctime>
#include <chrono>
#include <thread>

int main() {
    // 初始化随机数种子
    srand(time(nullptr));

    oboe::AudioStreamBuilder streamBuilder;
    streamBuilder.setSampleRate(22000);
    // 显式设置单声道,避免默认立体声的帧数计算问题
    streamBuilder.setChannelCount(oboe::ChannelCount::Mono);
    streamBuilder.setFormat(oboe::AudioFormat::I16);

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

    // 打开流并校验结果
    oboe::Result result = streamBuilder.openStream(mStream);
    if (result != oboe::Result::OK) {
        return 10;
    }

    // 启动流并校验结果
    result = mStream->requestStart();
    if (result != oboe::Result::OK) {
        mStream->close();
        return 11;
    }

    const int sampleCount = 80096;
    int16_t buffer[sampleCount];
    
    // 生成-32768到32767的有符号16位随机样本
    for (int i = 0; i < sampleCount; i++) {
        buffer[i] = static_cast<int16_t>(rand() % 65536 - 32768);
    }

    // 单声道下样本数等于帧数
    int numFrames = sampleCount;
    // 写入数据并校验结果
    result = mStream->write(buffer, numFrames, -1);
    if (result != oboe::Result::OK) {
        mStream->requestStop();
        mStream->close();
        return 9;
    }

    // 等待音频播放完毕:按采样率计算时长,额外加100ms缓冲
    double durationSeconds = static_cast<double>(sampleCount) / mStream->getSampleRate();
    std::this_thread::sleep_for(std::chrono::milliseconds(static_cast<int>(durationSeconds * 1000) + 100));

    // 停止并关闭流,等待流完全停止
    mStream->requestStop();
    mStream->waitForStateChange(oboe::StreamState::Started, nullptr, 1000 * oboe::kNanosPerMillisecond);
    mStream->close();

    return 150;
}

内容的提问来源于stack exchange,提问作者cs_guy98

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 12:12:46