Android 如果要渲染的数据太多,双簧管将停止渲染音频

Android 如果要渲染的数据太多,双簧管将停止渲染音频,android,c++,audio,oboe,Android,C++,Audio,Oboe,我正在尝试在我的应用程序中实现双簧管库,这样我就可以执行低延迟音频播放。我可以进行平移、播放操作、声音缩放等。我一直在问一些关于这个主题的问题,因为我对音频世界完全陌生 现在我可以执行内部Android音频类提供的基本功能,比如SoundPool。我可以同时播放多个声音,没有明显的延迟 但现在我遇到了另一个问题。例如,我做了一个非常简单的应用程序;屏幕上有一个按钮,若用户点击这个屏幕,它会播放简单的钢琴声。无论用户如何快速点击此按钮,它都必须能够像SoundPool一样混合这些钢琴声音 我的代码

我正在尝试在我的应用程序中实现双簧管库,这样我就可以执行低延迟音频播放。我可以进行平移、播放操作、声音缩放等。我一直在问一些关于这个主题的问题,因为我对音频世界完全陌生

现在我可以执行内部Android音频类提供的基本功能,比如
SoundPool
。我可以同时播放多个声音,没有明显的延迟

但现在我遇到了另一个问题。例如,我做了一个非常简单的应用程序;屏幕上有一个按钮,若用户点击这个屏幕,它会播放简单的钢琴声。无论用户如何快速点击此按钮,它都必须能够像
SoundPool
一样混合这些钢琴声音

我的代码可以很好地做到这一点,直到我点击按钮太多次,所以有许多音频队列要混合

OggPlayer类;
类播放器队列{
私人:
OggPlayer*播放器;
void renderStereo(浮点*音频数据,整数帧);
void renderMono(浮点*音频数据,整数帧);
公众:
整数偏移=0;
浮盘;
浮动螺距;
国际音阶;
bool-queueend=false;
PlayerQueue(浮动平移、浮动音高、整数播放比例、OggPlayer*播放器){
这个->平移=平移;
此->播放比例=播放比例;
这个->玩家=玩家;
这个->音高=音高;
如果(此->平移<-1.0)
这个->泛=-1.0;
否则如果(此->平移>1.0)
这个->平移=1.0;
}
void renderAudio(浮点*音频数据、整数帧、布尔isStreamStereo);
};
类OggPlayer{
私人:
std::vector队列=std::vector();
公众:
整数偏移=0;
布尔·伊斯特雷奥;
浮动默认螺距=1.0;
OggPlayer(std::vector data、bool-isStereo、int-fileSampleRate、int-deviceSampleRate){
这->数据=数据;
这->isStereo=isStereo;
defaultPitch=(浮点)(fileSampleRate)/(浮点)(deviceSampleRate);
}
void renderAudio(浮点*音频数据、整数帧、布尔重置、布尔isStreamStereo);
静态void smoothAudio(浮点*音频数据、整数帧、布尔isStreamStereo);
void addQueue(浮动盘、浮动节距、int playerScale){
队列。向后推(PlayerQueue(平移,默认音高*音高,playerScale,this));
};
静态无效重置音频数据(浮点*音频数据,整数帧,布尔isStreamStereo);
std::矢量数据;
};
OggPlayer
使用
defulatPitch
值保存解码的PCM数据,以同步扬声器的采样率和音频文件的采样率。每个
OggPlayer
保存自己的PCM数据(表示每个音频文件的数据),并且保存自己的
PlayerQueue
向量
PlayerQueue
是实际呈现音频数据的类
OggPlayer
PlayerQueue
类的PCM数据提供程序
PlayerQueue
有自己的自定义音高、平移和音频比例值。由于
AudioStream
可以在回调方法中提供有限的数组大小,我添加了
offset
,因此
PlayerQueue
可以在下一个会话中继续呈现音频,而不会丢失其状态

void OggPlayer::renderAudio(浮点*音频数据、整数帧、布尔重置、布尔isStreamStereo){
如果(重置){
重置音频数据(音频数据、numFrames、isStreamStereo);
}
用于(自动排队:队列(&W){
如果(!queue.queueEnded){
renderAudio(音频数据、numFrames、isStreamStereo);
}
}
smoothAudio(音频数据、数字帧、isStreamStereo);
queues.erase(std::remove_if(queues.begin(),queues.end(),
[](const PlayerQueue&p){return p.queueend;}),queues.end();
}
这就是我当前呈现音频数据的方式,我通过每个
OggPlayer
PlayerQueue
向量进行搜索,如果音频数据尚未到达PCM数据数组的末尾,则通过传递数组指针使其呈现音频数据。我平滑音频数据后,完成音频数据,以防止剪辑或其他事情。最后,如果队列完成了音频渲染(完全),则从vector中移除队列

void PlayerQueue::renderAudio(浮点*音频数据、整数帧、布尔isStreamStereo){
如果(isStreamStereo){
renderStereo(音频数据、numFrames);
}否则{
renderMono(音频数据、numFrames);
}
}
void PlayerQueue::renderStereo(浮点*音频数据,整数帧){
对于(int i=0;i伊斯特雷奥){
如果((int)((float)(offset+i)*音高)*2+1data.size()){
左浮动=玩家->数据。在((整数)((浮动)(偏移量+i)*音高)*2);
右浮动=玩家->数据。在((整数)((浮动)(偏移量+i)*音高)*2+1);
if(pan<0){
音频数据[i*2]+=(左+右*(浮点)sin(abs(pan)*M_PI/2.0))*(浮点)音阶;
音频数据[i*2+1]+=右*(浮点)cos(abs(pan)*M_PI/2.0)*(浮点)音阶;
}否则{
音频数据[i*2]+=左*(浮点)cos(pan*M_PI/2.0)*(浮点)播放比例;
音频数据[i*2+1]+=(右+左*(浮点)sin(pan*M_PI/2.0))*(浮点)播放比例;
}
}否则{
打破
}
}否则{
如果((int)((float)(offset+i)*音高)data.size()){
float sample=player->data.at((int)((float)(offset+i)*音高));
if(pan<0){
音频数据[i*2]+=sample*(1+(float)sin(abs(pan)*M_PI/2.0))*(float)音阶;
音频数据[i*2+1]+=sample*(float)cos(abs(pan)*M_PI/2.0)*(float)播放音阶;
}否则{
音频数据[i*2]+=sample*(float)cos(pan*M_PI/2.0)*(float)播放音阶;
音频数据[i*2+1]+=样本*(1+(浮点)