audio是如何用数字表示的?

我喜欢思考如何做一切事情,并用数字来表示。 例如,明文用ASCII码等代码表示,图像用RGB值表示。 这些是表示文字和图像的最简单的方法。

audio可以用数字表示的最简单的方法是什么? 我想学习如何编写与audio兼容的程序,并认为这将是一个很好的开始。 但是,我似乎无法在网上find任何好的解释。

身体上,你可能知道,audio是一种振动。 通常情况下,我们正在谈论空气的振动约20Hz和20,000Hz之间。 这意味着空气每秒钟来回移动20到20,000次。

如果您测量振动并将其转换为电信号(例如,使用麦克风),您将获得电压与声音波形相同的电信号。 在我们的纯音假设中,该波形将与正弦函数的波形相匹配。

现在,我们有一个模拟信号,电压。 仍然不是数字的。 但是,我们知道这个电压在(例如)-1V和+ 1V之间变化。 当然,我们可以在电线上加一个电压表并读取电压。

任意地,我们将改变我们的电压表的规模。 我们将电压乘以32767,现在调用-1V -32767和+ 1V 32767 。 哦,它会四舍五入到最接近的整数。

现在,我们把伏特计挂在电脑上,指示电脑每秒钟读44100次。 添加第二个电压表(用于另一个立体声通道),现在我们有一个audioCD上的数据。

这种格式被称为立体声44,100赫兹,16位线性PCM 。 这实际上只是一堆电压测量。

audio可以由数字样本表示。 实质上,采样器(也称为模数转换器)每隔1 / fs抓取audio信号的值,其中fs是采样频率。 ADC然后量化信号,这是一个舍入操作。 所以,如果你的信号范围从0到3伏(满量程),那么一个采样将被舍入到例如一个16位数字。 在这个例子中,一个16位的数字每1 / fs /

例如,大多数WAV / MP3都是以44 kHz的频率采样audio信号的。 我不知道你想要什么细节,但有一件叫做奈奎斯特采样率(Nyquist Sampling Rate)的东西,即采样频率必须至less是所需频率的两倍。 所以在你的WAV / MP3文件中,你最多可以听到22 kHz的频率。

你可以在这方面进行很多细节。 最简单的forms肯定是WAV格式。 这是未压缩的audio。 像MP3和ogg格式,必须进行解压缩之前,你可以使用它们。

将声音表示为数字的最简单方式是PCM(脉码调制)。 这意味着声音的幅度以设定的频率被logging(每个幅度值被称为样本)。 CD质量的声音例如是在44100Hz的频率下的16位采样(以立体声)。

样本可以表示为整数(通常为8,12,16,24或32位)或浮点数(16位浮点型或32位双精度型)。 该号码可以是有符号的或无符号的。

对于16位有符号采样,值0将在中间,-32768和32767将是最大的放大。 对于16位无符号采样,值32768将在中间,0和65535将是最大幅度。

对于浮点采样,通常的格式是0在中间,-1.0和1.0是最大幅度。

PCM数据然后可以被压缩,例如使用MP3。

我认为特定采样频率下的波形样本将是最基本的代表。

你有没有看过波形? Y轴简单表示为一个整数,通常为16位。

查找模拟数字转换之类的东西。 这应该让你开始。 这些设备可以将audio信号(正弦波)转换为数字表示。 所以,一个16位ADC将能够表示-32768到32768之间的一个正弦。这是一个固定点。 也可以用浮点的方式来完成(尽pipe不是出于性能原因而推荐的,但是由于范围的原因可能是需要的)。 当我们将数字转换为正弦波时,会发生相反的(数字 – 模拟转换)。 这是由一个叫做DAC的东西来处理的。

我认为开始播放audio的一个好方法是使用Processing和Minim 。 这个程序将画出你的麦克风的声audio谱!

import ddf.minim.*; import ddf.minim.analysis.*; AudioInput in; FFT fft; void setup() { size(1024, 600); noSmooth(); Minim.start(this); in = Minim.getLineIn(); fft = new FFT(in.bufferSize(), in.sampleRate()); } void draw() { background(0); fft.forward(in.mix); stroke(255); for(int i = 0; i < fft.specSize(); i++) line(i*2+1, height, i*2+1, height - fft.getBand(i)*10); } void stop() { in.close(); Minim.stop(); super.stop(); } 

最小的Caudio生成示例

下面的例子以原始格式生成一个纯的1000k Hz窦。 在44.1kHz采样率下,将持续4秒:

 #include <math.h> #include <stdio.h> #include <stdlib.h> #include <stdint.h> int main(void) { FILE *f; const double PI2 = 2 * acos(-1.0); const double SAMPLE_FREQ = 44100; const unsigned int NSAMPLES = 4 * SAMPLE_FREQ; uint16_t ampl; uint8_t bytes[2]; unsigned int t; f = fopen("out.raw", "wb"); for (t = 0; t < NSAMPLES; ++t) { ampl = UINT16_MAX * 0.5 * (1.0 + sin(PI2 * t * 1000.0 / SAMPLE_FREQ)); bytes[0] = ampl >> 8; bytes[1] = ampl & 8; fwrite(bytes, 2, sizeof(uint8_t), f); } fclose(f); return EXIT_SUCCESS; } 

玩起来:

 sudo apt-get install ffmpeg ffplay -autoexit -f u16be -ar 44100 -ac 1 out.raw 

参数解释在: https : //superuser.com/a/1063230/128124

在Ubuntu 15.10上testing GitHub上更有趣的例子 ,包括一个简单的佳能合成器。

物理

audio在每个时刻都被编码为一个单一的号码。 将它与一个video进行比较,该video需要每时每刻的WIDTH * HEIGHT数字。

这个数字然后被转换为您的扬声器膜片的线性位移:

 | / | / |-/ | | AIR |-\ | \ | \ <-> displacement | / | / |---/ | | AIR |---\ | \ | \ <---> displacement | / | / |-----/ | | AIR |-----\ | \ | \ <-----> displacement 

位移推动空气前后移动,产生压力差,以P波forms穿过空气。

只有位移才是重要的:即使最大,信号也不会产生声音:振动膜只停留在固定位置。

采样频率决定了应该以多快的速度完成位移。

由于奈奎斯特 – 香农(Nyquist-Shannon)采样定理 ,人耳可以听到高达20kHz的频率,因此44.1kHz是一种常见的采样频率。

采样频率类似于video的FPS,虽然它比我们通常看到的video的25(电影)-144(铁杆游戏显示器)范围高得多。

格式

.raw是一个不足指定的格式,只包含振幅字节,不包含元数据。

我们必须在命令行上传递一些元数据参数,如采样频率,因为格式不包含这些数据。

还有其他未压缩格式,包含所有需要的元数据,例如.wav ,参见: WAV File Synthesis From Scratch – C

然而在实践中,大多数人只处理压缩​​格式,这使得文件/stream式传输变得更小。 其中一些格式考虑到人耳的特征,以有损的方式进一步压缩audio。

生物学

人类主要通过频率分解(AKA 傅立叶变换 )来感知声音。

我认为这是因为内耳有不同频率共振的部分(TODO确认)。

因此,在合成音乐时,我们更多地考虑频率合计而不是时间点。 在这个例子中说明了这一点 。

这导致了对于每个时间点在20Hz和20kHz之间的1Dvector的思考。

math傅里叶变换失去了时间的概念,所以我们在合成时要做的是取一组点,并对该组进行求和,然后在那里进行傅立叶变换。

幸运的是,傅立叶变换是线性的,所以我们可以直接叠加和归一化位移。

每组点的大小导致了一个时频精度的折衷,由海森伯不确定性原理的相同math调解。

小波可能是这种中介时频描述的更精确的math描述。

将实际的模拟audio转换成数字forms涉及两个步骤。

  1. 采样
  2. 量化

采样

连续波形(在这种情况下是audio)的采样率被称为采样率。 人类感知的频率范围是20 – 20000 Hz。 然而,CD使用奈奎斯特采样定理,这意味着采样率为44,100赫兹,覆盖范围为0 – 22,050赫兹的频率。

量化

现在需要将从“采样”阶段接收到的离散值转换成有限数量的值。 8位量化提供256个可能的值,而16位量化提供高达65,536个值。

答案都与抽样频率有关,但不涉及这个问题。 我想,一个特定的声音快照会包含许多不同频率的个别幅度(例如,您同时在键盘上同时按下A和C,A会变大)。 这是如何logging在一个16位数字? 如果你只是在测量幅度(声音多大),你怎么得到不同的音符?

啊! 我想我从这个评论中得到:“这个数字,然后转换为你的扬声器膜片的线性位移”。 音符显示振动膜振动的速度。 这就是为什么你需要每秒44,000个不同的值。 一个音符在1000赫兹左右的地方,所以一个纯音符会使振膜进出每秒约1000次。 整个pipe弦乐队的录音在整个地方都有许多不同的音符,奇迹般地可以转换成一个单一的膈膜运动历史。 每隔44,000次膈板指示进出一点点,这个简单(长)的数字列表可以代表碧昂丝到贝多芬!