Укажите минимальную частоту запуска для записи звука на Python

#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. Предложенный алгоритм не будет работать для обнаружения резких пиков, как в этом примере. Есть и другие методы, но теперь мы выходим далеко за рамки первоначального вопроса. Вы можете открыть новую запись, прикрепить ссылку на эту запись, построить спектр и показать, что вы хотели бы обнаружить. Код, предложенный здесь, работает, но для разных задач, где энергия находится на более высоких концах спектра.