我目前正在尝试使用AudioTrack播放音频。音频通过网络和应用程序连续读取数据并添加到内部缓冲器中。一个单独的线程正在消耗数据并使用AudioTrack进行回放。
问题:
为了避免网络延迟等因素,我做了应用程序等待,直到它读取足够的数据和回放在最后。
这使得音频播放得非常快。下面是我使用的逻辑的基本示例。
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类不具备基于环境条件的音频播放控制功能是正确的吗?如果是这样的话,是否有更好的库可以使用一种简化的音频回放方式?
发布于 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
返回的。即:
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);
发布于 2018-07-13 07:02:02
就像用户@pskink说的,
您的sampleRate (或传递给AudioTrack构造函数的任何其他参数)很可能是无效的。
因此,我将首先检查您实际设置的采样率是多少。
作为参考,还可以通过调用AudioTrack
方法来设置setPlayBackParams
的速度:
public void setPlaybackParams (PlaybackParams params)
如果您检查AudioTrack文档,您可以看到PlaybackParams文档,并可以设置输出音频的速度和音高。然后可以传递此对象以在AudioTrack对象中设置回放参数。
但是,如果您的唯一问题是原始构造函数sampleRate
(因为我们无法看到变量sampleRate
的来源),则不太可能需要使用它。
https://stackoverflow.com/questions/51319208
复制相似问题