在Android中使用AudioTrack播放WAV文件

我正在使用Android,试图让我的AudioTrack应用程序播放Windows .wav文件(Tada.wav)。 坦率地说,这不应该这么难,但我听到很多奇怪的东西。 该文件保存在我的手机的迷你SD卡上,并阅读内容似乎不是一个问题,但是当我玩文件(带参数我只是绝对是正确的),我得到了几秒钟的白噪声在声音似乎将自己解决为可能是正确的事情之前。

我已经成功录制并在电话上播放了自己的声音 – 根据本示例中的说明,我创build了一个.pcm文件:

http://emeadev.blogspot.com/2009/09/raw-audio-manipulation-in-android.html

(没有反向掩盖)…

任何人都有一些build议或意识的例子在网上播放Android上的.wav文件?

谢谢,R.

Solutions Collecting From Web of "在Android中使用AudioTrack播放WAV文件"

我偶然发现了答案(坦率地说,通过尝试&^ @!我不认为会起作用),以防有人感兴趣…在我最初的代码中(这是从原始文章中的链接例子中派生出来的)数据是从文件中读取,如下所示:

InputStream is = new FileInputStream (file); BufferedInputStream bis = new BufferedInputStream (is, 8000); DataInputStream dis = new DataInputStream (bis); // Create a DataInputStream to read the audio data from the saved file int i = 0; // Read the file into the "music" array while (dis.available() > 0) { music[i] = dis.readShort(); // This assignment does not reverse the order i++; } dis.close(); // Close the input stream 

在这个版本中,music []是短裤arrays。 所以,readShort()方法在这里似乎是有道理的,因为数据是16位PCM …但是,在Android上似乎是问题所在。 我将该代码更改为以下内容:

  music=new byte[(int) file.length()];//size & length of the file InputStream is = new FileInputStream (file); BufferedInputStream bis = new BufferedInputStream (is, 8000); DataInputStream dis = new DataInputStream (bis); // Create a DataInputStream to read the audio data from the saved file int i = 0; // Read the file into the "music" array while (dis.available() > 0) { music[i] = dis.readByte(); // This assignment does not reverse the order i++; } dis.close(); // Close the input stream 

在这个版本中,music []是一个BYTES数组。 我仍然告诉AudioTrack,它是16位的PCM数据,而我的Android似乎没有写入一个AudioTrack这样configuration的字节数组的问题…无论如何,它终于听起来是正确的,所以如果有人其他人想要在Android上播放Windows声音,出于某种原因,这就是解决scheme。 啊,Endianness ……

R.

在将文件数据的其余部分转储到缓冲区之前,是否跳过文件的前44个字节? 前44个字节是WAVE标题,如果你试图播放它们,它们会听起来像随机噪声。

另外,您是否确定您正在创build与正试图播放的WAVE属性相同的AudioTrack(采样率,比特率,通道数量等)? Windows实际上在文件属性页面中给你提供了这个信息: 替代文字

我发现这个问题有很多很长的答案。 我的最终解决scheme,给予所有的切割和粘贴是不是我的,归结为:

 public boolean play() { int i = 0; byte[] music = null; InputStream is = mContext.getResources().openRawResource(R.raw.noise); at = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, minBufferSize, AudioTrack.MODE_STREAM); try{ music = new byte[512]; at.play(); while((i = is.read(music)) != -1) at.write(music, 0, i); } catch (IOException e) { e.printStackTrace(); } at.stop(); at.release(); return STOPPED; } 

STOPPED只是一个“真”的信号,作为重置暂停/播放button的信号。 而在类初始化程序中:

 public Mp3Track(Context context) { mContext = context; minBufferSize = AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT); } 

上下文就是来自调用活动的“this”。 你可以在SD卡上使用FileInputStream等。我的文件是res / raw

正如Aaron C所说的,你必须跳过最初的44个字节,或者(如我所愿)读取WAVE头的前44个字节。 通过这种方式,您可以知道WAVE包含多less个通道,每个采样的位数,长度等等。

在这里你可以find一个WAVE头parsing器/写入器的很好的实现。

请不要让可怕的parsing代码长期存在。 WAVparsing对于实现http://soundfile.sapp.org/doc/WaveFormat/来说是微不足道的,你可以通过parsing诸如采样率,比特深度和频道数量来感谢你自己。

此外,x86和ARM(至less默认情况下)都是小端,所以native-endian WAV文件应该没有任何洗牌罚款。