#python #audio #triggers
Вопрос:
Я пишу сценарий для записи с активацией звука на Python с помощью pyaudio. Я хочу запустить запись 5 секунд после звука, который превышает заданную громкость и частоту. Мне удалось заставить часть громкости работать, но я не знаю, как указать минимальную частоту срабатывания (я бы хотел, чтобы она срабатывала на частотах выше 10 кГц, например).:
import pyaudio
import wave
from array import array
import time
FORMAT=pyaudio.paInt16
CHANNELS=1
RATE=44100
CHUNK=1024
RECORD_SECONDS=5
audio=pyaudio.PyAudio()
stream=audio.open(format=FORMAT,channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK)
nighttime=True
while nighttime:
data=stream.read(CHUNK)
data_chunk=array('h',data)
vol=max(data_chunk)
if(vol>=3000):
print("recording triggered")
frames=[]
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK)
frames.append(data)
print("recording saved")
# write to file
words = ["RECORDING-", time.strftime("%Y%m%d-%H%M%S"), ".wav"]
FILE_NAME= "".join(words)
wavfile=wave.open(FILE_NAME,'wb')
wavfile.setnchannels(CHANNELS)
wavfile.setsampwidth(audio.get_sample_size(FORMAT))
wavfile.setframerate(RATE)
wavfile.writeframes(b''.join(frames))
wavfile.close()
# check if still nighttime
nighttime=True
stream.stop_stream()
stream.close()
audio.terminate()
Я хотел бы добавить в строку if(vol>=3000):
что-то вроде if(vol>=3000 and frequency>10000):
, но я не знаю, как это настроить frequency
. Как это сделать?
Комментарии:
1. Я надеюсь, что наш чат объяснил все предостережения. По сути: найдите пик выше 10 кГц и / или фильтр высоких частот. Полный код для поиска пиков частот: github.com/tracek/audio-explorer/blob/master/audioexplorer/… (вероятно, вы найдете более интересный код). Примите ответ, если он был полезен.
Ответ №1:
Чтобы получить частоту сигнала, вы можете вычислить преобразование Фурье, переключившись таким образом в частотную область ( freq
в коде). Ваш следующий шаг-вычислить относительную амплитуду сигнала ( amp
) . Последнее пропорционально громкости звука.
spec = np.abs(np.fft.rfft(audio_array))
freq = np.fft.rfftfreq(len(audio_array), d=1 / sampling_freq)
spec = np.abs(spec)
amp = spec / spec.sum()
Имейте в виду, что 3000
это тоже не громкость звука. Информация об истинной громкости звука была потеряна при оцифровке сигнала. Теперь вы работаете только с относительными числами, поэтому вы можете просто проверить, например, превышает ли 1/3 энергии в кадре 10 кГц.
Вот несколько кодов, иллюстрирующих эту концепцию:
idx_above_10khz = np.argmax(freq > 10000)
amp_below_10k = amp[:idx_above_10khz].sum()
amp_above_10k = amp[idx_above_10khz:].sum()
Теперь вы можете указать, что из определенного соотношения amp_below_10k / amp_above_10k
вы должны запускать свою программу.
Комментарии:
1. Отлично, спасибо! Как мне включить это в
if
инструкцию, чтобы запустить запись?if(vol>=3000 and max(freq) > threshold):
? Могу ли я использоватьamp
, чтобы указать, что он также должен превышать определенную амплитуду?if(vol>=3000 and max(freq) > threshold and amp > threshold2):
2. Также что такое
X
?3. @Thomas
X
был артефактом от переименования переменных, теперь исправлен. Вы должны окончательно использоватьamp
, так как это в сочетании сfreq
позволит вам определить, есть ли достаточно значительный сигнал около 10 кз.vol
дает вам общую мощность сигнала и ничего не говорит о том , как он распределен в спектре.4. Отлично, спасибо. Все это выглядит хорошо, но я не могу заставить это работать — см. Правку выше. Верен ли мой код?
5. @Thomas Файл 12 кГц содержит почти всю энергию в нижних концах spetrum. Предложенный алгоритм не будет работать для обнаружения резких пиков, как в этом примере. Есть и другие методы, но теперь мы выходим далеко за рамки первоначального вопроса. Вы можете открыть новую запись, прикрепить ссылку на эту запись, построить спектр и показать, что вы хотели бы обнаружить. Код, предложенный здесь, работает, но для разных задач, где энергия находится на более высоких концах спектра.