2

如何获取 AMR 文件的持续时间?

mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

我想在录制停止后获取文件的持续时间而不创建任何 MediaPlayer 并从中获取持续时间。对于常规的 Wav 文件,我只需执行以下操作:

fileLength / byteRate

但是对于 AMR,我不知道 byteRate 并且我不确定这是否可以,因为 WAV 是原始 PCM 数据(未压缩)并且 AMR 是压缩的。

4

2 回答 2

6

也许 3GP 容器包含有关内容长度的信息?如果您想阅读,可以使用3GPP文件格式规范。


对于原始 .amr 文件,您必须遍历所有帧才能找到音频的长度,因为每个帧都可以使用不同的比特率进行编码。

这样做的过程是:

  • 跳过文件的前 6 个字节(AMR 签名)。

  • 文件的其余部分将是音频帧,每个帧都以一个字节的标题开头。读取该字节并查看位 3..6(编解码器模式)。对于 AMR-NB,有效的编解码器模式为 0..7,您可以使用下表将其映射到以字节为单位的帧大小。

  • 一旦你知道当前帧的大小,跳过它并解析下一帧。重复直到到达文件末尾。

如果您计算了文件中的帧数,您可以将该数字乘以 20 以获得音频的长度(以毫秒为单位)。

车架尺寸表:

编解码器模式 帧大小
----------------------
0 13
1 14
2 16
3 18
4 20
5 21
6 27
7 32

来源

于 2013-07-04T09:11:33.670 回答
0

Java代码: https ://blog.csdn.net/fjh658/article/details/12869073

C# 代码(来自 MemoryStream):

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;
    }
于 2020-01-16T23:36:06.743 回答