VS语音信号处理(7) C语言调用SoundTouch进行变速不变调工程集成调试

VS语音信号处理(7) C语言调用SoundTouch进行变速不变调工程集成调试

前言

语音识别相关算法一般在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:\project\vs\project6\project6\soundtouchfile\wavfile.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 kits\10\include\10.0.10240.0\ucrt\stdio.h(205): note: 参见“fopen”的声明
1>e:\project\vs\project6\project6\soundtouchfile\wavfile.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 kits\10\include\10.0.10240.0\ucrt\stdio.h(205): note: 参见“fopen”的声明
1>  TDStretch.cpp
1>  sse_optimized.cpp
1>  SoundTouchDLL.cpp
1>e:\project\vs\project6\project6\soundtouchfile\soundtouchdll.cpp(86): error C2491: “soundtouch_createInstance”: 不允许 dllimport 函数 的定义
1>e:\project\vs\project6\project6\soundtouchfile\soundtouchdll.cpp(104): error C2491: “soundtouch_destroyInstance”: 不允许 dllimport 函数 的定义
1>e:\project\vs\project6\project6\soundtouchfile\soundtouchdll.cpp(117): error C2491: “soundtouch_getVersionString”: 不允许 dllimport 函数 的定义
1>e:\project\vs\project6\project6\soundtouchfile\soundtouchdll.cpp(125): error C2491: “soundtouch_getVersionString2”: 不允许 dllimport 函数 的定义
1>e:\project\vs\project6\project6\soundtouchfile\soundtouchdll.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 kits\10\include\10.0.10240.0\ucrt\string.h(346): note: 参见“strncpy”的声明
1>e:\project\vs\project6\project6\soundtouchfile\soundtouchdll.cpp(133): error C2491: “soundtouch_getVersionId”: 不允许 dllimport 函数 的定义
1>e:\project\vs\project6\project6\soundtouchfile\soundtouchdll.cpp(140): error C2491: “soundtouch_setRate”: 不允许 dllimport 函数 的定义
1>e:\project\vs\project6\project6\soundtouchfile\soundtouchdll.cpp(151): error C2491: “soundtouch_setTempo”: 不允许 dllimport 函数 的定义
1>e:\project\vs\project6\project6\soundtouchfile\soundtouchdll.cpp(161): error C2491: “soundtouch_setRateChange”: 不允许 dllimport 函数 的定义
1>e:\project\vs\project6\project6\soundtouchfile\soundtouchdll.cpp(171): error C2491: “soundtouch_setTempoChange”: 不允许 dllimport 函数 的定义
1>e:\project\vs\project6\project6\soundtouchfile\soundtouchdll.cpp(181): error C2491: “soundtouch_setPitch”: 不允许 dllimport 函数 的定义
1>e:\project\vs\project6\project6\soundtouchfile\soundtouchdll.cpp(191): error C2491: “soundtouch_setPitchOctaves”: 不允许 dllimport 函数 的定义
1>e:\project\vs\project6\project6\soundtouchfile\soundtouchdll.cpp(201): error C2491: “soundtouch_setPitchSemiTones”: 不允许 dllimport 函数 的定义
1>e:\project\vs\project6\project6\soundtouchfile\soundtouchdll.cpp(211): error C2491: “soundtouch_setChannels”: 不允许 dllimport 函数 的定义
1>e:\project\vs\project6\project6\soundtouchfile\soundtouchdll.cpp(228): error C2491: “soundtouch_setSampleRate”: 不允许 dllimport 函数 的定义
1>e:\project\vs\project6\project6\soundtouchfile\soundtouchdll.cpp(251): error C2491: “soundtouch_flush”: 不允许 dllimport 函数 的定义
1>e:\project\vs\project6\project6\soundtouchfile\soundtouchdll.cpp(275): error C2491: “soundtouch_putSamples”: 不允许 dllimport 函数 的定义
1>e:\project\vs\project6\project6\soundtouchfile\soundtouchdll.cpp(298): error C2491: “soundtouch_putSamples_i16”: 不允许 dllimport 函数 的定义
1>e:\project\vs\project6\project6\soundtouchfile\soundtouchdll.cpp(329): error C2491: “soundtouch_clear”: 不允许 dllimport 函数 的定义
1>e:\project\vs\project6\project6\soundtouchfile\soundtouchdll.cpp(344): error C2491: “soundtouch_setSetting”: 不允许 dllimport 函数 的定义
1>e:\project\vs\project6\project6\soundtouchfile\soundtouchdll.cpp(358): error C2491: “soundtouch_getSetting”: 不允许 dllimport 函数 的定义
1>e:\project\vs\project6\project6\soundtouchfile\soundtouchdll.cpp(368): error C2491: “soundtouch_numUnprocessedSamples”: 不允许 dllimport 函数 的定义
1>e:\project\vs\project6\project6\soundtouchfile\soundtouchdll.cpp(385): error C2491: “soundtouch_receiveSamples”: 不允许 dllimport 函数 的定义
1>e:\project\vs\project6\project6\soundtouchfile\soundtouchdll.cpp(406): error C2491: “soundtouch_receiveSamples_i16”: 不允许 dllimport 函数 的定义
1>e:\project\vs\project6\project6\soundtouchfile\soundtouchdll.cpp(454): error C2491: “soundtouch_numSamples”: 不允许 dllimport 函数 的定义
1>e:\project\vs\project6\project6\soundtouchfile\soundtouchdll.cpp(464): error C2491: “soundtouch_isEmpty”: 不允许 dllimport 函数 的定义
1>e:\project\vs\project6\project6\soundtouchfile\soundtouchdll.cpp(473): error C2491: “bpm_createInstance”: 不允许 dllimport 函数 的定义
1>e:\project\vs\project6\project6\soundtouchfile\soundtouchdll.cpp(498): error C2491: “bpm_destroyInstance”: 不允许 dllimport 函数 的定义
1>e:\project\vs\project6\project6\soundtouchfile\soundtouchdll.cpp(513): error C2491: “bpm_putSamples”: 不允许 dllimport 函数 的定义
1>e:\project\vs\project6\project6\soundtouchfile\soundtouchdll.cpp(526): error C2491: “bpm_putSamples_i16”: 不允许 dllimport 函数 的定义
1>e:\project\vs\project6\project6\soundtouchfile\soundtouchdll.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 <string>
#include <iostream>
#include <fstream>
#include "SoundTouchFile/SoundTouchDLL.h"
#include "SoundTouchFile/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 = "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语音进行处理,这个是对语音进行加速减速播放时需要保证语音不失真,上一篇文章介绍了实例工程调试跑通,本篇文章介绍的是将三个工程进行整合,合并到一个工程中,后续再整合到一个函数中,即可直接对语音进行变速不变调调用处理,目前根据调试结果来看确实效果不错。

猜你喜欢

转载自blog.csdn.net/sinat_34897952/article/details/124976497
今日推荐