使用带有 Android AudioTrack 的缓冲区
Posted
技术标签:
【中文标题】使用带有 Android AudioTrack 的缓冲区【英文标题】:Using a buffer with Android AudioTrack 【发布时间】:2013-12-11 05:22:27 【问题描述】:我试图弄清楚如何使用带有AudioTrack 的缓冲区来有效地流式传输音乐。我知道您可以使用write 方法对音频进行排队,但是一旦音频排队,您如何判断剩余的数量与已使用/播放的数量?抱歉,如果这是一个基本问题。我了解缓冲区的概念,但不知道如何编写,尤其是使用 AudioTrack。
【问题讨论】:
您为什么想知道:“还剩多少与已使用/播放了多少”?? 通知用户应用正在缓冲并执行相关逻辑。 【参考方案1】:AudioTrack.write() 以 int 形式返回“写入的字节数”,您在构造 AudioTrack 时指定缓冲区中的字节数。
因此,要跟踪剩余的缓冲区空间,您可以保留一个累加器变量,以便知道总共写入了多少字节,并在调用AudioTrack.flush() 时将此变量设置为零。但是,链接文档指出“通常使用总大小的 1/2 的块来允许双缓冲”,因此它可能很简单,只需记住自调用 flush 以来是否写过零、一次或两次.
要知道已经播放了多少缓冲区,请使用AudioTrack.getPlaybackHeadPosition(),它返回当前缓冲区已播放的帧数(即重置为停止、刷新或重新加载时为零)作为有符号 32 位整数,但被解释为无符号 32 位整数。这实际上意味着您将其分配给一个 int,如下所示。
int bufferPlaybackFrame = myAudioTrack.getPlaybackHeadPosition() & 0xFF;
您可以将帧视为等同于样本。即,您可以从用于构造 AudioTrack 的 AudioFormat 中计算出每个样本使用了多少位(以及因此字节)。
最后,如果有人想知道,您将永远无法知道有多少源文件或流要通过该对象播放(一个原因是它被设计为与永久 24/7 流一起使用,具有没有结束),所以如果你想像在某些视频播放网站上看到的那样进行计算,暂停流直到缓冲足够的 id 以当前下载速率查看整个视频,你必须在一些中传递该信息另一种方式。
【讨论】:
谢谢,非常有帮助的回答。 @Andrew 如果我想从服务器下载(一次)音频文件,然后文件应该离线播放。 ? @DevendraSingh 那么您将一起使用不同的类和方法(我没有直觉)。这是为了访问您无法真正下载和离线播放的持续、无休止的 24/7 流。 我认为帧不等同于样本。如果输出为单声道,则帧数等于样本数。如果是立体声,则样本数是帧数的两倍,因为每一帧将是左声道的一个样本,右声道的一个样本。【参考方案2】:*此代码将有助于使用缓冲区播放音频*
private void PlayShortAudioFileViaAudioTrack(String filePath) throws IOException
// We keep temporarily filePath globally as we have only two sample sounds now..
if (filePath==null)
return;
//Reading the file..
byte[] byteData = null;
File file = null;
file = new File(filePath);
// for ex. path= "/sdcard/samplesound.pcm" or "/sdcard/samplesound.wav"
byteData = new byte[(int) file.length()];
FileInputStream in = null;
try
in = new FileInputStream( file );
in.read( byteData );
in.close();
catch (FileNotFoundException e)
// TODO Auto-generated catch block
e.printStackTrace();
// Set and push to audio track..
int intSize = android.media.AudioTrack.getMinBufferSize(8000, AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_8BIT);
AudioTrack at = new AudioTrack(AudioManager.STREAM_MUSIC, 8000, AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_8BIT, intSize, AudioTrack.MODE_STREAM);
if (at!=null)
at.play();
// Write the byte array to the track
at.write(byteData, 0, byteData.length);
at.stop();
at.release();
else
Log.d("TCAudio", "audio track is not initialised ");
【讨论】:
对不起,我应该更具体。我无法访问整个文件,因为我正在流式传输它,因此我无法在播放之前将整个文件加载到缓冲区中。以上是关于使用带有 Android AudioTrack 的缓冲区的主要内容,如果未能解决你的问题,请参考以下文章