Использование AudioTrack в Android для воспроизведения файла WAV

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

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

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

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

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

Спасибо, Р.

6 ответов

Решение

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

    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......

Р.

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

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

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

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

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

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

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

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

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

Просто подтвердите, если у вас есть 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
);

Пример файла 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;
}

}

Другие вопросы по тегам