Я надеюсь, что кто-то может указать мне правильное направление. Я смог получить хорошую запись звука, а также измерители уровня. Я перешел на воспроизведение аудио, что вызывает у меня некоторые головные боли. Я читал различные статьи, касающиеся MediaPlayer и AudioTrack, а также некоторые различия между этими двумя классами. Одна вещь, которую я прочитал, состояла в том, что оба класса поддерживают PCM, который является форматом моего записанного аудио.
При записи звука я использую класс AudioRecord для захвата 16-битных моно-данных PCM. Я собираю данные, а затем записываю их в файл, который сохраняется на SD-карте. Вот ядро кода для записи в файл:
totalAudioLen = in.getChannel().size();
totalDataLen = totalAudioLen + 36;
WriteWaveFileHeader(out, totalAudioLen, totalDataLen,
longSampleRate, channels, byteRate);
while (dis.available() > 0 )
{
dos.writeShort(dis.readShort());
}
и вот код для написания заголовка WAVE:
byte[] header = new byte[44];
header[0] = 'R'; // RIFF/WAVE header
header[1] = 'I';
header[2] = 'F';
header[3] = 'F';
header[4] = (byte) (totalDataLen & 0xff);
header[5] = (byte) ((totalDataLen >> 8) & 0xff);
header[6] = (byte) ((totalDataLen >> 16) & 0xff);
header[7] = (byte) ((totalDataLen >> 24) & 0xff);
header[8] = 'W';
header[9] = 'A';
header[10] = 'V';
header[11] = 'E';
header[12] = 'f'; // 'fmt ' chunk
header[13] = 'm';
header[14] = 't';
header[15] = ' ';
header[16] = 16; // 4 bytes: size of 'fmt ' chunk
header[17] = 0;
header[18] = 0;
header[19] = 0;
header[20] = 1; // format = 1
header[21] = 0;
header[22] = (byte) channels;
header[23] = 0;
header[24] = (byte) (longSampleRate & 0xff);
header[25] = (byte) ((longSampleRate >> 8) & 0xff);
header[26] = (byte) ((longSampleRate >> 16) & 0xff);
header[27] = (byte) ((longSampleRate >> 24) & 0xff);
header[28] = (byte) (byteRate & 0xff);
header[29] = (byte) ((byteRate >> 8) & 0xff);
header[30] = (byte) ((byteRate >> 16) & 0xff);
header[31] = (byte) ((byteRate >> 24) & 0xff);
header[32] = (byte) (2 * 16 / 8); // block align
header[33] = 0;
header[34] = RECORDER_BPP; // bits per sample
header[35] = 0;
header[36] = 'd';
header[37] = 'a';
header[38] = 't';
header[39] = 'a';
header[40] = (byte) (totalAudioLen & 0xff);
header[41] = (byte) ((totalAudioLen >> 8) & 0xff);
header[42] = (byte) ((totalAudioLen >> 16) & 0xff);
header[43] = (byte) ((totalAudioLen >> 24) & 0xff);
out.write(header, 0, 44);
Проблема с воспроизведением аудиофайла. MediaPlayer действительно быстр, когда дело доходит до воспроизведения, но результат громкий статический. Я беру файл, который был создан с кодом выше, и пытаюсь протолкнуть его через MediaPlayer для воспроизведения. Из того, что я прочитал, MediaPlayer поддерживает 16-битный звук PCM, который, как мне кажется, я создал выше.
mPlayer = new MediaPlayer();
mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
File file = new File(mFileName);
FileInputStream fis = new FileInputStream(file);
mPlayer.setDataSource(mFileName);
mPlayer.prepare();
mPlayer.start();
Когда я использую AudioTrack, воспроизведение звука нормальное, то есть звук такой, какой он был записан. Большая проблема с использованием этого класса - это задержка, которую я испытываю при попытке начать воспроизведение. Я использую режим потока, и для воспроизведения звука требуется 5-15 секунд, что совершенно неприемлемо.
Вот код, который у меня есть для вызова класса AudioTrack:
int intSize = android.media.AudioTrack.getMinBufferSize(RECORDER_SAMPLERATE,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT);
audioPlayer = new AudioTrack(AudioManager.STREAM_MUSIC,RECORDER_SAMPLERATE,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT,
intSize,
AudioTrack.MODE_STREAM);
short[] byteData = null;
File file = null;
file = new File(mFileName);
InputStream is = null;
BufferedInputStream bis = null;
DataInputStream dis = null;
try
{
is = new FileInputStream( file );
bis = new BufferedInputStream(is);
dis = new DataInputStream(bis);
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
try
{
int bytesread = 0, ret = 0;
int size = (int) file.length();
audioPlayer.play();
byteData = new short[size/2];
while (dis.available() > 0 )
{
byteData[ret] = dis.readShort();
ret++;
}
if (byteData != null )
{
// Write the byte array to the track
audioPlayer.write(byteData,0, ret);
bytesread += ret;
}
dis.close();
is.close();
audioPlayer.stop();
audioPlayer.release();
}
catch(IOException e)
{
e.printStackTrace();
}
catch(Exception e)
{
e.printStackTrace();
}
Есть идеи о том, что может вызывать статическое электричество при использовании MediaPlayer? Или есть идеи о том, как улучшить производительность при использовании AudioTrack?