,直接在include包含SoundTouch目录下的include路径,接着在lib添加SoundTouch目录下
的lib路径,然后在代码的头文件中添加头文件以及引用的库。如下:根据_DEBUG这个宏,
我们可以进行一些编译预处理,假如是以DEBUG编译就采用debug库,其他的话就采用
release库。他们的区别就是文件名后面是否多了一个“D”。
#include <SoundTouch.h>
#ifdef _DEBUG
#pragma comment(lib, "SoundTouchD.lib")
#else
#pragma comment(lib, "SoundTouch.lib")
#endif
当然你也可以直接在vc的项目工程中直接添加,某些人比较喜欢如此。
最重要的一点还要声明一个命名空间,至于原因,和SoundTouch这个库的声明定义有关,
以下在分析的时候会提到。
using namespace soundtouch
然后就可以直接在自己的代码中定义一个类变量SoundTouch m_SoundTouch
SoundTouch 类的声明包含在SoundTouch.h和SoundTouch.cpp之中,由FIFOProcessor类直
接派生,而FIFOProcessor类又直接从基类FIFOSamplePipe派生。同时声明SoundTouch这个
类包含在命名空间 soundtouch,这就是为什么我们使用这个库的时候需要声明命名空间的
主要原因。感觉有点多余。且仅仅定义了一些常量,诸如版本号,版本ID号等等,这两个
父类都包含在FIFOSamplePipe.h和FIFOSamplePipe.cpp文件中。
不管什么库,如果要使用的话,一般的流程都是先定义然后进行一些必要的初始化,
SoundTouch(以下简称ST)也不例外。ST的初始化也和他的编译一样异常的简单,具体可以
参考他的例子SoundStretch来实现,也可以参考源代码中有关SoundTouch这个类的声明,
现在只关心我们会用到的那部分,可以看到在private中定义了另外两个类指针
RateTransposer*,TDStretch*;
RateTransposer从FIFOProcessor派生,而FIFOProcessor又直接从基类FIFOSamplePipe派
生,TDStretch和RateTransposer类似。由此可见,单单从两个类的名字上看:拉长?传输
速率?不难想象出这个库对声音信号的处理可能就是“拉长”,然后“变速”。难道就是传说
中的不变调变速?事实正是如此。这还不是我们现在关心的话题。
……
private:
/// Rate transposer class instance
class RateTransposer *pRateTransposer
/// Time-stretch class instance
class TDStretch *pTDStretch
/// Virtual pitch parameter. Effective rate &tempo are calculated from
these parameters.
float virtualRate
/// Virtual pitch parameter. Effective rate &tempo are calculated from
these parameters.
float virtualTempo
/// Virtual pitch parameter. Effective rate &tempo are calculated from
these parameters.
float virtualPitch
/// Flag: Has sample rate been set?
BOOL bSrateSet
/// Calculates effective rate &tempo valuescfrom 'virtualRate',
'virtualTempo' and
/// 'virtualPitch' parameters.
void calcEffectiveRateAndTempo()
protected :
/// Number of channels
uint channels
/// Effective 'rate' value calculated from 'virtualRate', 'virtualTempo'
and 'virtualPitch'
float rate
/// Effective 'tempo' value calculated from 'virtualRate', 'virtualTempo'
and 'virtualPitch'
float tempo
/// Sets new rate control value. Normal rate = 1.0, smaller values
/// represent slower rate, larger faster rates.
void setRate(float newRate)
/// Sets new tempo control value. Normal tempo = 1.0, smaller values
/// represent slower tempo, larger faster tempo.
void setTempo(float newTempo)
/// Sets new rate control value as a difference in percents compared
/// to the original rate (-50 .. +100 %)
void setRateChange(float newRate)
/// Sets new tempo control value as a difference in percents compared
/// to the original tempo (-50 .. +100 %)
void setTempoChange(float newTempo)
/// Sets new pitch control value. Original pitch = 1.0, smaller values
/// represent lower pitches, larger values higher pitch.
void setPitch(float newPitch)
/// Sets pitch change in octaves compared to the original pitch
/// (-1.00 .. +1.00)
void setPitchOctaves(float newPitch)
/// Sets pitch change in semi-tones compared to the original pitch
/// (-12 .. +12)
void setPitchSemiTones(int newPitch)
void setPitchSemiTones(float newPitch)
/// Sets the number of channels, 1 = mono, 2 = stereo
void setChannels(uint numChannels)
/// Sets sample rate.
void setSampleRate(uint srate)
/// Changes a setting controlling the processing system behaviour. See the
/// 'SETTING_...' defines for available setting ID's.
/// /return 'TRUE' if the setting was succesfully changed
BOOL setSetting(int settingId, ///<Setting ID number. see SETTING_...
defines.
int value///<New setting value.
)
……
参考ST提供的例子SoundStretch,初始化SoundTouch这个类:
m_SoundTouch.setSampleRate(sampleRate)//设置声音的采样频率
m_SoundTouch.setChannels(channels)//设置声音的声道
m_SoundTouch.setTempoChange(tempoDelta)//这个就是传说中的变速不变调
m_SoundTouch.setPitchSemiTones(pitchDelta)//设置声音的pitch
m_SoundTouch.setRateChange(rateDelta)//设置声音的速率
// quick是一个bool变量,USE_QUICKSEEK具体有什么用我暂时也不太清楚。
m_SoundTouch.setSetting(SETTING_USE_QUICKSEEK, quick)
// noAntiAlias是一个bool变量,USE_AA_FILTER具体有什么用我暂时也不太清楚。
m_SoundTouch.setSetting(SETTING_USE_AA_FILTER, !(noAntiAlias))
// speech也是一个bool变量,初步估计可能是没有音乐只有人声的时候,需要设置一下。
if (speech)
{
// use settings for speech processing
m_SoundTouch.setSetting(SETTING_SEQUENCE_MS, 40)
m_SoundTouch.setSetting(SETTING_SEEKWINDOW_MS, 15)
m_SoundTouch.setSetting(SETTING_OVERLAP_MS, 8)
fprintf(stderr, "Tune processing parameters for speech processing./n")
}
通过那么简单的几个函数调用,现在我们就可以感受一下ST的强大。通过SoundTouch类提
供的函数调用方法:
putSamples(sampleBuffer,nSamples)
第一个参数为一个指向PCM编码的一段音频数据的指针,第二个参数就是要处理多少个
sample也可以理解为多少帧。
需要注意的是,一般数据流都是字节流,也就是说,sample的大小和声道、位的声音参数
有关,假如sampleBuffer指针指向一个 长度为64bytes的一个PCM数据缓冲区,16位2声道
,那么实际上这里只存放了(16*2)/8=4bytes,64/4=1616个sample,这是我们需要注意的
地方。m_SoundTouch.putSamples(sampleBuffer, nSamples)数据是传进去了,可是从哪
里接收处理过的音频数据呢?这个时候我们就要用SoundTouch提供的receiveSamples函数
调用方法。
uint receiveSamples(SAMPLETYPE *outBuffer, ///<Buffer where to copy output
samples.
uint maxSamples///<How many samples to receive at max.
)他也是两个参数,第一个为接收数据的参数,第二个最大可以接收多少sample。
通过这段注释,大概明白receiveSamples这个函数不会在putSamples之后马上返回数据,
另外一方面有可能返回比maxSamples更多的数据,因此需要放在一个do…while(…)的循环里
面把他们都榨干。
// Read ready samples from SoundTouch processor &write them output file.
// NOTES:
// - 'receiveSamples' doesn't necessarily return any samples at all
// during some rounds!
// - On the other hand, during some round 'receiveSamples' may have more
// ready samples than would fit into 'sampleBuffer', and for this reason
// the 'receiveSamples' call is iterated for as many times as it
// outputs samples.
do
{
nSamples = m_SoundTouch.receiveSamples(sampleBuffer, buffSizeSamples)
//把sampleBuffer写入一个文件,或者填充进声卡的缓冲区,播放声音。
} while (nSamples != 0)
今天就先写到这里,比较劳累。
转载
加上头文件 #include <mmsystem.h>音频文件名改用英文 ASCII 字符,不含空格,而且要确认 音频文件 路径正确,名字拼写无误。可以是 mp3, wma, wav 等格式歌曲
#include<iostream>
using namespace std
#include <stdio.h>
#include <windows.h>
#include <mmsystem.h>
#pragma comment(lib, "winmm.lib")
int main()
{
PlaySound (TEXT("E:\\kugoumusic\\ssjs.mp3"), NULL, SND_ASYNC | SND_NODEFAULT)
while (1)
{
cout <<"program is running... here\n"
Sleep(1000)
}
return 0
}
手机也不能播放吧,应该是程序有错,最好把程序贴出来。可以参考这个程序
http://blog.csdn.net/peijiangping1989/article/details/7042610
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)