Ensina-lhe como brincar com arquivos de som com Python e cortar o som em fragmentos de acordo com a lacuna da fala

Existem muitos sinais sonoros na vida real. Na sociedade atual da explosão da informação, é muito importante extrair sinais sonoros úteis. Quando coletamos um pedaço de sinal sonoro, às vezes é necessário separar cada frase desse som para análise para extrair as informações sonoras de que precisamos. Esta é uma maneira de cortar efetivamente uma grande parte do som.

Primeiro, precisamos importar o pacote de biblioteca de recursos necessário.

Importar biblioteca de recursos

Baixar arquivo de som: pip install soundfile
Insira a descrição da imagem aqui
nova tentativa de download:pip install retry
Insira a descrição da imagem aqui

Leia os arquivos de áudio para observar a forma de onda do som

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()

Informações de som obtidas:
Insira a descrição da imagem aqui
a forma de onda do som:
Insira a descrição da imagem aqui

Definição de três parâmetros

Na verdade, depois de ler o arquivo de som, ele se torna um vetor. Na verdade, é o processamento do vetor. Pode-se ver que a forma de onda do som flutua e há um certo intervalo entre cada frase, e ainda há um certo ruído no intervalo do som . Para concluir o corte, três parâmetros são definidos:

  1. voiceMinValue: Volume mínimo, menos do que este valor é julgado como ruído
  2. voiceMaxDistanceSecond: Aumenta o intervalo de tempo entre duas frases, se for maior que este valor é considerado como duas frases, caso contrário é considerado como uma frase
  3. voiceMinSecond: O tempo mínimo de duração de um único áudio, menor do que este valor é considerado ruído

Valor inicial da aula

Os três parâmetros acima, mais o nome do arquivo de áudio e o caminho de saída do arquivo, constituem o valor inicial da classe

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

Use estes três parâmetros principais para corte de som

# 分割声音,分段保存
    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)

Salve o clipe de som 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 segmentação de som

O segmento final de som do meu arquivo de som é 1. O arquivo de som específico pode ser obtido de acordo com suas próprias informações.
Insira a descrição da imagem aqui
Insira a descrição da imagem aqui

Acho que você gosta

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