【数据与封装格式】音频PCM

PCM(脉冲编码调制)是将声音模拟信号转化为数字信号的技术,涉及采样频率、量化精度和声道数等关键参数。音频文件大小可通过采样率、位宽和声道数计算。在音频处理中,PCM数据无帧概念,而压缩格式如MP3则有帧头。音频驱动主要负责PCM数据的播放和捕捉。了解这些基础知识对于音频调试至关重要。
摘要由CSDN通过智能技术生成

简介

  • PCM(Pulse Code Modulation),脉冲编码调制
  • 人耳听到的是模拟信号,PCM是把声音从模拟信号转化为数字信号的技术。
  • 原理是用一个固定的频率对模拟信号进行采样,采样后的信号在波形上看就像一串连续的幅值不一的脉冲(脉搏似的短暂起伏的电冲击),把这些脉冲的幅值按一定精度进行量化,这些量化后的数值被连续的输出、传输、处理或记录到存储介质中
  • 数字音频的产生过程(抽样、量化、编码三个过程)。

概念

音频调试需要知道下面几个概念:

  • 采样频率:设备一秒钟内对模拟信号的采样次数,在主流的采集卡上分为
  • 量化精度:一个采样点用多少位数据表示,比如:8bit、16bit(常用)和24bit
  • 声道数:声音在录制或播放时在不同空间位置采集或回放的相互独立的音频信号
  • 音频文件大小计算:
[时长]s * [采样率]Hz * [采样位数]bit * [声道数] / 8 = [文件大小]byte
  • 音频跟视频很不一样,视频每一帧就是一张图像,音频数据是流式的,不同的编码格式各自不同的编码标准,拿PCM和MP3做一个对比。PCM因为没有压缩,根据采样率位宽等数据可以得到每秒的音频数据,并不需要帧的概念,音频实际上是没有帧的概念的;MP3则是因为压缩后信息比较多,则有了类似H264的帧概念,每一个帧都有一个帧头
  • 位速:即比特率、取样率,1s传输的位;
    • 例:22050HZ / 16bit / 立体声格式,位速为22050162 = 705600(bit/s)

存储格式

1、平面模式(非交错模式)

LLLLLLRRRRRRLLLLLLRRRRRRLLLLLLRRRRRRL...( 每个LLLLLLRRRRRR为一个音频帧)

2、交错模式

LRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRL... ( 每个LR为一个音频样本 )

在这里插入图片描述

采集、播放

播放音乐时,应用程序从存储介质中读取音频数据(MP3、WMA、AAC…),经过解码后,最终送到音频驱动程序中的就是PCM数据,反过来,在录音时,音频驱动不停地把采样所得的PCM数据送回给应用程序,由应用程序完成压缩、存储等任务。所以,音频驱动的两大核心任务就是:

  • playback:如何把用户空间的应用程序发过来的PCM数据,转化为人耳可以辨别的模拟音频
  • capture:把mic拾取到得模拟信号,经过采样、量化,转换为PCM信号送回给用户空间的应用程序。

pcm数据播放工具

Adobe_Audition_3.0.rar

要将PCM数据封装为WAV文件格式,需要将PCM数据流保存到WAV文件中,并为WAV文件添加相应的文件头和元数据。WAV文件格式是一种常见的音频文件格式,通常用于存储未经压缩的音频数据。 下面是一个简单的示例代码,演示了如何将PCM数据封装为WAV文件格式: ```java public static void pcmToWav(String pcmPath, String wavPath, int sampleRate, int channels, int bitPerSample) { FileInputStream pcmInputStream = null; FileOutputStream wavOutputStream = null; long totalAudioLen, totalDataLen; long longSampleRate = sampleRate; int byteRate = bitPerSample * channels * (int) (longSampleRate / 8); try { pcmInputStream = new FileInputStream(new File(pcmPath)); wavOutputStream = new FileOutputStream(new File(wavPath)); totalAudioLen = pcmInputStream.getChannel().size(); totalDataLen = totalAudioLen + 36; byte[] data = new byte[1024]; writeWaveFileHeader(wavOutputStream, totalAudioLen, totalDataLen, longSampleRate, channels, byteRate); while (pcmInputStream.read(data) != -1) { wavOutputStream.write(data); } pcmInputStream.close(); wavOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } private static void writeWaveFileHeader( FileOutputStream outputStream, long totalAudioLen, long totalDataLen, long longSampleRate, int channels, int byteRate) throws IOException { byte[] header = new byte[44]; header[0] = 'R'; // RIFF/WAVE header header[1] = 'I'; header[2] = 'F'; header[3] = 'F'; header[4] = (byte) (totalDataLen & 0xff); header[5] = (byte) ((totalDataLen >> 8) & 0xff); header[6] = (byte) ((totalDataLen >> 16) & 0xff); header[7] = (byte) ((totalDataLen >> 24) & 0xff); header[8] = 'W'; header[9] = 'A'; header[10] = 'V'; header[11] = 'E'; header[12] = 'f'; // 'fmt ' chunk header[13] = 'm'; header[14] = 't'; header[15] = ' '; header[16] = 16; // 4 bytes: size of 'fmt ' chunk header[17] = 0; header[18] = 0; header[19] = 0; header[20] = 1; // format = 1 header[21] = 0; header[22] = (byte) channels; header[23] = 0; header[24] = (byte) (longSampleRate & 0xff); header[25] = (byte) ((longSampleRate >> 8) & 0xff); header[26] = (byte) ((longSampleRate >> 16) & 0xff); header[27] = (byte) ((longSampleRate >> 24) & 0xff); header[28] = (byte) (byteRate & 0xff); header[29] = (byte) ((byteRate >> 8) & 0xff); header[30] = (byte) ((byteRate >> 16) & 0xff); header[31] = (byte) ((byteRate >> 24) & 0xff); header[32] = (byte) (2 * 16 / 8); // block align header[33] = 0; header[34] = (byte) bitPerSample; header[35] = 0; header[36] = 'd'; // data chunk header[37] = 'a'; header[38] = 't'; header[39] = 'a'; header[40] = (byte) (totalAudioLen & 0xff); header[41] = (byte) ((totalAudioLen >> 8) & 0xff); header[42] = (byte) ((totalAudioLen >> 16) & 0xff); header[43] = (byte) ((totalAudioLen >> 24) & 0xff); outputStream.write(header, 0, 44); } ``` 在这个示例代码中,我们定义了一个`pcmToWav()`方法,用于将PCM数据流保存为WAV文件。该方法接收三个参数:PCM文件路径、WAV文件路径、采样率、声道数和位宽。在方法中,我们使用FileInputStream读取PCM文件中的数据,并使用FileOutputStream将WAV文件写入磁盘。同时,我们调用了`writeWaveFileHeader()`方法,向WAV文件中添加WAV文件头和元数据。在添加WAV文件头和元数据时,我们需要根据采样率、声道数和位宽计算出相应的文件头和元数据,并将其写入WAV文件中。 通过调用`pcmToWav()`方法,我们可以将PCM数据流保存为WAV文件,并在保存的过程中添加相应的文件头和元数据
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值