【发布时间】:2018-02-22 12:07:08
【问题描述】:
(这是用 Python 编写的,代码会很棒,但我主要对算法感兴趣。)
我正在监视一个音频流 (PyAudio) 并寻找一系列 5 个弹出声(参见底部的可视化)。我正在读取()流并获取我刚刚读取的块的 RMS 值(类似于this question)。我的问题是我不是在寻找单个事件,而是一系列具有某些特征但不像我想要的布尔值的事件(pop)。检测这五个爆裂声的最直接(和高效)的方法是什么?
RMS 函数给了我这样的流:
0.000580998485254, 0.00045098391298, 0.00751436443973, 0.002733730043, 0.00160775708652, 0.000847808804511
如果我为你四舍五入(类似的流)看起来会更有用:
0.001, 0.001, 0.018, 0.007, 0.003, 0.001, 0.001
您可以在第 3 项中看到弹出,并且大概在第 4 项中它安静下来,并且可能尾端出现在第 5 项的一小部分。
我想连续检测 5 个。
我天真的做法是: a) 定义什么是 pop:Block 的 RMS 超过 0.002。至少 2 个区块,但不超过 4 个区块。以沉默开始,以沉默结束。
此外,我很想定义什么是静音(忽略不太响亮但不太静音的块,但我不确定这是否比考虑 'pop' 为布尔值更有意义)。
b) 然后有一个状态机来跟踪一堆变量并有一堆 if 语句。喜欢:
while True:
is_pop = isRMSAmplitudeLoudEnoughToBeAPop(stream.read())
if is_pop:
if state == 'pop':
#continuation of a pop (or maybe this continuation means
#that it's too long to be a pop
if num_pop_blocks <= MAX_POP_RECORDS:
num_pop_blocks += 1
else:
# too long to be a pop
state = 'waiting'
num_sequential_pops = 0
else if state == 'silence':
#possible beginning of a pop
state = 'pop'
num_pop_blocks += 1
num_silence_blocks = 0
else:
#silence
if state = 'pop':
#we just transitioned from pop to silence
num_sequential_pops += 1
if num_sequential_pops == 5:
# we did it
state = 'waiting'
num_sequential_pops = 0
num_silence_blocks = 0
fivePopsCallback()
else if state = 'silence':
if num_silence_blocks >= MAX_SILENCE_BLOCKS:
#now we're just waiting
state = 'waiting'
num_silence_blocks = 0
num_sequential_pops = 0
该代码并不完整(可能有一两个错误),但说明了我的思路。它肯定比我希望的要复杂,这就是我寻求建议的原因。
【问题讨论】:
标签: python algorithm audio stream