我正在开发一个原生的android项目并尝试使用OpenSL来播放一些音频效果。使用VisualGDB提供的本机音频示例项目,我已经编写了下面发布的代码。
接近结尾,你可以看到我已经注释了一行,它将缓冲区中名为hello的变量的内容存储到目标。 hello来自示例项目,包含大约700行字符字节,如下所示:
" \ X02 \ X00 \ X01 \ X00 \ XFF \ XFF \ X09 \ X00 \ X0C \ X00 \ X10 \ X00 \ X07 \ X00 \ X07 \ X00"
制作某人说"你好"的音频文件。当将该字节数据读入流中时,我的代码工作正常,我听到"你好"当我运行应用程序时。当我从wav文件中读取我想要的资产时,我只听静电。数据缓冲区的大小与文件的大小相同,因此它似乎正在被正确读取。静态播放wav文件的持续时间(或非常接近它)。
我对数据格式或音频编程一无所知。我尝试使用不同的枚举值调整format_pcm变量,但没有成功。使用我在互联网上找到的名为GSpot的工具,我知道以下关于我试图播放的音频文件:
文件大小:557 KB(570,503字节)(这与数据缓冲区的大小相同 AAsset_read返回
编解码器:PCM音频
采样率:48000Hz
比特率:1152 kb / s
频道:1
非常感谢任何帮助或指示。
SLDataLocator_AndroidSimpleBufferQueue loc_bufq = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 1 };
SLDataFormat_PCM format_pcm;
format_pcm.formatType = SL_DATAFORMAT_PCM;
format_pcm.numChannels = 1;
format_pcm.samplesPerSec = SL_SAMPLINGRATE_48;// SL_SAMPLINGRATE_8;
format_pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_8; // SL_PCMSAMPLEFORMAT_FIXED_16;
format_pcm.containerSize = 16;
format_pcm.channelMask = SL_SPEAKER_FRONT_CENTER;
format_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
SLDataSource audioSrc = { &loc_bufq, &format_pcm };
// configure audio sink
SLDataLocator_OutputMix loc_outmix = { SL_DATALOCATOR_OUTPUTMIX, manager->GetOutputMixObject() };
SLDataSink audioSnk = { &loc_outmix, NULL };
//create audio player
const SLInterfaceID ids[3] = { SL_IID_BUFFERQUEUE, SL_IID_EFFECTSEND, SL_IID_VOLUME };
const SLboolean req[3] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE };
SLEngineItf engineEngine = manager->GetEngine();
result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk,
3, ids, req);
// realize the player
result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE);
// get the play interface
result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay);
// get the buffer queue interface
result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE,
&bqPlayerBufferQueue);
// register callback on the buffer queue
result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, NULL);
// get the effect send interface
result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_EFFECTSEND,
&bqPlayerEffectSend);
// get the volume interface
result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_VOLUME, &bqPlayerVolume);
// set the player's state to playing
result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING);
uint8* pOutBytes = nullptr;
uint32 outSize = 0;
result = MyFileManager::GetInstance()->OpenFile(m_strAbsolutePath, (void**)&pOutBytes, &outSize, true);
const char* filename = m_strAbsolutePath->GetUTF8String();
result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, pOutBytes, outSize);
// result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, hello, sizeof(hello));
if (SL_RESULT_SUCCESS != result) {
return JNI_FALSE;
}
答案 0 :(得分:0)
有几件事要归咎于此。我测试的波形文件的格式不是规范描述的。在第一块标题数据之后似乎有很多空数据。此外,需要传递给队列的缓冲区需要只是wav数据的char *,而不是标头。我错误地认为队列解析了标题。