基于自动编码器VAE的声音生成之音频预处理模块preprocess pipeline的实现和代码讲解

news2024/11/26 10:26:45

文章目录

    • 概述
    • Preprocessline模块实现以及代码讲解
      • Loader模块
      • Padder模块
      • LogSpectrogramExtractor模块
      • MinMaxNormaliser模块
      • Saver模块
      • PreprocessPipeLine模块
        • 知识补充
          • property修饰词
    • 总结

概述

  • 这部分是将原来基于mnist手写数据集生成模型,一个用到基于FSDD音频数据集的声音生成模型的关键。二者差别,就在于多了这一步。
  • 通过这一步,将音频文件转为频谱图,所以,后半部分生成图片的就可以重复利用了,这部分是关键。
  • 具体流程如下图,就是多了前后的预处理这部分。

在这里插入图片描述

Preprocessline模块实现以及代码讲解

  • 这部分需要一些基础知识,需要自己学一下,这里也会做相关介绍:
    • 总的课程笔记
    • 快速理解短时傅立叶变换
    • 理解声音密度、强度和音色等基础声音特征

省流,直接看流程图
在这里插入图片描述

预处理流程

  • 在代码中,作者将预处理分成了几个模块,并且每一个模块都负责一个功能,然后再用一个preprocess类,按照需求将各个模块进行组装。
  • 具体功能如下
    • Loader模块:负责读取音频文件,并返回对应的信号序列
    • Padder模块:对信号的进行补充,确保每一个信号的长度都是统一长度相同
    • LogSpectrogramExtractor模块:从数据序列中,提取出对应的频谱数据,并返回
    • MinMaxNormaliser模块:正则化模块,对频谱数据,按照要求,将之隐射到对应的范围之内
    • Saver模块:保存模块,将数据进行保存,主要保存两种特征,分别如下
      • 数据的最值,这个是用来进行数据恢复的,因为数据还需要从正则化之后的数据恢复到原来的数据
      • 提取出来的特征:将提取出来的频谱数据和声音的振幅,以及声音的时间序列进行保存

下面几个部分也是按照流程图的顺序,逐个实现的

Loader模块

class Loader:
    """ 关于这个函数还是有一些不懂的地方,需要学习一下,相关的音频知识 """
    def __init__(self,
                 sample_rate,
                 duration,
                 mono   # 这是单声道还是双声道
                 ):
        self.sample_rate = sample_rate
        self.duration = duration
        self.mono = mono

    def load(self,file_path):
        """ 加载文件,这里加载的是什么东西 """
        signal = librosa.load(file_path,
                              sr = self.sample_rate,
                              duration = self.duration,
                              mono = self.mono)[0]
        return signal
  • 参数说明
    • sample_rate:采样频率
    • duration:加载的音频时长,默认是完全加载的
    • mono:是否将音频转换为单声道
  • 返回值
    • numpy数组:音频的时间序列,支持多通道
    • 采样率
      在这里插入图片描述

Padder模块

class Padder:
    """ padder这个类别是用来对数组进行填补,保证数据的大小一致 """

    def __init__(self,mode ="constant"):
        self.mode = mode

    def left_pad(self,array,num_missing_items):
        paded_array = np.pad(array,
                             (num_missing_items,0),
                             mode = self.mode)
        return paded_array

    def right_pad(self, array, num_missing_items):
        paded_array = np.pad(array,
                             ( 0,num_missing_items),
                             mode=self.mode)
        return paded_array
  • 很常见的就是对数组进行扩充,是的数组能够保证大小一致
  • 这里就是根据需要添加对应的列,使得所有的array的shape一致

LogSpectrogramExtractor模块

class LogSpectrogramExtractor:
    """ LogSpectrogram是提取了时间序列中的频谱信息(以DB为单位) """
    def __init__(self,frame_size,hop_length):
        self.frame_size = frame_size
        self.hop_length = hop_length

    def extract(self,signal):
        stft = librosa.stft(signal,
                            n_fft = self.frame_size,
                            hop_length=self.hop_length)[:-1]	# 注意,这里为了能够输入模型训练,原来是(257,64)变成了(256,64),取出了最后一列
        spectrogram = np.abs(stft)  # 取绝对值,化成频谱图
        log_spectrogram = librosa.amplitude_to_db(spectrogram)  # 加上分贝图
        return log_spectrogram
  • 这部分主要是负责提取时域中音频信息的频域信息,主要用了两种方法,具体介绍如下

  • librosa.stft:

    • 这部分是用来短时傅立叶变换,返回一个复数矩阵
    • 参数说明
      • n_fft:进行傅立叶变化的时域窗口
      • hop_length:帧移动的跳数,时域窗口的每一次迭代的移动步数
    • 返回
      • 复数矩阵,这里仅仅不需要最后一个输出,具体执行如下效果图,
  • 原来生成复数矩阵是(257,64),这里去除了最后一列
    在这里插入图片描述

  • 短时傅立叶如何将波形图转成频谱图的

  • librosa.amplitude_to_db:

    • 将幅度频谱转换为dB标度频谱,就是用分贝表示幅度
    • 参数
      • 输入幅度
    • 返回
      • 复数序列,将原来的数据替换为对应的dB,下面是转换之后的db图

在这里插入图片描述

  • 在网上找了一下,关于这块,这部分介绍的是比较详细的

    • 链接
    • 一般来说,这里需要了解一下对应的log-spectrogram数据到底是什么样的,有什么特征
  • 振幅和分贝的关系,为啥需要这样转换

MinMaxNormaliser模块

class MinMaxNormaliser:
    """ 对数据进行正则化 """
    def __init__(self,min_val,max_val):
        self.min = min_val
        self.max = max_val

    def nomalise(self,array):
        """" 将原来的数组映射到min_val,max_val之间,这部分是用来将声音提取出来,提取特征"""
        norm_array = (array - array.min) / (array.max - array.min)
        norm_array = norm_array * (self.max - self.min) + self.min
        return norm_array

    def denormalise(self,norm_array,original_min,original_max):
        """ 这个是用来还原的,后续生成声音 """
        array = (norm_array -self.min) / (self.max - self.min)
        array = array * (original_max - original_min) * original_min
        return array

  • 这部分使用来对数据进行正则化的,我觉得他大部分函数都是自己实现的,可能就是让你学习一下的
  • normalise:对数据进行正则化,将原来的数据映射到新的min和max之间
  • denormalise:对数据进行还原

Saver模块

class Saver:
    """ 保存特征和对应的min和max """

    def __init__(self,feature_save_dir,min_max_values_save_dir):
        self.feature_save_dir = feature_save_dir    # 这是特征保存的路径,和原来的路径并不相同
        self.min_max_values_save_dir = min_max_values_save_dir
    def save_feature(self,feature,file_path):
        """ 经过处理之后的特征 """
        save_path = self._generate_save_path(file_path)
        np.save(save_path,feature)

    def save_min_max_values(self,min_max_values):
        """ 保存音频文件对应的最大最小值 """
        save_path = os.path.join(self.min_max_values_save_dir,"min_max_values.pkl")
        self._save(min_max_values,save_path)

    @staticmethod
    def _save(data,save_path):
        with open(save_path,"wb") as f:
            pickle.dump(data,f)

    def  _generate_save_path(self,file_path):
        file_name = os.path.split(file_path)[1]
        save_path = os.path.join(self.feature_save_dir,file_name + ".npy")
        return save_path

  • 这个模块是负责保存提取出来的特征和保存原数据的最值
    • min_max_values.pkl
      • 将提取出来的数据,获取其最大值和最小值,保存为对应的pkl文件
    • 文件名.npy
      • 将提取出来的频谱特征保存为对应的npy文件

PreprocessPipeLine模块

class PreprocessingPipeline:
    """ 将上述的每一个文件经过下述流程处理:
            1、加载音频文件
            2、对数据进行padding,确保等长
            3、从数据中提取出log频谱图
            4、将频谱图进行正则花
            5、保存频谱图
        store the min max values for all the log spectrogram
    """
    def __init__(self):
        """ 这里并没有写死,考虑到了代码的鲁棒性,可以通用于不同的预处理模块 """
        self.padder = None
        self.extractor = None
        self.normaliser = None
        self.saver = None
        self._loader = None
        self._num_expected_samples = None
        self.min_max_value = dict()


        # 这部分是用来判定是否需要进行padding的

    # 将成员变量定义为padder,判定是否需要进行
    @property
    def loader(self):
        return self._loader

    @loader.setter
    def loader(self,loader):
        self._loader = loader
        self._num_expected_samples = int(loader.sample_rate * loader.duration)

    def process(self,audio_files_dir):
        for root, _, files in os.walk(audio_files_dir):
            for file in files:
                file_path = os.path.join(root, file)
                self._process_file(file_path)
                print(f"Processed file {file_path}")
        self.saver.save_min_max_values(self.min_max_value)

        # 这里还需要保存对应每一个音频文件对应的最大和最小值,便于还原
        self.saver.save_min_max_values(self.min_max_value)


    def _process_file(self,file_path):
        """ 处理单个文件的过程 """
        signal = self.loader.load(file_path)    # 加载信号
        if self._is_padding_necessary(signal):  # 判定是否需要进行padding
            signal = self._apply_padding(signal)
        feature = self.extractor.extract(signal)    # 提取特定的特征,这里保留一个通用的函数
        norm_feature = self.normaliser.normalise(feature)   # 对特征进行正则化
        save_path = self.saver.save_feature(norm_feature,file_path)
        self._store_min_max_value(save_path,feature.min(),feature.max())


    # 4.3 逐步实现上述的方法
    def _is_padding_necessary(self,signal):
        """ 判定是否需要对这个array进行扩充 """
        if len(signal) < self._num_expected_samples:
            return True
        return False

    def _apply_padding(self,signal):
        """ 对array进行padding """
        padding_signal = self.padder.right_pad(signal,self._num_expected_samples - len(signal))
        return padding_signal

    def _store_min_max_value(self,save_path,min_value,max_value):
        self.min_max_value[save_path] = {
            "min" :min_value,
            "max":max_value
        }
  • 数据预处理的完整流程,主要是调用的process方法实现,然后处理单个文件,是调用私有函数_process方法
    在这里插入图片描述
    在这里插入图片描述

知识补充

property修饰词
  • 参考连接 , property修饰词的说明
  • 作用
    • 使用property来创建只读属性,将方法转为相同名称的只读属性,防止属性被修改。

总结

  • 这段代码的复用性还是很强的,如果你是实现不同的预处理流程,只需要实现特定阶段的类即可,然后将新的对象,组装到新的preprocess pipeline即可,这里需要学习一下。说到这里,还是需要了解一下设计模式,毕竟是前人总结出来,针对不同情况的编程的习惯。现在的编码习惯太差了,一点都不好,无论是python、java还是C++都是可以面向对象编程,我忽然间想起,我在程序精英编程大赛中,居然还使用一个一个函数进行实现功能,羞愧。
  • 这部分是对音频进行预处理,将之变为图片,然后音频生成就转成了图片的生成问题。
  • 这里预处理的流程,涉及到很多环节,都是音频处理的基础知识,需要好好学习一下。
    • log spectrogram和spectrogram的关系
    • 短时傅立叶怎么把波形图转成频谱图的
    • 。。。。
  • 现在会的都是一些皮毛。这篇博客,也仅仅会讲述这个项目中会用到的相关知识,多的并不会讲,但是如果想去专门了解一下这个版块,还是需要专门学习一下相关的基础知识。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/538800.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

蓝桥:前端开发笔面必刷题——Day2 数组(二)

文章目录 &#x1f4cb;前言&#x1f3af;删除有序数组中的重复项&#x1f4da;题目内容✅解答 &#x1f3af;移动零&#x1f4da;题目内容✅解答 &#x1f3af;长度最小的子数组&#x1f4da;题目内容✅解答 &#x1f3af;反转字符串数组&#x1f4da;题目内容✅解答 &#x1…

麒麟操作系统软件更新灾难连篇之二:QQ罢工

在解决了中文输入法消失的问题后&#xff0c;还没缓过气来&#xff0c;又发现QQ罢工了&#xff1a;双击电脑桌面上的QQ图标&#xff0c;没有显示QQ登录界面。 重启电脑再试&#xff0c;还是不显示QQ登录界面。 前不久腾讯正式宣布&#xff0c;QQ Linux 版 3.0 已在 QQ 官网上…

最好用的文本与文件查询软件AnyTXT Searcher与Listary简介

1. 工具简介 1.1 Listary简介 Listary是一个革命性的Windows搜索工具&#xff0c;借助 Listary软件&#xff0c;你可以快速搜索电脑文件、定位文件、执行智能命令、记录访问历史、快速切换目录、收藏常用项目等。 Listary为Windows传统低效的文件打开/保存对话框提供了便捷、…

Apache Tomcat AJP协议文件读取与包含

永远也不要忘记能够笑的坚强&#xff0c;就算受伤&#xff0c;我也从不彷徨。 0x01.漏洞情况分析 Tomcat是Apache软件基金会Jakarta 项目中的一个核心项目&#xff0c;作为目前比较流行的Web应用服务器&#xff0c;深受Java爱好者的喜爱&#xff0c;并得到了部分软件开发商的…

makefile 学习(2):C语言的编译及库文件的生成与链接

文章目录 1. 介绍2. C语言编译2.1 预处理2.2 生成汇编语言2.3 编译目标文件2.4 编译为可执行文件 3. .a静态库的编译与链接案例 4 .so 动态库的编译与链接 1. 介绍 编译C语言的相关后缀 .a 文件是一个静态库文件.c文件是c语言的源文件.h c语言的头文件.i 是预处理文件.o 目标文…

两个用字符串表示的大数字的和

文章目录 题目详情Java实现分析Java 怎么获取到字符串中的对应位置的数字值Java完整代码测试验证 python实现python 怎么获取到字符串中的对应位置的数字值python完整代码 总结 这是遇到的一道快手数仓岗位的面试题目&#xff0c;题目大意如下&#xff1a; 题目详情 现在有两个…

【树莓派4B安装18.04桌面+远程SSH】

【树莓派4B安装18.04桌面远程SSH】 1. 前言2 .树莓派安装ubuntu18.04 系统2.1 下载ubuntu Server 18.04 的镜像包2.2 镜像烧录2.3 高级设置2.4 配置WiFi2.5 ssh文件配置2.6 Pi 4B启动文件 3. 安装finalshell3.1 windows版下载3.2 windows版安装3.3 SSH连接 4. 安装ubuntu桌面4.…

【野火启明_瑞萨RA6M5】梦的开始 ---- 点灯(寄存器)

文章目录 一、IOPORT简介二、IOPORT的框图分析三、IOPORT的寄存器描述1. 端口引脚功能选择寄存器2. 端口输出数据寄存器3. 端口输入数据寄存器4. 端口输出置位/复位寄存器5. 写保护寄存器 四、点亮LED灯&#xff08;寄存器&#xff09; 从本文开始&#xff0c;我将以瑞萨RA系列…

【夜莺(Flashcat)V6监控】3.链路追踪

链路追踪 介绍 链路追踪是分布式系统下的一个概念&#xff0c;它的目的就是要解决上面所提出的问题&#xff0c;也就是将一次分布式请求还原成调用链路&#xff0c;将一次分布式请求的调用情况集中展示&#xff0c;比如&#xff0c;各个服务节点上的耗时、请求具体到达哪台机…

Java 把一个 List 转换为字符串

在本快速指南中&#xff0c;我们将会解释如何在 Java 把一个 List 转换为 String 字符串。 这个在某些特定的场合可能比较有用&#xff0c;比如说在控制台中输出 List 中的内容&#xff0c;转换为可以人为阅读的内容来进行调试。 使用 List 中标准的 toString() 方法 一个最简…

(2)数码管

LED数码管:数码管是一种简单、廉价的显示器&#xff0c;是由多个发光二极管封装在一起组成"8"字器件 51单片机是共阴极连接 74HC245这个芯片有什么作用呢&#xff1f;解&#xff1a;这个芯片被称之为双向数据缓冲器这个芯片的作用&#xff0c;用来进行数据缓冲(提高驱…

【网络编程】详解UDP/TCP套接字的创建流程

目录 一、网络编程套接字 1、一些概念 1.1源IP地址和目的IP地址 1.2端口号port 1.3TCP和UDP的性质 1.4网络字节序、IP地址类型转换、数据接收与发送函数、popen函数 2、UDP套接字 2.1UDP服务器创建流程 2.2UDP客户端创建流程 2.3创建socket套接字 2.4绑定套接字对应…

快速找出PATH 路径下重复的命令程序文件

RT&#xff0c;就是想找出命名冲突的可执行文件。日积月累的&#xff0c;PATH 环境变量里乱七八糟堆了一堆东西&#xff0c;很可能想叫一个命令出来&#xff0c;结果实际执行的是另一个地方的程序。 Python 脚本 import ospath os.environ[PATH] folders path.split(;) fil…

理解HttpSession

什么是session 在我刚刚从事后端开发的时候&#xff0c;有一个问题困扰了我很久。 就有个玩意叫session。 PostMapping("login")public Result login(RequestParam("id") String id,RequestParam("password") String password, HttpSession se…

哈希及模拟实现

文章目录 哈希1. 哈希相关概念1.1 哈希概念1.2 哈希冲突1.3 哈希函数1.4 哈希冲突解决1.4.1 闭散列/开放定址法(1)线性探测(2) 二次探测 1.4.2 开散列/哈希桶 2. 开放定址法的实现2.1 结构2.2 插入Insert2.2.1 传统写法2.2.2 现代写法 2.3 查找Find2.4 删除Erase2.5 整体代码 3…

springcloud基于web的智慧养老平台

系统分析 可行性分析 在开发系统之前要进行系统可行性分析&#xff0c;目的是在用最简单的方法去解决最大的问题&#xff0c;程序一旦开发出来满足了用户的需要&#xff0c;所带来的利益也很多。下面我们将从技术、操作、经济等方面来选择这个系统最终是否开发。 1、技术可行…

一图看懂 dateutil 模块:Python datetime 模块的扩展,资料整理+笔记(大全)

本文由 大侠(AhcaoZhu)原创&#xff0c;转载请声明。 链接: https://blog.csdn.net/Ahcao2008 一图看懂 dateutil 模块&#xff1a;Python datetime 模块的扩展&#xff0c;资料整理笔记&#xff08;大全&#xff09; &#x1f9ca;摘要&#x1f9ca;模块图&#x1f9ca;类关系…

005、数据库结构

数据库结构 1、数据库集簇逻辑结构2、对象标识符3、数据库集簇物理结构4、其它目录结构表空间物理文件位置1、数据库集簇逻辑结构 • 数据库集簇逻辑结构 数据库 : 把数据逻辑分开存放。 对象是放在数据库当中。表空间: 把数据从逻辑或者物理上分割存放2、对象标识符 Postg…

Weblogic SSRF 漏洞(CVE-2014-4210)

SSRF漏洞 ​ SSRF&#xff08;服务端请求伪造&#xff09;&#xff0c;指的是攻击者在未能取得服务器所有权限时&#xff0c;利用服务器漏洞以服务器的身份发送一条构造好的请求给服务器所在内网。SSRF攻击通常针对外部网络无法直接访问的内部系统。 ​ 简单的说就是利用一个可…

《统计学习方法》——隐马尔可夫模型(下)

学习算法 HMM的学习&#xff0c;在有观测序列的情况下&#xff0c;根据训练数据是否包含状态序列&#xff0c;可以分别由监督学习算法和无监督学习算法实现。 监督学习算法 监督学习算法就比较简单&#xff0c;基于已有的数据利用极大似然估计法来估计隐马尔可夫模型的参数。…