фильтр нижних частот обнаружил аудиопоток и записал отфильтрованные данные в аудиофайл - PullRequest
0 голосов
/ 19 мая 2019

Я пытаюсь обнаружить звук с микрофона ноутбука. Как только звук обнаружен, код должен начать запись входного звука в течение следующих 10 секунд. После этого я должен пропустить эти данные через фильтр нижних частот с последующей дискретизацией (по порядку 2). Далее, сигнал пониженной дискретизации должен быть сохранен как аудиофайл (. WAV формат).

после записи в течение 10 секунд я получаю данные в переменную с именем 'data', а тип - массив. Далее я передаю данные через функцию фильтра нижних частот с именем lowpass () Эта функция возвращает вывод в виде типа 'numpy.ndarray' Я не могу записать этот вывод как аудиофайл с помощью функции writeframes () даже после преобразования типа со следующим синтаксисом:

data = data.tobytes()

from array import array
from struct import pack
from sys import byteorder
from email import encoders
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import copy
import pyaudio
import wave
import email, smtplib, ssl
import scipy.io.wavfile as wav
import matplotlib.pyplot as plt
from scipy.signal import butter, lfilter, freqz
import numpy as np
from datetime import datetime, time

THRESHOLD = 500
CHUNK_SIZE = 1024
FORMAT = pyaudio.paInt16
FRAME_MAX_VALUE = 2 ** 15 - 1
NORMALIZE_MINUS_ONE_dB = 10 ** (-1.0 / 20)
RATE = 44100
CHANNELS = 1
cutoff = 10000
ts_start = 0
ts_end = 0

def is_silent(data_chunk):
    """Returns 'True' if below the 'silent' threshold"""
    return max(data_chunk) < THRESHOLD

def normalize(data_all):
    """Amplify the volume out to max -1dB"""
    normalize_factor = (float(NORMALIZE_MINUS_ONE_dB * FRAME_MAX_VALUE)/ max(abs(i) for i in data_all))

    r = array('h')
    for i in data_all:
        r.append(int(i * normalize_factor))
    return r

def recordTenSec():
    """Record a word or words from the microphone and 
    return the data as an array of signed shorts."""

    p = pyaudio.PyAudio()
    stream = p.open(format=FORMAT, channels=CHANNELS, 
    rate=RATE, input=True, output=True, frames_per_buffer=CHUNK_SIZE)

    silent_chunks = 0
    audio_started = False
    data_all = array('h')

    while True:
        global ts_start #global variable
        global ts_end   #global variable
        # little endian, signed short
        data_chunk = array('h', stream.read(CHUNK_SIZE))
        if byteorder == 'big':
            data_chunk.byteswap()
            data_all.extend(data_chunk)

            silent = is_silent(data_chunk)

            if audio_started:
                if ts_start == 0:
                    del data_all[:] #used to remove all elements from array before starting actual recording
                    ts_start = datetime.now()
                elif ts_start != 0:
                    ts_end = datetime.now()
                    x = date_diff_in_Seconds(ts_end, ts_start)
                    if int(x) >= 10:
                        break
            elif not silent:
                audio_started = True              

        sample_width = p.get_sample_size(FORMAT)
        stream.stop_stream()
        stream.close()
        p.terminate()

    data_all = normalize(data_all)
    return sample_width, data_all

def record_audio_file(path):
    "Records from the microphone and outputs the resulting data to 'path'"
    sample_width, data = recordTenSec()
    print(type(data))
    data, b, a = lowpass(data, cutoff, RATE, order=5)

    data = data[::2]
    data = data.tobytes()
    #data = pack('<' + ('h' * len(data)), *data)

    print(type(data))
    wave_file = wave.open(path, 'wb')
    wave_file.setnchannels(CHANNELS)
    wave_file.setsampwidth(sample_width)
    wave_file.setframerate(RATE)
    wave_file.writeframes(data)
    wave_file.close()

    def lowpass(data, cutoff, fs, order=5):
        nyq = 0.5 * fs
        normal_cutoff = cutoff / nyq
        b, a = butter(order, normal_cutoff, btype='low', analog=False)
        y = lfilter(b, a, data)
        return y, b, a

def date_diff_in_Seconds(dt2, dt1):
    timedelta = dt2 - dt1
    return timedelta.days * 24 * 3600 + timedelta.seconds


if __name__ == '__main__':
    print("Wait in silence to begin recording;we are recording 10 sec long audio clip")
    record_audio_file('MyRecording.wav')
    print("done - result written to MyRecording.wav")

С этим кодом файл сгенерирован успешно, но у него нет звука. Это пустой файл. В идеале он должен воспроизводить звук

...