#python
#python
Вопрос:
Я реализовал аналогичный метод, который можно увидеть в этом репозитории https://github.com/rraval/pied-piper/blob/master/decode.py
Моя проблема в том, что я не понимаю, как правильно анализировать следующий входящий аудиосигнал, который я воспроизводю и записываю на стороне приемника.
Это сигнал, который я сгенерировал программно, а затем добавил немного шума с помощью audacity. Этот аудиосигнал начинается с НАЧАЛЬНОГО сигнала с частотой 400 Гц и заканчивается тоном 500 Гц, между ними находятся тоны (в данном случае 8) с частотами от 10 кГц до 20 кГц, что довольно далеко от частот ЗАПУСКА / остановки.
Я хочу воспроизвести этот звук и записать его в приемник с помощью записи. Запись выполняется непрерывно до тех пор, пока не будет обнаружен START и не будет обнаружен STOP. Таким образом, приемник на самом деле не знает, когда начинается звук. Ранее мне удавалось декодировать файл wav, когда я напрямую считывал созданный мной файл wav, не записывая его.
Итак, как именно мне интерпретировать точный момент записи сигнала НАЧАЛЬНОЙ частоты, продолжать запись до тех пор, пока не будет записан стоп-сигнал, а затем получить массив nump или даже wav-файл, с которым я могу работать?
Некоторые значения, которые известны получателю:
Sampling Rate: 44100 Hz
Tone length: 0.1s (can be changed)
Silence (noise) length: 0.1s (can be changed)
START and END tone frequencies: i.e. 400 and 500 Hz
Эти значения указывают на размер окна в 4410 сэмплов, см. Расчет frame_rate ниже, где я пытался уменьшить окно до половины во время записи.
Перед началом и после завершения я добавил 0,5 секунды тишины (шума), чтобы audacity не отключал некоторые звуковые сэмплы
Я немного отладил, чтобы увидеть, когда и если я когда-нибудь введу фрагмент, в котором указана НАЧАЛЬНАЯ / конечная частота, но это очень ненадежно. Я думаю, что это просто чистая удача, поскольку вычисляется dominant_frequency .
Функция сопоставления имеет отклонение около 50 Гц, на всякий случай. Я записываю с помощью sounddevice.
stop_sync_freq = 500
start_sync_freq = 400
fs = 44100
tone_len = 0.1
silence_len = 0.1
def get_dominant_frequency(data_chunk):
w = np.fft.fft(data_chunk)
frequencies = np.fft.fftfreq(len(data_chunk))
peak_coeff = np.argmax(np.abs(w))
peak_freq = frequencies[peak_coeff]
return abs(peak_freq * fs
def record_audio():
# devices = sd.query_devices()
frame_rate = int(round(tone_len / 2 * fs))
in_window = False
audio_packet = []
while True:
data_input = sd.rec(frames=frame_rate, samplerate=fs, channels=1)
sd.wait()
if not data_input.size > 0:
continue
dominant_frequency = get_dominant_frequency(data_input)
print(dominant_frequency)
if in_window and match(dominant_frequency, stop_sync_freq):
# End - Stop freq
in_window = False
break
elif in_window:
audio_packet.append(dominant_frequency)
elif match(dominant_frequency, start_sync_freq):
# Start - Start freq
in_window = True
record_audio()
Комментарии:
1. Если волна всегда такая, как в вашем примере, проблема кажется «как начать запись, когда амплитуда больше нуля», что проще. В любом случае, использование записи для этой цели кажется немного сложным: то, что вы хотите сделать, это просто обрезать существующий файл. Почему бы не загрузить его в буфер и тихо изменить его размер оттуда?
2. @dspr Волна может быть длиннее, короче, но начало и конец всегда одинаковы. Амплитуда важных частей всегда около «1». Так что, я думаю, это может быть вариант проверить, когда это так, а затем отключить любую информацию до этого сценария, а затем то же самое в конце? Но тогда я не вижу смысла в синхронизации, если только я не хочу убедиться, что это действительно отправляемое сообщение, а не какой-то случайный окружающий звук, который вызвал запуск.
3. В конце, поскольку между звуками есть некоторые паузы, выполнение того, что для начала, невозможно. Если вы будете работать с буфером вместо своего рода потока, я бы предложил сделать то же самое, но в обратном направлении и начать с конца.
4. @dspr И просто для пояснения, я хочу явно отправить его по звуку и записать его с помощью микрофона, а не обрезать сам исходный файл, потому что это могут быть разные клиенты, которые это делают.
5. Ну, это намного сложнее, поскольку вы вынуждены работать в режиме реального времени. Теоретически для этого вам нужен обратный вызов из звуковой системы. В рамках этого обратного вызова вы должны проанализировать сигнал, начать захватывать все сэмплы в массиве, как только вы столкнулись с начальным сигналом, и пока не дойдете до конечного сигнала. После этого вы можете делать с захваченными данными все, что хотите.