如何获取AMR文件的持续时间?
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
我想在不创建任何MediaPlayer的情况下停止录制后获得文件的持续时间,并从中获得持续时间。对于常规的Wav文件,我只需这样做:
fileLength / byteRate
但对于AMR,我不知道字节率,我不确定这是否可以,因为WAV是原始PCM数据(未压缩),AMR是压缩的。
也许3GP容器包含有关内容长度的信息?如果你想阅读,3GPP文件格式规范是可用的。
对于原始.amr文件,您必须遍历所有帧才能找到音频的长度,因为每个帧都可以用不同的比特率进行编码。
这样做的过程是:
-
跳过文件的前6个字节(AMR签名)。
-
文件的其余部分将是音频帧,每个帧以一个字节的标头开始。读取该字节并查看第3..6位(编解码器模式)。对于AMR-NB,有效的编解码器模式为0..7,您可以使用下表将其映射到以字节为单位的帧大小。
-
一旦知道了当前帧的大小,就跳过它并解析下一帧。重复此步骤,直到到达文件末尾。
如果你已经计算了文件中的帧数,你可以将这个数字乘以20,得到音频的长度(以毫秒为单位)。
帧大小表:
编解码器模式帧大小----------------------0 131 142 163 184 205 216 277 32
(来源)
Java代码:https://blog.csdn.net/fjh658/article/details/12869073
C#代码(来自内存流):
private double getAmrDuration(MemoryStream originalAudio)
{
double duration = -1;
int[] packedSize = new int[] { 12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0 };
long length = originalAudio.Length;
int pos = 6;
int frameCount = 0;
int packedPos = -1;
byte[] datas = new byte[1];
while ((pos <= length))
{
originalAudio.Seek(pos, SeekOrigin.Begin);
if ((originalAudio.Read(datas, 0, 1) != 1))
{
duration = length > 0 ? ((length - 6) / 650) : 0;
break;
}
packedPos = (datas[0] >> 3) & 0x0F;
pos += packedSize[packedPos] + 1;
frameCount++;
}
/// //////////////////////////////////////////////////
duration = (duration + (frameCount * 20));
// 'p*20
return duration/1000;
}