使用SoundTouch库写一个歌声合成程序

  以前在学习WAV文件格式的时候发现了一个叫SoundTouch的开源小众库,提供WAV音频的变调和变速功能。这几天忽然想起来这个库,无聊的我就写了一个简单的歌声合成程序。功能和质量都比不上专业的音频合成软件,而且我也不想再做下去了......

  这个简单的歌声合成程序,我称它为FA♂乐器好了,因为音源是FA(滑稽

http://files.cnblogs.com/files/CodeMIRACLE/fa.zip

  我的开发环境是win10 CodeBlock+Mingw32,我没有预先编译这个库,直接把源代码添加到工程里。source\SouthStretch文件夹里面有个WavFile.cpp提供了一系列对WAV文件操作的函数,很方便,我直接加进工程里使用。

  程序的设计参考了官方SouthStretch的实现。编译的时候这个库的SSE和MMX优化会报编译错误,我就把那些优化的代码都注释掉了。

  SoundTouch的使用十分简单

  1  #include <stdexcept>
  2  #include <stdio.h>
  3  #include <string.h>
  4  #include <time.h>
  5  #include<cstdlib>
  6  #include "WavFile.h"
  7  #include "SoundTouch.h"
  8  #include "BPMDetect.h"
  9  #include<iostream>
 10  #include<algorithm>
 11  #include "STTypes.h"
 12  #include <vector>
 13  #include <sstream>
 14  #include <map>
 15  #include <windows.h>
 16  using namespace soundtouch;
 17  using namespace std;
 18  #define BUFF_SIZE           6720
 19  map<string,int> tonemap;
 20  template<class T>
 21  string tostring(T& x)
 22  {
 23      stringstream ss;
 24      ss<<x;
 25      return ss.str();
 26  }
 27  void InitToneMap()
 28  {
 29      string keys[]={"C","C#","D","D#","E","F","F#","G","G#","A","A#","B"};
 30      for(int i=0;i<=10;i++)
 31      {
 32          for(int j=0;j<12;j++)
 33             tonemap[keys[j]+tostring(i)]=i*12+j-82;
 34      }
 35  }
 36  void WriteVoidSample(WavOutFile* wavout,SoundTouch* pSoundTouch,int num,int channels,double tempo)
 37  {
 38          short *sampleBuffer=new short[num];
 39          memset(sampleBuffer,0,sizeof(short)*num);
 40          pSoundTouch->setTempo(tempo);
 41          pSoundTouch->putSamples(sampleBuffer,num/channels);
 42          pSoundTouch->receiveSamples(sampleBuffer,num);
 43          wavout->write(sampleBuffer,num);
 44          delete []sampleBuffer;
 45  }
 46  void WriteProcessSample(WavInFile* wavin,WavOutFile* wavout,SoundTouch* pSoundTouch,int tone,double tempo)
 47  {
 48          int nSamples;
 49          int nChannels;
 50          int buffSizeSamples;
 51          short *sampleBuffer=new short[BUFF_SIZE];
 52          pSoundTouch->setPitchSemiTones(tone);
 53          pSoundTouch->setTempo(tempo);
 54          while(!wavin->eof())
 55          {
 56              int num;
 57              num = wavin->read(sampleBuffer, BUFF_SIZE);
 58              nSamples = num / (int)wavin->getNumChannels();
 59              nChannels = (int)wavin->getNumChannels();
 60              buffSizeSamples = BUFF_SIZE / nChannels;
 61              pSoundTouch->putSamples(sampleBuffer, nSamples);
 62              do
 63              {
 64                  nSamples = pSoundTouch->receiveSamples(sampleBuffer,buffSizeSamples);
 65                  wavout->write(sampleBuffer, nSamples * nChannels);
 66              } while (nSamples != 0);
 67          }
 68          wavin->rewind();
 69          pSoundTouch->clear();
 70          delete []sampleBuffer;
 71  }
 72  int main()
 73  {
 74      FILE* fp=fopen("tone.txt","r");
 75      if(fp)
 76      {
 77          WavInFile *wavin;
 78          WavOutFile *wavout;
 79          SoundTouch *pSoundTouch;
 80          wavin = new WavInFile("fa.wav");
 81          pSoundTouch = new SoundTouch;
 82          pSoundTouch->setSampleRate(wavin->getSampleRate());
 83          pSoundTouch->setChannels(wavin->getNumChannels());
 84          wavout = new WavOutFile("out.wav",wavin->getSampleRate(),wavin->getNumBits(),wavin->getNumChannels());
 85          InitToneMap();
 86          char tone[4];
 87          double meter;
 88          while(~fscanf(fp,"%s%lf",tone,&meter))
 89          {
 90                  if(tone[0]!=‘0‘)
 91                      WriteProcessSample(wavin,wavout,pSoundTouch,tonemap[tone],1/meter);
 92                  else
 93                      WriteVoidSample(wavout,pSoundTouch,wavin->getDataSizeInBytes(),wavin->getNumChannels(),1/meter);
 94          }
 95          delete wavin;
 96          delete wavout;
 97          delete pSoundTouch;
 98          PlaySound("out.wav",NULL,SND_SYNC);
 99      }
100  }
时间: 2024-11-05 21:59:18

使用SoundTouch库写一个歌声合成程序的相关文章

DuiLib学习笔记2——写一个简单的程序

我们要独立出来自己创建一个项目,在我们自己的项目上加皮肤这才是初衷.我的新建项目名为:duilibTest 在duilib根目录下面有个 Duilib入门文档.doc 我们就按这个教程开始入门 首先新建一个win32项目 去DuiLib根目录,把目录下DuiLib文件夹拷贝到新建项目的根目录.再把这个项目添加进我们解决方案中. 从教程里面把以下代码粘贴到我们项目的stdafx.h中 // Duilib使用设置部分 #pragma once #define WIN32_LEAN_AND_MEAN

利用列表的知识写一个购物小程序

利用列表,写一个购物小程序,实现显示商品,显示余额,显示购物车的商品,可以随时退出. 1 product_list = [ 2 ('Mac', 9000), 3 ('Kindle', 800), 4 ('tesla', 900000), 5 ('python book', 105), 6 ('bike', 2000), 7 ] 8 9 saving = input('please input your money:') 10 shopping_car = [] 11 if saving.isdi

写一个c语言程序

在Mac系统环境下编写第一个C语言程序,最后把程序运行起来,跟计算机做一个小小的互动 一.编写第一个C语言程序-Hello World 为什么称第一个程序为“Hello Wolrd”呢?其实计算机行业里面,学习任何技术的第一个程序都可以称为“Hello World”.“Hello World”的字面意思是“你好,世界”,也就是跟世界打招呼.我们第一个程序在这世界上诞生了,那肯定要跟世界打声招呼嘛,所以就称为“Hello World”. 1.用什么工具写代码 首先我们要做的肯定是写代码,在代码里面

手把手教你写一个RN小程序!

时间过得真快,眨眼已经快3年了! 1.我的第一个App 还记得我14年初写的第一个iOS小程序,当时是给别人写的一个单机的相册,也是我开发的第一个完整的app,虽然功能挺少,但是耐不住心中的激动啊,现在我开始学react native,那么现在对于react native也算是有所了解了,就用网上的接口开发一个小程序,现在带大家来写这个程序!接口是用看知乎的API,简简单单的只有get,可以从这里入门,也算是带大家入门吧,过后我会把源代码放在我的github上,前期项目肯定特别简陋,后面慢慢来优

自己写一个chrome扩展程序 - 右键菜单扩展

最近在学习Spring,心想dotnet如何实现类似形式呢.于是想认真学习Casetle组件,发现没有书籍!而spring的书多得很.于是只好找网上教程了.发现系统的文章不多.Terrylee好多文章似乎都旧了,只好回头来看官方的文档.英文呀!好些单词需要去查,于是想到划词翻译.下载几个扩展程序提示不安全!好吧,自己写一个!开放的体系就是好! 百度搜一下好多的例子,不过几乎都没说background.js是怎么放在manifest.json.大部分代码来自这里 http://www.cnblog

硬货 | 利用 Linux tap/tun 虚拟设备写一个 ICMP echo 程序

本文首发于我的公众号 CloudDeveloper(ID: cloud_dev),专注于干货分享,号内有大量书籍和视频资源,后台回复「1024」即可领取,欢迎大家关注,二维码文末可以扫. 前面两篇文章已经介绍过 tap/tun 的原理和配置工具.这篇文章通过一个编程示例来深入了解 tap/tun 的程序结构. 01 准备工作 首先通过 modinfo tun 查看系统内核是否支持 tap/tun 设备驱动. [root@by ~]# modinfo tun filename: /lib/modu

用什么库写 Python 命令行程序?看这一篇就够了

作者:HelloGitHub-Prodesire HelloGitHub 的<讲解开源项目>系列,项目地址:https://github.com/HelloGitHub-Team/Article 一.前言 在近半年的 Python 命令行旅程中,我们依次学习了 argparse.docopt.click 和 fire 库的特点和用法,逐步了解到 Python 命令行库的设计哲学与演变. 本文作为本次旅程的终点,希望从一个更高的视角对这些库进行横向对比,总结它们的异同点和使用场景,以期在应对不同

用c-free 5写一个入门的程序

本文记录了在windows系统中使用C-FREE 5新建一个Hello HoverTree程序的步骤. 安装好C-Free 5之后,打开.新建一个工程: 附C-Free 5下载:http://hovertree.com/h/bjaf/xrjx4nht.htm 选择工程类型,保存位置,并输入工程名称,这里选择控制台程序,工程名称为HelloHoverTree: 选择空程序选择ming5: 新建一个文件,并保存: 保存的时候选择保存为C语言文件: 选择确定,添加到工程中:输入以下程序: void m

跟我一起写一个chrome扩展程序

在我没有看这本书之前,我都想象不到,原来chrome扩展程序可以这样写,真的非常有意思. 就是用最简单最基础的代码,然后就实现了一些非常有意思的玩意儿. 先看效果图 实际运用要和现实联系在一起,经历和知识的体系不断的关联,才不会忘记 学习的知识如果在现实工作中没有用到,就会淡忘它.经历要达到一定的程度,项目要达到一定的阶段 这个就是一个很简单的例子,当我们输入facebook网站,就会弹出一个弹框,然后我们输入名字,这个网站就会被我们输入的名字所代替. 这个网站换成随便什么网站都是可以的.接下来