У меня есть аудиофайл AAC-формата, который я пытаюсь преобразовать в файл PCM с необработанным форматом, чтобы смешать его с другим аудиофайлом и воспроизвести его с помощью AudioTrack позже.Декодирование аудиофайла AAC в файл RAW PCM
После некоторого исследования я наткнулся на this library, который соответствующим образом декодирует мой файл AAC. Тем не менее, он передает только декодированные байты непосредственно в AudioTrack. При попытке записать декодированные байты в выходной поток вместо этого, результирующий файл содержит только шум.
это код, я использую для декодирования AAC файла -
public void AACDecoderAndPlay() {
ByteBuffer[] inputBuffers = mDecoder.getInputBuffers();
ByteBuffer[] outputBuffers = mDecoder.getOutputBuffers();
BufferInfo info = new BufferInfo();
// create an audiotrack object
AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, JamboxAudioTrack.FREQUENCY,
JamboxAudioTrack.CHANNEL_CONFIGURATION, JamboxAudioTrack.AUDIO_ENCODING,
JamboxAudioTrack.BUFFER_SIZE, AudioTrack.MODE_STREAM);
audioTrack.play();
long bytesWritten = 0;
while (!eosReceived) {
int inIndex = mDecoder.dequeueInputBuffer(TIMEOUT_US);
if (inIndex >= 0) {
ByteBuffer buffer = inputBuffers[inIndex];
int sampleSize = mExtractor.readSampleData(buffer, 0);
if (sampleSize < 0) {
// We shouldn't stop the playback at this point, just pass the EOS
// flag to mDecoder, we will get it again from the
// dequeueOutputBuffer
Log.d(LOG_TAG, "InputBuffer BUFFER_FLAG_END_OF_STREAM");
mDecoder.queueInputBuffer(inIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
} else {
mDecoder.queueInputBuffer(inIndex, 0, sampleSize, mExtractor.getSampleTime(), 0);
mExtractor.advance();
}
int outIndex = mDecoder.dequeueOutputBuffer(info, TIMEOUT_US);
switch (outIndex) {
case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
Log.d(LOG_TAG, "INFO_OUTPUT_BUFFERS_CHANGED");
outputBuffers = mDecoder.getOutputBuffers();
break;
case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
MediaFormat format = mDecoder.getOutputFormat();
Log.d(LOG_TAG, "New format " + format);
// audioTrack.setPlaybackRate(format.getInteger(MediaFormat.KEY_SAMPLE_RATE));
break;
case MediaCodec.INFO_TRY_AGAIN_LATER:
Log.d(LOG_TAG, "dequeueOutputBuffer timed out!");
break;
default:
ByteBuffer outBuffer = outputBuffers[outIndex];
Log.v(LOG_TAG, "We can't use this buffer but render it due to the API limit, " + outBuffer);
final byte[] chunk = new byte[info.size];
outBuffer.get(chunk); // Read the buffer all at once
outBuffer.clear(); // ** MUST DO!!! OTHERWISE THE NEXT TIME YOU GET THIS SAME BUFFER BAD THINGS WILL HAPPEN
audioTrack.write(chunk, info.offset, info.offset + info.size); // AudioTrack write data
if (info.offset > 0) {
Log.v(LOG_TAG, "" + info.offset);
}
try {
mOutputStream.write(chunk, info.offset, info.offset + info.size);
bytesWritten += info.offset + info.size;
} catch (IOException e) {
e.printStackTrace();
}
mDecoder.releaseOutputBuffer(outIndex, false);
break;
}
// All decoded frames have been rendered, we can stop playing now
if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
Log.d(LOG_TAG, "OutputBuffer BUFFER_FLAG_END_OF_STREAM");
break;
}
}
}
Log.v(LOG_TAG, "Bytes written: " + bytesWritten);
mDecoder.stop();
mDecoder.release();
mDecoder = null;
mExtractor.release();
mExtractor = null;
audioTrack.stop();
audioTrack.release();
audioTrack = null;
}
Для воспроизведения декодированного файла я использую простую аудиодорожку, который читает и играет из буфера -
public void start() {
new Thread(new Runnable() {
public void run() {
try {
Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_AUDIO);
InputStream inputStream = new FileInputStream(playingFile);
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
DataInputStream dataInputStream = new DataInputStream(bufferedInputStream);
AudioTrack track = new AudioTrack(AudioManager.STREAM_MUSIC, FREQUENCY,
CHANNEL_CONFIGURATION, AUDIO_ENCODING, BUFFER_SIZE, AudioTrack.MODE_STREAM);
short[] buffer = new short[BUFFER_SIZE/4];
long startTime = System.currentTimeMillis();
track.play();
while (dataInputStream.available() > 0) {
int i = 0;
while (dataInputStream.available() > 0 && i < buffer.length
) {
buffer[i] = dataInputStream.readShort();
i++;
}
track.write(buffer, 0, buffer.length);
if (latency < 0) {
latency = System.currentTimeMillis() - startTime;
}
}
//
// int i = 0;
// while((i = dataInputStream.read(buffer, 0, BUFFER_SIZE)) > -1){
// track.write(buffer, 0, i);
// }
track.stop();
track.release();
dataInputStream.close();
inputStream.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}).start();
}
Что я Я пропустил?
Endianness, похоже, всегда будет проблемой :) Непонимание этого процесса заставило меня написать реализацию AudioTrack совершенно неправильно. Спасибо большое! –