在Android中使用AudioTrack播放WAV文件

时间:2010-10-13 14:56:57

标签: android wav audio-streaming

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

我已经成功录制并在手机上播放了自己的声音 - 我根据此示例中的说明创建了一个.pcm文件:

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

(没有向后掩盖)......

在Android上播放.wav文件时,有人在网上得到一些建议或意识吗?

谢谢, R上。

7 个答案:

答案 0 :(得分:26)

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

    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 []是SHORTS的数组。所以,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这样配置的问题......无论如何,它最终听起来是正确的,所以如果有人否则他们想在他们的Android上播放Windows声音,出于某种原因,这就是解决方案。啊,Endianness ......

R上。

答案 1 :(得分:8)

我在这个问题上找到了很多很长的答案。我的最终解决方案,即所有切割和粘贴都不是我的,归结为:

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只是一个“true”,作为重置暂停/播放按钮的信号发回。 在类初始化程序中:

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

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

答案 2 :(得分:5)

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

另外,您确定要创建的AudioTrack具有与您尝试播放的WAVE相同的属性(采样率,比特率,通道数等)吗? Windows实际上可以很好地在“文件属性”页面中向您提供此信息: alt text

答案 3 :(得分:2)

Aaron C所述,您必须跳过最初的44个字节或(我更喜欢)读取前面44个字节的WAVE标头。通过这种方式,您可以知道有多少通道,每个样本的位数,长度等...... WAVE包含。

Here你可以找到一个很好的WAVE头解析器/编写器实现。

答案 4 :(得分:1)

请不要使可怕的解析代码永久化。 WAV解析很容易实现 http://soundfile.sapp.org/doc/WaveFormat/ 你会感谢自己能够解析采样率,比特深度和频道数等事情。

x86和ARM(至少默认情况下)都是小端,所以native-endian WAV文件应该没有任何改组。

答案 5 :(得分:0)

样本wav文件:
http://www.mauvecloud.net/sounds/pcm1644m.wav

示例代码:

public class AudioTrackPlayer {
Context mContext;
int minBufferSize;
AudioTrack at;
boolean STOPPED;

public AudioTrackPlayer(Context context) {
    Log.d("------","init");
    mContext = context;
    minBufferSize = AudioTrack.getMinBufferSize(44100,
            AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT);
}

public boolean play() {
    Log.d("------","play");
    int i = 0;
    byte[] music = null;
    InputStream is = mContext.getResources().openRawResource(R.raw.pcm1644m);

    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;
}

}

答案 6 :(得分:0)

只需确认AudioTrack.MODE_STREAM构造函数中是否有AudioTrack.MODE_STATIC而不是AudioTrack

AudioTrack at = new AudioTrack(
  AudioManager.STREAM_MUSIC,
  sampleRate,
  AudioFormat.CHANNEL_IN_STEREO,
  AudioFormat.ENCODING_PCM_16BIT,
  // buffer length in bytes
  outputBufferSize,
  AudioTrack.MODE_STREAM
);