- 前言
- 一. 源码下载即链接库准备
- 二. 工程编译准备
- 三. 例程实现
- 四. 小结
语音识别相关算法一般在MATLAB上进行仿真验证与实验,在工程上一般还是在VS中进行实现落地,本系列将介绍语音信号处理在C语言中的一系列应用,后期将以此为基础,再落地移植到嵌入式平台。
今天介绍SoundTouch语音变速不变调算法的工程应用。SoundTouch是一个支持音频倍速播放的开源库。支持变速(加速减速)、变调、变速同时变调等三类功能模块,能够对流媒体实时操作,也能对音频文件操作。采用 32 位浮点或者 16 位定点,支持单声道或者双声道,采样率范围为 8k~48k。
上一篇文章已经介绍了下载SoundTouch源码在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)
根据调试成功的记录可知,所有的源码都在上述文件夹中,新建一个SoundTouchFile文件夹,将上述解压文件soundtouch中source目录SoundStretch文件中的以下选中文件复制到SoundTouchFile文件夹。
再将解压文件soundtouch中source目录SoundTouch文件中的以下选中文件复制到SoundTouchFile文件夹。
再将解压文件soundtouch中source目录SoundTouchDll文件中的以下文件复制到SoundTouchFile文件夹。
再将解压文件soundtouch中include目录中的以下文件复制到SoundTouchFile文件夹。
SoundTouchFile的文件夹如下图所示:
下面新建工程进行集成。
二. 工程编译准备打开VS2015
点击新建一个项目(工程)
点击“确定”,创建项目
将SoundTouchFile文件夹复制到该工程目录下,如下图所示
左侧解决方案资源管理器视图中,头文件栏右键添加现有项,将SoundTouchFile中所有.h的头文件全部添加进来,如下图所示
左侧解决方案资源管理器视图中,源文件栏右键添加现有项,将SoundTouchFile中所有.cpp的源文件全部添加进来,如下图所示
选择编译平台为x64,点击“生成解决方案”
出现如下报错信息
1>------ 已启动全部重新生成: 项目: Project6, 配置: Debug x64 ------ 1> WavFile.cpp 1>e:projectvsproject6project6soundtouchfilewavfile.cpp(175): error C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. 1> c:program files (x86)windows kits10include10.0.10240.0ucrtstdio.h(205): note: 参见“fopen”的声明 1>e:projectvsproject6project6soundtouchfilewavfile.cpp(709): error C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. 1> c:program files (x86)windows kits10include10.0.10240.0ucrtstdio.h(205): note: 参见“fopen”的声明 1> TDStretch.cpp 1> sse_optimized.cpp 1> SoundTouchDLL.cpp 1>e:projectvsproject6project6soundtouchfilesoundtouchdll.cpp(86): error C2491: “soundtouch_createInstance”: 不允许 dllimport 函数 的定义 1>e:projectvsproject6project6soundtouchfilesoundtouchdll.cpp(104): error C2491: “soundtouch_destroyInstance”: 不允许 dllimport 函数 的定义 1>e:projectvsproject6project6soundtouchfilesoundtouchdll.cpp(117): error C2491: “soundtouch_getVersionString”: 不允许 dllimport 函数 的定义 1>e:projectvsproject6project6soundtouchfilesoundtouchdll.cpp(125): error C2491: “soundtouch_getVersionString2”: 不允许 dllimport 函数 的定义 1>e:projectvsproject6project6soundtouchfilesoundtouchdll.cpp(126): error C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. 1> c:program files (x86)windows kits10include10.0.10240.0ucrtstring.h(346): note: 参见“strncpy”的声明 1>e:projectvsproject6project6soundtouchfilesoundtouchdll.cpp(133): error C2491: “soundtouch_getVersionId”: 不允许 dllimport 函数 的定义 1>e:projectvsproject6project6soundtouchfilesoundtouchdll.cpp(140): error C2491: “soundtouch_setRate”: 不允许 dllimport 函数 的定义 1>e:projectvsproject6project6soundtouchfilesoundtouchdll.cpp(151): error C2491: “soundtouch_setTempo”: 不允许 dllimport 函数 的定义 1>e:projectvsproject6project6soundtouchfilesoundtouchdll.cpp(161): error C2491: “soundtouch_setRateChange”: 不允许 dllimport 函数 的定义 1>e:projectvsproject6project6soundtouchfilesoundtouchdll.cpp(171): error C2491: “soundtouch_setTempoChange”: 不允许 dllimport 函数 的定义 1>e:projectvsproject6project6soundtouchfilesoundtouchdll.cpp(181): error C2491: “soundtouch_setPitch”: 不允许 dllimport 函数 的定义 1>e:projectvsproject6project6soundtouchfilesoundtouchdll.cpp(191): error C2491: “soundtouch_setPitchOctaves”: 不允许 dllimport 函数 的定义 1>e:projectvsproject6project6soundtouchfilesoundtouchdll.cpp(201): error C2491: “soundtouch_setPitchSemiTones”: 不允许 dllimport 函数 的定义 1>e:projectvsproject6project6soundtouchfilesoundtouchdll.cpp(211): error C2491: “soundtouch_setChannels”: 不允许 dllimport 函数 的定义 1>e:projectvsproject6project6soundtouchfilesoundtouchdll.cpp(228): error C2491: “soundtouch_setSampleRate”: 不允许 dllimport 函数 的定义 1>e:projectvsproject6project6soundtouchfilesoundtouchdll.cpp(251): error C2491: “soundtouch_flush”: 不允许 dllimport 函数 的定义 1>e:projectvsproject6project6soundtouchfilesoundtouchdll.cpp(275): error C2491: “soundtouch_putSamples”: 不允许 dllimport 函数 的定义 1>e:projectvsproject6project6soundtouchfilesoundtouchdll.cpp(298): error C2491: “soundtouch_putSamples_i16”: 不允许 dllimport 函数 的定义 1>e:projectvsproject6project6soundtouchfilesoundtouchdll.cpp(329): error C2491: “soundtouch_clear”: 不允许 dllimport 函数 的定义 1>e:projectvsproject6project6soundtouchfilesoundtouchdll.cpp(344): error C2491: “soundtouch_setSetting”: 不允许 dllimport 函数 的定义 1>e:projectvsproject6project6soundtouchfilesoundtouchdll.cpp(358): error C2491: “soundtouch_getSetting”: 不允许 dllimport 函数 的定义 1>e:projectvsproject6project6soundtouchfilesoundtouchdll.cpp(368): error C2491: “soundtouch_numUnprocessedSamples”: 不允许 dllimport 函数 的定义 1>e:projectvsproject6project6soundtouchfilesoundtouchdll.cpp(385): error C2491: “soundtouch_receiveSamples”: 不允许 dllimport 函数 的定义 1>e:projectvsproject6project6soundtouchfilesoundtouchdll.cpp(406): error C2491: “soundtouch_receiveSamples_i16”: 不允许 dllimport 函数 的定义 1>e:projectvsproject6project6soundtouchfilesoundtouchdll.cpp(454): error C2491: “soundtouch_numSamples”: 不允许 dllimport 函数 的定义 1>e:projectvsproject6project6soundtouchfilesoundtouchdll.cpp(464): error C2491: “soundtouch_isEmpty”: 不允许 dllimport 函数 的定义 1>e:projectvsproject6project6soundtouchfilesoundtouchdll.cpp(473): error C2491: “bpm_createInstance”: 不允许 dllimport 函数 的定义 1>e:projectvsproject6project6soundtouchfilesoundtouchdll.cpp(498): error C2491: “bpm_destroyInstance”: 不允许 dllimport 函数 的定义 1>e:projectvsproject6project6soundtouchfilesoundtouchdll.cpp(513): error C2491: “bpm_putSamples”: 不允许 dllimport 函数 的定义 1>e:projectvsproject6project6soundtouchfilesoundtouchdll.cpp(526): error C2491: “bpm_putSamples_i16”: 不允许 dllimport 函数 的定义 1>e:projectvsproject6project6soundtouchfilesoundtouchdll.cpp(561): error C2491: “bpm_getBpm”: 不允许 dllimport 函数 的定义 1> SoundTouch.cpp 1> RunParameters.cpp 1> RateTransposer.cpp 1> PeakFinder.cpp 1> mmx_optimized.cpp 1> main.cpp 1> InterpolateShannon.cpp 1> InterpolateLinear.cpp 1> InterpolateCubic.cpp 1> FIRFilter.cpp 1> FIFOSampleBuffer.cpp 1> cpu_detect_x86.cpp 1> BPMDetect.cpp 1> AAFilter.cpp 1> 正在生成代码... ========== 全部重新生成: 成功 0 个,失败 1 个,跳过 0 个 ==========
根据报错提示可知宏定义未找到,进入项目属性页C/C++的预处理器定义中添加_CRT_SECURE_NO_WARNINGS与DLL_EXPORTS,
点击“确定”,重新生成解决方案
生成成功!将原压缩文件soundtouch中的lib文件夹复制到工程中,在项目属性VC++目录的库目录中添加lib文件夹如下
点击“确定”
点击“确定”,修改mian.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 "SoundTouchFile/SoundTouchDLL.h" #include "SoundTouchFile/WavFile.h" using namespace std; // DllTest main int main(int argc, char *argv[]) { // Check program arguments const char *inFileName = "infile.wav"; const char *outFileName = "outfile2.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_setTempoChange(st, -50); soundtouch_setTempo(st, 3); 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; }
导入一个语音文件infile.wav到工程目录下
三. 例程实现点击“调试”运行,生成一个三倍速的语音文件outfile2.wav
生成语音如下图所示
cooledit查看两段语音
可以看到处理的非常不错,试听效果也比sonic确实好不少。
最近项目上需要对WAV语音进行处理,这个是对语音进行加速减速播放时需要保证语音不失真,上一篇文章介绍了实例工程调试跑通,本篇文章介绍的是将三个工程进行整合,合并到一个工程中,后续再整合到一个函数中,即可直接对语音进行变速不变调调用处理,目前根据调试结果来看确实效果不错。



