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

📄 tdstretch.cpp

📁 Audacity是一款用於錄音和編輯聲音的、免費的開放源碼軟體。它可以執行於Mac OS X、Microsoft Windows、GNU/Linux和其它作業系統
💻 CPP
📖 第 1 页 / 共 2 页
字号:
                bestCorr = corr;                bestOffs = tempOffset;            }            j ++;        }        corrOffset = bestOffs;    }    // clear cross correlation routine state if necessary (is so e.g. in MMX routines).    clearCrossCorrState();    return bestOffs;}/// clear cross correlation routine state if necessary void TDStretch::clearCrossCorrState(){    // default implementation is empty.}// Sets new target tempo. Normal tempo = 'SCALE', smaller values represent slower // tempo, larger faster tempo.void TDStretch::setTempo(float newTempo){    uint intskip;    tempo = newTempo;    // Calculate ideal skip length (according to tempo value)     nominalSkip = tempo * (seekWindowLength - overlapLength);    skipFract = 0;    intskip = (int)(nominalSkip + 0.5f);    // Calculate how many samples are needed in the 'inputBuffer' to     // process another batch of samples    sampleReq = max(intskip + overlapLength, seekWindowLength) + maxOffset;}// Sets the number of channels, 1 = mono, 2 = stereovoid TDStretch::setChannels(uint numChannels){    if (channels == numChannels) return;    assert(numChannels == 1 || numChannels == 2);    channels = numChannels;    inputBuffer.setChannels(channels);    outputBuffer.setChannels(channels);}// nominal tempo, no need for processing, just pass the samples through// to outputBuffervoid TDStretch::processNominalTempo(){    assert(tempo == 1.0f);    if (bMidBufferDirty)     {        // If there are samples in pMidBuffer waiting for overlapping,        // do a single sliding overlapping with them in order to prevent a         // clicking distortion in the output sound        if (inputBuffer.numSamples() < overlapLength)         {            // wait until we've got overlapLength input samples            return;        }        // Mix the samples in the beginning of 'inputBuffer' with the         // samples in 'midBuffer' using sliding overlapping         overlap(outputBuffer.ptrEnd(overlapLength), inputBuffer.ptrBegin(), 0);        outputBuffer.putSamples(overlapLength);        inputBuffer.receiveSamples(overlapLength);        clearMidBuffer();        // now we've caught the nominal sample flow and may switch to        // bypass mode    }    // Simply bypass samples from input to output    outputBuffer.moveSamples(inputBuffer);}// Processes as many processing frames of the samples 'inputBuffer', store// the result into 'outputBuffer'void TDStretch::processSamples(){    uint ovlSkip, offset;    int temp;    if (tempo == 1.0f)     {        // tempo not changed from the original, so bypass the processing        processNominalTempo();        return;    }    if (bMidBufferDirty == FALSE)     {        // if midBuffer is empty, move the first samples of the input stream         // into it        if (inputBuffer.numSamples() < overlapLength)         {            // wait until we've got overlapLength samples            return;        }        memcpy(pMidBuffer, inputBuffer.ptrBegin(), channels * overlapLength * sizeof(SAMPLETYPE));        inputBuffer.receiveSamples(overlapLength);        bMidBufferDirty = TRUE;    }    // Process samples as long as there are enough samples in 'inputBuffer'    // to form a processing frame.    while (inputBuffer.numSamples() >= sampleReq)     {        // If tempo differs from the normal ('SCALE'), scan for the best overlapping        // position        offset = seekBestOverlapPosition(inputBuffer.ptrBegin());        // Mix the samples in the 'inputBuffer' at position of 'offset' with the         // samples in 'midBuffer' using sliding overlapping        // ... first partially overlap with the end of the previous sequence        // (that's in 'midBuffer')        overlap(outputBuffer.ptrEnd(overlapLength), inputBuffer.ptrBegin(), offset);        outputBuffer.putSamples(overlapLength);        // ... then copy sequence samples from 'inputBuffer' to output        temp = (seekWindowLength - 2 * overlapLength);// & 0xfffffffe;        if (temp > 0)        {            outputBuffer.putSamples(inputBuffer.ptrBegin() + channels * (offset + overlapLength), temp);        }        // Copies the end of the current sequence from 'inputBuffer' to         // 'midBuffer' for being mixed with the beginning of the next         // processing sequence and so on        assert(offset + seekWindowLength <= inputBuffer.numSamples());        memcpy(pMidBuffer, inputBuffer.ptrBegin() + channels * (offset + seekWindowLength - overlapLength),             channels * sizeof(SAMPLETYPE) * overlapLength);        bMidBufferDirty = TRUE;        // Remove the processed samples from the input buffer. Update        // the difference between integer & nominal skip step to 'skipFract'        // in order to prevent the error from accumulating over time.        skipFract += nominalSkip;   // real skip size        ovlSkip = (int)skipFract;   // rounded to integer skip        skipFract -= ovlSkip;       // maintain the fraction part, i.e. real vs. integer skip        inputBuffer.receiveSamples(ovlSkip);    }}// Adds 'numsamples' pcs of samples from the 'samples' memory position into// the input of the object.void TDStretch::putSamples(const SAMPLETYPE *samples, uint numSamples){    // Add the samples into the input buffer    inputBuffer.putSamples(samples, numSamples);    // Process the samples in input buffer    processSamples();}/// Set new overlap length parameter & reallocate RefMidBuffer if necessary.void TDStretch::acceptNewOverlapLength(uint newOverlapLength){    uint prevOvl;    prevOvl = overlapLength;    overlapLength = newOverlapLength;    if (overlapLength > prevOvl)    {        delete[] pMidBuffer;        delete[] pRefMidBufferUnaligned;        pMidBuffer = new SAMPLETYPE[overlapLength * 2];        bMidBufferDirty = TRUE;        clearMidBuffer();        pRefMidBufferUnaligned = new SAMPLETYPE[2 * overlapLength + 16 / sizeof(SAMPLETYPE)];        // ensure that 'pRefMidBuffer' is aligned to 16 byte boundary for efficiency        pRefMidBuffer = (SAMPLETYPE *)((((ulong)pRefMidBufferUnaligned) + 15) & -16);    }}// Operator 'new' is overloaded so that it automatically creates a suitable instance // depending on if we've a MMX/SSE/etc-capable CPU available or not.void * TDStretch::operator new(size_t s){    // Notice! don't use "new TDStretch" directly, use "newInstance" to create a new instance instead!    assert(FALSE);      return NULL;}TDStretch * TDStretch::newInstance(){    uint uExtensions;    uExtensions = detectCPUextensions();    // Check if MMX/SSE/3DNow! instruction set extensions supported by CPU#ifdef ALLOW_MMX    // MMX routines available only with integer sample types    if (uExtensions & SUPPORT_MMX)    {        return ::new TDStretchMMX;    }    else#endif // ALLOW_MMX#ifdef ALLOW_SSE    if (uExtensions & SUPPORT_SSE)    {        // SSE support        return ::new TDStretchSSE;    }    else#endif // ALLOW_SSE#ifdef ALLOW_3DNOW    if (uExtensions & SUPPORT_3DNOW)    {        // 3DNow! support        return ::new TDStretch3DNow;    }    else#endif // ALLOW_3DNOW    {        // ISA optimizations not supported, use plain C version        return ::new TDStretch;    }}////////////////////////////////////////////////////////////////////////////////// Integer arithmetics specific algorithm implementations.////////////////////////////////////////////////////////////////////////////////#ifdef INTEGER_SAMPLES// Slopes the amplitude of the 'midBuffer' samples so that cross correlation// is faster to calculatevoid TDStretch::precalcCorrReferenceStereo(){    int i, cnt2;    int temp, temp2;    for (i=0 ; i < (int)overlapLength ;i ++)     {        temp = i * (overlapLength - i);        cnt2 = i * 2;        temp2 = (pMidBuffer[cnt2] * temp) / slopingDivider;        pRefMidBuffer[cnt2] = (short)(temp2);        temp2 = (pMidBuffer[cnt2 + 1] * temp) / slopingDivider;        pRefMidBuffer[cnt2 + 1] = (short)(temp2);    }}// Slopes the amplitude of the 'midBuffer' samples so that cross correlation// is faster to calculatevoid TDStretch::precalcCorrReferenceMono(){    int i;    long temp;    long temp2;    for (i=0 ; i < (int)overlapLength ;i ++)     {        temp = i * (overlapLength - i);        temp2 = (pMidBuffer[i] * temp) / slopingDivider;        pRefMidBuffer[i] = (short)temp2;    }}// Overlaps samples in 'midBuffer' with the samples in 'input'. The 'Stereo' // version of the routine.void TDStretch::overlapStereo(short *output, const short *input) const{    int i;    short temp;    uint cnt2;    for (i = 0; i < (int)overlapLength ; i ++)     {        temp = (short)(overlapLength - i);        cnt2 = 2 * i;        output[cnt2] = (input[cnt2] * i + pMidBuffer[cnt2] * temp )  / overlapLength;        output[cnt2 + 1] = (input[cnt2 + 1] * i + pMidBuffer[cnt2 + 1] * temp ) / overlapLength;    }}/// Calculates overlap period length in samples./// Integer version rounds overlap length to closest power of 2/// for a divide scaling operation.void TDStretch::calculateOverlapLength(uint overlapMs){    uint newOvl;    overlapDividerBits = _getClosest2Power((sampleRate * overlapMs) / 1000.0);    if (overlapDividerBits > 9) overlapDividerBits = 9;    if (overlapDividerBits < 4) overlapDividerBits = 4;    newOvl = (uint)pow(2, overlapDividerBits);    acceptNewOverlapLength(newOvl);    // calculate sloping divider so that crosscorrelation operation won't     // overflow 32-bit register. Max. sum of the crosscorrelation sum without     // divider would be 2^30*(N^3-N)/3, where N = overlap length    slopingDivider = (newOvl * newOvl - 1) / 3;}long TDStretch::calcCrossCorrMono(const short *mixingPos, const short *compare) const{    long corr;    uint i;    corr = 0;    for (i = 1; i < overlapLength; i ++)     {        corr += (mixingPos[i] * compare[i]) >> overlapDividerBits;    }    return corr;}long TDStretch::calcCrossCorrStereo(const short *mixingPos, const short *compare) const{    long corr;    uint i;    corr = 0;    for (i = 2; i < 2 * overlapLength; i += 2)     {        corr += (mixingPos[i] * compare[i] +                 mixingPos[i + 1] * compare[i + 1]) >> overlapDividerBits;    }    return corr;}#endif // INTEGER_SAMPLES////////////////////////////////////////////////////////////////////////////////// Floating point arithmetics specific algorithm implementations.//#ifdef FLOAT_SAMPLES// Slopes the amplitude of the 'midBuffer' samples so that cross correlation// is faster to calculatevoid TDStretch::precalcCorrReferenceStereo(){    int i, cnt2;    float temp;    for (i=0 ; i < (int)overlapLength ;i ++)     {        temp = (float)i * (float)(overlapLength - i);        cnt2 = i * 2;        pRefMidBuffer[cnt2] = (float)(pMidBuffer[cnt2] * temp);        pRefMidBuffer[cnt2 + 1] = (float)(pMidBuffer[cnt2 + 1] * temp);    }}// Slopes the amplitude of the 'midBuffer' samples so that cross correlation// is faster to calculatevoid TDStretch::precalcCorrReferenceMono(){    int i;    float temp;    for (i=0 ; i < (int)overlapLength ;i ++)     {        temp = (float)i * (float)(overlapLength - i);        pRefMidBuffer[i] = (float)(pMidBuffer[i] * temp);    }}// SSE-optimized version of the function overlapStereovoid TDStretch::overlapStereo(float *output, const float *input) const{    int i;    uint cnt2;    float fTemp;    float fScale;    float fi;    fScale = 1.0f / (float)overlapLength;    for (i = 0; i < (int)overlapLength ; i ++)     {        fTemp = (float)(overlapLength - i) * fScale;        fi = (float)i * fScale;        cnt2 = 2 * i;        output[cnt2 + 0] = input[cnt2 + 0] * fi + pMidBuffer[cnt2 + 0] * fTemp;        output[cnt2 + 1] = input[cnt2 + 1] * fi + pMidBuffer[cnt2 + 1] * fTemp;    }}/// Calculates overlap period length in samples.void TDStretch::calculateOverlapLength(uint overlapMs){    uint newOvl;    newOvl = (sampleRate * overlapMs) / 1000;    if (newOvl < 16) newOvl = 16;    acceptNewOverlapLength(newOvl);}double TDStretch::calcCrossCorrMono(const float *mixingPos, const float *compare) const{    double corr;    uint i;    corr = 0;    for (i = 1; i < overlapLength; i ++)     {        corr += mixingPos[i] * compare[i];    }    return corr;}double TDStretch::calcCrossCorrStereo(const float *mixingPos, const float *compare) const{    double corr;    uint i;    corr = 0;    for (i = 2; i < 2 * overlapLength; i += 2)     {        corr += mixingPos[i] * compare[i] +                mixingPos[i + 1] * compare[i + 1];    }    return corr;}#endif // FLOAT_SAMPLES

⌨️ 快捷键说明

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