Моя главная цель - иметь возможность передавать аудио с одного устройства на другое устройство в локальной сети.Я планирую сделать это, прочитав mp3-файл в байт [] (который у меня уже работает) и отправив его как udp-пакет на 2-е устройство и воспроизведя его там (я говорю вам об этом на случай, если это уженеправильный подход).В настоящее время я застрял с игрой моих байтовых массивов.Я читаю мой файл с функцией decoder(path, startMs, durationMs)
из mp3.В данный момент я могу слышать звук, но после каждого тика (части, в которых я читаю файл) я слышу ничего в течение нескольких мс, что приводит к плохому завершению прослушивания.Я думал, что это связано с размером буфера, и попытался немного поиграть с ним, но это ничего не изменило, а также добавило AudioTrack.WRITE_NON_BLOCKING
.Я также подумал о том, чтобы поместить цикл for () в другой поток, но это не работает вообще (что имеет смысл).Я также уже пытался сначала прочитать файл и поместить свой байт [] в Arraylist, так как это может быть причиной проблемы из-за медленного чтения файла, но все равно тот же опыт.Это также может помочь узнать, что Log.e("DEBUG", "Length " + data.length);
отображается только на каждом тике, что означает, что запись также происходит только на каждом тике (что, вероятно, является проблемой).Как мне избавиться от этих пустых частей в моей песне?
Вот мой код, выполняемый при нажатии кнопки:
song.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Thread thrd = new Thread(new Runnable() {
@Override
public void run() {
try {
int tick = 1000;
int max = 9000;
int sampleRate = 44100;
int bufSize = AudioTrack.getMinBufferSize(sampleRate*4, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT);
byte[] data = decode(path, 0, tick);
AudioTrack track = new AudioTrack(AudioManager.STREAM_MUSIC,
44100, AudioFormat.CHANNEL_OUT_STEREO,
AudioFormat.ENCODING_PCM_16BIT, bufSize,
AudioTrack.MODE_STREAM, AudioTrack.WRITE_NON_BLOCKING);
track.play();
track.write(data, 0, data.length);
Log.e("DEBUG", "Length " + data.length);
for(int i = tick; i < max; i+=tick) {
data = decode(path, i, tick);
track.write(data, 0, data.length);
Log.e("DEBUG", "Length " + data.length);
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
thrd.start();
}
});
Моя decode()
-функция (на основе этот урок ) с JLayer 1.0.1:
public static byte[] decode(String path, int startMs, int maxMs)
throws IOException {
ByteArrayOutputStream outStream = new ByteArrayOutputStream(1024);
float totalMs = 0;
boolean seeking = true;
File file = new File(path);
InputStream inputStream = new BufferedInputStream(new FileInputStream(file), 8 * 1024);
try {
Bitstream bitstream = new Bitstream(inputStream);
Decoder decoder = new Decoder();
boolean done = false;
while (! done) {
Header frameHeader = bitstream.readFrame();
if (frameHeader == null) {
done = true;
} else {
totalMs += frameHeader.ms_per_frame();
if (totalMs >= startMs) {
seeking = false;
}
if (!seeking) {
SampleBuffer output = (SampleBuffer) decoder.decodeFrame(frameHeader, bitstream);
if (output.getSampleFrequency() != 44100
|| output.getChannelCount() != 2) {
Log.w("ERROR", "mono or non-44100 MP3 not supported");
}
short[] pcm = output.getBuffer();
for (short s : pcm) {
outStream.write(s & 0xff);
outStream.write((s >> 8) & 0xff);
}
}
if (totalMs >= (startMs + maxMs)) {
done = true;
}
}
bitstream.closeFrame();
}
} catch (BitstreamException e) {
throw new IOException("Bitstream error: " + e);
} catch (DecoderException e) {
Log.w("ERROR", "Decoder error", e);
} finally {
inputStream.close();
}
return outStream.toByteArray();
}
Я не думаю, что проблема с функцией декодирования, так как возвращаемый байт [] кажется довольно хорошим.Возможно, процесс чтения можно было бы оптимизировать позже, когда я действительно транслирую аудио и читаю всегда около 10 мсек, всегда может быть проблема открытия и закрытия файла.