⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tdstretch.cpp

📁 Audacity是一款用於錄音和編輯聲音的、免費的開放源碼軟體。它可以執行於Mac OS X、Microsoft Windows、GNU/Linux和其它作業系統
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************** *  * Sampled sound tempo changer/time stretch algorithm. Changes the sound tempo  * while maintaining the original pitch by using a time domain WSOLA-like  * method with several performance-increasing tweaks. * * Note : MMX optimized functions reside in a separate, platform-specific  * file, e.g. 'mmx_win.cpp' or 'mmx_gcc.cpp' * * Author        : Copyright (c) Olli Parviainen  * Author e-mail : oparviai @ iki.fi * File created  : 13-Jan-2002 * * Last changed  : $Date: 2004/10/26 19:09:37 $ * File revision : $Revision: 1.4 $ * * $Id: TDStretch.cpp,v 1.4 2004/10/26 19:09:37 vjohnson Exp $ * * License : *  *  SoundTouch sound processing library *  Copyright (c) Olli Parviainen * *  This library is free software; you can redistribute it and/or *  modify it under the terms of the GNU Lesser General Public *  License as published by the Free Software Foundation; either *  version 2.1 of the License, or (at your option) any later version. * *  This library is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU *  Lesser General Public License for more details. * *  You should have received a copy of the GNU Lesser General Public *  License along with this library; if not, write to the Free Software *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * *****************************************************************************/#include <string.h>#include <stdlib.h>#include <memory.h>#include <limits.h>#include <math.h>#include <assert.h>#include "STTypes.h"#include "cpu_detect.h"#include "TDStretch.h"using namespace soundtouch;#ifndef min#define min(a,b) ((a > b) ? b : a)#define max(a,b) ((a < b) ? b : a)#endif/***************************************************************************** * * Constant definitions * *****************************************************************************/#define MAX_SCAN_DELTA      124// Table for the hierarchical mixing position seeking algorithmint scanOffsets[4][24]={    { 124,  186,  248,  310,  372,  434,  496,  558,  620,  682,  744, 806,       868,  930,  992, 1054, 1116, 1178, 1240, 1302, 1364, 1426, 1488,   0},     {-100,  -75,  -50,  -25,   25,   50,   75,  100,    0,    0,    0,   0,        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,   0},    { -20,  -15,  -10,   -5,    5,   10,   15,   20,    0,    0,    0,   0,        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,   0},    {  -4,   -3,   -2,   -1,    1,    2,    3,    4,    0,    0,    0,   0,        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,   0}};/***************************************************************************** * * Implementation of the class 'TDStretch' * *****************************************************************************/TDStretch::TDStretch() : FIFOProcessor(&outputBuffer){    bQuickseek = FALSE;    channels = 2;    bMidBufferDirty = FALSE;    pMidBuffer = NULL;    pRefMidBufferUnaligned = NULL;    overlapLength = 0;    setParameters(44100, DEFAULT_SEQUENCE_MS, DEFAULT_SEEKWINDOW_MS, DEFAULT_OVERLAP_MS);    setTempo(1.0f);}TDStretch::~TDStretch(){    delete[] pMidBuffer;    delete[] pRefMidBufferUnaligned;}    // Calculates the x having the closest 2^x value for the given valuestatic int _getClosest2Power(double value){    return (int)(log(value) / log(2.0) + 0.5);}// Sets routine control parameters. These control are certain time constants// defining how the sound is stretched to the desired duration.//// 'sampleRate' = sample rate of the sound// 'sequenceMS' = one processing sequence length in milliseconds (default = 82 ms)// 'seekwindowMS' = seeking window length for scanning the best overlapping //      position (default = 28 ms)// 'overlapMS' = overlapping length (default = 12 ms)void TDStretch::setParameters(uint aSampleRate, uint aSequenceMS,                               uint aSeekWindowMS, uint aOverlapMS){    this->sampleRate = aSampleRate;    this->sequenceMs = aSequenceMS;    this->seekWindowMs = aSeekWindowMS;    this->overlapMs = aOverlapMS;    seekLength = (sampleRate * seekWindowMs) / 1000;    seekWindowLength = (sampleRate * sequenceMs) / 1000;    maxOffset = seekLength;    calculateOverlapLength(overlapMs);    // set tempo to recalculate 'sampleReq'    setTempo(tempo);}/// Get routine control parameters, see setParameters() function./// Any of the parameters to this function can be NULL, in such case corresponding parameter/// value isn't returned.void TDStretch::getParameters(uint *pSampleRate, uint *pSequenceMs, uint *pSeekWindowMs, uint *pOverlapMs){    if (pSampleRate)    {        *pSampleRate = sampleRate;    }    if (pSequenceMs)    {        *pSequenceMs = sequenceMs;    }    if (pSeekWindowMs)    {        *pSeekWindowMs = seekWindowMs;    }    if (pOverlapMs)    {        *pOverlapMs = overlapMs;    }}// Overlaps samples in 'midBuffer' with the samples in 'input'void TDStretch::overlapMono(SAMPLETYPE *output, const SAMPLETYPE *input) const{    int i, itemp;    for (i = 0; i < (int)overlapLength ; i ++)     {        itemp = overlapLength - i;        output[i] = (input[i] * i + pMidBuffer[i] * itemp ) / overlapLength;    // >> overlapDividerBits;    }}void TDStretch::clearMidBuffer(){    if (bMidBufferDirty)     {        memset(pMidBuffer, 0, 2 * sizeof(SAMPLETYPE) * overlapLength);        bMidBufferDirty = FALSE;    }}void TDStretch::clearInput(){    inputBuffer.clear();    clearMidBuffer();}// Clears the sample buffersvoid TDStretch::clear(){    outputBuffer.clear();    inputBuffer.clear();    clearMidBuffer();}// Enables/disables the quick position seeking algorithm. Zero to disable, nonzero// to enablevoid TDStretch::enableQuickSeek(BOOL enable){    bQuickseek = enable;}// Returns nonzero if the quick seeking algorithm is enabled.BOOL TDStretch::isQuickSeekEnabled() const{    return bQuickseek;}// Seeks for the optimal overlap-mixing position.uint TDStretch::seekBestOverlapPosition(const SAMPLETYPE *refPos){    if (channels == 2)     {        // stereo sound        if (bQuickseek)         {            return seekBestOverlapPositionStereoQuick(refPos);        }         else         {            return seekBestOverlapPositionStereo(refPos);        }    }     else     {        // mono sound        if (bQuickseek)         {            return seekBestOverlapPositionMonoQuick(refPos);        }         else         {            return seekBestOverlapPositionMono(refPos);        }    }}// Overlaps samples in 'midBuffer' with the samples in 'inputBuffer' at position// of 'ovlPos'.inline void TDStretch::overlap(SAMPLETYPE *output, const SAMPLETYPE *input, uint ovlPos) const{    if (channels == 2)     {        // stereo sound        overlapStereo(output, input + 2 * ovlPos);    } else {        // mono sound.        overlapMono(output, input + ovlPos);    }}// Seeks for the optimal overlap-mixing position. The 'stereo' version of the// routine//// The best position is determined as the position where the two overlapped// sample sequences are 'most alike', in terms of the highest cross-correlation// value over the overlapping perioduint TDStretch::seekBestOverlapPositionStereo(const SAMPLETYPE *refPos) {    uint bestOffs;    LONG_SAMPLETYPE bestCorr, corr;    uint i;    // Slopes the amplitudes of the 'midBuffer' samples    precalcCorrReferenceStereo();    bestCorr = INT_MIN;    bestOffs = 0;    // Scans for the best correlation value by testing each possible position    // over the permitted range.    for (i = 0; i < seekLength; i ++)     {        // Calculates correlation value for the mixing position corresponding        // to 'i'        corr = calcCrossCorrStereo(refPos + 2 * i, pRefMidBuffer);        // Checks for the highest correlation value        if (corr > bestCorr)         {            bestCorr = corr;            bestOffs = i;        }    }    // clear cross correlation routine state if necessary (is so e.g. in MMX routines).    clearCrossCorrState();    return bestOffs;}// Seeks for the optimal overlap-mixing position. The 'stereo' version of the// routine//// The best position is determined as the position where the two overlapped// sample sequences are 'most alike', in terms of the highest cross-correlation// value over the overlapping perioduint TDStretch::seekBestOverlapPositionStereoQuick(const SAMPLETYPE *refPos) {    uint j;    uint bestOffs;    LONG_SAMPLETYPE bestCorr, corr;    uint scanCount, corrOffset, tempOffset;    // Slopes the amplitude of the 'midBuffer' samples    precalcCorrReferenceStereo();    bestCorr = INT_MIN;    bestOffs = 0;    corrOffset = 0;    tempOffset = 0;    // Scans for the best correlation value using four-pass hierarchical search.    //    // The look-up table 'scans' has hierarchical position adjusting steps.    // In first pass the routine searhes for the highest correlation with     // relatively coarse steps, then rescans the neighbourhood of the highest    // correlation with better resolution and so on.    for (scanCount = 0;scanCount < 4; scanCount ++)     {        j = 0;        while (scanOffsets[scanCount][j])         {            tempOffset = corrOffset + scanOffsets[scanCount][j];            if (tempOffset >= seekLength) break;            // Calculates correlation value for the mixing position corresponding            // to 'tempOffset'            corr = calcCrossCorrStereo(refPos + 2 * tempOffset, pRefMidBuffer);            // Checks for the highest correlation value            if (corr > bestCorr)             {                bestCorr = corr;                bestOffs = tempOffset;            }            j ++;        }        corrOffset = bestOffs;    }    // clear cross correlation routine state if necessary (is so e.g. in MMX routines).    clearCrossCorrState();    return bestOffs;}// Seeks for the optimal overlap-mixing position. The 'mono' version of the// routine//// The best position is determined as the position where the two overlapped// sample sequences are 'most alike', in terms of the highest cross-correlation// value over the overlapping perioduint TDStretch::seekBestOverlapPositionMono(const SAMPLETYPE *refPos) {    uint bestOffs;    LONG_SAMPLETYPE bestCorr, corr;    uint tempOffset;    const SAMPLETYPE *compare;    // Slopes the amplitude of the 'midBuffer' samples    precalcCorrReferenceMono();    bestCorr = INT_MIN;    bestOffs = 0;    // Scans for the best correlation value by testing each possible position    // over the permitted range.    for (tempOffset = 0; tempOffset < seekLength; tempOffset ++)     {        compare = refPos + tempOffset;        // Calculates correlation value for the mixing position corresponding        // to 'tempOffset'        corr = calcCrossCorrMono(pRefMidBuffer, compare);        // Checks for the highest correlation value        if (corr > bestCorr)         {            bestCorr = corr;            bestOffs = tempOffset;        }    }    // clear cross correlation routine state if necessary (is so e.g. in MMX routines).    clearCrossCorrState();    return bestOffs;}// Seeks for the optimal overlap-mixing position. The 'mono' version of the// routine//// The best position is determined as the position where the two overlapped// sample sequences are 'most alike', in terms of the highest cross-correlation// value over the overlapping perioduint TDStretch::seekBestOverlapPositionMonoQuick(const SAMPLETYPE *refPos) {    uint j;    uint bestOffs;    LONG_SAMPLETYPE bestCorr, corr;    uint scanCount, corrOffset, tempOffset;    // Slopes the amplitude of the 'midBuffer' samples    precalcCorrReferenceMono();    bestCorr = INT_MIN;    bestOffs = 0;    corrOffset = 0;    tempOffset = 0;    // Scans for the best correlation value using four-pass hierarchical search.    //    // The look-up table 'scans' has hierarchical position adjusting steps.    // In first pass the routine searhes for the highest correlation with     // relatively coarse steps, then rescans the neighbourhood of the highest    // correlation with better resolution and so on.    for (scanCount = 0;scanCount < 4; scanCount ++)     {        j = 0;        while (scanOffsets[scanCount][j])         {            tempOffset = corrOffset + scanOffsets[scanCount][j];            if (tempOffset >= seekLength) break;            // Calculates correlation value for the mixing position corresponding            // to 'tempOffset'            corr = calcCrossCorrMono(refPos + tempOffset, pRefMidBuffer);            // Checks for the highest correlation value            if (corr > bestCorr)             {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -