Te enseñará a jugar con archivos de sonido con Python y a cortar el sonido en fragmentos de acuerdo con la brecha del habla.

Hay muchas señales de sonido en la vida real. En la sociedad actual de explosión de la información, es muy importante extraer señales de sonido útiles. Cuando recolectamos un fragmento de señal de sonido, a veces es necesario separar cada oración de este sonido para su análisis y extraer la información sonora que necesitamos. A continuación se muestra una forma de cortar de forma eficaz una gran parte del sonido.

Primero, necesitamos importar el paquete de biblioteca de recursos requerido.

Importar biblioteca de recursos

Descargar archivo de sonido: pip install soundfile
Inserte la descripción de la imagen aquí
volver a intentar descargar:pip install retry
Inserte la descripción de la imagen aquí

Leer archivos de audio para observar la forma de onda del sonido

import matplotlib.pyplot as plt
import soundfile as sf

musicFileName = '8_Channel_ID.wav'
sig, sample_rate = sf.read(musicFileName)
print("采样率:%d" % sample_rate)
print("时长:", sig.shape[0]/sample_rate, '秒')

# 声音有两个通道
serviceData = sig.T[0]
clientData = sig.T[1]

plt.rcParams['figure.figsize'] = (20, 5) # 设置figure_size尺寸
plt.figure()
l=sig.shape[0]
x = [i/8000 for i in range(l)]
plt.plot(x, serviceData, c='b')
plt.show()

Información de sonido tomada:
Inserte la descripción de la imagen aquí
la forma de onda del sonido:
Inserte la descripción de la imagen aquí

Definición de tres parámetros

De hecho, después de leer el archivo de sonido, se convierte en un vector. De hecho, es el procesamiento del vector. Se puede ver que la forma de onda del sonido fluctúa y hay una cierta brecha entre cada oración, y todavía hay una cierta cantidad de ruido en la brecha de sonido. . Para completar el corte, se establecen tres parámetros:

  1. voiceMinValue: Volumen mínimo, menos de este valor se considera ruido
  2. voiceMaxDistanceSecond: Incrementa el intervalo de tiempo entre dos oraciones, si es mayor que este valor, se considera como dos oraciones, en caso contrario se considera como una sola oración.
  3. voiceMinSecond: La duración mínima de un solo audio, menos de este valor se considera ruido

Valor inicial de la clase

Los tres parámetros anteriores, más el nombre del archivo de audio y la ruta de salida del archivo, constituyen el valor inicial de la clase.

class Voicesplit(object):
    def __init__(self, musicFileName, outFilePath):
        # 音频文件名称
        self.musicFileName = musicFileName
        # 文件输出路径
        self.outFilePath = outFilePath
        # 最小音量
        self.voiceMinValue = 0.01
        # 两句话之间最大时间间隔(秒)
        self.voiceMaxDistanceSecond = 0.1
        # 单个音频最小时间长度(秒)
        self.voiceMinSecond = 0.1

Utilice estos tres parámetros clave para cortar el sonido

# 分割声音,分段保存
    def splitVoiceAndSave(self):
        sig, self.sample_rate = sf.read(self.musicFileName)
        print('正在读取文件:%s' % musicFileName)
        print("采样率:%d" % self.sample_rate)
        print("时长:%s" % (sig.shape[0] / self.sample_rate), '秒')

        # 我的音频文件有两个通道,这里读取第一个通道,你需要根据你的音频文件是否是双通道,进行修改
        inputData = sig.T[0]

        dd = {
    
    }
        for k, v in tqdm(enumerate(inputData)):
            if abs(v) < self.voiceMinValue:
                dd[k] = 0
            else:
                dd[k] = v

        x = [i / self.sample_rate for i in range(len(inputData))]
        y = list(dd.values())

        # 删除空白部分
        for key in list(dd):
            if dd[key] == 0:
                dd.pop(key)

        # 判断声音间隔
        voiceSignalTime = list(dd.keys())
        list1 = []
        list2 = []
        for k, v in enumerate(voiceSignalTime[:-2]):
            list2.append(v)
            if voiceSignalTime[k + 1] - v > self.voiceMaxDistanceSecond * self.sample_rate:
                list1.append(list2)
                list2 = []

        if len(list1) == 0:
            list1.append(list2)

        if len(list1) > 0 and (
                voiceSignalTime[-1] - voiceSignalTime[-2]) < self.voiceMaxDistanceSecond * self.sample_rate:
            list1[-1].append(voiceSignalTime[-2])

        voiceTimeList = [x for x in list1 if len(x) > self.voiceMinSecond * self.sample_rate]
        print('分解出声音片段:', len(voiceTimeList))

        for voiceTime in voiceTimeList:
            voiceTime1 = int(max(0, voiceTime[0] - 0.8 * self.sample_rate))
            voiceTime2 = int(min(sig.shape[0], voiceTime[-1] + 0.8 * self.sample_rate))
            self.wavWriteByTime(musicFileName=self.musicFileName, outData=inputData, voiceTime1=voiceTime1, voiceTime2=voiceTime2)

Guarde el clip de sonido cortado

# wav文件写入,分时间间隔
def wavWriteByTime(self, musicFileName, outData, voiceTime1, voiceTime2):
    outData = outData[voiceTime1:voiceTime2]
    fileAbsoluteName = os.path.splitext(os.path.split(musicFileName)[-1])[0]
    fileSavePath = os.path.join(self.outFilePath, fileAbsoluteName)

    if not os.path.exists(fileSavePath):
        os.makedirs(fileSavePath)

    outfile = os.path.join(fileSavePath,os.path.splitext(os.path.split(musicFileName)[-1])[0] + '_%d_%d_%s_split.wav' % (voiceTime1, voiceTime2, self.sample_rate))


    # 判断文件是否存在
    if not os.path.exists(outfile):
        print('正在生成文件:', outfile)
        with wave.open(outfile, 'wb') as outwave:  # 定义存储路径以及文件名
            nchannels = 1
            sampwidth = 2
            fs = 8000
            data_size = len(outData)
            framerate = int(fs)
            nframes = data_size
            comptype = "NONE"
            compname = "not compressed"
            outwave.setparams((nchannels, sampwidth, framerate, nframes, comptype, compname))
            for v in outData:
                outwave.writeframes(struct.pack('h', int(v * 64000 / 2)))

Resultado de segmentación de sonido

El segmento de sonido final de mi archivo de sonido es 1. El archivo de sonido específico se puede obtener de acuerdo con su propia información.
Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/ywsydwsbn/article/details/107699470
Recomendado
Clasificación