如何从 .wav 文件中提取特定频率范围?
Posted
技术标签:
【中文标题】如何从 .wav 文件中提取特定频率范围?【英文标题】:How to extract a specific frequency range from a .wav file? 【发布时间】:2011-09-21 17:59:25 【问题描述】:我在声音处理方面真的是新手,所以也许我的问题会是微不足道的。 我想要做的是使用 R 从 wav 文件中提取特定的频率范围(比如说 150-400 Hz)。换句话说,我想创建另一个仅包含频率分量的波形文件(wave2)我指定(150 到 400 Hz,或其他)。
我在网上看了一些东西,发现可以通过 FFT 分析来完成,问题就来了。
假设我有这个代码:
library(sound)
s1 <- Sine(440, 1)
s2 <- Sine(880, 1)
s3 <- s1 + s2
s3.s <- as.vector(s3$sound)
# s3.s is now a vector, with length 44100;
# bitrate is 44100 (by default)
# so total time of s3 is 1sec.
# now I calculate frequencies
N <- length(s3.s) # 44100
k <- c(0:(N-1))
Fs <- 44100 # sampling rate
T <- N / Fs
freq <- k / T
x <- fft(s3.s) / N
plot(freq[1:22050], x[1:22050], type="l") # we need just the first half of FFT computation
我们得到的情节是:
嗯,有两个高峰。如果我们想知道它们对应的频率,只需找到:
order(Mod(x)[1:22050], decreasing=T)[1:10]
[1] 441 881 882 880 883 442 440 879 884 878
前两个值非常接近我用来创建声音的频率:
real computed
Freq1: 440 | 441
Freq2: 880 | 881
那么,现在问题来了:如果我想从我的声音中删除范围内的频率,比如(1, 500)
,如何进行?以及如何仅选择(并保存)范围 (1, 500)
?
我参加的是,我的新声音(删除频率)将接近简单的Sine(freq=880, duration=1)
(我知道,它不可能完全一样!)。
那可能吗?
我很确定fft(DATA, inverse = TRUE)
是我需要的。但我不确定,但我不知道如何进行。
【问题讨论】:
【参考方案1】:如果你不想编程,你可以使用 Praat。
Praat 是一个免费的科学软件程序,用于分析语音中的语音。 但您也可以使用它来编辑任何声音的频谱(删除频率,...),然后将结果导出为新的声音文件。
【讨论】:
【参考方案2】:也许我没有抓住重点,但你还没有答案吗?来自您的帖子:
order(Mod(x)[1:22050], decreasing=T)[1:10]
[1] 441 881 882 880 883 442 440 879 884 878
只需收集所有高于 500 的值:
junk <- order(Mod(x)[1:22050], decreasing=T)[1:10]
(junk1 <- junk[junk > 500])
[1] 881 882 880 883 879 884 878
要生成新信号,只需重复您为构建原始信号所做的操作:
junk2 <- Sine(0, 1)
for (i in 1:length(junk1))
junk2 <- junk2 + Sine(junk1[i], 1)
junk2.s <- as.vector(junk2$sound)
将值保持在 500 以下:
(junk3 <- junk[junk <= 500])
[1] 441 442 440
【讨论】:
Ops,太容易成为真正的 XD 感谢您的回答!只是一个简单的问题,这可能是我的下一个正式问题:产生的声音可怕,不完全是我想要的。你知道改进fft分析的方法吗?有没有更好的方法来提取频率? @Tommaso;我认为“坏”的声音是由于多个频率造成的。在您的程序中,尝试以下操作:play(s1)
play(s2)
和 play(s3)
。正是频率的混合导致了“坏”的声音。您可以选择一个范围内的中间/中值频率,而不是提取一系列频率。
@Tommaso;哎呀,没时间了……选择中频可以通过(junk1 <- median(junk[junk > 500]))
来完成。
@Tommaso;在与play()
混在一起之后,我注意到了一些奇怪的结果。长话短说,试试play(s3)
和play(s3/2)
。 s3
由两个频率组成。如果你建立 Z 频率,除以 Z 来播放它。
我得出了同样的结论。问题是在(-1, 1)
范围内缩放输出。这可以通过库sound
的normalize
函数来完成。在 fft 分析之后,我试图重建原始声音。绘制 plot(normalize(s3[1:600]))
和 plot(normalize(junk4[1:600]+junk2[1:600]))
(junk2 包含频率 > 500,而 junk4 频率
【参考方案3】:
看一下 cran 上的“信号”包,那里应该做的过滤功能之一
【讨论】:
以上是关于如何从 .wav 文件中提取特定频率范围?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 java 从 pcm 字节数组 .wav 文件中获取频率和音高?