PCM音频格式的深入理解

PCM:其数据排列格式为左右声道每个样本点数据交错排列

16bit的PCM数据是有 负数的,至于负数的意义,我估计是代表电压的正负的,0值代表无声。

如下为FFmpeg中所定义的音频格式:

enum AVSampleFormat {
AV_SAMPLE_FMT_NONE = -1,
AV_SAMPLE_FMT_U8, ///< unsigned 8 bits
AV_SAMPLE_FMT_S16, ///< signed 16 bits
AV_SAMPLE_FMT_S32, ///< signed 32 bits
AV_SAMPLE_FMT_FLT, ///< float
AV_SAMPLE_FMT_DBL, ///< double

// 以下都是带平面格式
AV_SAMPLE_FMT_U8P, ///< unsigned 8 bits, planar
AV_SAMPLE_FMT_S16P, ///< signed 16 bits, planar
AV_SAMPLE_FMT_S32P, ///< signed 32 bits, planar
AV_SAMPLE_FMT_FLTP, ///< float, planar
AV_SAMPLE_FMT_DBLP, ///< double, planar

AV_SAMPLE_FMT_NB ///< Number of sample formats. DO NOT USE if linking dynamically
};

其中,

AV_SAMPLE_FMT_FLT 为float类型(4字节)

AV_SAMPLE_FMT_FLTP 为平面排列float类型(4字节)

带P和不带P的数据类型的区别:
P表示Planar(平面),其数据格式排列方式为 :
LLLLLLRRRRRRLLLLLLRRRRRRLLLLLLRRRRRRL...( 每个LLLLLLRRRRRR为一个音频帧
而不带P的数据格式(即交错排列)排列方式为:
LRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRL... 每个LR为一个音频样本

注:L表示左声道一个采样点数据,R表示右声道一个采样点数据

之前由于没有透彻了解音频的数据结构,使用Adobe Audition软件播放PCM音频数据总是出现问题,如下图所示,此图的原始数据为左声道为0而右声道为正常声音采集,由于是Planar的数据排列方式而非交错排列方式,导致最终音频失真。

  • 7
    点赞
  • 58
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
是的,可以使用Springboot启动UDP服务来接收RTP流,并将RTP流中PCMA/PCMU格式音频数据转换成PCM格式。下面是一个简单的示例代码,可以作为参考: ```java import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.SourceDataLine; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; public class RTPReceiver { private static final int BUFFER_SIZE = 1024; private static final int SAMPLE_RATE = 8000; private static final int CHANNELS = 1; private static final boolean SIGNED = true; private static final boolean BIG_ENDIAN = true; public static void main(String[] args) throws Exception { DatagramSocket socket = new DatagramSocket(5000); byte[] buffer = new byte[BUFFER_SIZE]; // Create audio format AudioFormat format = new AudioFormat(SAMPLE_RATE, 16, CHANNELS, SIGNED, BIG_ENDIAN); // Create audio line SourceDataLine line = AudioSystem.getSourceDataLine(format); line.open(format); line.start(); while (true) { DatagramPacket packet = new DatagramPacket(buffer, buffer.length); socket.receive(packet); // Extract audio data from RTP packet byte[] data = packet.getData(); int offset = packet.getOffset(); int length = packet.getLength(); // Convert PCMA/PCMU audio data to PCM format byte[] pcmData = convertToPCM(data, offset, length); // Play audio data line.write(pcmData, 0, pcmData.length); } } private static byte[] convertToPCM(byte[] data, int offset, int length) { // TODO: Implement PCMA/PCMU to PCM conversion logic // For example, you could use the following code to create an AudioInputStream: // ByteArrayInputStream bais = new ByteArrayInputStream(data, offset, length); // return AudioSystem.getAudioInputStream(bais).readAllBytes(); return null; } } ``` 在这个示例代码中,我们创建了一个UDP socket,并在端口5000上进行监听。当收到数据包时,我们将其转换成PCM格式,并通过音频线播放。实际上,将PCMA/PCMU格式音频数据转换成PCM格式的过程需要一定的复杂度,需要对RFC3551等相关规范进行深入了解,并且不同的厂商实现可能会有所不同。因此,在实际应用中需要仔细考虑这些问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lifei092

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值