Использование AudioTrack в Android для воспроизведения файла WAV - PullRequest
23 голосов
/ 13 октября 2010

Я работаю с Android, пытаюсь заставить мое приложение AudioTrack воспроизводить файл Windows .wav (Tada.wav). Честно говоря, это не должно быть так сложно, но я слышу много странных вещей. Файл сохраняется на мини-SD-карте моего телефона, и чтение содержимого, похоже, не является проблемой, но когда я играю файл (с параметрами, которые я только ДОВОЛЬНО УВЕРЕН, что верны), я получаю несколько секунд белого шума прежде чем звук превращается в нечто, что может быть правильным.

Я успешно записал и воспроизвел свой голос на телефоне - я создал файл .pcm в соответствии с инструкциями в этом примере:

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

(без маскировки назад) ...

Кто-нибудь получил какие-либо предложения или информацию о примере в Интернете для воспроизведения файла .wav на Android ??

Спасибо, R.

Ответы [ 7 ]

26 голосов
/ 14 октября 2010

Я наткнулся на ответ (честно говоря, пытаясь & ^ @! Я не думал, что это сработает), если кому-то интересно ... В моем исходном коде (который получен из примера в ссылке в оригинале post), данные читаются из файла примерно так:

    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 [] - это массив байтов. Я до сих пор говорю AudioTrack, что это 16-битные данные PCM, и у моего Android, похоже, нет проблем с записью массива байтов в AudioTrack, настроенный таким образом ... В любом случае, он, наконец, звучит правильно, так что если кто-нибудь еще кто-то хочет воспроизводить звуки Windows на своих Android, по какой-то причине это решение. Ах, Endianness ......

R.

8 голосов
/ 28 мая 2013

Я нашел много длинных ответов на этот вопрос. Мое окончательное решение, которое с учетом того, что все вырезки и вставки едва ли являются моими, сводится к:

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 - это просто «истина», отправляемая в качестве сигнала для сброса кнопки паузы / воспроизведения. И в инициализаторе класса:

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

Контекст - это просто «это» из вызывающего действия. Вы можете использовать FileInputStream на SD-карте и т. Д. Мои файлы находятся в res / raw

5 голосов
/ 13 октября 2010

Вы пропускаете первые 44 байта файла перед тем, как выгружать оставшиеся данные файла в буфер?Первые 44 байта являются заголовком WAVE, и они будут звучать как случайный шум, если вы попытаетесь их воспроизвести.

Кроме того, вы уверены, что вы создаете AudioTrack с теми же свойствами, что и WAVE, который вы пытаетесь воспроизвести(частота дискретизации, битрейт, количество каналов и т. д.)На самом деле Windows хорошо справляется с этой задачей на странице свойств файла: alt text

2 голосов
/ 12 апреля 2013

Как сказал Аарон С , вы должны пропустить первые 44 байта или (как я предпочитаю) прочитать первые 44 байта, которые являются заголовком WAVE. Таким образом, вы узнаете, сколько каналов, бит на семпл, длину и т. Д. ... содержит WAVE.

Здесь вы можете найти хорошую реализацию анализатора / записи заголовка WAVE.

1 голос
/ 06 ноября 2013

Пожалуйста, не увековечивайте ужасный код разбора. Разбор WAV тривиален для реализации http://soundfile.sapp.org/doc/WaveFormat/ и вы будете благодарны, если сможете анализировать такие вещи, как частота дискретизации, битовая глубина и количество каналов.

Кроме того, x86 и ARM (по крайней мере по умолчанию) оба имеют порядок байтов, поэтому WAV-файлы с прямым порядком байтов должны быть в порядке без каких-либо перемешиваний.

0 голосов
/ 21 мая 2019

Просто подтвердите, если у вас есть 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
);
0 голосов
/ 25 октября 2018

Пример 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;
}

}

...