Android-以编程方式获取AMR音频文件的持续时间



如何获取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;
    }

最新更新