получить звуковой уровень воспроизведения wav в качестве выходного

Я хочу сделать говорящий рот, который движется или излучает свет или что-то, когда воспроизводимый 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, чтобы он работал, когда голос присутствует. Самый простой способ сделать это – искать громкие и спокойные периоды. Поскольку звук работает с волнами, когда он тихий, значения в волновом файле не будут сильно меняться, и когда он громкий, они будут сильно меняться.

Одним из способов оценки громкости является дисперсия . Как вы можете видеть статью, это можно определить как E[(X - mu)^2] , которое можно было бы записать в average((X - average(X))^2) . Здесь X – это значение сигнала в данной точке (значения, хранящиеся в WAV-файле, называемые sample в коде). Если он сильно изменится, дисперсия будет большой.

Это позволит рассчитать громкость всего файла. Тем не менее, вы хотите отслеживать, насколько громким является файл в любой момент времени, что означает, что вам нужна форма скользящей средней . Легкий способ получить это с фильтром нижних частот первого порядка .

Я не тестировал код ниже, поэтому он вряд ли сработает, но он должен вас начать. Он загружает WAV-файл, использует фильтры нижних частот для отслеживания среднего и дисперсии и работает, когда дисперсия идет выше и ниже определенного порога. Затем, во время воспроизведения WAV-файла, он отслеживает время с момента начала воспроизведения и выводит, является ли WAV-файл громким или тихим.

Вот что вам еще нужно сделать:

  • Исправьте все мои преднамеренные ошибки в коде
  • Добавьте что-то полезное, чтобы реагировать на громкие / тихие изменения
  • Измените порог и реакцию_time, чтобы получить хорошие результаты с вашим звуком
  • Добавьте некоторый гистерезис (переменный порог), чтобы остановить мерцание света

Надеюсь, это поможет!

 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'