首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >调节Android AudioTrack播放速度

调节Android AudioTrack播放速度
EN

Stack Overflow用户
提问于 2018-07-13 06:50:26
回答 2查看 2K关注 0票数 0

我目前正在尝试使用AudioTrack播放音频。音频通过网络和应用程序连续读取数据并添加到内部缓冲器中。一个单独的线程正在消耗数据并使用AudioTrack进行回放。

问题:

  1. 音频播放不断波动(感觉就像有规律的音程下降),使它变得不清晰。
  2. 播放速度太高或太低,这使它们不现实。

为了避免网络延迟等因素,我做了应用程序等待,直到它读取足够的数据和回放在最后。

这使得音频播放得非常快。下面是我使用的逻辑的基本示例。

代码语言:javascript
运行
复制
    sampleRate = AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_MUSIC);
    audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate,
                    AudioFormat.CHANNEL_OUT_STEREO,
                    AudioFormat.ENCODING_PCM_16BIT,
                    AudioTrack.getMinBufferSize(sampleRate, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT),
                    AudioTrack.MODE_STREAM);
audioTrack.play();

short shortBuffer[] = new short[AudioTrack.getMinBufferSize(sampleRate, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT)];
while (!stopRequested){
    readData(shortBuffer);
    audioTrack.write(shortBuffer, 0, shortBuffer.length, AudioTrack.WRITE_BLOCKING);
}

说安卓AudiTrack类不具备基于环境条件的音频播放控制功能是正确的吗?如果是这样的话,是否有更好的库可以使用一种简化的音频回放方式?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-07-13 09:32:28

我看到的第一个问题,它是任意抽样率。

AudioTrack.getNativeOutputSampleRate将返回声音系统使用的采样率。可能是44100,48000,96000,192000等等。但是看起来你有一些独立来源的音频数据,它以非常精确的采样率产生数据。

假设来自源的音频数据以每秒44100个样本采样。如果你在96000开始玩它,它将加速和更高的音调。

因此,使用采样率设置,以及通道数、样本格式等,由源提供,而不依赖于系统的默认设置。

第二个:您确定readData过程总是足够快,能够成功地填充缓冲区,而不管缓冲区大小如何,并且返回速度比播放的缓冲区快吗?

您已经使用传递为AudioTrack参数的AudioTrack.getMinBufferSize创建了bufferSizeInBytes

getMinBufferSize函数返回可用于此参数的缓冲区的最小可能大小。假设它返回与10‘s长度的缓冲区对应的大小。这意味着新的数据应该在这个时间间隔内准备好。也就是说,前一个write返回的控件与新的write之间的时间间隔应该小于缓冲区的时间大小。

因此,如果readData函数可能因某些原因而延迟超过该时间间隔,则播放将暂停一段时间,您将听到回放中的小间隙。

readData可能延迟的原因可能是多方面的:如果它从文件中读取数据,那么它可能会延迟等待IO操作;如果它分配java对象,它可能会遇到垃圾收集器的延迟;如果它使用另一种使用自己缓冲的音频源的某种解码器,它可能会周期性地延迟填充缓冲区。

但是无论如何,如果您没有创建某种实时合成器,它应该尽快响应用户的输入,请始终使用缓冲区大小合理的高,但不少于getMinBufferSize返回的。即:

代码语言:javascript
运行
复制
sampleRate = 44100;// sampling rate of the source

int bufSize = sampleRate * 4; // 1 second length; 4 - is the frame size: 2 chanels * 2 bytes per each sample
bufSize = max(bufSize, AudioTrack.getMinBufferSize(sampleRate, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT)); // Not less than getMinBufferSize returns
audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate,
                AudioFormat.CHANNEL_OUT_STEREO,
                AudioFormat.ENCODING_PCM_16BIT,
                bufSize,
                AudioTrack.MODE_STREAM);
票数 2
EN

Stack Overflow用户

发布于 2018-07-13 07:02:02

就像用户@pskink说的,

您的sampleRate (或传递给AudioTrack构造函数的任何其他参数)很可能是无效的。

因此,我将首先检查您实际设置的采样率是多少。

作为参考,还可以通过调用AudioTrack方法来设置setPlayBackParams的速度:

代码语言:javascript
运行
复制
public void setPlaybackParams (PlaybackParams params)

如果您检查AudioTrack文档,您可以看到PlaybackParams文档,并可以设置输出音频的速度音高。然后可以传递此对象以在AudioTrack对象中设置回放参数。

但是,如果您的唯一问题是原始构造函数sampleRate (因为我们无法看到变量sampleRate的来源),则不太可能需要使用它。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51319208

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档