解码音频数据中的 NaN 值
NaN values in decoded audio data
我想使用 MediaCodec
从音频文件中获取 pcm 样本。我成功得到了它们,但是解码数据中有 NaN 值。
这些是什么意思?如何消除它们?
这是我的代码:
public float[] getPCMSamples(String audioPath) throws IOException {
MediaExtractor extractor = new MediaExtractor();
MediaCodec decoder = null;
int byte_num = 0;
extractor.setDataSource(audioPath);
int numTracks = extractor.getTrackCount();
for (int i = 0; i < numTracks; ++i) {
MediaFormat format = extractor.getTrackFormat(i);
String mime = format.getString(MediaFormat.KEY_MIME);
if (mime.startsWith("audio/")) {
extractor.selectTrack(i);
decoder = MediaCodec.createDecoderByType(mime);
decoder.configure(format, null, null, 0);
int rate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
int channels = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
long duration = format.getLong(MediaFormat.KEY_DURATION);
duration = (duration / 1000000) + 1;
int bitspersample = 16;
//compute how much byte required for whole song
byte_num = (rate * channels * (int) duration * bitspersample) / 8;
}
}
//Decode
decoder.start();
ByteBuffer[] inputBuffers = decoder.getInputBuffers();
ByteBuffer[] outputBuffers = decoder.getOutputBuffers();
//info for passing to the dequeueOutputBuffer
MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
//flag for the end of the stream
boolean isEOS = false;
//holding bytes obtained from each outputBuffer
byte[] decodedBytes = new byte[byte_num];
//index of decoded bytes so far
int decodedIdx = 0;
//Start decoding
while (true) {
//fill inputBuffer with audio encoded data
if (!isEOS) {
int inputBufferIndex = decoder.dequeueInputBuffer(10000);
if (inputBufferIndex >= 0) {
int sampleSize = extractor.readSampleData(inputBuffers[inputBufferIndex], 0);
if (sampleSize < 0) {
decoder.queueInputBuffer(inputBufferIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
isEOS = true;
} else {
decoder.queueInputBuffer(inputBufferIndex, 0, sampleSize, extractor.getSampleTime(), 0);
extractor.advance();
}
}
}
int outputBufIndex = decoder.dequeueOutputBuffer(info, 10000);
if (outputBufIndex >= 0) {
Log.d(TAG, "got frame, size " + info.size + "/" + info.presentationTimeUs);
ByteBuffer buffer = outputBuffers[outputBufIndex];
byte[] temp = new byte[buffer.remaining()];
buffer.get(temp);
System.arraycopy(temp, 0, decodedBytes, decodedIdx, temp.length);
decodedIdx += temp.length;
decoder.releaseOutputBuffer(outputBufIndex, false /* render */);
if (info.flags == MediaCodec.BUFFER_FLAG_END_OF_STREAM) {
Log.d(TAG, "saw output EOS.");
break;
}
} else if (outputBufIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
outputBuffers = decoder.getOutputBuffers();
Log.d(TAG, "output buffers have changed.");
} else if (outputBufIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
MediaFormat oformat = decoder.getOutputFormat();
Log.d(TAG, "output format has changed to " + oformat);
} else {
Log.d(TAG, "dequeueOutputBuffer returned " + outputBufIndex);
}
}
decoder.stop();
decoder.release();
FloatBuffer floatBuffer = ByteBuffer.wrap(decodedBytes).asFloatBuffer();
float[] decoded = new float[floatBuffer.remaining()];
floatBuffer.get(decoded);
return decoded;
}
android 上的原始解码音频通常是 16 位整数,而不是浮点数。因此,请使用 ShortBuffer
.
而不是 FloatBuffer
我想使用 MediaCodec
从音频文件中获取 pcm 样本。我成功得到了它们,但是解码数据中有 NaN 值。
这些是什么意思?如何消除它们?
这是我的代码:
public float[] getPCMSamples(String audioPath) throws IOException {
MediaExtractor extractor = new MediaExtractor();
MediaCodec decoder = null;
int byte_num = 0;
extractor.setDataSource(audioPath);
int numTracks = extractor.getTrackCount();
for (int i = 0; i < numTracks; ++i) {
MediaFormat format = extractor.getTrackFormat(i);
String mime = format.getString(MediaFormat.KEY_MIME);
if (mime.startsWith("audio/")) {
extractor.selectTrack(i);
decoder = MediaCodec.createDecoderByType(mime);
decoder.configure(format, null, null, 0);
int rate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
int channels = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
long duration = format.getLong(MediaFormat.KEY_DURATION);
duration = (duration / 1000000) + 1;
int bitspersample = 16;
//compute how much byte required for whole song
byte_num = (rate * channels * (int) duration * bitspersample) / 8;
}
}
//Decode
decoder.start();
ByteBuffer[] inputBuffers = decoder.getInputBuffers();
ByteBuffer[] outputBuffers = decoder.getOutputBuffers();
//info for passing to the dequeueOutputBuffer
MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
//flag for the end of the stream
boolean isEOS = false;
//holding bytes obtained from each outputBuffer
byte[] decodedBytes = new byte[byte_num];
//index of decoded bytes so far
int decodedIdx = 0;
//Start decoding
while (true) {
//fill inputBuffer with audio encoded data
if (!isEOS) {
int inputBufferIndex = decoder.dequeueInputBuffer(10000);
if (inputBufferIndex >= 0) {
int sampleSize = extractor.readSampleData(inputBuffers[inputBufferIndex], 0);
if (sampleSize < 0) {
decoder.queueInputBuffer(inputBufferIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
isEOS = true;
} else {
decoder.queueInputBuffer(inputBufferIndex, 0, sampleSize, extractor.getSampleTime(), 0);
extractor.advance();
}
}
}
int outputBufIndex = decoder.dequeueOutputBuffer(info, 10000);
if (outputBufIndex >= 0) {
Log.d(TAG, "got frame, size " + info.size + "/" + info.presentationTimeUs);
ByteBuffer buffer = outputBuffers[outputBufIndex];
byte[] temp = new byte[buffer.remaining()];
buffer.get(temp);
System.arraycopy(temp, 0, decodedBytes, decodedIdx, temp.length);
decodedIdx += temp.length;
decoder.releaseOutputBuffer(outputBufIndex, false /* render */);
if (info.flags == MediaCodec.BUFFER_FLAG_END_OF_STREAM) {
Log.d(TAG, "saw output EOS.");
break;
}
} else if (outputBufIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
outputBuffers = decoder.getOutputBuffers();
Log.d(TAG, "output buffers have changed.");
} else if (outputBufIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
MediaFormat oformat = decoder.getOutputFormat();
Log.d(TAG, "output format has changed to " + oformat);
} else {
Log.d(TAG, "dequeueOutputBuffer returned " + outputBufIndex);
}
}
decoder.stop();
decoder.release();
FloatBuffer floatBuffer = ByteBuffer.wrap(decodedBytes).asFloatBuffer();
float[] decoded = new float[floatBuffer.remaining()];
floatBuffer.get(decoded);
return decoded;
}
android 上的原始解码音频通常是 16 位整数,而不是浮点数。因此,请使用 ShortBuffer
.
FloatBuffer