SoundTouch音頻處理庫的使用異常簡單,經過簡單的編譯之後,設定編譯環境,以vc為例
,直接在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=16;16個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);
今天就先寫到這裡,比較勞累。
本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/suhetao/archive/2010/08/27/5843480.aspx