一、基础知识
语音信号有四个重要的参数:声道数、采样频率、量化位数(位深)和比特率。
声道数: 可以是单声道、双声道 …
采样率(Sample rate): 声音是模拟信号,物理信号转化为数字信号的过程我们称之为采样,采样率则表示 每秒对声音信号(模拟信号)抽取的总采样点数,44100Hz采样频率意味着每秒钟信号被均匀抽取44100次。采样频率越高,即采样的间隔时间越短,则在单位时间内得到的样本数据就越多,对信号波形的表示也越精确。
量化位数(Bit depth): 也称为“位深”,每个采样点中信息的比特(bit)数。1 byte等于8 bit。通常有8bit、16bit、24bit、32bit…,位深越大,每个采样点能够表示的信息越多,精度越高。
比特率(Bit rate): 每秒处理多少个Bit。计算公式为:采样率(kHz) * 位深(bit) * 声道数。比如一个单声道,用44.1KHz/16Bit的配置来说,它的比特率就为44100161=705600,单位是bit/s(或者bps),因为通常计算出来的数字都比较大,大家就用kbit/s了,也就是705.6kbit/s。在对音频进行压缩时,比特率就成为了我们的一个要选的选项了,越高的比特率,其音质也就越好。一些常用的比特率有:16kbps:为可视电话质量、32kbit/s: 一般只适用于语音、96kbit/s: 一般用于语音或低质量流媒体、128或160kbit/s: 中等比特率质量、192kbit/s: 中等质量比特率、256kbit/s: 常用的高质量比特率、320kbit/s: MP3标准支持的最高水平
音频从业人员用的两款查看音频软件:
Adobe Audition: 他是Adobe公司开发专门处理音频的专业软件,可以快速看语音波形和语谱图,微博关注vposy,下载地址见置顶。他破解了很多adobe公司的软件,包括PS、PR…
Audacity: 它是一款开源的、跨平台、多声道的录音编辑软件。在我的工作中经常使用Audacity进行声音信号的录制,然后再输出成WAV文件供Python程序处理。
音频在网络中传播,主要分为如下几个阶段:录制-编码-传输-解码-播放,音频编解码发挥这不可忽视的作用,能够优化数据包大小,通常通过媒体采集设备采集的音频数据被编码后,可以极大的压缩数据,并且音质影响不大。本节主要介绍常见的音频编解码格式。
音频编码是为了将 PCM 音频采样数据转换为音频码流, 减少存储来提升网络传输效率。常见的格式有:FLAC、APE、WAV、Opus、MP3、WMA、AAC。
FLAC、APE、WAV 是属于无损编码格式,压缩率低,通常用于音质要求较高的音乐等内容; Opus、MP3、WMA、AAC 属于有损压缩格式,压缩率高利于网络传输; 其中 Opus、OGG 属于完全免费开源的编码格式。不同的编码格式特点也不尽相同,不同编码面向的使用场景不同,没有绝对的优劣。
二、PCM、RAW、SAM
RAW、PCM(Pulse Code Modulation)、SAM 都是一种存储 原始数据 的音频文件格式,未经过任何编码和压缩处理,他们的本质一样,只是文件扩展名不同,也可以没有扩展名。与WAV或AIFF的大小相比,这音频文件不包含任何头信息(采样率、位深度、通道数)。
如果在PCM文件的前面添加WAV文件头,就可以生成WAV格式文件。
如果是16位的话,pcm每个采样点的值在0~ 2^15,因为第一位是符号位。所以我们有时候用librosa读取的音频每个采样点都是0~1之间的,如果该音频是16bit的,如果想将他换成short型应该乘以2 ^ 15。
1.pcm转wav
版本一:代码参考自:https://github.com/pliu6/pcm2wav
/**
* https://github.com/pliu6/pcm2wav
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
typedef struct {
unsigned char chunk_id[4]; /*{'R', 'I', 'F', 'F'}*/
unsigned int chunk_size;
unsigned char format[4];
} FIFFChunk;
typedef struct {
unsigned char chunk_id[4]; /* {'f', 'm', 't', ' '} */
unsigned int chunk_size;
unsigned short audio_format; // 2字节
unsigned short channels; // 4字节
unsigned int sample_rate; // 4字节
unsigned int byte_rate; // 4字节
unsigned short block_align; // 2字节
unsigned short bits_per_sample; // 2字节
} FormatChunk;
typedef struct {
unsigned char chunk_id[4]; /* {'d', 'a', 't', 'a'} */
unsigned int chunk_size;
} DataChunk;
// pcm2wav ***.pcm ***.wav 通道 采样率 量化位数
int main(int argc, char *argv[]) {
FILE *pcmfile, *wavfile;
long pcmfile_size;
FIFFChunk fiffchunk;
FormatChunk formatchunk;
DataChunk datachunk;
int read_len;
char buf[1024];
if (argc != 6) {
printf("usage:\n"
"\t%s pcmfile wavfile channel samplerate bitspersample\n", argv[0]);
return 1;
}
pcmfile = fopen(argv[1], "rb");
if (pcmfile == NULL) {
printf("!Error: Can't open pcmfile.\n");
return 1;
}
fseek(pcmfile, 0, SEEK_END); // 将文件指针移动到文件最后
pcmfile_size = ftell(pcmfile); // 返回给定流 stream 的当前文件位置(字节)
fseek(pcmfile, 0, SEEK_SET); // 将文件指针移动到文件开头
wavfile = fopen(argv[2], "wb");
if (wavfile == NULL) {
printf("!Error: Can't create wavfile.\n");
return 1;
}
/* *********** RIFF区块 ********************* */
strncpy(fiffchunk.chunk_id,"RIFF", 4);
fiffchunk.chunk_size = pcmfile_size+36;
strncpy(fiffchunk.format,"WAVE",4);
fwrite(&fiffchunk, sizeof(fiffchunk)