VS语音信号处理(6) C语言调用SoundTouch进行变速不变调工程实例

VS语音信号处理(6) C语言调用SoundTouch进行变速不变调工程实例

  • 前言
  • 一. 源码下载即链接库准备
  • 二. 工程编译准备
  • 三. 例程实现
  • 四. 小结

前言

语音识别相关算法一般在MATLAB上进行仿真验证与实验,在工程上一般还是在VS中进行实现落地,本系列将介绍语音信号处理在C语言中的一系列应用,后期将以此为基础,再落地移植到嵌入式平台。

今天介绍SoundTouch语音变速不变调算法的工程应用。SoundTouch是一个支持音频倍速播放的开源库。支持变速(加速减速)、变调、变速同时变调等三类功能模块,能够对流媒体实时操作,也能对音频文件操作。采用 32 位浮点或者 16 位定点,支持单声道或者双声道,采样率范围为 8k~48k。

自己之前应用sonic进行变速不变调处理时,也得到了了一定的效果,但相比于SoundTouch,整体效果确实差了一些,网上此前有同学也做过对比,但sonic实现简单,所以一开始采用的是sonic变速不变调,但后期主要由于sonic合成的时长控制,语音数据都不及SoundTouch,这次跑通了SoundTouch的变速不变调实例,做一下记录,网上资料主要基于 android或者是其他编译平台的经验介绍,自己的需求是需要C++进行调用,所以本工程基于SoundTouch的C源码实现的,(原工程已经迭代到VS2019,自己在VS2015上亲测可以跑通),话不多说,开干!

一. 源码下载即链接库准备

SoundTouch官网
SoundTouch地址:http://soundtouch.surina.net
在这里插入图片描述
SoundTouch 库适用于编写需要速度/音高控制功能的声音处理工具的应用程序开发人员,或者只是用于播放声音效果。SoundTouch 库源套件还包括一个示例实用程序 SoundStretch,用于从命令行界面处理 .wav 音频文件。

SoundTouch 库特点:
(1)开源实现;
(2)使用GNU C 编译器 (gcc)或Visual C++支持任何处理器和操作系统平台:Windows、Mac OS、Linux 和其他*nixes、Raspberry Pi、Android、Apple iOS等等;
(3)支持 16 位整数和 32 位浮点单声道/立体声/多声道音频格式;
(4)可以进行实时音频处理;
(5)最大输入/输出流延迟 ~ 100 毫秒;
(6)使用 133 Mhz Intel Pentium 处理器或更好的处理器可以实现 CD 质量立体声的真实处理;
(7)通过单个 C++ 类实现简单的编程接口;
(8)C++、C# 和 Java 示例应用程序;
(9)用于从 C#、Pascal/Delphi 和 Java 调用 SoundTouch 库例程的 API 接口模块;
(10)使用针对 x86 处理器的 MMX 和 SSE 指令集优化以及针对通用多核 CPU 的 OpenMP 优化的 C++ 实现。

在这里插入图片描述
点击官网上图中源码链接:https://codeberg.org/soundtouch/soundtouch
SoundTouch源码链接
在这里插入图片描述
进入源码网站,点击上图标记位置,进行下载
下载后解压到当前文件夹(下载文件为soundtouch-master.zip,解压为soundtouch)
在这里插入图片描述

二. 工程编译准备

进入解压文件soundtouch文件夹目录下…\soundtouch\source\SoundTouchDLL\DllTest
文件夹,
VS语音信号处理(6) C语言调用SoundTouch进行变速不变调工程实例_第1张图片
双击DllTest.vcxproj,以VS2015打开工程如下图所示(包含三个工程,主要是互有调用,所以需要一起进行编译运行)
VS语音信号处理(6) C语言调用SoundTouch进行变速不变调工程实例_第2张图片
根据输出栏的提示信息:

E:\PROJECT\VS\soundtouch\source\SoundTouchDLL\SoundTouchDLL.vcxproj : warning  : 无法找到 v142 的生成工具。安装 v142 可使用 v142 生成工具进行生成。

E:\PROJECT\VS\soundtouch\source\SoundTouch\SoundTouch.vcxproj : warning  : 无法找到 v142 的生成工具。安装 v142 可使用 v142 生成工具进行生成。

E:\PROJECT\VS\soundtouch\source\SoundTouchDLL\DllTest\DllTest.vcxproj : warning  : 无法找到 v142 的生成工具。安装 v142 可使用 v142 生成工具进行生成。

修改三个工程的生成平台,以SoundTouchDll为例,右键进入工程属性页,可以看到
VS语音信号处理(6) C语言调用SoundTouch进行变速不变调工程实例_第3张图片
将目标平台版本修改为:8.1(电脑为win7系统时修改,win10应该不用修改)
平台工具集修改为:v140 (v140为VS2015,v142为VS2019)
VS语音信号处理(6) C语言调用SoundTouch进行变速不变调工程实例_第4张图片
点击确定即可保存
同样的,将SoundTouch与DllTest工程的属性也修改为目标平台版本修改为:8.1,平台工具集为v140
VS语音信号处理(6) C语言调用SoundTouch进行变速不变调工程实例_第5张图片
VS语音信号处理(6) C语言调用SoundTouch进行变速不变调工程实例_第6张图片
点击生成中的重新生成解决方案
VS语音信号处理(6) C语言调用SoundTouch进行变速不变调工程实例_第7张图片
生成成功!

三. 例程实现

变速不变调例程在DllTest工程,右键点击DllTest工程,设为启动项,
再右键点击DllTest工程,点击“调试”,选择“启动新实例”,弹出以下窗口
VS语音信号处理(6) C语言调用SoundTouch进行变速不变调工程实例_第8张图片
点击“是”,弹出缺少库信息,缺少SoundRouchDllD_x64.dll库
VS语音信号处理(6) C语言调用SoundTouch进行变速不变调工程实例_第9张图片
回到解压库soundtouch的lib文件夹中
VS语音信号处理(6) C语言调用SoundTouch进行变速不变调工程实例_第10张图片
复制SoundRouchDllD_x64.dll与SoundRouchDllD_x64.lib放到DllTest.exe同目录下
VS语音信号处理(6) C语言调用SoundTouch进行变速不变调工程实例_第11张图片
重新调试,没有报错信息,即调试成功,下面介绍语音变速不变调例程实现

首先复制一个原语音infile.wav到工程目录下(DllTest目录,DllTest.cpp的同级目录)
VS语音信号处理(6) C语言调用SoundTouch进行变速不变调工程实例_第12张图片
打开DllTest工程中的DllTest.cpp文件
VS语音信号处理(6) C语言调用SoundTouch进行变速不变调工程实例_第13张图片
修改DllTest.cpp源码如下


///
/// DllTest.cpp : This is small app main routine used for testing sound processing
/// with SoundTouch.dll API
///
/// Author        : Copyright (c) Olli Parviainen
/// Author e-mail : oparviai 'at' iki.fi
/// SoundTouch WWW: http://www.surina.net/soundtouch
///


#include 
#include 
#include 
#include "../SoundTouchDLL.h"
#include "../../SoundStretch/WavFile.h"

using namespace std;

// DllTest main
int main(int argc, char *argv[])
{
    // Check program arguments
   /* if (argc < 4)
    {
        cout << "Too few arguments. Usage: DllTest [infile.wav] [outfile.wav] [sampletype]" << endl;
        return -1;
    }*/

    //const char *inFileName = argv[1];
    //const char *outFileName = argv[2];
    //string str_sampleType = argv[3];

	const char *inFileName = "infile.wav";
	const char *outFileName = "outfile.wav";
	string str_sampleType = "short";


    bool floatSample;
    if (str_sampleType.compare("float") == 0)
    {
        floatSample = true;
    }
    else if (str_sampleType.compare("short") == 0)
    {
        floatSample = false;
    }
    else
    { 
        cerr << "Missing or invalid sampletype '" << str_sampleType << "'. Expected either short or float" << endl;
        return -1;
    }

    try
    {
        // Open input & output WAV files
        WavInFile inFile(inFileName);
        int numChannels = inFile.getNumChannels();
        int sampleRate = inFile.getSampleRate();
        WavOutFile outFile(outFileName, sampleRate, inFile.getNumBits(), numChannels);

        // Create SoundTouch DLL instance
        HANDLE st = soundtouch_createInstance();
        soundtouch_setChannels(st, numChannels);
        soundtouch_setSampleRate(st, sampleRate);
        soundtouch_setPitchSemiTones(st, 2);

		soundtouch_setTempo(st, 2);
		//soundtouch_setTempoChange(st,100);

        cout << "processing with soundtouch.dll routines";

        if (floatSample)
        {
            // Process file with SoundTouch.DLL float sample (default) API
            float fbuffer[2048];
            int nmax = 2048 / numChannels;

            cout << " using float api ..." << endl;
            while (inFile.eof() == false)
            {
                int n = inFile.read(fbuffer, nmax * numChannels) / numChannels;
                soundtouch_putSamples(st, fbuffer, n);
                do
                {
                    n = soundtouch_receiveSamples(st, fbuffer, nmax);
                    outFile.write(fbuffer, n * numChannels);
                } while (n > 0);
            }
        }
        else
        {
            // Process file with SoundTouch.DLL int16 (short) sample API.
            // Notice that SoundTouch.dll does internally processing using floating
            // point routines so the int16 API is not any faster, but provided for 
            // convenience.
            short i16buffer[2048];
            int nmax = 2048 / numChannels;

            cout << " using i16 api ..." << endl;
            while (inFile.eof() == false)
            {
                int n = inFile.read(i16buffer, nmax * numChannels) / numChannels;
                soundtouch_putSamples_i16(st, i16buffer, n);
                do
                {
                    n = soundtouch_receiveSamples_i16(st, i16buffer, nmax);
                    outFile.write(i16buffer, n * numChannels);
                } while (n > 0);
            }
        }

        soundtouch_destroyInstance(st);
        cout << "done." << endl;
    }
    catch (const runtime_error &e)
    {
        cerr << e.what() << endl;
    }

    return 0;
}

重新调试运行DllTest工程
VS语音信号处理(6) C语言调用SoundTouch进行变速不变调工程实例_第14张图片
调试成功!
VS语音信号处理(6) C语言调用SoundTouch进行变速不变调工程实例_第15张图片
生成一个outfile.wav文件,生成语音信息如下
VS语音信号处理(6) C语言调用SoundTouch进行变速不变调工程实例_第16张图片
oufile.wav语音已加速一倍
变速指令为第68行(soundtouch_setTempo与soundtouch_setTempoChange军可以进行变速不变调,但两者参数范围不一样)

soundtouch_setTempo(st, 2);
//soundtouch_setTempoChange(st,100);

两个函数的定义(SoundTouchDll.cpp中)VS语音信号处理(6) C语言调用SoundTouch进行变速不变调工程实例_第17张图片
cooledit查看两段语音
VS语音信号处理(6) C语言调用SoundTouch进行变速不变调工程实例_第18张图片
可以看到处理的非常不错,相比sonic确实好不少。

四. 小结

最近项目上需要对WAV语音进行处理,这个是对语音进行加速减速播放时需要保证语音不失真,目前工程已经可以跑通,但目前SoundTouchDll源码工程DllTest需要包含两个工程,所以下一篇文章将介绍将三个工程进行整合,合并到一个工程中,后续再整合到一个函数中,即可直接对语音进行变速不变调调用处理,完成调试后再进行具体的介绍。

你可能感兴趣的:(VP1:语音信号处理,soundtouch,变速不变调,语音信号处理,c++,VS2015)