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


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

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

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

      我的开发环境是win10 CodeBlock+Mingw32,我没有预先编译这个库,直接把源代码添加到工程里。sourceSouthStretch文件夹里面有个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  }
    
  • 相关阅读:
    vmware 虚拟机共享 windows 目录
    下载 golang.org/x 包出错不用代理的解决办法
    c++小游戏——彩票
    恶意代码要注意
    Pascal到c++,求大佬翻译!
    【CYH-01】小奔的国庆练习赛:赛后标程
    鸽巢原理及其扩展——Ramsey定理
    区块链,你知道多少?
    go语言
    10.2:异或树经验
  • 原文地址:https://www.cnblogs.com/CodeMIRACLE/p/5514806.html
Copyright © 2020-2023  润新知