我想制作一个会说话的嘴巴,当播放的 wav 文件发出声音时,它会移动或发出光或其他东西。所以我需要检测 wav 文件何时说话或何时在单词之间保持沉默。目前我正在使用我找到的 pygame 脚本
import pygame
pygame.mixer.init()
pygame.mixer.music.load("my_sentence.wav")
pygame.mixer.music.play()
while pygame.mixer.music.get_busy() == True:
continue
我想我可以在 while 循环中进行一些检查以查看声音输出电平或类似的东西,然后将其发送到 gpio 输出之一。但我不知道如何实现。
任何帮助将不胜感激
最佳答案
您需要检查 WAV 文件才能确定语音何时出现。最简单的方法是寻找嘈杂和安静的时段。因为声音与波形一起工作,所以当它很安静时,波形文件中的值不会发生太大变化,而当声音很大时,它们会发生很大变化。
估计响度的一种方法是 variance .正如您在文章中看到的,这可以定义为 E[(X - mu)^2]
,可以写成 average((X - average(X))^2 )
。这里,X 是给定点的信号值(存储在 WAV 文件中的值,在代码中称为 sample
)。如果它变化很大,方差就会很大。
这可以让您计算整个文件的响度。但是,您想跟踪文件在任何给定时间的音量,这意味着您需要一种 moving average 的形式.一个简单的方法是使用 first-order low-pass filter .
我没有测试下面的代码,所以它不太可能工作,但它应该能让你开始。它加载 WAV 文件,使用低通滤波器来跟踪均值和方差,并在方差高于和低于特定阈值时进行计算。然后,在播放 WAV 文件时,它会跟踪自开始播放以来的时间,并打印出 WAV 文件是大声还是安静。
以下是您可能还需要做的事情:
- 修正我在代码中所有故意的错误
- 添加一些有用的东西来对大声/安静的变化使用react
- 更改阈值和 react 时间以获得良好的音频效果
- 添加一些 hysteresis (可变阈值)停止光闪烁
希望对您有所帮助!
import wave
import struct
import time
def get_loud_times(wav_path, threshold=10000, time_constant=0.1):
'''Work out which parts of a WAV file are loud.
- threshold: the variance threshold that is considered loud
- time_constant: the approximate reaction time in seconds'''
wav = wave.open(wav_path, 'r')
length = wav.getnframes()
samplerate = wav.getframerate()
assert wav.getnchannels() == 1, 'wav must be mono'
assert wav.getsampwidth() == 2, 'wav must be 16-bit'
# Our result will be a list of (time, is_loud) giving the times when
# when the audio switches from loud to quiet and back.
is_loud = False
result = [(0., is_loud)]
# The following values track the mean and variance of the signal.
# When the variance is large, the audio is loud.
mean = 0
variance = 0
# If alpha is small, mean and variance change slower but are less noisy.
alpha = 1 / (time_constant * float(sample_rate))
for i in range(length):
sample_time = float(i) / samplerate
sample = struct.unpack('<h', wav.readframes(1))
# mean is the average value of sample
mean = (1-alpha) * mean + alpha * sample
# variance is the average value of (sample - mean) ** 2
variance = (1-alpha) * variance + alpha * (sample - mean) ** 2
# check if we're loud, and record the time if this changes
new_is_loud = variance > threshold
if is_loud != new_is_loud:
result.append((sample_time, new_is_loud))
is_loud = new_is_loud
return result
def play_sentence(wav_path):
loud_times = get_loud_times(wav_path)
pygame.mixer.music.load(wav_path)
start_time = time.time()
pygame.mixer.music.play()
for (t, is_loud) in loud_times:
# wait until the time described by this entry
sleep_time = start_time + t - time.time()
if sleep_time > 0:
time.sleep(sleep_time)
# do whatever
print 'loud' if is_loud else 'quiet'
关于python - 获取播放 wav 音频级别作为输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30571955/