Использование AudioTrack в Android для воспроизведения WAV файла
Я работаю с Android, пытаясь заставить приложение AudioTrack воспроизводить Windows.wav файл (Tada.wav). Честно говоря, это не должно быть так сложно, но я слышу много странных вещей. Файл сохраняется на моей мини-карте mini SD и чтение содержимого не кажется проблемой, но когда я играю в файл (с параметрами я только PRETTY SURE прав), я получаю несколько секунд белого шума прежде чем звук, кажется, разрешит себя во что-то, что просто может быть правильным.
Я успешно записал и воспроизвел свой собственный голос на телефоне - я создал файл .pcm в соответствии с указаниями в этом примере:
http://emeadev.blogspot.com/2009/09/raw-audio-manipulation-in-android.html
(без маскировки назад)...
У кого-нибудь есть какие-то предложения или понимание примера в Интернете для воспроизведения WAV файла на Android?
Спасибо,
R.
Ответы
Ответ 1
Я наткнулся на ответ (честно говоря, пытаясь & ^ @! Я не думал, что это сработает), если кто-то заинтересован... В моем исходном коде (который получен из примера в ссылке в оригинальное сообщение), данные считываются из файла следующим образом:
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
В этой версии музыка [] представляет собой массив 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
В этой версии музыка [] представляет собой массив BYTES. Я все еще говорю AudioTrack, что 16-битные данные PCM, и у моего Android, похоже, не проблема с записью массива байтов в конфигурацию AudioTrack, настроенную таким образом... Во всяком случае, это, наконец, звучит правильно, поэтому, если кто-нибудь другой хочет воспроизвести звуки Windows на своем Android, почему-то, что решение. Ах, Endianness......
R.
Ответ 2
Я нашел много длинных ответов на этот вопрос. Мое окончательное решение, которое давало все вырезание и склеивание, вряд ли мое, сводится к:
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 - это просто "истина", отправленная в качестве сигнала на reset кнопку паузы/воспроизведения.
И в инициализаторе класса:
public Mp3Track(Context context) {
mContext = context;
minBufferSize = AudioTrack.getMinBufferSize(44100,
AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT);
}
Контекст - это просто "this" из вызывающей активности.
Вы можете использовать FileInputStream на SD-карте и т.д. Мои файлы находятся в res/raw
Ответ 3
Пропускаете ли вы первые 44 байта файла, прежде чем вы оставите остальную часть данных файла в буфере? Первые 44 байта - это заголовок WAVE, и они будут звучать как случайный шум, если вы попытаетесь воспроизвести их.
Также вы уверены, что создаете AudioTrack с теми же свойствами, что и WAVE, который вы пытаетесь воспроизвести (частота дискретизации, скорость передачи, количество каналов и т.д.)? Windows действительно хорошо справляется с предоставлением этой информации на странице "Свойства файла":
![alt text]()
Ответ 4
Как сказано Aaron C, вам нужно пропустить начальные 44 байта или (как я предпочитаю) читать первые 44 байта, которые являются заголовком WAVE. Таким образом, вы знаете, сколько каналов, бит на выборку, длину и т.д. Содержит WAVE.
Здесь вы можете найти хорошую реализацию анализатора WAVE заголовка/записи.
Ответ 5
Пожалуйста, не увековечивайте ужасный код синтаксического анализа. Разбор WAV тривиально для реализации
http://soundfile.sapp.org/doc/WaveFormat/
и вы поблагодарите себя за то, что сможете анализировать такие вещи, как частота дискретизации, глубина бит и количество каналов.
Кроме того, x86 и ARM (по крайней мере, по умолчанию) являются минимальными, поэтому файлы WAV с открытым контентом должны быть хорошими без перетасовки.
Ответ 6
Пример файла 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;
}
}
Ответ 7
Просто подтвердите, есть ли у вас 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
);