VariantAutoencoder(VAE)中使用生成好的模型进行声音生成

news2025/1/18 8:49:05

文章目录

    • 概述
    • 一、soundgenerator.py文件
      • soundgenerator.py实现代码
      • 一、convert_spectrogram_to_audio方法
        • librosa.db_to_amplitude
        • librosa.istft
      • generate方法
    • 二、generate.py文件
      • 实现代码
      • load_fsdd函数说明
      • select_spectrogram函数说明
      • save_signals函数说明
      • main函数说明
    • 三、运行异常
      • File Not Found
      • KeyError: '/root/PycharmProjects/VAEGenerate/Mycode/fsdd/spectrogram/6_nicolas_15.wav.npy'
    • 总结

概述

  • 这部分主要是在已经训练好的模型的基础上,利用模型生成声音,主要是两个py文件,分别是soundgenerator.py和generate.py,
    • 前一个文件是声明一个SoundGenerator类,实现如下功能
      • 将频谱图中的db转为振幅
      • 将频谱图转为波形图
    • 后一个是具体调用的已经训练好的模型和SoundGenerator类,进行声音生成的文件。
  • 下面是针对各个模块进行的说明,并展示最后的执行效果。

一、soundgenerator.py文件

soundgenerator.py实现代码

import librosa

from preprocess import MinMaxNormaliser


class SoundGenerator:
    """ Soundgenerator负责从频谱图生成对应的声音 """

    def __init__(self, vae, hop_length):
        self.vae = vae
        self.hop_length = hop_length
        self._min_max_normaliser = MinMaxNormaliser(0, 1)

    def generate(self, spectrograms, min_max_values):
        generated_spectrograms, latent_representations = \
            self.vae.reconstruct(spectrograms)
        signals = self.convert_spectrograms_to_audio(generated_spectrograms, min_max_values)
        return signals, latent_representations

    def convert_spectrograms_to_audio(self, spectrograms, min_max_values):
        signals = []
        for spectrogram, min_max_value in zip(spectrograms, min_max_values):
            # reshape the log spectrogram
            log_spectrogram = spectrogram[:, :, 0]
            # apply denormalisation
            denorm_log_spec = self._min_max_normaliser.denormalise(
                log_spectrogram, min_max_value["min"], min_max_value["max"])
            # log spectrogram -> spectrogram
            spec = librosa.db_to_amplitude(denorm_log_spec)
            # apply Griffin-Lim
            signal = librosa.istft(spec, hop_length=self.hop_length)
            # append signal to "signals"
            signals.append(signal)
        return signals

一、convert_spectrogram_to_audio方法

def convert_spectrograms_to_audio(self, spectrograms, min_max_values):
        signals = []
        for spectrogram, min_max_value in zip(spectrograms, min_max_values):
            log_spectrogram = spectrogram[:, :, 0]	# 对频谱图进行调整
            denorm_log_spec = self._min_max_normaliser.denormalise(
                log_spectrogram, min_max_value["min"], min_max_value["max"])	# 对数据进行反正则化,进行恢复
            spec = librosa.db_to_amplitude(denorm_log_spec)	# 将分贝图转成振幅
            signal = librosa.istft(spec, hop_length=self.hop_length)	# 使用反短傅立叶变化,将数据恢复到频域
            signals.append(signal)	# 将数据加载signal中,并进行返回
        return signals
  • 这部分是负责将频谱图转成音频文件,基本流程图下
    • 对生成的数据,进行逆正则化,还原成原来的范围下的数据
    • 将分贝频域图,转成振幅的数据模式librosa.db_to_amplitude
    • 将时频图还原成,线性的,时间域的波形图

librosa.db_to_amplitude

参考连接

  • 功能描述:将dB尺度下的频谱图转变成振幅频谱图,使用分贝来衡量振幅
  • 原理:下面的公式知道就行了,不用记着
    • d b t o a m p l i t u d e ( S d b )   = 10.0 ∗ ∗ ( 0.5 ∗ S d b / 10 + l o g 10 ( r e f ) ) db_to_amplitude(S_db) ~= 10.0**(0.5 * S_db/10 + log10(ref)) dbtoamplitude(Sdb) =10.0(0.5Sdb/10+log10(ref))
  • 输入:
    • 有分贝构成的数组
  • 输出
    • 是一个np.ndarray
    • 线性振幅频谱图

librosa.istft

  • 功能描述:
    • 短时傅立叶变换的逆函数,将时频领域的频谱图转成时间序列的频域图
  • 输入
    • stft_matrix:需要转换的频谱图数组
    • hop_length:窗口移动的步长
  • 输出
    • ynp.ndarray
    • 有原来的stft_matrix重建之后的,时间序列的信号

generate方法

def generate(self, spectrograms, min_max_values):
    generated_spectrograms, latent_representations = \
        self.vae.reconstruct(spectrograms)
    signals = self.convert_spectrograms_to_audio(generated_spectrograms, min_max_values)
    return signals, latent_representations
  • 这是生成函数的总函数,具体流程如下
    • 调用vae模型的重建方法,根据潜在特征模型,生成新的频谱图
    • 然后调用上一节将的函数,将频谱图转成波形,返回波形图和对应的特征表示

二、generate.py文件

实现代码

  • 调用函数如下
    • load_fsdd:加载频谱文件
    • select_spectrograms:选择频谱文件
    • save_signals:保存生成的文件
    • main主要的执行函数
import os
import pickle

import numpy as np
import soundfile as sf

from soundgenerator import SoundGenerator
from vae import VAE
from train_vae import SPECTROGRAMS_PATH


HOP_LENGTH = 256
SAVE_DIR_ORIGINAL = "samples/original/"
SAVE_DIR_GENERATED = "samples/generated/"
MIN_MAX_VALUES_PATH = "/home/valerio/datasets/fsdd/min_max_values.pkl"


def load_fsdd(spectrograms_path):
    x_train = []
    file_paths = []
    for root, _, file_names in os.walk(spectrograms_path):
        for file_name in file_names:
            file_path = os.path.join(root, file_name)
            spectrogram = np.load(file_path) # (n_bins, n_frames, 1)
            """  这部分不是很懂,需要了解一下,确定具体的一些要求  """
            x_train.append(spectrogram)
            file_paths.append(file_path)
    x_train = np.array(x_train)
    x_train = x_train[..., np.newaxis] # -> (3000, 256, 64, 1)
    return x_train, file_paths


def select_spectrograms(spectrograms,
                        file_paths,
                        min_max_values,
                        num_spectrograms=2):
    sampled_indexes = np.random.choice(range(len(spectrograms)), num_spectrograms)
    sampled_spectrogrmas = spectrograms[sampled_indexes]
    file_paths = [file_paths[index] for index in sampled_indexes]
    sampled_min_max_values = [min_max_values[file_path] for file_path in
                           file_paths]
    print(file_paths)
    print(sampled_min_max_values)
    return sampled_spectrogrmas, sampled_min_max_values


def save_signals(signals, save_dir, sample_rate=22050):
    for i, signal in enumerate(signals):
        save_path = os.path.join(save_dir, str(i) + ".wav")
        sf.write(save_path, signal, sample_rate)


if __name__ == "__main__":
    # initialise sound generator
    vae = VAE.load("model")
    sound_generator = SoundGenerator(vae, HOP_LENGTH)

    # load spectrograms + min max values
    with open(MIN_MAX_VALUES_PATH, "rb") as f:
        min_max_values = pickle.load(f)

    specs, file_paths = load_fsdd(SPECTROGRAMS_PATH)

    # sample spectrograms + min max values
    sampled_specs, sampled_min_max_values = select_spectrograms(specs,
                                                                file_paths,
                                                                min_max_values,
                                                                5)

    # generate audio for sampled spectrograms
    signals, _ = sound_generator.generate(sampled_specs,
                                          sampled_min_max_values)

    # convert spectrogram samples to audio
    original_signals = sound_generator.convert_spectrograms_to_audio(
        sampled_specs, sampled_min_max_values)

    # save audio signals
    save_signals(signals, SAVE_DIR_GENERATED)
    save_signals(original_signals, SAVE_DIR_ORIGINAL)

load_fsdd函数说明

def load_fsdd(spectrograms_path):
    x_train = []
    file_paths = []
    for root, _, file_names in os.walk(spectrograms_path):
        for file_name in file_names:
            file_path = os.path.join(root, file_name)
            spectrogram = np.load(file_path) # (n_bins, n_frames, 1)
            x_train.append(spectrogram)
            file_paths.append(file_path)
    x_train = np.array(x_train)
    x_train = x_train[..., np.newaxis] # -> (3000, 256, 64, 1)
    return x_train, file_paths
  • 这部分是用来加载频谱图的,spectrograms_path保存的是频谱文件的地址,并将单个数据合并成数据集。
  • 因为处理之后的频谱图是二维的,[n_bins,n_frames],但是模型是需要输入三维的数据,所以增加一个最后的维度,为1,充当channel数据
  • 同时获取对应频谱文件的保存路径。

select_spectrogram函数说明

def select_spectrograms(spectrograms,
                        file_paths,
                        min_max_values,
                        num_spectrograms=2):
    """
    在加载的频谱文件数据spectrograms中,随机抽取num_specctrograms个频谱,
    并返回对应的min_max_values,以便进行逆正则化
    :param spectrograms:处理过之后的频谱文件
    :param file_paths:每一个频谱图的对应的文件路径,用于获取对应的最大最小值
    :param min_max_values:每一个频谱文件对应的最值
    :param num_spectrograms:需要提取的频谱图数量
    :return:
    """
    sampled_indexes = np.random.choice(range(len(spectrograms)), num_spectrograms)  # 随机采样
    sampled_spectrogrmas = spectrograms[sampled_indexes]    # 获取抽样之后的数据图
    file_paths = [file_paths[index] for index in sampled_indexes]   # 获取对应索引的文件路径
    sampled_min_max_values = [min_max_values[file_path] for file_path in    # 获取对应频谱图的最大最小值索引
                           file_paths]
    print(file_paths)
    print(sampled_min_max_values)
    return sampled_spectrogrmas, sampled_min_max_values # 返回采样之后频谱图以及对应的最值
  • 在频谱图中随机抽样特定数量的样本数据,用于生成模型,并返回对应样本的最值,以便进行逆正则化

save_signals函数说明

import soundfile as sf
def save_signals(signals, save_dir, sample_rate=22050):
    """
    将波形信号保存为对应wav文件
    :param signals:生成的波形信号
    :param save_dir:保存的路径
    :param sample_rate:采样率
    :return:
    """
    for i, signal in enumerate(signals):
        save_path = os.path.join(save_dir, str(i) + ".wav")
        sf.write(save_path, signal, sample_rate)
  • 这部分是将数据保存为对应的波形图,用到了soundfile包,这个python自带的包,用于保存对应的数据

main函数说明

"""
主要步骤
1、初始化一个sound generator实例
2、加载对应文件下的频谱图文件和最值文件
3、从频谱图和最值文件进行对应采样
4、生成与采样样例针对的音频
5、将生成的频谱图转成波形图
6、保存对应的音频信号
"""
# 初始化对应
vae = VAE.load("model")
sound_generator = SoundGenerator(vae, HOP_LENGTH)

# load spectrograms + min max values
with open(MIN_MAX_VALUES_PATH, "rb") as f:
    min_max_values = pickle.load(f)

specs, file_paths = load_fsdd(SPECTROGRAMS_PATH)

# sample spectrograms + min max values
sampled_specs, sampled_min_max_values = select_spectrograms(specs,
                                                            file_paths,
                                                            min_max_values,
                                                            5)

# generate audio for sampled spectrograms
# 这里不仅仅生成了对应的信号,还返回了对应的特征空间,所以需要提前保存一下
signals, _ = sound_generator.generate(sampled_specs,
                                      sampled_min_max_values)

# convert spectrogram samples to audio
# 注意这里是原来的频谱图也转成了对应的声音,主要是和生成的声音进行对比
original_signals = sound_generator.convert_spectrograms_to_audio(
    sampled_specs, sampled_min_max_values)

# save audio signals
save_signals(signals, SAVE_DIR_GENERATED)
save_signals(original_signals, SAVE_DIR_ORIGINAL)
  • 这个main函数串联起了soundgenerator.py文件和generate.py文件,包含了完整的生成函数的流程

在这里插入图片描述

三、运行异常

File Not Found

  • 代码中,需要在当前的工程项目中创建两个文件

KeyError: ‘/root/PycharmProjects/VAEGenerate/Mycode/fsdd/spectrogram/6_nicolas_15.wav.npy’

在这里插入图片描述
在这里插入图片描述

  • 这个字典是有问题的,说明是preprocess的问题,所以重新回过去修改代码。preprocess pipeline中save_feature中并没有返回对应的路径。

在这里插入图片描述
在这里插入图片描述

  • 运行成功,生成对应的数据

在这里插入图片描述

总结

  • 这部分已经根据给的声音成功生成了相关的声音,如果只讲这个,估计时间不够,所以我还需要将这部分的代码应用到对应的自动编码器中,然后对比一下对应的生成效果,同时,还需要看一下相关的理论知识,尝试使用不同的特征进行生成。
  • 我在怀疑自己,这样写有什么意义?本来就不是那么复杂的东西,不过我自己太差了,还是得好好看吧。那我花那么久的时间,去实现这个,真的有意义吗?自己的研究方向又是什么那?哎,现在就是我想做,那就做。

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

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

相关文章

ESP32-C2模组使用AT固件示例

ESP32C2 AT固件使用 ESP32 C2模组,如图1-1所示 图1-1 ESP32 C2模组 ESP32 C2开发板,如图1-2所示 图1-2 ESP32 C2开发 方案亮点 1、完整的 WiFi 子系统,符合 IEEE 802.11b/g/n 协议,具有 Station 模式、SoftAP 模式、SoftAP Stat…

npm依赖更新无效

项目场景: 项目是使用ice2.0.0搭建的react项目 项目需要替换新版本的sdk,使用npm进行对应sdk的版本升级 问题描述 卸载sdk tnpm uninstall tds/sdk安装最新版本sdk tnpm i tds/sdk^0.0.16控制台依旧输出旧版本的输出 解决过程 提示:这里填写问题接解决…

C++设计模式之工厂方法模式(Factory Method)

工厂方法模式(Factory Method) 头号公社 文章目录 别名定义前言1、问题2、解决方案 结构适用场景实现方式优点缺点与其他模式的关系实例Reference 别名 虚拟构造函数(Virtual Constructor)。 定义 工厂方法是一种创建型设计模式…

前端需要注意和了解的SEO

SEO的基本了解 1.什么是SEO? SEO(Search Engine Optimization又叫做搜索引擎优化。是一种方式:利用搜索引擎的规则提高网站在有关搜索引擎内的自然排名。 2. 前端怎么理解SEO? 对于SEO引擎,在前端需要的是做出来的网站,页面…

从裸机启动开始运行一个C++程序(二)

先序文章请看: 从裸机启动开始运行一个C程序(一) 运行在8086上的第一个程序 既然硬件环境已经就绪了,那接下来,就要想办法让它运行我们的程序了。不过在此之前,我们必须要了解一下8086的主要架构&#xf…

小白安装 stabel diffusion 篇

windows 系统安装 stabel diffusion 软件的方法其实很简单,只有 4 步(安装过程遇到的报错问题,本文有详细的解决方案,都是我踩过的坑,给大家探路了): 1、安装 python(建议安装 3.10…

孙鑫VC++第五章 文本编程

目录 1. 插入符 1.1 创建文本插入符 1.2 创建图形插入符 2. 文字输出和OnDraw函数 2.1窗口重绘 2.2 添加字符串资源 3. 路径层和剪切区域 3.1 路径 3.2 裁剪区域 4. 字符输入 4.1 字符输入 5. 字幕变色功能的实现 5.1 设置字体 5.2字幕变色功能的实现 6. 总结 1…

windows11 安装WSL2全流程

文章目录 1、启用window子系统及虚拟化1.1 命令行方式1.2 使用图形界面 2、手动安装2.1、安装内核更新包2.2、设置默认WSL版本2.3、配置分发版本2.3.1 下载发行版本2.3.2 安装到C盘2.3.3 安装到D盘2.3.3.1 导出镜像2.3.3.2 导入镜像2.3.3.3 默认系统设置及多系统选择 3、自动安…

全景 I 0基础学习VR全景制作,第26章热点功能-文档

本期为大家带来蛙色VR平台,热点功能—文档功能操作。 功能位置示意 热点,指在全景作品中添加各种类型图标的按钮,引导用户通过按钮产生更多的交互,增加用户的多元化体验。 文档热点,即点击热点后会嵌入式弹出所选文档…

一次线上mysql 调优 ,join 的调优,索引优化(Block Nested Loop)

原因: 某接口调用十分缓慢,通过 Explain 发现是SQL问题 FROMorderInfo o LEFT JOIN orderDetail d ONo.orderCode d.orderCode LEFT JOIN user u ONo.userId u.userId LEFT JOIN product p ONd.productCode p.productCode LEFT JOIN adminUser au O…

Linux之打包压缩

1、参考 11-文件压缩与打包 linux tar压缩排除指定文件夹 2、打包与压缩 在windows上似乎打包和压缩是同一个东西,大家都明白你的意思,实际上是打包和压缩是两个过程,只不过常用zip压缩一站式解决了。 打包:就是将文件夹或多个…

《终身成长》笔记七——建设性的批评

目录 总结 经典摘录 我们能做什么 成长型思维模式与马上行动有异曲同工之妙 改变孩子的思维模式 两种思维模式对比 总结 《终身成长》是卡罗尔德韦克的代表作,在这部作品中,她以通俗易懂的笔触总结了自己对人类两种思维模式的研究。也许因为思维模…

mysq的约束学习

第13章_约束 1. 约束(constraint)概述 1.1 为什么需要约束 数据完整性(Data Integrity)是指数据的精确性(Accuracy)和可靠性(Reliability)。它是防止数据库中存在不符合语义规定的数据和防止因错误信息的…

鸿蒙Hi3861学习十五-Huawei LiteOS-M(Socket客户端)

一、简介 在网络编程的时候,不管是客户端还是服务端,都离不开Socket。那什么是Socket,这里做个简单介绍。详细的内容,可以参考这篇文章:WIFI学习一(socket介绍)_wifi socket_t_guest的博客-CSDN…

ChatGPT发展报告:原理、技术架构详解和产业未来(附下载)

今年12月1日,OpenAI推出人工智能聊天原型ChatGPT,再次赚足眼球,为AI界引发了类似AIGC让艺术家失业的大讨论。 据报道,ChatGPT在开放试用的短短几天,就吸引了超过 100 万互联网注册用户。并且社交网络流传出各种询问或…

其他类型的CMOS逻辑门

1.CMOS与非门 电路结构如图所示 如图所示,T1、 T3为两个串联的PMOS, T2、 T4为两个并联的NMOS. A、B有一个为“0”时,T2、 T4至少有一个截止, T1、 T3至少有一个导通,故输出为高电平,Y=1. A、…

用Colab免费部署AI绘画云平台Stable Diffusion webUI

Google Colab 版的 Stable Diffusion WebUI 1.4 webui github 地址:https://github.com/sd-webui/stable-diffusion-webui 平台搭建 今天就来交大家如果来搭建和使用这个云平台。 第一步: 打开链接 https://colab.research.google.com/github/altryne/sd-webu…

求最大字段和(穷举法、动态规划、分治法)

目录 1、案例要求2、算法设计与实现2.1 穷举法2.1.1 算法设计思路2.1.2 代码实现 2.2 动态规划2.2.1 算法设计思路2.2.2 实现代码 2.3 分治法2.3.1 算法实现思路2.3.2 代码实现 3、总结 1、案例要求 给定由n个整数(可能为负整数)组成的序列a1,a2,…,an&…

菜鸟对原型链的理解

1.什么是原型 函数下的prototype属性,是个指针,指向的对象就是原型 2.什么是原型链 很多个原型连接起来就是一条链了。 function Person() { } var test new Person(); 当我们new一个构造函数是,实例对象(test)&a…

Windows平台上的5种敏捷软件开发(过程)模型

我是荔园微风,作为一名在IT界整整25年的老兵,今天总结一下Windows平台上的5种敏捷软件开发(过程)模型。 说到这个问题,你必须先知道除了敏捷模型还有没有其他什么模型?同时要比较模型的区别,首先还要看看什么叫软件开…