语音识别与克隆算法(二)

简介: 语音识别与克隆算法(二)

基于音频指纹的音乐识别


说到音乐识别,相信很多小伙伴都很熟悉,比如酷狗音乐,QQ音乐,网易音乐,他们都有很多的功能,其中就有一个功能就有音乐识别。本届我们就来了解一下基于“音频指纹”的音乐识别系统。


03e2ae16beec758a4d8fc554109fd931_179f2e3b5b8347da84f6d4228826beb4.png


系统架构的核心模块包括信号采集,音频指纹(亦可称之为声纹)生成以及数据存储系统。其中,音频指纹生成苏算法的核心部分会采用傅里叶变换。


音频信号采集与播放

“听歌识曲”首先是“听”,然后才能“识”。“听”的过程,实际上就是一个音频采集(录音与采样)的过程。:识“的过程,是将采集到的音频片段与曲库中的歌曲数据进行比对来获取歌曲信息的过程。曲库中保存着大量的歌曲数据,包括歌曲名称,歌曲存储位置,歌曲声纹等信息。


在写代码之前,我们需要先进行安装模块pyaudio模块。


#音频信号采集与播放
import wave
import pyaudio
class SoundProcessing():
    def Record(self,CHUNK=44100,FORMAT=pyaudio.paInt16,CHANNELS=2,RATE=441100,
               RECORD_SECONDS=200,WAVE_OUTPUT_FILENAME="demoWave.wav"):
        p=pyaudio.PyAudio()
        stream=p.open(format=FORMAT,
                      channels=CHANNELS,
                      rate=RATE,
                      input=True,
                      frames_per_buffer=CHUNK)
        frames=[]
        for i in range(0,int(RATE/CHUNK*RECORD_SECONDS)):
            data=stream.read(CHUNK)
            frames.append(data)
        stream.stop_stream()
        stream.close()
        p.terminate()
        wf=wave.open(WAVE_OUTPUT_FILENAME,'wb')
        wf.setnchannels(CHANNELS)
        wf.setsampwidth(p.get_sample_size(FORMAT))
        wf.setframerate(RATE)
        wf.writeframes(b''.join(frames))
        wf.close()
    def Play(self,FILEPATH):
        chunk=1024
        wf=wave.open(FILEPATH,'rb')
        p=pyaudio.PyAudio()
        #打开声音输出流
        stream=p.open(format=p.get_format_from_width(wf.getsampwidth()),
                      channels=wf.getnchannels(),
                      raate=wf.getframerate(),
                      output=True)
        while True:
            data=wf.readframes(chunk)
            if data=="":
                break
            stream.write(data)
        stream.close()
        p.terminate()
if __name__=='__main__':
    snd=SoundProcessing() #类的实例化
    #录音并将其存储为demoWave.wav文件
    snd.Record(RECORD_SECONDS=30,WAVE_OUTPUT_FILENAME='demoWave.wav')
    snd.Play('demoWave.wav')


音频指纹生成


音频文件有很多格式,注入MP3,WAV,PCM等。其中,WAV格式是Microsoft公司研发的一种音频格式文件,它符合资源交换文件格式(Resource Interchange File Format,RIFF)规范,用于保存Windows操作系统的音频信息资源,beiWindows操作系统及其应用程序广泛支持。标准化的WAV文件采用44100采样率,16bit深度编码。WAV文件分为两个部分,第一个部分是WAV头文件,第二个部分是利用脉冲编码调制(Pulse Code Modulation,PCM)方式进行编码的音频数据。我们将以常见的WAV格式为例,来阐述如何生成音乐的音频指纹(声纹)。


从本质上来看,声音就是一种波。


我们用一个音频文件来描述其波形:


import wave
import matplotlib.pyplot as plt
import numpy as np
import os
waveFile=wave.open('./test.wav','rb')
params=waveFile.getparams()
nchannels,sampwidth,framerate,nframes=params[:4]
strData=waveFile.readframes(nframes)#读取音频文件并转为字符串格式
waveData=np.fromstring(strData,dtype=np.int16) #将字符串格式转化为int类型
waveData=waveData*1.0/(max(abs(waveData))) #wave幅值归一化
#音频波形可视化
time=np.arange(0,nframes)*(1.0/framerate)
waveData=np.arange(453632)
plt.plot(time,waveData)
plt.xlabel("Time(X)")
plt.ylabel("Amplitude(Y)")
plt.title("Single Channel Wave")
plt.grid("on")
plt.show()


8b8483846f9305f7d7474dc8be840e0f_ef4c132baacb46c192e9f74d09c847cf.png


音频波形文件是连续的模拟信号,经过采样可形成数字信号。对于一个单声道音频文件而言,经采样后,实际上就产生一个二维数组,每个元素是对应采样点的数值。对于我们普通人来说,我们该如何去实现听歌识曲?那就是背歌词,只要听到某一句或者多句歌词,就会记起来,但是对于像博主我记忆力不好的人而言,记住很多歌曲是不现实的,所以,我们就要采用其他的方式。那就是利用计算机来记住音频信号序列。声音属于时域信号,我们需要将其转化为频域信号以便后续的信号处理。以下示例代码,通过傅里叶变换将音频时域信号转换为频域信号。


import wave
import matplotlib.pyplot as plt
import numpy as np
import os
waveFile=wave.open('./test.wav','rb')
params=waveFile.getparams()
nchannels,sampwidth,framerate,nframes=params[:4]
strData=waveFile.readframes(nframes)#读取音频文件并转为字符串格式
waveData=np.fromstring(strData,dtype=np.int16) #将字符串格式转化为int类型
waveData=waveData*1.0/(max(abs(waveData))) #wave幅值归一化
#音频波形可视化
time=np.arange(0,nframes)*(1.0/framerate)
#waveData=np.arange(453632)
df=1
freq=[df*n for n in range(0,len(waveData))]
c=np.fft.fft(waveData)
plt.plot(freq,abs(c),color='blue')
plt.xlabel("Frequency(Hz)")
plt.ylabel("Amplitude(Y)")
plt.title("Frequency Domain Signal")
plt.grid(True)
plt.show()


4db5538edb4bc7dbefb2663f87127fe1_6255c67994c148d5a2da1c00cf22ec25.png



音频信号经傅里叶变换之后,原本x,y轴分别为时间和波幅,现在则是频率以及频率幅值,与此同时,也改变了我们对音频构成的理解。


对每一帧音频信号进行傅里叶变换后,就可以开始构造声纹了,这就是整个系统中最核心的部分。构造声纹的最大挑战就是在于如何从众多的频率中选出区分都最大的频率分量。直观上看,选择具有最大幅值的频率(峰值)较为可靠。由于一首音乐的频率分布跨度太大,所以分析的时候会存在难以选择,为了避免分析整个频谱,我们通常将频谱分成多个子带,从每个子带中选择一个频率峰值。低子音带为30Hz~40Hz,40~80Hz和80~120Hz,中音和高音子带分别为120Hz~180Hz和180Hz~300Hz(人声和大部分乐器的基频出现在这俩个子带)。每个子带的最大频率就构成了这一帧信号的签名,这也就是我们最核心的“音频指纹”。


音频文件载入,音频指纹生成功能的实现示例代码:


import numpy as np
import os
import wave
class SoundProcessing():
    SongName=""
    document=[] #存放歌曲指纹列表
    def DataLoad(self,FILEPATH):
        filename_list=os.listdir(FILEPATH)
        for filename in filename_list:
            if filename.endswith('wav'):  #检查文件是否是wav格式
                SoundProcessing.SongName=filename
                f=wave.open(FILEPATH+"\\"+filename,'rb')
                params=f.getparams()
                self.nchannels,self.sampwidth,self.framerate,self.nframes=params[:4]
                str_data=f.readframes(self.nframes)
                self.wave_data=np.fromstring(str_data,dtype=np.short)
                self.wave_data.shape=-1,self.sampwidth
                self.wave_data=self.wave_data.T
                self.GenerateFingerPrint()
                self.name=os.path.basename('./test1.wav')
                return True
        f.close()
    def GenerateFingerPrint(self,frames=40):
        block=[]
        fft_blocks=[]
        self.high_point=[]  #用于保存生成的音频指纹
        blocks_size=self.framerate//frames
        blocks_num=self.nframes/blocks_size
        for i in range(0,len(self.wave_data[0])-blocks_size,blocks_size):
            block.append(self.wave_data[0][i:i+blocks_size])
            fft_blocks.append(np.abs(np.fft.fft(self.wave_data[0][i:i+blocks_size])))
        self.high_point.append((np.argmax(fft_blocks[-1][0:40]),np.argmax(fft_blocks[-1][40:80])+40,
                                np.argmax(fft_blocks[-1][80:120])+40,
                                np.argmax(fft_blocks[-1][120:180])+120,))
        song_fp="{'songname'"+":'"+SoundProcessing.SongName+"','fingerprint'"+":"+str(self.high_point[20:25])+"}"
        song_fp=eval(song_fp)
        SoundProcessing.document.append(song_fp)
        print (SoundProcessing.document)
if __name__=="__main__":
    a=SoundProcessing()
    a.DataLoad('F:\人工智能算法')
    a.GenerateFingerPrint(frames=40)


结果展示:


[{'songname': 'test.wav', 'fingerprint': []}] [{'songname': 'test.wav', 'fingerprint': []}, {'songname': 'test.wav', 'fingerprint': []}]


在构造指纹的时候,我们需要注意的是,用户所除的环境的复杂,所以录制的音乐可能会有所杂音,于是,我建议在使用音频指纹的时候引入模糊化操作等手段来提高算法的抗噪能力。否则会影响最终检索质量。


语音克隆技术简介


语音合成,是指文本到音频的人工转换,或给定一段文字让计算机自动生成对应的人类读音。通过AI语音技术,在极短的时间内“克隆”出目标人物的声音。相信喜欢看碟战片的小伙伴比较了解,里面各个国家的特工,利用语音合成,模仿别人的声音,获取情报。在计算机技术发展迅速的今天,这些都已经能够实现。


合成自然语音,需要对大量高质量的语音转录进行训练。若要支持多人语音通常需要对每个人的语音数据集进行数十分钟的训练,而为多人记录大量高质量的数据不太现实。该项目所采用的方法是,通过独立训练一个捕捉说话人特征空间(Space of Speaker Characterstics)语音识别嵌入网络(Speaker-Descriminative Embedding Network),并在一个较小的数据集上训练一个高质量的TTS模型,从而将说话人建模与语音合成分离。解耦合网络使他们能够在独立的数据上进行训练,从而减少获得高质量多峰训练数据的需要。


该语音克隆系统由3个独立训练的神经网络组成。如图:


7884e9fa8a8eb866de5a313b253fce5d_f89b23087aac434abec07635922fb45f.png


1.说话人语音编码器(Speaker Encoder)


它先从说话人那里获取一段参考语音信号(Speaker Reference Waveform),亦即说话人的音频小样本,然后从中计算出一个固定维矢量(Fixed Dimensional Vector)。


2.序列合成器(Synthesizer)


它基于说话人嵌入矢量,根据一系列字素(Grapheme)或音素输入,预测出一个对数梅尔频谱(Log-Mel Spectrum)。也就是给定一段文本,将其编码为向量表示,然后,将语音与文本这两个向量结合起来解码成声谱图(Spectrogram)。


3.声码器(Vocoder)


它将对数梅尔频谱转换成时域波形(Waveform)。也就是将声谱图转换成我们可以听到的音频波形。


由于博主对机器学习知识还不掌握,这里只能稍做介绍。语音篇的学习就到此结束了,后面就是自然语言处理技术的分享。期待大家的关注,点赞,收藏。

相关实践学习
达摩院智能语音交互 - 声纹识别技术
声纹识别是基于每个发音人的发音器官构造不同,识别当前发音人的身份。按照任务具体分为两种: 声纹辨认:从说话人集合中判别出测试语音所属的说话人,为多选一的问题 声纹确认:判断测试语音是否由目标说话人所说,是二选一的问题(是或者不是) 按照应用具体分为两种: 文本相关:要求使用者重复指定的话语,通常包含与训练信息相同的文本(精度较高,适合当前应用模式) 文本无关:对使用者发音内容和语言没有要求,受信道环境影响比较大,精度不高 本课程主要介绍声纹识别的原型技术、系统架构及应用案例等。 讲师介绍: 郑斯奇,达摩院算法专家,毕业于美国哈佛大学,研究方向包括声纹识别、性别、年龄、语种识别等。致力于推动端侧声纹与个性化技术的研究和大规模应用。
相关文章
|
3月前
|
机器学习/深度学习 算法 TensorFlow
【深度学习】深度学习语音识别算法的详细解析
深度学习语音识别算法是一种基于人工神经网络的语音识别技术,其核心在于利用深度神经网络(Deep Neural Network,DNN)自动从语音信号中学习有意义的特征,并生成高效的语音识别模型。以下是对深度学习语音识别算法的详细解析
95 5
|
3月前
|
机器学习/深度学习 人工智能 算法
【语音识别算法】深度学习语音识别算法与传统语音识别算法的区别、对比及联系
深度学习语音识别算法与传统语音识别算法在理论基础、实现方式、性能表现等方面存在显著区别,同时也有一些联系。下面将从几个方面详细比较这两种方法,并给出应用实例和代码示例
39 4
|
3月前
|
机器学习/深度学习 人工智能 算法
【人工智能】传统语音识别算法概述,应用场景,项目实践及案例分析,附带代码示例
传统语音识别算法是将语音信号转化为文本形式的技术,它主要基于模式识别理论和数学统计学方法。以下是传统语音识别算法的基本概述
70 2
|
4月前
|
机器学习/深度学习 算法 数据可视化
Python基于librosa和人工神经网络实现语音识别分类模型(ANN算法)项目实战
Python基于librosa和人工神经网络实现语音识别分类模型(ANN算法)项目实战
|
7天前
|
算法 安全 数据安全/隐私保护
基于game-based算法的动态频谱访问matlab仿真
本算法展示了在认知无线电网络中,通过游戏理论优化动态频谱访问,提高频谱利用率和物理层安全性。程序运行效果包括负载因子、传输功率、信噪比对用户效用和保密率的影响分析。软件版本:Matlab 2022a。完整代码包含详细中文注释和操作视频。
|
25天前
|
机器学习/深度学习 算法 数据安全/隐私保护
基于MSER和HOG特征提取的SVM交通标志检测和识别算法matlab仿真
### 算法简介 1. **算法运行效果图预览**:展示算法效果,完整程序运行后无水印。 2. **算法运行软件版本**:Matlab 2017b。 3. **部分核心程序**:完整版代码包含中文注释及操作步骤视频。 4. **算法理论概述**: - **MSER**:用于检测显著区域,提取图像中稳定区域,适用于光照变化下的交通标志检测。 - **HOG特征提取**:通过计算图像小区域的梯度直方图捕捉局部纹理信息,用于物体检测。 - **SVM**:寻找最大化间隔的超平面以分类样本。 整个算法流程图见下图。
|
4天前
|
人工智能 算法 数据安全/隐私保护
基于遗传优化的SVD水印嵌入提取算法matlab仿真
该算法基于遗传优化的SVD水印嵌入与提取技术,通过遗传算法优化水印嵌入参数,提高水印的鲁棒性和隐蔽性。在MATLAB2022a环境下测试,展示了优化前后的性能对比及不同干扰下的水印提取效果。核心程序实现了SVD分解、遗传算法流程及其参数优化,有效提升了水印技术的应用价值。
|
5天前
|
机器学习/深度学习 算法 数据安全/隐私保护
基于贝叶斯优化CNN-LSTM网络的数据分类识别算法matlab仿真
本项目展示了基于贝叶斯优化(BO)的CNN-LSTM网络在数据分类中的应用。通过MATLAB 2022a实现,优化前后效果对比明显。核心代码附带中文注释和操作视频,涵盖BO、CNN、LSTM理论,特别是BO优化CNN-LSTM网络的batchsize和学习率,显著提升模型性能。
|
10天前
|
存储
基于遗传算法的智能天线最佳阵列因子计算matlab仿真
本课题探讨基于遗传算法优化智能天线阵列因子,以提升无线通信系统性能,包括信号质量、干扰抑制及定位精度。通过MATLAB2022a实现的核心程序,展示了遗传算法在寻找最优阵列因子上的应用,显著改善了天线接收功率。
|
12天前
|
监控 算法 数据安全/隐私保护
基于三帧差算法的运动目标检测系统FPGA实现,包含testbench和MATLAB辅助验证程序
本项目展示了基于FPGA与MATLAB实现的三帧差算法运动目标检测。使用Vivado 2019.2和MATLAB 2022a开发环境,通过对比连续三帧图像的像素值变化,有效识别运动区域。项目包括完整无水印的运行效果预览、详细中文注释的代码及操作步骤视频,适合学习和研究。

热门文章

最新文章