我正在寻找帮助开始编程与音频工作。
具体地说,我正在使用的平台公开了从资源(如MP3)提取音频数据或将任意数据作为音频播放的API。在这两种情况下,实际数据都是32位浮点数的字节数组,表示44.1 KHz立体声。我正在寻找的是帮助理解这些浮点数代表什么,以及可以用它们做什么事情来动态分析或修改它们代表的声音。
要以这种方式使用音频,我需要学习哪些概念?
发布于 2008-12-14 06:57:19
正如一些人在评论中指出的那样,你想要研究的是PCM audio。
简而言之,sound是一种在空气中传播的波。为了捕捉这种声音,我们使用了一个microphone,它包含一个薄膜,当声波击中它时,它会振动。这种振动被转换成电信号,在那里电压上升和下降。然后,通过每秒采样一定次数("sampling rate“- 44 KHz,或每秒44,100个采样),通过模数转换器( analog-to-digital converter )将电压的这种变化改变为数字信号,并且在当前情况下,将其存储为脉冲编码调制(PCM)音频数据。
speaker的工作原理与之相反;digital-to-analog converter (数模转换器)将PCM信号转换为模拟信号,然后模拟信号到达扬声器,在扬声器上振动薄膜,薄膜在空气中产生振动,从而产生声音。
操纵音频的
有许多针对多种语言的库,您可以使用这些库来操作音频,但是您将这个问题标记为“语言不可知”,我将提到一些简单的方法(因为这就是我所知道的全部!)你将能够以你喜欢的语言操作音频。
我将以伪代码的形式呈现代码示例。
伪码将使每个音频样本的幅度在-1到1的范围内。这将取决于您用于存储每个样本的数据类型。(我以前没有接触过32位float,所以这次可能会有所不同。)
Amplification
为了放大音频,(因此,增加声音的音量)你需要使扬声器的振动更大,这样声波的幅度就会增加。
为了使扬声器移动得更多,您必须增加每个样本的值:
original_samples = [0, 0.5, 0, -0.5, 0]
def amplify(samples):
foreach s in samples:
s = s * 2
amplified_samples = amplify(original_samples)
// result: amplified_samples == [0, 1, 0, -1, 0]产生的样本现在被放大2,在回放时,它应该听起来比以前响亮得多。
静默
当没有振动时,就没有声音。静默可以通过将每个样本降至0或任何特定值来实现,但样本之间的幅度没有任何变化:
original_samples = [0, 0.5, 0, -0.5, 0]
def silence(samples):
foreach s in samples:
s = 0
silent_samples = silence(original_samples)
// result: silent_samples == [0, 0, 0, 0, 0]回放上面的声音应该不会有声音,因为扬声器上的薄膜根本不会移动,这是由于样本中的振幅没有变化。
加速和降低
加速和减速可以通过两种方式实现:(1)更改播放采样率或(2)更改采样本身。
将播放采样率从44100 Hz更改为22050 Hz将使播放速度降低2。这将使声音变慢并降低音调。从22 KHz音源开始,以44 KHz回放,声音将非常快速和高音,就像鸟儿在鸣叫一样。
改变样本本身(并保持恒定的回放采样率)意味着要么(a)被抛出,要么(b)被加入。
若要加快音频播放速度,请抛出示例:
original_samples = [0, 0.1, 0.2, 0.3, 0.4, 0.5]
def faster(samples):
new_samples = []
for i = 0 to samples.length:
if i is even:
new_samples.add(samples[i])
return new_samples
faster_samples = faster(original_samples)
// result: silent_samples == [0, 0.2, 0.4]上述程序的结果是音频将加速2倍,类似于播放在44 KHz下以22 KHz采样的音频。
若要放慢音频的播放速度,请抛出几个示例:
original_samples = [0, 0.1, 0.2, 0.3]
def slower(samples):
new_samples = []
for i = 0 to samples.length:
new_samples.add(samples[i])
new_samples.add(interpolate(s[i], s[i + 1]))
return new_samples
slower_samples = slower(original_samples)
// result: silent_samples == [0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3]在这里,添加了额外的样本,从而减慢了播放速度。在这里,我们有一个interpolation函数,它“猜测”如何填充要添加的额外空格。
基于快速傅立叶变换的频谱分析与声音修正
利用一种称为快速傅立叶变换( Fast Fourier transform )的技术,可以将幅度-时间域中的声音数据映射到频率-时间域,以找出音频的频率分量。这可以用来产生你可能会在你最喜欢的音频播放器上看到的spectrum analyzers。
不仅如此,因为现在你有了音频的频率分量,如果你改变
如果您想要截断某些频率,可以使用FFT将声音数据转换到频率-时域,并将不需要的频率分量置零。这称为filtering。
制作一个允许频率高于某个特定频率的,可以像这样执行:
data = fft(orignal_samples)
for i = (data.length / 2) to data.length:
data[i] = 0
new_samples = inverse_fft(data)在上面的示例中,超过中途标记的所有频率都是截止的。因此,如果音频能够产生22 KHz作为最大频率,则任何高于11 KHz的频率都将被切断。(对于44 KHz的音频播放,理论上可以产生的最大频率是22 KHz。参见Nyquist–Shannon sampling theorem。)
如果你想做一些事情,比如增加低频范围(类似于低音增强效果),取FFT变换数据的较低端并增加其幅度:
data = fft(orignal_samples)
for i = 0 to (data.length / 4):
increase(data[i])
new_samples = inverse_fft(data)这个例子增加了音频频率分量的低四分之一,导致低频变得更大。
有相当多的事情可以做的样本,以操纵音频。尽管去做实验吧!这是最令人兴奋的学习方式。
祝好运!
发布于 2008-12-14 06:15:05
看起来您想了解更多关于PCM audio的信息
基本上,每个32位值代表指定时间的电压电平。由于采样频率为44100 the,因此每个通道每秒可获得441000个32位值(*2,因为您有立体声)
对于立体声,左声道和右声道通常是交错的,因此第一个采样表示左声道,第二个采样表示右声道,依此类推。
发布于 2008-12-22 09:42:53
要理解这些32位浮点数组所代表的内容,您需要阅读一篇很好的数字音频简介。
如果你在图书馆附近,Curtis Roads的“电脑音乐教程”可能会很有用。具体来说,第一章“数字音频概念”。(我已经很久没有读过这本书了)。
一旦你对数字音频有了理解,就有很多方法来操纵它。当你准备好了,这些链接可能会有所帮助。
Dsp + Plugin Development forum at KVR Audio是一个可以提问的地方。这里的帖子通常分为通用音频DSP和VST插件主题。
MusicDsp有很多代码片段。
The Scientist and Engineer's Guide to Digital Signal Processing是一个免费的在线教科书,深入了解标准的数字信号处理器主题。其中大部分也适用于数字音频。
https://stackoverflow.com/questions/366187
复制相似问题