From: <rel...@us...> - 2009-02-14 19:45:25
|
Revision: 250 http://modplug.svn.sourceforge.net/modplug/?rev=250&view=rev Author: relabsoluness Date: 2009-02-14 19:45:18 +0000 (Sat, 14 Feb 2009) Log Message: ----------- / SoundTouch: Updated to SoundTouch 1.4.0 Modified Paths: -------------- trunk/OpenMPT/soundtouch/3dnow_win.cpp trunk/OpenMPT/soundtouch/AAFilter.cpp trunk/OpenMPT/soundtouch/AAFilter.h trunk/OpenMPT/soundtouch/BPMDetect.h trunk/OpenMPT/soundtouch/FIFOSampleBuffer.cpp trunk/OpenMPT/soundtouch/FIFOSampleBuffer.h trunk/OpenMPT/soundtouch/FIFOSamplePipe.h trunk/OpenMPT/soundtouch/FIRFilter.cpp trunk/OpenMPT/soundtouch/FIRFilter.h trunk/OpenMPT/soundtouch/README.html trunk/OpenMPT/soundtouch/RateTransposer.cpp trunk/OpenMPT/soundtouch/RateTransposer.h trunk/OpenMPT/soundtouch/STTypes.h trunk/OpenMPT/soundtouch/SoundTouch.cpp trunk/OpenMPT/soundtouch/SoundTouch.h trunk/OpenMPT/soundtouch/TDStretch.cpp trunk/OpenMPT/soundtouch/TDStretch.h trunk/OpenMPT/soundtouch/cpu_detect.h trunk/OpenMPT/soundtouch/cpu_detect_x86_win.cpp trunk/OpenMPT/soundtouch/mmx_optimized.cpp trunk/OpenMPT/soundtouch/soundtouch.vcproj trunk/OpenMPT/soundtouch/sse_optimized.cpp Added Paths: ----------- trunk/OpenMPT/soundtouch/BPMDetect.cpp trunk/OpenMPT/soundtouch/PeakFinder.cpp trunk/OpenMPT/soundtouch/PeakFinder.h Removed Paths: ------------- trunk/OpenMPT/soundtouch/soundtouch-1.3.1.zip Modified: trunk/OpenMPT/soundtouch/3dnow_win.cpp =================================================================== --- trunk/OpenMPT/soundtouch/3dnow_win.cpp 2009-02-14 16:22:07 UTC (rev 249) +++ trunk/OpenMPT/soundtouch/3dnow_win.cpp 2009-02-14 19:45:18 UTC (rev 250) @@ -24,7 +24,7 @@ /// NOTICE: If using Visual Studio 6.0, you'll need to install the "Visual C++ /// 6.0 processor pack" update to support 3DNow! instruction set. The update is /// available for download at Microsoft Developers Network, see here: -/// http://msdn.microsoft.com/vstudio/downloads/tools/ppack/default.aspx +/// http://msdn.microsoft.com/en-us/vstudio/aa718349.aspx /// /// If the above URL is expired or removed, go to "http://msdn.microsoft.com" and /// perform a search with keywords "processor pack". @@ -35,10 +35,10 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2006/02/05 16:44:06 $ -// File revision : $Revision: 1.10 $ +// Last changed : $Date: 2009-01-25 16:13:39 +0200 (Sun, 25 Jan 2009) $ +// File revision : $Revision: 4 $ // -// $Id: 3dnow_win.cpp,v 1.10 2006/02/05 16:44:06 Olli Exp $ +// $Id: 3dnow_win.cpp 51 2009-01-25 14:13:39Z oparviai $ // //////////////////////////////////////////////////////////////////////////////// // @@ -82,10 +82,10 @@ ////////////////////////////////////////////////////////////////////////////// #include "TDStretch.h" -#include <limits.h> +//#include <limits.h> // these are declared in 'TDStretch.cpp' -extern int scanOffsets[4][24]; +// extern int scanOffsets[4][24]; // Calculates cross correlation of two buffers @@ -181,12 +181,15 @@ FIRFilter3DNow::FIRFilter3DNow() : FIRFilter() { filterCoeffsUnalign = NULL; + filterCoeffsAlign = NULL; } FIRFilter3DNow::~FIRFilter3DNow() { delete[] filterCoeffsUnalign; + filterCoeffsUnalign = NULL; + filterCoeffsAlign = NULL; } @@ -203,7 +206,7 @@ // Ensure that filter coeffs array is aligned to 16-byte boundary delete[] filterCoeffsUnalign; filterCoeffsUnalign = new float[2 * newLength + 4]; - filterCoeffsAlign = (float *)(((uint)filterCoeffsUnalign + 15) & -16); + filterCoeffsAlign = (float *)(((uint)filterCoeffsUnalign + 15) & (uint)-16); fDivider = (float)resultDivider; @@ -217,10 +220,10 @@ // 3DNow!-optimized version of the filter routine for stereo sound -uint FIRFilter3DNow::evaluateFilterStereo(float *dest, const float *src, const uint numSamples) const +uint FIRFilter3DNow::evaluateFilterStereo(float *dest, const float *src, uint numSamples) const { float *filterCoeffsLocal = filterCoeffsAlign; - uint count = (numSamples - length) & -2; + uint count = (numSamples - length) & (uint)-2; uint lengthLocal = length / 4; assert(length != 0); Modified: trunk/OpenMPT/soundtouch/AAFilter.cpp =================================================================== --- trunk/OpenMPT/soundtouch/AAFilter.cpp 2009-02-14 16:22:07 UTC (rev 249) +++ trunk/OpenMPT/soundtouch/AAFilter.cpp 2009-02-14 19:45:18 UTC (rev 250) @@ -12,10 +12,10 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2006/02/05 16:44:06 $ -// File revision : $Revision: 1.9 $ +// Last changed : $Date: 2009-01-11 13:34:24 +0200 (Sun, 11 Jan 2009) $ +// File revision : $Revision: 4 $ // -// $Id: AAFilter.cpp,v 1.9 2006/02/05 16:44:06 Olli Exp $ +// $Id: AAFilter.cpp 45 2009-01-11 11:34:24Z oparviai $ // //////////////////////////////////////////////////////////////////////////////// // @@ -58,11 +58,11 @@ * *****************************************************************************/ -AAFilter::AAFilter(const uint length) +AAFilter::AAFilter(uint len) { pFIR = FIRFilter::newInstance(); cutoffFreq = 0.5; - setLength(length); + setLength(len); } @@ -77,7 +77,7 @@ // Sets new anti-alias filter cut-off edge frequency, scaled to // sampling frequency (nyquist frequency = 0.5). // The filter will cut frequencies higher than the given frequency. -void AAFilter::setCutoffFreq(const double newCutoffFreq) +void AAFilter::setCutoffFreq(double newCutoffFreq) { cutoffFreq = newCutoffFreq; calculateCoeffs(); @@ -86,7 +86,7 @@ // Sets number of FIR filter taps -void AAFilter::setLength(const uint newLength) +void AAFilter::setLength(uint newLength) { length = newLength; calculateCoeffs(); @@ -104,7 +104,7 @@ double *work; SAMPLETYPE *coeffs; - assert(length > 0); + assert(length >= 2); assert(length % 4 == 0); assert(cutoffFreq >= 0); assert(cutoffFreq <= 0.5); Modified: trunk/OpenMPT/soundtouch/AAFilter.h =================================================================== --- trunk/OpenMPT/soundtouch/AAFilter.h 2009-02-14 16:22:07 UTC (rev 249) +++ trunk/OpenMPT/soundtouch/AAFilter.h 2009-02-14 19:45:18 UTC (rev 250) @@ -13,10 +13,10 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2006/02/05 16:44:06 $ -// File revision : $Revision: 1.10 $ +// Last changed : $Date: 2008-02-10 18:26:55 +0200 (Sun, 10 Feb 2008) $ +// File revision : $Revision: 4 $ // -// $Id: AAFilter.h,v 1.10 2006/02/05 16:44:06 Olli Exp $ +// $Id: AAFilter.h 11 2008-02-10 16:26:55Z oparviai $ // //////////////////////////////////////////////////////////////////////////////// // Added: trunk/OpenMPT/soundtouch/BPMDetect.cpp =================================================================== --- trunk/OpenMPT/soundtouch/BPMDetect.cpp (rev 0) +++ trunk/OpenMPT/soundtouch/BPMDetect.cpp 2009-02-14 19:45:18 UTC (rev 250) @@ -0,0 +1,311 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// Beats-per-minute (BPM) detection routine. +/// +/// The beat detection algorithm works as follows: +/// - Use function 'inputSamples' to input a chunks of samples to the class for +/// analysis. It's a good idea to enter a large sound file or stream in smallish +/// chunks of around few kilosamples in order not to extinguish too much RAM memory. +/// - Inputted sound data is decimated to approx 500 Hz to reduce calculation burden, +/// which is basically ok as low (bass) frequencies mostly determine the beat rate. +/// Simple averaging is used for anti-alias filtering because the resulting signal +/// quality isn't of that high importance. +/// - Decimated sound data is enveloped, i.e. the amplitude shape is detected by +/// taking absolute value that's smoothed by sliding average. Signal levels that +/// are below a couple of times the general RMS amplitude level are cut away to +/// leave only notable peaks there. +/// - Repeating sound patterns (e.g. beats) are detected by calculating short-term +/// autocorrelation function of the enveloped signal. +/// - After whole sound data file has been analyzed as above, the bpm level is +/// detected by function 'getBpm' that finds the highest peak of the autocorrelation +/// function, calculates it's precise location and converts this reading to bpm's. +/// +/// Author : Copyright (c) Olli Parviainen +/// Author e-mail : oparviai 'at' iki.fi +/// SoundTouch WWW: http://www.surina.net/soundtouch +/// +//////////////////////////////////////////////////////////////////////////////// +// +// Last changed : $Date: 2008-12-25 19:54:41 +0200 (Thu, 25 Dec 2008) $ +// File revision : $Revision: 4 $ +// +// $Id: BPMDetect.cpp 43 2008-12-25 17:54:41Z oparviai $ +// +//////////////////////////////////////////////////////////////////////////////// +// +// License : +// +// SoundTouch audio 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 <math.h> +#include <assert.h> +#include <string.h> +#include "FIFOSampleBuffer.h" +#include "PeakFinder.h" +#include "BPMDetect.h" + +using namespace soundtouch; + +#define INPUT_BLOCK_SAMPLES 2048 +#define DECIMATED_BLOCK_SAMPLES 256 + +typedef unsigned short ushort; + +/// decay constant for calculating RMS volume sliding average approximation +/// (time constant is about 10 sec) +const float avgdecay = 0.99986f; + +/// Normalization coefficient for calculating RMS sliding average approximation. +const float avgnorm = (1 - avgdecay); + + + +BPMDetect::BPMDetect(int numChannels, int sampleRate) +{ + xcorr = NULL; + + buffer = new FIFOSampleBuffer(); + + decimateSum = 0; + decimateCount = 0; + decimateBy = 0; + + this->sampleRate = sampleRate; + this->channels = numChannels; + + envelopeAccu = 0; + + // Initialize RMS volume accumulator to RMS level of 3000 (out of 32768) that's + // a typical RMS signal level value for song data. This value is then adapted + // to the actual level during processing. +#ifdef INTEGER_SAMPLES + // integer samples + RMSVolumeAccu = (3000 * 3000) / avgnorm; +#else + // float samples, scaled to range [-1..+1[ + RMSVolumeAccu = (0.092f * 0.092f) / avgnorm; +#endif + + init(numChannels, sampleRate); +} + + + +BPMDetect::~BPMDetect() +{ + delete[] xcorr; + delete buffer; +} + + +/// low-pass filter & decimate to about 500 Hz. return number of outputted samples. +/// +/// Decimation is used to remove the unnecessary frequencies and thus to reduce +/// the amount of data needed to be processed as calculating autocorrelation +/// function is a very-very heavy operation. +/// +/// Anti-alias filtering is done simply by averaging the samples. This is really a +/// poor-man's anti-alias filtering, but it's not so critical in this kind of application +/// (it'd also be difficult to design a high-quality filter with steep cut-off at very +/// narrow band) +int BPMDetect::decimate(SAMPLETYPE *dest, const SAMPLETYPE *src, int numsamples) +{ + int count, outcount; + LONG_SAMPLETYPE out; + + assert(decimateBy != 0); + outcount = 0; + for (count = 0; count < numsamples; count ++) + { + decimateSum += src[count]; + + decimateCount ++; + if (decimateCount >= decimateBy) + { + // Store every Nth sample only + out = (LONG_SAMPLETYPE)(decimateSum / decimateBy); + decimateSum = 0; + decimateCount = 0; +#ifdef INTEGER_SAMPLES + // check ranges for sure (shouldn't actually be necessary) + if (out > 32767) + { + out = 32767; + } + else if (out < -32768) + { + out = -32768; + } +#endif // INTEGER_SAMPLES + dest[outcount] = (SAMPLETYPE)out; + outcount ++; + } + } + return outcount; +} + + + +// Calculates autocorrelation function of the sample history buffer +void BPMDetect::updateXCorr(int process_samples) +{ + int offs; + SAMPLETYPE *pBuffer; + + assert(buffer->numSamples() >= (uint)(process_samples + windowLen)); + + pBuffer = buffer->ptrBegin(); + for (offs = windowStart; offs < windowLen; offs ++) + { + LONG_SAMPLETYPE sum; + int i; + + sum = 0; + for (i = 0; i < process_samples; i ++) + { + sum += pBuffer[i] * pBuffer[i + offs]; // scaling the sub-result shouldn't be necessary + } +// xcorr[offs] *= xcorr_decay; // decay 'xcorr' here with suitable coefficients + // if it's desired that the system adapts automatically to + // various bpms, e.g. in processing continouos music stream. + // The 'xcorr_decay' should be a value that's smaller than but + // close to one, and should also depend on 'process_samples' value. + + xcorr[offs] += (float)sum; + } +} + + + +// Calculates envelope of the sample data +void BPMDetect::calcEnvelope(SAMPLETYPE *samples, int numsamples) +{ + const float decay = 0.7f; // decay constant for smoothing the envelope + const float norm = (1 - decay); + + int i; + LONG_SAMPLETYPE out; + float val; + + for (i = 0; i < numsamples; i ++) + { + // calc average RMS volume + RMSVolumeAccu *= avgdecay; + val = (float)fabs((float)samples[i]); + RMSVolumeAccu += val * val; + + // cut amplitudes that are below 2 times average RMS volume + // (we're interested in peak values, not the silent moments) + val -= 2 * (float)sqrt(RMSVolumeAccu * avgnorm); + val = (val > 0) ? val : 0; + + // smooth amplitude envelope + envelopeAccu *= decay; + envelopeAccu += val; + out = (LONG_SAMPLETYPE)(envelopeAccu * norm); + +#ifdef INTEGER_SAMPLES + // cut peaks (shouldn't be necessary though) + if (out > 32767) out = 32767; +#endif // INTEGER_SAMPLES + samples[i] = (SAMPLETYPE)out; + } +} + + + +void BPMDetect::inputSamples(SAMPLETYPE *samples, int numSamples) +{ + SAMPLETYPE decimated[DECIMATED_BLOCK_SAMPLES]; + + // convert from stereo to mono if necessary + if (channels == 2) + { + int i; + + for (i = 0; i < numSamples; i ++) + { + samples[i] = (samples[i * 2] + samples[i * 2 + 1]) / 2; + } + } + + // decimate + numSamples = decimate(decimated, samples, numSamples); + + // envelope new samples and add them to buffer + calcEnvelope(decimated, numSamples); + buffer->putSamples(decimated, numSamples); + + // when the buffer has enought samples for processing... + if ((int)buffer->numSamples() > windowLen) + { + int processLength; + + // how many samples are processed + processLength = buffer->numSamples() - windowLen; + + // ... calculate autocorrelations for oldest samples... + updateXCorr(processLength); + // ... and remove them from the buffer + buffer->receiveSamples(processLength); + } +} + + +void BPMDetect::init(int numChannels, int sampleRate) +{ + this->sampleRate = sampleRate; + + // choose decimation factor so that result is approx. 500 Hz + decimateBy = sampleRate / 500; + assert(decimateBy > 0); + assert(INPUT_BLOCK_SAMPLES < decimateBy * DECIMATED_BLOCK_SAMPLES); + + // Calculate window length & starting item according to desired min & max bpms + windowLen = (60 * sampleRate) / (decimateBy * MIN_BPM); + windowStart = (60 * sampleRate) / (decimateBy * MAX_BPM); + + assert(windowLen > windowStart); + + // allocate new working objects + xcorr = new float[windowLen]; + memset(xcorr, 0, windowLen * sizeof(float)); + + // we do processing in mono mode + buffer->setChannels(1); + buffer->clear(); +} + + + +float BPMDetect::getBpm() +{ + double peakPos; + PeakFinder peakFinder; + + // find peak position + peakPos = peakFinder.detectPeak(xcorr, windowStart, windowLen); + + assert(decimateBy != 0); + if (peakPos < 1e-6) return 0.0; // detection failed. + + // calculate BPM + return (float)(60.0 * (((double)sampleRate / (double)decimateBy) / peakPos)); +} Modified: trunk/OpenMPT/soundtouch/BPMDetect.h =================================================================== --- trunk/OpenMPT/soundtouch/BPMDetect.h 2009-02-14 16:22:07 UTC (rev 249) +++ trunk/OpenMPT/soundtouch/BPMDetect.h 2009-02-14 19:45:18 UTC (rev 250) @@ -26,10 +26,10 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2006/02/05 16:44:06 $ -// File revision : $Revision: 1.5 $ +// Last changed : $Date: 2008-12-25 14:20:01 +0200 (Thu, 25 Dec 2008) $ +// File revision : $Revision: 4 $ // -// $Id: BPMDetect.h,v 1.5 2006/02/05 16:44:06 Olli Exp $ +// $Id: BPMDetect.h 33 2008-12-25 12:20:01Z oparviai $ // //////////////////////////////////////////////////////////////////////////////// // @@ -60,8 +60,11 @@ #include "STTypes.h" #include "FIFOSampleBuffer.h" +namespace soundtouch +{ + /// Minimum allowed BPM rate. Used to restrict accepted result above a reasonable limit. -#define MIN_BPM 45 +#define MIN_BPM 29 /// Maximum allowed BPM rate. Used to restrict accepted result below a reasonable limit. #define MAX_BPM 230 @@ -156,4 +159,6 @@ float getBpm(); }; +} + #endif // _BPMDetect_H_ Modified: trunk/OpenMPT/soundtouch/FIFOSampleBuffer.cpp =================================================================== --- trunk/OpenMPT/soundtouch/FIFOSampleBuffer.cpp 2009-02-14 16:22:07 UTC (rev 249) +++ trunk/OpenMPT/soundtouch/FIFOSampleBuffer.cpp 2009-02-14 19:45:18 UTC (rev 250) @@ -15,10 +15,10 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2006/02/05 16:44:06 $ -// File revision : $Revision: 1.11 $ +// Last changed : $Date: 2008-02-10 18:26:55 +0200 (Sun, 10 Feb 2008) $ +// File revision : $Revision: 4 $ // -// $Id: FIFOSampleBuffer.cpp,v 1.11 2006/02/05 16:44:06 Olli Exp $ +// $Id: FIFOSampleBuffer.cpp 11 2008-02-10 16:26:55Z oparviai $ // //////////////////////////////////////////////////////////////////////////////// // @@ -54,14 +54,15 @@ using namespace soundtouch; // Constructor -FIFOSampleBuffer::FIFOSampleBuffer(uint numChannels) +FIFOSampleBuffer::FIFOSampleBuffer(int numChannels) { + assert(numChannels > 0); sizeInBytes = 0; // reasonable initial value - buffer = NULL; //new SAMPLETYPE[sizeInBytes / sizeof(SAMPLETYPE)]; + buffer = NULL; bufferUnaligned = NULL; samplesInBuffer = 0; bufferPos = 0; - channels = numChannels; + channels = (uint)numChannels; } @@ -69,16 +70,19 @@ FIFOSampleBuffer::~FIFOSampleBuffer() { delete[] bufferUnaligned; + bufferUnaligned = NULL; + buffer = NULL; } // Sets number of channels, 1 = mono, 2 = stereo -void FIFOSampleBuffer::setChannels(const uint numChannels) +void FIFOSampleBuffer::setChannels(int numChannels) { uint usedBytes; + assert(numChannels > 0); usedBytes = channels * samplesInBuffer; - channels = numChannels; + channels = (uint)numChannels; samplesInBuffer = usedBytes / channels; } @@ -88,7 +92,7 @@ // location on to the beginning of the buffer. void FIFOSampleBuffer::rewind() { - if (bufferPos) + if (buffer && bufferPos) { memmove(buffer, ptrBegin(), sizeof(SAMPLETYPE) * channels * samplesInBuffer); bufferPos = 0; @@ -98,10 +102,10 @@ // Adds 'numSamples' pcs of samples from the 'samples' memory position to // the sample buffer. -void FIFOSampleBuffer::putSamples(const SAMPLETYPE *samples, uint numSamples) +void FIFOSampleBuffer::putSamples(const SAMPLETYPE *samples, uint nSamples) { - memcpy(ptrEnd(numSamples), samples, sizeof(SAMPLETYPE) * numSamples * channels); - samplesInBuffer += numSamples; + memcpy(ptrEnd(nSamples), samples, sizeof(SAMPLETYPE) * nSamples * channels); + samplesInBuffer += nSamples; } @@ -111,13 +115,13 @@ // This function is used to update the number of samples in the sample buffer // when accessing the buffer directly with 'ptrEnd' function. Please be // careful though! -void FIFOSampleBuffer::putSamples(uint numSamples) +void FIFOSampleBuffer::putSamples(uint nSamples) { uint req; - req = samplesInBuffer + numSamples; + req = samplesInBuffer + nSamples; ensureCapacity(req); - samplesInBuffer += numSamples; + samplesInBuffer += nSamples; } @@ -164,14 +168,14 @@ if (capacityRequirement > getCapacity()) { // enlarge the buffer in 4kbyte steps (round up to next 4k boundary) - sizeInBytes = (capacityRequirement * channels * sizeof(SAMPLETYPE) + 4095) & -4096; + sizeInBytes = (capacityRequirement * channels * sizeof(SAMPLETYPE) + 4095) & (uint)-4096; assert(sizeInBytes % 2 == 0); tempUnaligned = new SAMPLETYPE[sizeInBytes / sizeof(SAMPLETYPE) + 16 / sizeof(SAMPLETYPE)]; if (tempUnaligned == NULL) { throw std::runtime_error("Couldn't allocate memory!\n"); } - temp = (SAMPLETYPE *)(((ulong)tempUnaligned + 15) & -16); + temp = (SAMPLETYPE *)(((ulong)tempUnaligned + 15) & (ulong)-16); memcpy(temp, ptrBegin(), samplesInBuffer * channels * sizeof(SAMPLETYPE)); delete[] bufferUnaligned; buffer = temp; Modified: trunk/OpenMPT/soundtouch/FIFOSampleBuffer.h =================================================================== --- trunk/OpenMPT/soundtouch/FIFOSampleBuffer.h 2009-02-14 16:22:07 UTC (rev 249) +++ trunk/OpenMPT/soundtouch/FIFOSampleBuffer.h 2009-02-14 19:45:18 UTC (rev 250) @@ -15,10 +15,10 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2006/02/05 16:44:06 $ -// File revision : $Revision: 1.9 $ +// Last changed : $Date: 2008-02-10 18:26:55 +0200 (Sun, 10 Feb 2008) $ +// File revision : $Revision: 4 $ // -// $Id: FIFOSampleBuffer.h,v 1.9 2006/02/05 16:44:06 Olli Exp $ +// $Id: FIFOSampleBuffer.h 11 2008-02-10 16:26:55Z oparviai $ // //////////////////////////////////////////////////////////////////////////////// // @@ -85,7 +85,7 @@ void rewind(); /// Ensures that the buffer has capacity for at least this many samples. - void ensureCapacity(const uint capacityRequirement); + void ensureCapacity(uint capacityRequirement); /// Returns current capacity. uint getCapacity() const; @@ -93,7 +93,7 @@ public: /// Constructor - FIFOSampleBuffer(uint numChannels = 2 ///< Number of channels, 1=mono, 2=stereo. + FIFOSampleBuffer(int numChannels = 2 ///< Number of channels, 1=mono, 2=stereo. ///< Default is stereo. ); @@ -160,7 +160,7 @@ virtual uint numSamples() const; /// Sets number of channels, 1 = mono, 2 = stereo. - void setChannels(uint numChannels); + void setChannels(int numChannels); /// Returns nonzero if there aren't any samples available for outputting. virtual int isEmpty() const; Modified: trunk/OpenMPT/soundtouch/FIFOSamplePipe.h =================================================================== --- trunk/OpenMPT/soundtouch/FIFOSamplePipe.h 2009-02-14 16:22:07 UTC (rev 249) +++ trunk/OpenMPT/soundtouch/FIFOSamplePipe.h 2009-02-14 19:45:18 UTC (rev 250) @@ -26,11 +26,7 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2006/02/05 16:44:06 $ -// File revision : $Revision: 1.8 $ // -// $Id: FIFOSamplePipe.h,v 1.8 2006/02/05 16:44:06 Olli Exp $ -// //////////////////////////////////////////////////////////////////////////////// // // License : @@ -81,7 +77,7 @@ /// Adds 'numSamples' pcs of samples from the 'samples' memory position to /// the sample buffer. virtual void putSamples(const SAMPLETYPE *samples, ///< Pointer to samples. - uint numSamples ///< Number of samples to insert. + uint numSamples ///< Number of samples to insert. ) = 0; Modified: trunk/OpenMPT/soundtouch/FIRFilter.cpp =================================================================== --- trunk/OpenMPT/soundtouch/FIRFilter.cpp 2009-02-14 16:22:07 UTC (rev 249) +++ trunk/OpenMPT/soundtouch/FIRFilter.cpp 2009-02-14 19:45:18 UTC (rev 250) @@ -20,11 +20,7 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2006/02/05 16:44:06 $ -// File revision : $Revision: 1.16 $ // -// $Id: FIRFilter.cpp,v 1.16 2006/02/05 16:44:06 Olli Exp $ -// //////////////////////////////////////////////////////////////////////////////// // // License : @@ -67,6 +63,7 @@ FIRFilter::FIRFilter() { resultDivFactor = 0; + resultDivider = 0; length = 0; lengthDiv8 = 0; filterCoeffs = NULL; @@ -90,6 +87,9 @@ #endif assert(length != 0); + assert(src != NULL); + assert(dest != NULL); + assert(filterCoeffs != NULL); end = 2 * (numSamples - length); @@ -186,8 +186,8 @@ assert(length == newLength); resultDivFactor = uResultDivFactor; - //OpenMPT_change--> Fix to ambiguous pow(). - //resultDivider = (SAMPLETYPE)pow(2, resultDivFactor); + //OpenMPT_change--> + //resultDivider = (SAMPLETYPE)::pow(2, resultDivFactor); resultDivider = (1 << resultDivFactor); // == 2^resultDivFactor //<-- @@ -215,7 +215,6 @@ assert(length > 0); assert(lengthDiv8 * 8 == length); if (numSamples < length) return 0; - assert(resultDivFactor >= 0); if (numChannels == 2) { return evaluateFilterStereo(dest, src, numSamples); @@ -231,7 +230,7 @@ void * FIRFilter::operator new(size_t s) { // Notice! don't use "new FIRFilter" directly, use "newInstance" to create a new instance instead! - throw std::runtime_error("Don't use 'new FIRFilter', use 'newInstance' member instead!"); + throw std::runtime_error("Error in FIRFilter::new: Don't use 'new FIRFilter', use 'newInstance' member instead!"); return NULL; } Modified: trunk/OpenMPT/soundtouch/FIRFilter.h =================================================================== --- trunk/OpenMPT/soundtouch/FIRFilter.h 2009-02-14 16:22:07 UTC (rev 249) +++ trunk/OpenMPT/soundtouch/FIRFilter.h 2009-02-14 19:45:18 UTC (rev 250) @@ -11,10 +11,10 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2006/02/05 16:44:06 $ -// File revision : $Revision: 1.17 $ +// Last changed : $Date: 2008-02-10 18:26:55 +0200 (Sun, 10 Feb 2008) $ +// File revision : $Revision: 4 $ // -// $Id: FIRFilter.h,v 1.17 2006/02/05 16:44:06 Olli Exp $ +// $Id: FIRFilter.h 11 2008-02-10 16:26:55Z oparviai $ // //////////////////////////////////////////////////////////////////////////////// // @@ -77,7 +77,7 @@ /// Operator 'new' is overloaded so that it automatically creates a suitable instance /// depending on if we've a MMX-capable CPU available or not. - void * operator new(size_t s); + static void * operator new(size_t s); static FIRFilter *newInstance(); Added: trunk/OpenMPT/soundtouch/PeakFinder.cpp =================================================================== --- trunk/OpenMPT/soundtouch/PeakFinder.cpp (rev 0) +++ trunk/OpenMPT/soundtouch/PeakFinder.cpp 2009-02-14 19:45:18 UTC (rev 250) @@ -0,0 +1,236 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// Peak detection routine. +/// +/// The routine detects highest value on an array of values and calculates the +/// precise peak location as a mass-center of the 'hump' around the peak value. +/// +/// Author : Copyright (c) Olli Parviainen +/// Author e-mail : oparviai 'at' iki.fi +/// SoundTouch WWW: http://www.surina.net/soundtouch +/// +//////////////////////////////////////////////////////////////////////////////// +// +// Last changed : $Date: 2008-12-25 19:54:41 +0200 (Thu, 25 Dec 2008) $ +// File revision : $Revision: 4 $ +// +// $Id: PeakFinder.cpp 43 2008-12-25 17:54:41Z oparviai $ +// +//////////////////////////////////////////////////////////////////////////////// +// +// License : +// +// SoundTouch audio 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 <math.h> +#include <assert.h> + +#include "PeakFinder.h" + +using namespace soundtouch; + +#define max(x, y) (((x) > (y)) ? (x) : (y)) + + +PeakFinder::PeakFinder() +{ +} + + +// Finds 'ground level' of a peak hump by starting from 'peakpos' and proceeding +// to direction defined by 'direction' until next 'hump' after minimum value will +// begin +int PeakFinder::findGround(const float *data, int peakpos, int direction) const +{ + float refvalue; + int lowpos; + int pos; + int climb_count; + float delta; + + climb_count = 0; + refvalue = data[peakpos]; + lowpos = peakpos; + + pos = peakpos; + + while ((pos > minPos) && (pos < maxPos)) + { + int prevpos; + + prevpos = pos; + pos += direction; + + // calculate derivate + delta = data[pos] - data[prevpos]; + if (delta <= 0) + { + // going downhill, ok + if (climb_count) + { + climb_count --; // decrease climb count + } + + // check if new minimum found + if (data[pos] < refvalue) + { + // new minimum found + lowpos = pos; + refvalue = data[pos]; + } + } + else + { + // going uphill, increase climbing counter + climb_count ++; + if (climb_count > 5) break; // we've been climbing too long => it's next uphill => quit + } + } + return lowpos; +} + + +// Find offset where the value crosses the given level, when starting from 'peakpos' and +// proceeds to direction defined in 'direction' +int PeakFinder::findCrossingLevel(const float *data, float level, int peakpos, int direction) const +{ + float peaklevel; + int pos; + + peaklevel = data[peakpos]; + assert(peaklevel >= level); + pos = peakpos; + while ((pos >= minPos) && (pos < maxPos)) + { + if (data[pos + direction] < level) return pos; // crossing found + pos += direction; + } + return -1; // not found +} + + +// Calculates the center of mass location of 'data' array items between 'firstPos' and 'lastPos' +double PeakFinder::calcMassCenter(const float *data, int firstPos, int lastPos) const +{ + int i; + float sum; + float wsum; + + sum = 0; + wsum = 0; + for (i = firstPos; i <= lastPos; i ++) + { + sum += (float)i * data[i]; + wsum += data[i]; + } + return sum / wsum; +} + + + +/// get exact center of peak near given position by calculating local mass of center +double PeakFinder::getPeakCenter(const float *data, int peakpos) +{ + float peakLevel; // peak level + int crosspos1, crosspos2; // position where the peak 'hump' crosses cutting level + float cutLevel; // cutting value + float groundLevel; // ground level of the peak + int gp1, gp2; // bottom positions of the peak 'hump' + + // find ground positions. + gp1 = findGround(data, peakpos, -1); + gp2 = findGround(data, peakpos, 1); + + groundLevel = max(data[gp1], data[gp2]); + peakLevel = data[peakpos]; + + if (groundLevel < 1e-6) return 0; // ground level too small => detection failed + if ((peakLevel / groundLevel) < 1.3) return 0; // peak less than 30% of the ground level => no good peak detected + + // calculate 70%-level of the peak + cutLevel = 0.70f * peakLevel + 0.30f * groundLevel; + // find mid-level crossings + crosspos1 = findCrossingLevel(data, cutLevel, peakpos, -1); + crosspos2 = findCrossingLevel(data, cutLevel, peakpos, 1); + + if ((crosspos1 < 0) || (crosspos2 < 0)) return 0; // no crossing, no peak.. + + // calculate mass center of the peak surroundings + return calcMassCenter(data, crosspos1, crosspos2); +} + + + +double PeakFinder::detectPeak(const float *data, int minPos, int maxPos) +{ + + int i; + int peakpos; // position of peak level + double highPeak, peak; + + this->minPos = minPos; + this->maxPos = maxPos; + + // find absolute peak + peakpos = minPos; + peak = data[minPos]; + for (i = minPos + 1; i < maxPos; i ++) + { + if (data[i] > peak) + { + peak = data[i]; + peakpos = i; + } + } + + // Calculate exact location of the highest peak mass center + highPeak = getPeakCenter(data, peakpos); + peak = highPeak; + + // Now check if the highest peak were in fact harmonic of the true base beat peak + // - sometimes the highest peak can be Nth harmonic of the true base peak yet + // just a slightly higher than the true base + for (i = 2; i < 10; i ++) + { + double peaktmp, tmp; + int i1,i2; + + peakpos = (int)(highPeak / (double)i + 0.5f); + if (peakpos < minPos) break; + + // calculate mass-center of possible base peak + peaktmp = getPeakCenter(data, peakpos); + + // now compare to highest detected peak + i1 = (int)(highPeak + 0.5); + i2 = (int)(peaktmp + 0.5); + tmp = 2 * (data[i2] - data[i1]) / (data[i2] + data[i1]); + if (fabs(tmp) < 0.1) + { + // The highest peak is harmonic of almost as high base peak, + // thus use the base peak instead + peak = peaktmp; + } + } + + return peak; +} + + Added: trunk/OpenMPT/soundtouch/PeakFinder.h =================================================================== --- trunk/OpenMPT/soundtouch/PeakFinder.h (rev 0) +++ trunk/OpenMPT/soundtouch/PeakFinder.h 2009-02-14 19:45:18 UTC (rev 250) @@ -0,0 +1,93 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// The routine detects highest value on an array of values and calculates the +/// precise peak location as a mass-center of the 'hump' around the peak value. +/// +/// Author : Copyright (c) Olli Parviainen +/// Author e-mail : oparviai 'at' iki.fi +/// SoundTouch WWW: http://www.surina.net/soundtouch +/// +//////////////////////////////////////////////////////////////////////////////// +// +// Last changed : $Date: 2008-12-25 19:54:41 +0200 (Thu, 25 Dec 2008) $ +// File revision : $Revision: 4 $ +// +// $Id: PeakFinder.h 43 2008-12-25 17:54:41Z oparviai $ +// +//////////////////////////////////////////////////////////////////////////////// +// +// License : +// +// SoundTouch audio 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 +// +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _PeakFinder_H_ +#define _PeakFinder_H_ + +namespace soundtouch +{ + +class PeakFinder +{ +protected: + /// Min, max allowed peak positions within the data vector + int minPos, maxPos; + + /// Calculates the mass center between given vector items. + double calcMassCenter(const float *data, ///< Data vector. + int firstPos, ///< Index of first vector item beloging to the peak. + int lastPos ///< Index of last vector item beloging to the peak. + ) const; + + /// Finds the data vector index where the monotoniously decreasing signal crosses the + /// given level. + int findCrossingLevel(const float *data, ///< Data vector. + float level, ///< Goal crossing level. + int peakpos, ///< Peak position index within the data vector. + int direction /// Direction where to proceed from the peak: 1 = right, -1 = left. + ) const; + + /// Finds the 'ground' level, i.e. smallest level between two neighbouring peaks, to right- + /// or left-hand side of the given peak position. + int findGround(const float *data, /// Data vector. + int peakpos, /// Peak position index within the data vector. + int direction /// Direction where to proceed from the peak: 1 = right, -1 = left. + ) const; + + /// get exact center of peak near given position by calculating local mass of center + double getPeakCenter(const float *data, int peakpos); + +public: + /// Constructor. + PeakFinder(); + + /// Detect exact peak position of the data vector by finding the largest peak 'hump' + /// and calculating the mass-center location of the peak hump. + /// + /// \return The location of the largest base harmonic peak hump. + double detectPeak(const float *data, /// Data vector to be analyzed. The data vector has + /// to be at least 'maxPos' items long. + int minPos, ///< Min allowed peak location within the vector data. + int maxPos ///< Max allowed peak location within the vector data. + ); +}; + +} + +#endif // _PeakFinder_H_ Modified: trunk/OpenMPT/soundtouch/README.html =================================================================== --- trunk/OpenMPT/soundtouch/README.html 2009-02-14 16:22:07 UTC (rev 249) +++ trunk/OpenMPT/soundtouch/README.html 2009-02-14 19:45:18 UTC (rev 250) @@ -18,14 +18,13 @@ </head> <body class="normal"> <hr> -<font color=red><h4>NOTE: SoundTouch used with OpenMPT is slightly modified version. - The file soundtouch-1.3.1.zip, and this readme excluding this - note, are the original SoundTouch files. +<font color=red><h4>Note: Some of the SoundTouch files included in OpenMPT repository are modified versions +of the original SoundTouch files. This readme, excluding this note, is the original SoundTouch readme. </h4></font> -<h1>SoundTouch audio processing library v1.3.1 +<h1>SoundTouch audio processing library v1.4.0 </h1> <p class="normal">SoundTouch library Copyright (c) Olli -Parviainen 2002-2006 </p> +Parviainen 2002-2009 </p> <hr> <h2>1. Introduction </h2> <p>SoundTouch is an open-source audio @@ -51,37 +50,27 @@ for more information.</p> <h3>2.1. Building in Microsoft Windows</h3> <p>Project files for Microsoft Visual C++ 6.0 and Visual C++ .NET are -supplied with the source code package. Please notice that SoundTouch +supplied with the source code package. </p> +<p> Please notice that SoundTouch library uses processor-specific optimizations for Pentium III and AMD -processors that require a processor pack upgrade for -the Visual Studio 6.0 to be installed in order to support these -optimizations. The processor pack upgrade can be downloaded from +processors. Visual Studio .NET and later versions supports the required +instructions by default, but Visual Studio 6.0 requires a processor pack upgrade +to be installed in order to support these optimizations. The processor pack upgrade can be downloaded from Microsoft site at this URL:</p> -<p><a - href="http://msdn.microsoft.com/vstudio/downloads/tools/ppack/default.aspx"> -http://msdn.microsoft.com/vstudio/downloads/tools/ppack/default.aspx</a></p> +<p><a href="http://msdn.microsoft.com/en-us/vstudio/aa718349.aspx">http://msdn.microsoft.com/en-us/vstudio/aa718349.aspx</a></p> <p>If the above URL is unavailable or removed, go to <a href="http://msdn.microsoft.com/">http://msdn.microsoft.com</a> -and perform a search with keywords processor pack. </p> -<p>Visual Studio .NET supports required -instructions by default and thus doesn't require installing the -processor pack.</p> -<p>To build the binaries with Visual C++ 6.0 -compiler, either run "make-win.bat" script or open the +and perform a search with keywords "processor pack". </p> +<p>To build the binaries with Visual C++ +compiler, either run "make-win.bat" script, or open the appropriate project files in source code directories with Visual Studio. The final executable will appear under the "SoundTouch\bin" directory. If using the Visual Studio IDE instead of the make-win.bat script, directories bin and -lib have to be created manually to the SoundTouch +lib may need to be created manually to the SoundTouch package root for the final executables. The make-win.bat script creates these directories automatically. </p> -<p>Also other C++ compilers than Visual C++ can be -used, but project or makefiles then have to be adapted accordingly. -Performance optimizations are written in Visual C++ compatible -syntax, they may or may not be compatible with other compilers. If -using GCC (Gnu C Compiler) compiler package such as DJGPP or Cygwin, -please see next chapter for instructions. </p> <h3>2.2. Building in Gnu platforms</h3> <p>The SoundTouch library can be compiled in practically any platform supporting GNU compiler (GCC) tools. @@ -91,7 +80,7 @@ x86 platforms only, they are automatically disabled and replaced with standard C routines in other processor platforms.</p> <p>To build and install the binaries, run the -following commands in SoundTouch/ directory:</p> +following commands in the SoundTouch/ directory:</p> <table border="0" cellpadding="0" cellspacing="4"> <tbody> <tr valign="top"> @@ -125,14 +114,13 @@ </tr> </tbody> </table> -<p><b>NOTE:</b> At the time of release the SoundTouch package has been +<p><b>NOTE:</b> At the release time the SoundTouch package has been tested to compile in GNU/Linux platform. However, in past it's happened that new gcc versions aren't necessarily compatible with the assembler setttings used in the optimized routines. <b>If you have problems getting the -SoundTouch library compiled, try the workaround of disabling the -optimizations</b> by editing the file "include/STTypes.h" and removing +SoundTouch library compiled, try the workaround of disabling the optimizations</b> by editing the file "include/STTypes.h" and removing the following definition there:</p> <blockquote> <pre>#define ALLOW_OPTIMIZATIONS 1</pre> @@ -146,7 +134,7 @@ <p> In Windows environment, the sample data format is chosen -in file "STTypes.h" by choosing one of the following +in file "STTypes.h" by choosing one of the following defines:</p> <ul> <li><span style="font-weight: bold;">#define INTEGER_SAMPLES</span> @@ -171,7 +159,7 @@ recommended because processing the channels separately would result in losing the phase coherency between the channels, which consequently would ruin the stereo effect.</p> -<p>Sample rates between 8000-48000Hz are +<p>Sample rates between 8000-48000H are supported.</p> <h3>3.2. Processing latency</h3> <p>The processing and latency constraints of @@ -183,8 +171,8 @@ requirement is much shorter, see section 'About algorithms'.</li> <li>Processing CD-quality sound (16bit stereo -sound with 44100Hz sample rate) in real-time or faster is possible -starting from processors equivalent to Intel Pentium 133Mhz or better, +sound with 44100H sample rate) in real-time or faster is possible +starting from processors equivalent to Intel Pentium 133Mh or better, if using the "quick" processing algorithm. If not using the "quick" mode or if floating point sample data are being used, several times more CPU @@ -198,8 +186,7 @@ <p><em>Sample rate transposing</em> affects both the audio stream duration and pitch. It's implemented simply by converting the original audio sample stream to the desired -duration by interpolating from the original audio samples. In -SoundTouch, linear interpolation with anti-alias filtering is +duration by interpolating from the original audio samples. In SoundTouch, linear interpolation with anti-alias filtering is used. Theoretically a higher-order interpolation provide better result than 1st order linear interpolation, but in audio application linear interpolation together with anti-alias @@ -240,10 +227,10 @@ sound the default parameter set may result into a sub-optimal result.</p> <p>The time-stretch algorithm default -parameter values are set by these #defines in file "TDStretch.h":</p> +parameter values are set by these #defines in file "TDStretch.h":</p> <blockquote> - <pre>#define DEFAULT_SEQUENCE_MS 82 -#define DEFAULT_SEEKWINDOW_MS 28 + <pre>#define DEFAULT_SEQUENCE_MS AUTOMATIC +#define DEFAULT_SEEKWINDOW_MS AUTOMATIC #define DEFAULT_OVERLAP_MS 12</pre> </blockquote> <p>These parameters affect to the time-stretch @@ -255,13 +242,16 @@ the time-stretch algorithm. Larger values mean fewer sequences are used in processing. In principle a larger value sounds better when slowing down the tempo, but worse when increasing the tempo and vice -versa.<br> +versa. <br> + <br> + By default, this setting value is calculated automatically according to + tempo value.<br> </li> <li><strong>DEFAULT_SEEKWINDOW_MS</strong>: The seeking window default length in milliseconds is for the algorithm that seeks the best possible overlapping location. This determines from how wide a sample "window" the algorithm can use to find an optimal mixing -location when the sound sequences are to be linked back together.<br> +location when the sound sequences are to be linked back together. <br> <br> The bigger this window setting is, the higher the possibility to find a better mixing position becomes, but at the same time large values may @@ -269,6 +259,9 @@ chosen at more uneven intervals. If there's a disturbing artifact that sounds as if a constant frequency was drifting around, try reducing this setting.<br> + <br> + By default, this setting value is calculated automatically according to + tempo value.<br> </li> <li><strong>DEFAULT_OVERLAP_MS</strong>: Overlap length in milliseconds. When the sound sequences are mixed back @@ -282,7 +275,7 @@ <p>Notice that these parameters can also be set during execution time with functions "<strong>TDStretch::setParameters()</strong>" and "<strong>SoundTouch::setSetting()</strong>".</p> -<p>The table below summarizes how the +<p>The table below summaries how the parameters can be adjusted for different applications:</p> <table border="1"> <tbody> @@ -294,9 +287,7 @@ affects...</strong></td> <td valign="top"><strong>Smaller value affects...</strong></td> - <td valign="top"><strong>Music</strong></td> - <td valign="top"><strong>Speech</strong></td> - <td valign="top"><strong>Effect in CPU burden</strong></td> + <td valign="top"><strong>Effect to CPU burden</strong></td> </tr> <tr> <td valign="top"> @@ -310,9 +301,6 @@ <td valign="top">Smaller value might be better for speeding up tempo. Reducing the value accelerates the "echoing" artifact when slowing down the tempo </td> - <td valign="top">Default value usually good</td> - <td valign="top">A smaller value than default -might be better</td> <td valign="top">Increasing the parameter value reduces computation burden</td> </tr> @@ -326,9 +314,6 @@ good mixing position, but may cause a "drifting" artifact</td> <td valign="top">Smaller reduce possibility to find a good mixing position, but reduce the "drifting" artifact.</td> - <td valign="top">Default value usually good, -unless a "drifting" artifact is disturbing.</td> - <td valign="top">Default value usually good</td> <td valign="top">Increasing the parameter value increases computation burden</td> </tr> @@ -341,8 +326,6 @@ <td valign="top"> </td> <td valign="top">If you reduce the "sequence ms" setting, you might wish to try a smaller value.</td> - <td valign="top"> </td> - <td valign="top"> </td> <td valign="top">Increasing the parameter value increases computation burden</td> </tr> @@ -361,13 +344,11 @@ <p><strong>CPU-specific optimizations:</strong></p> <ul> <li>Intel MMX optimized routines are used with -compatible CPUs when 16bit integer sample type is used. MMX -optimizations are available both in Win32 and Gnu/x86 platforms. +compatible CPUs when 16bit integer sample type is used. MMX optimizations are available both in Win32 and Gnu/x86 platforms. Compatible processors are Intel PentiumMMX and later; AMD K6-2, Athlon and later. </li> <li>Intel SSE optimized routines are used with -compatible CPUs when floating point sample type is used. SSE -optimizations are currently implemented for Win32 platform only. +compatible CPUs when floating point sample type is used. SSE optimizations are currently implemented for Win32 platform only. Processors compatible with SSE extension are Intel processors starting from Pentium-III, and AMD processors starting from Athlon XP. </li> <li>AMD 3DNow! optimized routines are used with @@ -377,41 +358,67 @@ AMD K6-2 and Athlon (classic) CPU's; better performing SSE routines are used with AMD processor starting from Athlon XP. </li> </ul> +<h3>3.6 GNU compilation issues </h3> +<h4><b>3.6.1 Required GNU tools</b> </h4> +<p> Bash shell, GNU C++ compiler, libtool, autoconf and automake tools are required +for compiling +the SoundTouch library. These are usually included with the GNU/Linux distribution, but if +not, install these packages first. For example, in Ubuntu Linux these can be acquired and +installed with the following command:</p> +<pre><b>sudo apt-get install <font SIZE="2">automake autoconf libtool build-essential</font></b></pre> +<h4><b>3.6.2 Problems with configure script or build process</b> </h4> +<p>Incompatibilities between various GNU toolchain versions may cause errors when running the "configure" script or building the source +codes, if your GNU tool versions are not compatible with the versions used for +preparing the SoundTouch kit. </p> +<p>To resolve the issue, regenerate the configure scripts with your local tool +set by running +the "<b>./bootstrap</b>" script included in the SoundTouch source code +kit. After that, run the <b>configure</b> script and <b>make</b> as usually.</p> +<h4><b>3.6.3 Compiler issues with non-x86 processors</b></h4> +<p>SoundTouch library works also on non-x86 processors.</p> +<p>However, in case that you get compiler errors when trying to compile for non-Intel processor, edit the file +"<b>source\SoundTouch\Makefile.am</b>" and remove the "<b>-msse2</b>" +flag on the <b>AM_CXXFLAGS </b>line:</p> +<pre><b>AM_CXXFLAGS=-O3 -fcheck-new -I../../include # Note: -msse2 flag removed!</b></pre> +<p>After that, run "<b>./bootstrap</b>" script, and then run <b>configure</b> +and <b>make</b> again.</p> <hr> <h2><a name="SoundStretch"></a>4. SoundStretch audio processing utility </h2> <p>SoundStretch audio processing utility<br> -Copyright (c) Olli Parviainen 2002-2005</p> +Copyright (c) Olli Parviainen 2002-2009</p> <p>SoundStretch is a simple command-line application that can change tempo, pitch and playback rates of WAV sound files. This program is intended primarily to -demonstrate how the "SoundTouch" library can be used to +demonstrate how the "SoundTouch" library can be used to process sound in your own program, but it can as well be used for processing sound files.</p> <h3>4.1. SoundStretch Usage Instructions</h3> <p>SoundStretch Usage syntax:</p> <blockquote> - <pre>soundstretch infile.wav outfile.wav [switches]</pre> + <pre>soundstretch infilename outfilename [switches]</pre> </blockquote> <p>Where: </p> <table border="0" cellpadding="2" width="100%"> <tbody> <tr> <td valign="top"> - <pre>"infile.wav"</pre> + <pre>"infilename"</pre> </td> - <td valign="top">is the name of the input sound -data file (in .WAV audio file format). </td> + <td valign="top">Name of the input sound +data file (in .WAV audio file format). Give "stdin" as filename to use + standard input pipe. </td> </tr> <tr> <td valign="top"> - <pre>"outfile.wav"</pre> + <pre>"outfilename"</pre> </td> - <td valign="top">is the name of the output sound + <td valign="top">Name of the output sound file where the resulting sound is saved (in .WAV audio file format). This parameter may be omitted if you don't want to save the output -(e.g. when only calculating BPM rate with '-bpm' switch).</td> +(e.g. when only calculating BPM rate with '-bpm' switch). Give "stdout" + as filename to use standard output pipe.</td> </tr> <tr> <td valign="top"> @@ -450,11 +457,11 @@ <td valign="top"> <pre>-bpm=n</pre> </td> - <td valign="top">Detect the Beats-Per-Minute -(BPM) rate of the sound and adjust the tempo to meet 'n' BPMs. If this -switch is defined, the "-tempo=n" switch value is ignored. If "=n" is -omitted, i.e. switch "-bpm" is used alone, the program just calculates -and displays the BPM rate but doesn't adjust tempo according to the BPM + <td valign="top">Detect the Beats-Per-Minute (BPM) rate of the sound and adjust the tempo to meet 'n' + BPMs. When this switch is + applied, the "-tempo" switch is ignored. If "=n" is +omitted, i.e. switch "-bpm" is used alone, then the BPM rate is + estimated and displayed, but tempo not adjusted according to the BPM value. </td> </tr> <tr> @@ -483,57 +490,69 @@ </table> <p>Notes:</p> <ul> - <li>The numerical switch values can be entered -using either integer (e.g. "-tempo=123") or decimal (e.g. + <li>To use standard input/output pipes for processing, give "stdin" + and "stdout" as input/output filenames correspondingly. The + standard input/output pipes will still carry the audio data in .wav audio + file format.</li> + <li>The numerical switches allow both integer (e.g. "-tempo=123") and decimal (e.g. "-tempo=123.45") numbers.</li> <li>The "-naa" and/or "-quick" switches can be used to reduce CPU usage while compromising some sound quality </li> <li>The BPM detection algorithm works by detecting -repeating low-frequency (<250Hz) sound patterns and thus works -mostly with most rock/pop music with bass or drum beat. The BPM -detection doesn't work on pieces such as classical music without -distinct, repeating bass frequency patterns. Also pieces with varying -tempo, varying bass patterns or very complex bass patterns (jazz, hiphop) may produce odd BPM readings. <br> - <br> -In cases when the bass pattern drifts a bit around a nominal beat rate -(e.g. drummer is again drunken :), the BPM algorithm may report -incorrect harmonic one-halft to one-thirdth of the correct BPM value; -in such case the system could for example report BPM value of 50 or 100 -instead of correct BPM value of 150. </li> +repeating bass or drum patterns at low frequencies of <250Hz. A + lower-than-expected BPM figure may be reported for music with uneven or + complex bass patterns. </li> </ul> <h3>4.2. SoundStretch usage examples </h3> <p><strong>Example 1</strong></p> <p>The following command increases tempo of -the sound file "originalfile.wav" by 12.5% and saves -result to file "destinationfile.wav":</p> +the sound file "originalfile.wav" by 12.5% and stores result to file "destinationfile.wav":</p> <blockquote> <pre>soundstretch originalfile.wav destinationfile.wav -tempo=12.5</pre> </blockquote> <p><strong>Example 2</strong></p> <p>The following command decreases the sound pitch (key) of the sound file "orig.wav" by two -semitones and saves the result to file "dest.wav":</p> +semitones and stores the result to file "dest.wav":</p> <blockquote> <pre>soundstretch orig.wav dest.wav -pitch=-2</pre> </blockquote> <p><strong>Example 3</strong></p> <p>The following command processes the file "orig.wav" by decreasing the sound tempo by 25.3% and -increasing the sound pitch (key) by 1.5 semitones. Result is -saved to file "dest.wav":</p> +increasing the sound pitch (key) by 1.5 semitones. Resulting .wav audio data is +directed to standard output pipe:</p> <blockquote> - <pre>soundstretch orig.wav dest.wav -tempo=-25.3 -pitch=1.5</pre> + <pre>soundstretch orig.wav stdout -tempo=-25.3 -pitch=1.5</pre> </blockquote> <p><strong>Example 4</strong></p> <p>The following command detects the BPM rate of the file "orig.wav" and adjusts the tempo to match -100 beats per minute. Result is saved to file "dest.wav":</p> +100 beats per minute. Result is stored to file "dest.wav":</p> <blockquote> <pre>soundstretch orig.wav dest.wav -bpm=100</pre> </blockquote> +<p><strong>Example 5</strong></p> +<p>The following command reads .wav sound data from standard input pipe and +estimates the BPM rate:</p> +<blockquote> + <pre>soundstretch stdin -bpm</pre> +</blockquote> <hr> <h2>5. Change History</h2> <h3>5.1. SoundTouch library Change History </h3> +<p><strong>1.4.0:</strong></p> +<ul> +<li>Improved sound quality by automatic calculation of time stretch algorithm + processing parameters according to tempo settin... [truncated message content] |
From: <sag...@us...> - 2012-02-24 22:59:48
|
Revision: 1192 http://modplug.svn.sourceforge.net/modplug/?rev=1192&view=rev Author: saga-games Date: 2012-02-24 22:59:39 +0000 (Fri, 24 Feb 2012) Log Message: ----------- [Mod] Updated SoundTouch to v1.6.0 Modified Paths: -------------- trunk/OpenMPT/soundtouch/BPMDetect.cpp trunk/OpenMPT/soundtouch/BPMDetect.h trunk/OpenMPT/soundtouch/FIRFilter.cpp trunk/OpenMPT/soundtouch/FIRFilter.h trunk/OpenMPT/soundtouch/PeakFinder.cpp trunk/OpenMPT/soundtouch/README.html trunk/OpenMPT/soundtouch/RateTransposer.cpp trunk/OpenMPT/soundtouch/STTypes.h trunk/OpenMPT/soundtouch/SoundTouch.cpp trunk/OpenMPT/soundtouch/SoundTouch.h trunk/OpenMPT/soundtouch/SoundTouchDLL.cpp trunk/OpenMPT/soundtouch/SoundTouchDLL.h trunk/OpenMPT/soundtouch/SoundTouchDLL.rc trunk/OpenMPT/soundtouch/TDStretch.cpp trunk/OpenMPT/soundtouch/TDStretch.h trunk/OpenMPT/soundtouch/cpu_detect_x86_win.cpp trunk/OpenMPT/soundtouch/mmx_optimized.cpp trunk/OpenMPT/soundtouch/soundtouch.vcproj trunk/OpenMPT/soundtouch/soundtouch_08.vcproj trunk/OpenMPT/soundtouch/soundtouch_10.vcxproj trunk/OpenMPT/soundtouch/soundtouch_10.vcxproj.filters trunk/OpenMPT/soundtouch/sse_optimized.cpp Added Paths: ----------- trunk/OpenMPT/soundtouch/OpenMPT.txt Modified: trunk/OpenMPT/soundtouch/BPMDetect.cpp =================================================================== --- trunk/OpenMPT/soundtouch/BPMDetect.cpp 2012-02-24 22:46:13 UTC (rev 1191) +++ trunk/OpenMPT/soundtouch/BPMDetect.cpp 2012-02-24 22:59:39 UTC (rev 1192) @@ -26,10 +26,10 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2009-02-21 18:00:14 +0200 (Sat, 21 Feb 2009) $ +// Last changed : $Date: 2011-07-13 11:07:14 +0300 (Wed, 13 Jul 2011) $ // File revision : $Revision: 4 $ // -// $Id: BPMDetect.cpp 63 2009-02-21 16:00:14Z oparviai $ +// $Id: BPMDetect.cpp 105 2011-07-13 08:07:14Z oparviai $ // //////////////////////////////////////////////////////////////////////////////// // @@ -57,6 +57,7 @@ #include <math.h> #include <assert.h> #include <string.h> +#include <stdio.h> #include "FIFOSampleBuffer.h" #include "PeakFinder.h" #include "BPMDetect.h" @@ -74,7 +75,38 @@ const float avgnorm = (1 - avgdecay); +//////////////////////////////////////////////////////////////////////////////// +// Enable following define to create bpm analysis file: + +// #define _CREATE_BPM_DEBUG_FILE + +#ifdef _CREATE_BPM_DEBUG_FILE + + #define DEBUGFILE_NAME "c:\\temp\\soundtouch-bpm-debug.txt" + + static void _SaveDebugData(const float *data, int minpos, int maxpos, double coeff) + { + FILE *fptr = fopen(DEBUGFILE_NAME, "wt"); + int i; + + if (fptr) + { + printf("\n\nWriting BPM debug data into file " DEBUGFILE_NAME "\n\n"); + for (i = minpos; i < maxpos; i ++) + { + fprintf(fptr, "%d\t%.1lf\t%f\n", i, coeff / (double)i, data[i]); + } + fclose(fptr); + } + } +#else + #define _SaveDebugData(a,b,c,d) +#endif + +//////////////////////////////////////////////////////////////////////////////// + + BPMDetect::BPMDetect(int numChannels, int aSampleRate) { this->sampleRate = aSampleRate; @@ -88,7 +120,7 @@ // Initialize RMS volume accumulator to RMS level of 3000 (out of 32768) that's // a typical RMS signal level value for song data. This value is then adapted // to the actual level during processing. -#ifdef INTEGER_SAMPLES +#ifdef SOUNDTOUCH_INTEGER_SAMPLES // integer samples RMSVolumeAccu = (3000 * 3000) / avgnorm; #else @@ -96,6 +128,10 @@ RMSVolumeAccu = (0.092f * 0.092f) / avgnorm; #endif + cutCoeff = 1.75; + aboveCutAccu = 0; + totalAccu = 0; + // choose decimation factor so that result is approx. 500 Hz decimateBy = sampleRate / 500; assert(decimateBy > 0); @@ -165,7 +201,7 @@ out = (LONG_SAMPLETYPE)(decimateSum / (decimateBy * channels)); decimateSum = 0; decimateCount = 0; -#ifdef INTEGER_SAMPLES +#ifdef SOUNDTOUCH_INTEGER_SAMPLES // check ranges for sure (shouldn't actually be necessary) if (out > 32767) { @@ -175,7 +211,7 @@ { out = -32768; } -#endif // INTEGER_SAMPLES +#endif // SOUNDTOUCH_INTEGER_SAMPLES dest[outcount] = (SAMPLETYPE)out; outcount ++; } @@ -215,16 +251,15 @@ } - // Calculates envelope of the sample data void BPMDetect::calcEnvelope(SAMPLETYPE *samples, int numsamples) { - const float decay = 0.7f; // decay constant for smoothing the envelope - const float norm = (1 - decay); + const static double decay = 0.7f; // decay constant for smoothing the envelope + const static double norm = (1 - decay); int i; LONG_SAMPLETYPE out; - float val; + double val; for (i = 0; i < numsamples; i ++) { @@ -233,22 +268,50 @@ val = (float)fabs((float)samples[i]); RMSVolumeAccu += val * val; - // cut amplitudes that are below 2 times average RMS volume + // cut amplitudes that are below cutoff ~2 times RMS volume // (we're interested in peak values, not the silent moments) - val -= 2 * (float)sqrt(RMSVolumeAccu * avgnorm); - val = (val > 0) ? val : 0; + val -= cutCoeff * sqrt(RMSVolumeAccu * avgnorm); + if (val > 0) + { + aboveCutAccu += 1.0; // sample above threshold + } + else + { + val = 0; + } + totalAccu += 1.0; + + // maintain sliding statistic what proportion of 'val' samples is + // above cutoff threshold + aboveCutAccu *= 0.99931; // 2 sec time constant + totalAccu *= 0.99931; + + if (totalAccu > 500) + { + // after initial settling, auto-adjust cutoff level so that ~8% of + // values are above the threshold + double d = (aboveCutAccu / totalAccu) - 0.08; + cutCoeff += 0.001 * d; + } + // smooth amplitude envelope envelopeAccu *= decay; envelopeAccu += val; out = (LONG_SAMPLETYPE)(envelopeAccu * norm); -#ifdef INTEGER_SAMPLES +#ifdef SOUNDTOUCH_INTEGER_SAMPLES // cut peaks (shouldn't be necessary though) if (out > 32767) out = 32767; -#endif // INTEGER_SAMPLES +#endif // SOUNDTOUCH_INTEGER_SAMPLES samples[i] = (SAMPLETYPE)out; } + + // check that cutoff doesn't get too small - it can be just silent sequence! + if (cutCoeff < 1.5) + { + cutCoeff = 1.5; + } } @@ -295,14 +358,20 @@ float BPMDetect::getBpm() { double peakPos; + double coeff; PeakFinder peakFinder; + coeff = 60.0 * ((double)sampleRate / (double)decimateBy); + + // save bpm debug analysis data if debug data enabled + _SaveDebugData(xcorr, windowStart, windowLen, coeff); + // find peak position peakPos = peakFinder.detectPeak(xcorr, windowStart, windowLen); assert(decimateBy != 0); - if (peakPos < 1e-6) return 0.0; // detection failed. + if (peakPos < 1e-9) return 0.0; // detection failed. // calculate BPM - return (float)(60.0 * (((double)sampleRate / (double)decimateBy) / peakPos)); + return (float) (coeff / peakPos); } Modified: trunk/OpenMPT/soundtouch/BPMDetect.h =================================================================== --- trunk/OpenMPT/soundtouch/BPMDetect.h 2012-02-24 22:46:13 UTC (rev 1191) +++ trunk/OpenMPT/soundtouch/BPMDetect.h 2012-02-24 22:59:39 UTC (rev 1192) @@ -26,10 +26,10 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2009-02-21 18:00:14 +0200 (Sat, 21 Feb 2009) $ +// Last changed : $Date: 2010-01-06 20:59:23 +0200 (Wed, 06 Jan 2010) $ // File revision : $Revision: 4 $ // -// $Id: BPMDetect.h 63 2009-02-21 16:00:14Z oparviai $ +// $Id: BPMDetect.h 86 2010-01-06 18:59:23Z oparviai $ // //////////////////////////////////////////////////////////////////////////////// // @@ -78,11 +78,20 @@ float *xcorr; /// Amplitude envelope sliding average approximation level accumulator - float envelopeAccu; + double envelopeAccu; /// RMS volume sliding average approximation level accumulator - float RMSVolumeAccu; + double RMSVolumeAccu; + /// Level below which to cut off signals + double cutCoeff; + + /// Accumulator for accounting what proportion of samples exceed cutCoeff level + double aboveCutAccu; + + /// Accumulator for total samples to calculate proportion of samples that exceed cutCoeff level + double totalAccu; + /// Sample average counter. int decimateCount; Modified: trunk/OpenMPT/soundtouch/FIRFilter.cpp =================================================================== --- trunk/OpenMPT/soundtouch/FIRFilter.cpp 2012-02-24 22:46:13 UTC (rev 1191) +++ trunk/OpenMPT/soundtouch/FIRFilter.cpp 2012-02-24 22:59:39 UTC (rev 1192) @@ -11,10 +11,10 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2009-02-25 19:13:51 +0200 (Wed, 25 Feb 2009) $ +// Last changed : $Date: 2011-02-13 21:13:57 +0200 (Sun, 13 Feb 2011) $ // File revision : $Revision: 4 $ // -// $Id: FIRFilter.cpp 67 2009-02-25 17:13:51Z oparviai $ +// $Id: FIRFilter.cpp 104 2011-02-13 19:13:57Z oparviai $ // //////////////////////////////////////////////////////////////////////////////// // @@ -75,7 +75,7 @@ { uint i, j, end; LONG_SAMPLETYPE suml, sumr; -#ifdef FLOAT_SAMPLES +#ifdef SOUNDTOUCH_FLOAT_SAMPLES // when using floating point samples, use a scaler instead of a divider // because division is much slower operation than multiplying. double dScaler = 1.0 / (double)resultDivider; @@ -108,7 +108,7 @@ ptr[2 * i + 7] * filterCoeffs[i + 3]; } -#ifdef INTEGER_SAMPLES +#ifdef SOUNDTOUCH_INTEGER_SAMPLES suml >>= resultDivFactor; sumr >>= resultDivFactor; // saturate to 16 bit integer limits @@ -118,7 +118,7 @@ #else suml *= dScaler; sumr *= dScaler; -#endif // INTEGER_SAMPLES +#endif // SOUNDTOUCH_INTEGER_SAMPLES dest[j] = (SAMPLETYPE)suml; dest[j + 1] = (SAMPLETYPE)sumr; } @@ -133,7 +133,7 @@ { uint i, j, end; LONG_SAMPLETYPE sum; -#ifdef FLOAT_SAMPLES +#ifdef SOUNDTOUCH_FLOAT_SAMPLES // when using floating point samples, use a scaler instead of a divider // because division is much slower operation than multiplying. double dScaler = 1.0 / (double)resultDivider; @@ -154,13 +154,13 @@ src[i + 2] * filterCoeffs[i + 2] + src[i + 3] * filterCoeffs[i + 3]; } -#ifdef INTEGER_SAMPLES +#ifdef SOUNDTOUCH_INTEGER_SAMPLES sum >>= resultDivFactor; // saturate to 16 bit integer limits sum = (sum < -32768) ? -32768 : (sum > 32767) ? 32767 : sum; #else sum *= dScaler; -#endif // INTEGER_SAMPLES +#endif // SOUNDTOUCH_INTEGER_SAMPLES dest[j] = (SAMPLETYPE)sum; src ++; } @@ -233,36 +233,27 @@ uExtensions = detectCPUextensions(); - // Check if MMX/SSE/3DNow! instruction set extensions supported by CPU + // Check if MMX/SSE instruction set extensions supported by CPU -#ifdef ALLOW_MMX +#ifdef SOUNDTOUCH_ALLOW_MMX // MMX routines available only with integer sample types if (uExtensions & SUPPORT_MMX) { return ::new FIRFilterMMX; } else -#endif // ALLOW_MMX +#endif // SOUNDTOUCH_ALLOW_MMX -#ifdef ALLOW_SSE +#ifdef SOUNDTOUCH_ALLOW_SSE if (uExtensions & SUPPORT_SSE) { // SSE support return ::new FIRFilterSSE; } else -#endif // ALLOW_SSE +#endif // SOUNDTOUCH_ALLOW_SSE -#ifdef ALLOW_3DNOW - if (uExtensions & SUPPORT_3DNOW) { - // 3DNow! support - return ::new FIRFilter3DNow; - } - else -#endif // ALLOW_3DNOW - - { // ISA optimizations not supported, use plain C version return ::new FIRFilter; } Modified: trunk/OpenMPT/soundtouch/FIRFilter.h =================================================================== --- trunk/OpenMPT/soundtouch/FIRFilter.h 2012-02-24 22:46:13 UTC (rev 1191) +++ trunk/OpenMPT/soundtouch/FIRFilter.h 2012-02-24 22:59:39 UTC (rev 1192) @@ -11,10 +11,10 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2009-02-21 18:00:14 +0200 (Sat, 21 Feb 2009) $ +// Last changed : $Date: 2011-02-13 21:13:57 +0200 (Sun, 13 Feb 2011) $ // File revision : $Revision: 4 $ // -// $Id: FIRFilter.h 63 2009-02-21 16:00:14Z oparviai $ +// $Id: FIRFilter.h 104 2011-02-13 19:13:57Z oparviai $ // //////////////////////////////////////////////////////////////////////////////// // @@ -102,7 +102,7 @@ // Optional subclasses that implement CPU-specific optimizations: -#ifdef ALLOW_MMX +#ifdef SOUNDTOUCH_ALLOW_MMX /// Class that implements MMX optimized functions exclusive for 16bit integer samples type. class FIRFilterMMX : public FIRFilter @@ -119,29 +119,10 @@ virtual void setCoefficients(const short *coeffs, uint newLength, uint uResultDivFactor); }; -#endif // ALLOW_MMX +#endif // SOUNDTOUCH_ALLOW_MMX -#ifdef ALLOW_3DNOW - - /// Class that implements 3DNow! optimized functions exclusive for floating point samples type. - class FIRFilter3DNow : public FIRFilter - { - protected: - float *filterCoeffsUnalign; - float *filterCoeffsAlign; - - virtual uint evaluateFilterStereo(float *dest, const float *src, uint numSamples) const; - public: - FIRFilter3DNow(); - ~FIRFilter3DNow(); - virtual void setCoefficients(const float *coeffs, uint newLength, uint uResultDivFactor); - }; - -#endif // ALLOW_3DNOW - - -#ifdef ALLOW_SSE +#ifdef SOUNDTOUCH_ALLOW_SSE /// Class that implements SSE optimized functions exclusive for floating point samples type. class FIRFilterSSE : public FIRFilter { @@ -157,7 +138,7 @@ virtual void setCoefficients(const float *coeffs, uint newLength, uint uResultDivFactor); }; -#endif // ALLOW_SSE +#endif // SOUNDTOUCH_ALLOW_SSE } Added: trunk/OpenMPT/soundtouch/OpenMPT.txt =================================================================== --- trunk/OpenMPT/soundtouch/OpenMPT.txt (rev 0) +++ trunk/OpenMPT/soundtouch/OpenMPT.txt 2012-02-24 22:59:39 UTC (rev 1192) @@ -0,0 +1,5 @@ +Note: The SoundTouch package has pretty much been left untouched (pardon the pun), +except for a small change in SoundTouchDLL.h: + +The "samples" parameter type of soundtouch_putSamples (line 116) has been changed +from float to short. Modified: trunk/OpenMPT/soundtouch/PeakFinder.cpp =================================================================== --- trunk/OpenMPT/soundtouch/PeakFinder.cpp 2012-02-24 22:46:13 UTC (rev 1191) +++ trunk/OpenMPT/soundtouch/PeakFinder.cpp 2012-02-24 22:59:39 UTC (rev 1192) @@ -11,10 +11,10 @@ /// //////////////////////////////////////////////////////////////////////////////// // -// Last changed : $Date: 2009-02-21 18:00:14 +0200 (Sat, 21 Feb 2009) $ +// Last changed : $Date: 2010-08-24 18:53:56 +0300 (Tue, 24 Aug 2010) $ // File revision : $Revision: 4 $ // -// $Id: PeakFinder.cpp 63 2009-02-21 16:00:14Z oparviai $ +// $Id: PeakFinder.cpp 91 2010-08-24 15:53:56Z oparviai $ // //////////////////////////////////////////////////////////////////////////////// // @@ -164,7 +164,7 @@ groundLevel = max(data[gp1], data[gp2]); peakLevel = data[peakpos]; - if (groundLevel < 1e-6) return 0; // ground level too small => detection failed + if (groundLevel < 1e-9) return 0; // ground level too small => detection failed if ((peakLevel / groundLevel) < 1.3) return 0; // peak less than 30% of the ground level => no good peak detected // calculate 70%-level of the peak Modified: trunk/OpenMPT/soundtouch/README.html =================================================================== --- trunk/OpenMPT/soundtouch/README.html 2012-02-24 22:46:13 UTC (rev 1191) +++ trunk/OpenMPT/soundtouch/README.html 2012-02-24 22:59:39 UTC (rev 1192) @@ -1,755 +1,751 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html> -<head> - <meta http-equiv="Content-Type" - content="text/html; charset=windows-1252"> - <meta http-equiv="Content-Language" content="en-us"> - <meta name="author" content="Olli Parviainen"> - <meta name="description" - content="Readme file for SoundTouch audio processing library"> - <meta name="GENERATOR" content="Microsoft FrontPage 4.0"> - <meta name="ProgId" content="FrontPage.Editor.Document"> - <title>SoundTouch library README</title> - <style> -<!-- -.normal { font-family: Arial } ---> - </style> -</head> -<body class="normal"> -<hr> -<font color=red><h4>Note: Some of the SoundTouch files included in OpenMPT repository are modified versions -of the original SoundTouch files. This readme, excluding this note, is the original SoundTouch readme. -</h4></font> -<h1>SoundTouch audio processing library v1.5.0 -</h1> -<p class="normal">SoundTouch library Copyright (c) Olli -Parviainen 2002-2009 </p> -<hr> -<h2>1. Introduction </h2> -<p>SoundTouch is an open-source audio -processing library that allows changing the sound tempo, pitch -and playback rate parameters independently from each other, i.e.:</p> -<ul> - <li>Sound tempo can be increased or decreased while -maintaining the original pitch</li> - <li>Sound pitch can be increased or decreased while -maintaining the original tempo </li> - <li>Change playback rate that affects both tempo -and pitch at the same time </li> - <li>Choose any combination of tempo/pitch/rate</li> -</ul> -<h3>1.1 Contact information </h3> -<p>Author email: oparviai 'at' iki.fi </p> -<p>SoundTouch WWW page: <a href="http://www.surina.net/soundtouch">http://www.surina.net/soundtouch</a></p> -<hr> -<h2>2. Compiling SoundTouch</h2> -<p>Before compiling, notice that you can choose the sample data format -if it's desirable to use floating point sample -data instead of 16bit integers. See section "sample data format" -for more information.</p> -<h3>2.1. Building in Microsoft Windows</h3> -<p>Project files for Microsoft Visual C++ 6.0 and Visual C++ .NET are -supplied with the source code package. </p> -<p> Please notice that SoundTouch -library uses processor-specific optimizations for Pentium III and AMD -processors. Visual Studio .NET and later versions supports the required -instructions by default, but Visual Studio 6.0 requires a processor pack upgrade -to be installed in order to support these optimizations. The processor pack upgrade can be downloaded from -Microsoft site at this URL:</p> -<p><a href="http://msdn.microsoft.com/en-us/vstudio/aa718349.aspx">http://msdn.microsoft.com/en-us/vstudio/aa718349.aspx</a></p> -<p>If the above URL is unavailable or removed, go -to <a href="http://msdn.microsoft.com/">http://msdn.microsoft.com</a> -and perform a search with keywords "processor pack". </p> -<p>To build the binaries with Visual C++ -compiler, either run "make-win.bat" script, or open the -appropriate project files in source code directories with Visual -Studio. The final executable will appear under the "SoundTouch\bin" -directory. If using the Visual Studio IDE instead of the make-win.bat script, directories bin and -lib may need to be created manually to the SoundTouch -package root for the final executables. The make-win.bat script -creates these directories automatically. -</p> -<h3>2.2. Building in Gnu platforms</h3> -<p>The SoundTouch library can be compiled in -practically any platform supporting GNU compiler (GCC) tools. -SoundTouch have been tested with gcc version 3.3.4., but it -shouldn't be very specific about the gcc version. Assembler-level -performance optimizations for GNU platform are currently available in -x86 platforms only, they are automatically disabled and replaced with -standard C routines in other processor platforms.</p> -<p>To build and install the binaries, run the -following commands in the SoundTouch/ directory:</p> -<table border="0" cellpadding="0" cellspacing="4"> - <tbody> - <tr valign="top"> - <td> - <pre>./configure -</pre> - </td> - <td> - <p>Configures the SoundTouch package for the local -environment.</p> - </td> - </tr> - <tr valign="top"> - <td> - <pre>make -</pre> - </td> - <td> - <p>Builds the SoundTouch library & -SoundStretch utility.</p> - </td> - </tr> - <tr valign="top"> - <td> - <pre>make install -</pre> - </td> - <td> - <p>Installs the SoundTouch & BPM libraries -to <b>/usr/local/lib</b> and SoundStretch utility to <b>/usr/local/bin</b>. -Please notice that 'root' privileges may be required to install the -binaries to the destination locations.</p> - </td> - </tr> - </tbody> -</table> -<h4><b>2.2.1 Required GNU tools</b> </h4> -<p> Bash shell, GNU C++ compiler, libtool, autoconf and automake tools are required -for compiling -the SoundTouch library. These are usually included with the GNU/Linux distribution, but if -not, install these packages first. For example, in Ubuntu Linux these can be acquired and -installed with the following command:</p> -<pre><b>sudo apt-get install <font SIZE="2">automake autoconf libtool build-essential</font></b></pre> -<h4><b>2.2.2 Problems with GCC compiler compatibility</b></h4> -<p>At the release time the SoundTouch package has been tested to compile in -GNU/Linux platform. However, in past it's happened that new gcc versions aren't -necessarily compatible with the assembler settings used in the optimized -routines. <b>If you have problems getting the -SoundTouch library compiled, try the workaround of disabling the optimizations</b> -by editing the file "include/STTypes.h" and removing the following -definition there:</p> -<blockquote> - <pre>#define ALLOW_OPTIMIZATIONS 1</pre> -</blockquote> -<h4><b>2.2.3 Problems with configure script or build process</b> </h4> -<p>Incompatibilities between various GNU toolchain versions may cause errors when running the "configure" script or building the source -codes, if your GNU tool versions are not compatible with the versions used for -preparing the SoundTouch kit. </p> -<p>To resolve the issue, regenerate the configure scripts with your local tool -set by running -the "<b>./bootstrap</b>" script included in the SoundTouch source code -kit. After that, run the <b>configure</b> script and <b>make</b> as usually.</p> -<h4><b>2.2.4 Compiler issues with non-x86 processors</b></h4> -<p>SoundTouch library works also on non-x86 processors.</p> -<p>However, in case that you get compiler errors when trying to compile for non-Intel processor, edit the file -"<b>source\SoundTouch\Makefile.am</b>" and remove the "<b>-msse2</b>" -flag on the <b>AM_CXXFLAGS </b>line:</p> -<pre><b>AM_CXXFLAGS=-O3 -fcheck-new -I../../include # Note: -msse2 flag removed!</b></pre> -<p>After that, run "<b>./bootstrap</b>" script, and then run <b>configure</b> -and <b>make</b> again.</p> -<hr> -<h2>3. About implementation & Usage tips</h2> -<h3>3.1. Supported sample data formats</h3> -<p>The sample data format can be chosen -between 16bit signed integer and 32bit floating point values, the -default is 32bit floating point. </p> - -<p> -In Windows environment, the sample data format is chosen -in file "STTypes.h" by choosing one of the following -defines:</p> -<ul> - <li><span style="font-weight: bold;">#define INTEGER_SAMPLES</span> -for 16bit signed -integer</li> - <li><span style="font-weight: bold;">#define FLOAT_SAMPLES</span> for -32bit floating point</li> -</ul> -<p> -In GNU environment, the floating sample format is used by default, but -integer sample format can be chosen by giving the -following switch to the configure script: -<blockquote> -<pre>./configure --enable-integer-samples</pre> -</blockquote> - -<p>The sample data can have either single (mono) -or double (stereo) audio channel. Stereo data is interleaved so -that every other data value is for left channel and every second -for right channel. Notice that while it'd be possible in theory -to process stereo sound as two separate mono channels, this isn't -recommended because processing the channels separately would -result in losing the phase coherency between the channels, which -consequently would ruin the stereo effect.</p> -<p>Sample rates between 8000-48000H are -supported.</p> -<h3>3.2. Processing latency</h3> -<p>The processing and latency constraints of -the SoundTouch library are:</p> -<ul> - <li>Input/output processing latency for the -SoundTouch processor is around 100 ms. This is when time-stretching is -used. If the rate transposing effect alone is used, the latency -requirement -is much shorter, see section 'About algorithms'.</li> - <li>Processing CD-quality sound (16bit stereo -sound with 44100H sample rate) in real-time or faster is possible -starting from processors equivalent to Intel Pentium 133Mh or better, -if using the "quick" processing algorithm. If not using the "quick" -mode or -if floating point sample data are being used, several times more CPU -power is typically required.</li> -</ul> -<h3>3.3. About algorithms</h3> -<p>SoundTouch provides three seemingly -independent effects: tempo, pitch and playback rate control. -These three controls are implemented as combination of two primary -effects, <em>sample rate transposing</em> and <em>time-stretching</em>.</p> -<p><em>Sample rate transposing</em> affects -both the audio stream duration and pitch. It's implemented simply -by converting the original audio sample stream to the desired -duration by interpolating from the original audio samples. In SoundTouch, linear interpolation with anti-alias filtering is -used. Theoretically a higher-order interpolation provide better -result than 1st order linear interpolation, but in audio -application linear interpolation together with anti-alias -filtering performs subjectively about as well as higher-order -filtering would.</p> -<p><em>Time-stretching </em>means changing -the audio stream duration without affecting it's pitch. SoundTouch -uses WSOLA-like time-stretching routines that operate in the time -domain. Compared to sample rate transposing, time-stretching is a -much heavier operation and also requires a longer processing -"window" of sound samples used by the -processing algorithm, thus increasing the algorithm input/output -latency. Typical i/o latency for the SoundTouch -time-stretch algorithm is around 100 ms.</p> -<p>Sample rate transposing and time-stretching -are then used together to produce the tempo, pitch and rate -controls:</p> -<ul> - <li><strong>'Tempo'</strong> control is -implemented purely by time-stretching.</li> - <li><strong>'Rate</strong>' control is implemented -purely by sample rate transposing.</li> - <li><strong>'Pitch</strong>' control is -implemented as a combination of time-stretching and sample rate -transposing. For example, to increase pitch the audio stream is first -time-stretched to longer duration (without affecting pitch) and then -transposed back to original duration by sample rate transposing, which -simultaneously reduces duration and increases pitch. The result is -original duration but increased pitch.</li> -</ul> -<h3>3.4 Tuning the algorithm parameters</h3> -<p>The time-stretch algorithm has few -parameters that can be tuned to optimize sound quality for -certain application. The current default parameters have been -chosen by iterative if-then analysis (read: "trial and error") -to obtain best subjective sound quality in pop/rock music -processing, but in applications processing different kind of -sound the default parameter set may result into a sub-optimal -result.</p> -<p>The time-stretch algorithm default -parameter values are set by the following #defines in file "TDStretch.h":</p> -<blockquote> - <pre>#define DEFAULT_SEQUENCE_MS AUTOMATIC -#define DEFAULT_SEEKWINDOW_MS AUTOMATIC -#define DEFAULT_OVERLAP_MS 8</pre> -</blockquote> -<p>These parameters affect to the time-stretch -algorithm as follows:</p> -<ul> - <li><strong>DEFAULT_SEQUENCE_MS</strong>: This is -the default length of a single processing sequence in milliseconds -which determines the how the original sound is chopped in -the time-stretch algorithm. Larger values mean fewer sequences -are used in processing. In principle a larger value sounds better when -slowing down the tempo, but worse when increasing the tempo and vice -versa. <br> - <br> - By default, this setting value is calculated automatically according to - tempo value.<br> - </li> - <li><strong>DEFAULT_SEEKWINDOW_MS</strong>: The seeking window -default length in milliseconds is for the algorithm that seeks the best -possible overlapping location. This determines from how -wide a sample "window" the algorithm can use to find an optimal mixing -location when the sound sequences are to be linked back together. <br> - <br> -The bigger this window setting is, the higher the possibility to find a -better mixing position becomes, but at the same time large values may -cause a "drifting" sound artifact because neighboring sequences can be -chosen at more uneven intervals. If there's a disturbing artifact that -sounds as if a constant frequency was drifting around, try reducing -this setting.<br> - <br> - By default, this setting value is calculated automatically according to - tempo value.<br> - </li> - <li><strong>DEFAULT_OVERLAP_MS</strong>: Overlap -length in milliseconds. When the sound sequences are mixed back -together to form again a continuous sound stream, this parameter -defines how much the ends of the consecutive sequences will overlap with each other.<br> - <br> - This shouldn't be that critical parameter. If you reduce the -DEFAULT_SEQUENCE_MS setting by a large amount, you might wish to try a -smaller value on this.</li> -</ul> -<p>Notice that these parameters can also be -set during execution time with functions "<strong>TDStretch::setParameters()</strong>" -and "<strong>SoundTouch::setSetting()</strong>".</p> -<p>The table below summaries how the -parameters can be adjusted for different applications:</p> -<table border="1"> - <tbody> - <tr> - <td valign="top"><strong>Parameter name</strong></td> - <td valign="top"><strong>Default value -magnitude</strong></td> - <td valign="top"><strong>Larger value -affects...</strong></td> - <td valign="top"><strong>Smaller value -affects...</strong></td> - <td valign="top"><strong>Effect to CPU burden</strong></td> - </tr> - <tr> - <td valign="top"> - <pre>SEQUENCE_MS</pre> - </td> - <td valign="top">Default value is relatively -large, chosen for slowing down music tempo</td> - <td valign="top">Larger value is usually -better for slowing down tempo. Growing the value decelerates the -"echoing" artifact when slowing down the tempo.</td> - <td valign="top">Smaller value might be better -for speeding up tempo. Reducing the value accelerates the "echoing" -artifact when slowing down the tempo </td> - <td valign="top">Increasing the parameter -value reduces computation burden</td> - </tr> - <tr> - <td valign="top"> - <pre>SEEKWINDOW_MS</pre> - </td> - <td valign="top">Default value is relatively -large, chosen for slowing down music tempo</td> - <td valign="top">Larger value eases finding a -good mixing position, but may cause a "drifting" artifact</td> - <td valign="top">Smaller reduce possibility to -find a good mixing position, but reduce the "drifting" artifact.</td> - <td valign="top">Increasing the parameter -value increases computation burden</td> - </tr> - <tr> - <td valign="top"> - <pre>OVERLAP_MS</pre> - </td> - <td valign="top">Default value is relatively -large, chosen to suit with above parameters.</td> - <td valign="top"> </td> - <td valign="top">If you reduce the "sequence -ms" setting, you might wish to try a smaller value.</td> - <td valign="top">Increasing the parameter -value increases computation burden</td> - </tr> - </tbody> -</table> -<h3>3.5 Performance Optimizations </h3> -<p><strong>General optimizations:</strong></p> -<p>The time-stretch routine has a 'quick' mode -that substantially speeds up the algorithm but may degrade the -sound quality by a small amount. This mode is activated by -calling SoundTouch::setSetting() function with parameter id -of SETTING_USE_QUICKSEEK and value "1", i.e. </p> -<blockquote> - <p>setSetting(SETTING_USE_QUICKSEEK, 1);</p> -</blockquote> -<p><strong>CPU-specific optimizations:</strong></p> -<ul> - <li>Intel MMX optimized routines are used with -compatible CPUs when 16bit integer sample type is used. MMX optimizations are available both in Win32 and Gnu/x86 platforms. -Compatible processors are Intel PentiumMMX and later; AMD K6-2, Athlon -and later. </li> - <li>Intel SSE optimized routines are used with -compatible CPUs when floating point sample type is used. SSE optimizations are currently implemented for Win32 platform only. -Processors compatible with SSE extension are Intel processors starting -from Pentium-III, and AMD processors starting from Athlon XP. </li> - <li>AMD 3DNow! optimized routines are used with -compatible CPUs when floating point sample type is used, but SSE -extension isn't supported . 3DNow! optimizations are currently -implemented for Win32 platform only. These optimizations are used in -AMD K6-2 and Athlon (classic) CPU's; better performing SSE routines are -used with AMD processor starting from Athlon XP. </li> -</ul> -<hr> -<h2><a name="SoundStretch"></a>4. SoundStretch audio processing utility -</h2> -<p>SoundStretch audio processing utility<br> -Copyright (c) Olli Parviainen 2002-2009</p> -<p>SoundStretch is a simple command-line -application that can change tempo, pitch and playback rates of -WAV sound files. This program is intended primarily to -demonstrate how the "SoundTouch" library can be used to -process sound in your own program, but it can as well be used for -processing sound files.</p> -<h3>4.1. SoundStretch Usage Instructions</h3> -<p>SoundStretch Usage syntax:</p> -<blockquote> - <pre>soundstretch infilename outfilename [switches]</pre> -</blockquote> -<p>Where: </p> -<table border="0" cellpadding="2" width="100%"> - <tbody> - <tr> - <td valign="top"> - <pre>"infilename"</pre> - </td> - <td valign="top">Name of the input sound -data file (in .WAV audio file format). Give "stdin" as filename to use - standard input pipe. </td> - </tr> - <tr> - <td valign="top"> - <pre>"outfilename"</pre> - </td> - <td valign="top">Name of the output sound -file where the resulting sound is saved (in .WAV audio file format). -This parameter may be omitted if you don't want to save the -output -(e.g. when only calculating BPM rate with '-bpm' switch). Give "stdout" - as filename to use standard output pipe.</td> - </tr> - <tr> - <td valign="top"> - <pre> [switches]</pre> - </td> - <td valign="top">Are one or more control -switches.</td> - </tr> - </tbody> -</table> -<p>Available control switches are:</p> -<table border="0" cellpadding="2" width="100%"> - <tbody> - <tr> - <td valign="top"> - <pre>-tempo=n </pre> - </td> - <td valign="top">Change the sound tempo by n -percents (n = -95.0 .. +5000.0 %) </td> - </tr> - <tr> - <td valign="top"> - <pre>-pitch=n</pre> - </td> - <td valign="top">Change the sound pitch by n -semitones (n = -60.0 .. + 60.0 semitones) </td> - </tr> - <tr> - <td valign="top"> - <pre>-rate=n</pre> - </td> - <td valign="top">Change the sound playback rate by -n percents (n = -95.0 .. +5000.0 %) </td> - </tr> - <tr> - <td valign="top"> - <pre>-bpm=n</pre> - </td> - <td valign="top">Detect the Beats-Per-Minute (BPM) rate of the sound and adjust the tempo to meet 'n' - BPMs. When this switch is - applied, the "-tempo" switch is ignored. If "=n" is -omitted, i.e. switch "-bpm" is used alone, then the BPM rate is - estimated and displayed, but tempo not adjusted according to the BPM -value. </td> - </tr> - <tr> - <td valign="top"> - <pre>-quick</pre> - </td> - <td valign="top">Use quicker tempo change -algorithm. Gains speed but loses sound quality. </td> - </tr> - <tr> - <td valign="top"> - <pre>-naa</pre> - </td> - <td valign="top">Don't use anti-alias -filtering in sample rate transposing. Gains speed but loses sound -quality. </td> - </tr> - <tr> - <td valign="top"> - <pre>-license</pre> - </td> - <td valign="top">Displays the program license -text (LGPL)</td> - </tr> - </tbody> -</table> -<p>Notes:</p> -<ul> - <li>To use standard input/output pipes for processing, give "stdin" - and "stdout" as input/output filenames correspondingly. The - standard input/output pipes will still carry the audio data in .wav audio - file format.</li> - <li>The numerical switches allow both integer (e.g. "-tempo=123") and decimal (e.g. -"-tempo=123.45") numbers.</li> - <li>The "-naa" and/or "-quick" switches can be -used to reduce CPU usage while compromising some sound quality </li> - <li>The BPM detection algorithm works by detecting -repeating bass or drum patterns at low frequencies of <250Hz. A - lower-than-expected BPM figure may be reported for music with uneven or - complex bass patterns. </li> -</ul> -<h3>4.2. SoundStretch usage examples </h3> -<p><strong>Example 1</strong></p> -<p>The following command increases tempo of -the sound file "originalfile.wav" by 12.5% and stores result to file "destinationfile.wav":</p> -<blockquote> - <pre>soundstretch originalfile.wav destinationfile.wav -tempo=12.5</pre> -</blockquote> -<p><strong>Example 2</strong></p> -<p>The following command decreases the sound -pitch (key) of the sound file "orig.wav" by two -semitones and stores the result to file "dest.wav":</p> -<blockquote> - <pre>soundstretch orig.wav dest.wav -pitch=-2</pre> -</blockquote> -<p><strong>Example 3</strong></p> -<p>The following command processes the file "orig.wav" by decreasing the sound tempo by 25.3% and -increasing the sound pitch (key) by 1.5 semitones. Resulting .wav audio data is -directed to standard output pipe:</p> -<blockquote> - <pre>soundstretch orig.wav stdout -tempo=-25.3 -pitch=1.5</pre> -</blockquote> -<p><strong>Example 4</strong></p> -<p>The following command detects the BPM rate -of the file "orig.wav" and adjusts the tempo to match -100 beats per minute. Result is stored to file "dest.wav":</p> -<blockquote> - <pre>soundstretch orig.wav dest.wav -bpm=100</pre> -</blockquote> -<p><strong>Example 5</strong></p> -<p>The following command reads .wav sound data from standard input pipe and -estimates the BPM rate:</p> -<blockquote> - <pre>soundstretch stdin -bpm</pre> -</blockquote> -<hr> -<h2>5. Change History</h2> -<h3>5.1. SoundTouch library Change History </h3> - -<p><strong>1.5.0:</strong></p> -<ul> -<li>Added normalization to correlation calculation and improvement automatic seek/sequence parameter calculation to improve sound quality</li> - -<li>Bugfixes: - <ul> - <li>Fixed negative array indexing in quick seek algorithm</li> - <li>FIR autoalias filter running too far in processing buffer</li> - <li>Check against zero sample count in rate transposing</li> - <li>Fix for x86-64 support: Removed pop/push instructions from the cpu detection algorithm. </li> - <li>Check against empty buffers in FIFOSampleBuffer</li> - <li>Other minor fixes & code cleanup</li> - </ul> -</li> - -<li>Fixes in compilation scripts for non-Intel platforms</li> -<li>Added Dynamic-Link-Library (DLL) version of SoundTouch library build, - provided with Delphi/Pascal wrapper for calling the dll routines</li> -<li>Added #define PREVENT_CLICK_AT_RATE_CROSSOVER that prevents a click artifact - when crossing the nominal pitch from either positive to negative side or vice - versa</li> - -</ul> - -<p><strong>1.4.1:</strong></p> -<ul> -<li>Fixed a buffer overflow bug in BPM detect algorithm routines if processing - more than 2048 samples at one call </li> - -</ul> - -<p><strong>1.4.0:</strong></p> -<ul> -<li>Improved sound quality by automatic calculation of time stretch algorithm - processing parameters according to tempo setting</li> -<li>Moved BPM detection routines from SoundStretch application into SoundTouch - library</li> -<li>Bugfixes: Usage of uninitialied variables, GNU build scripts, compiler errors - due to 'const' keyword mismatch.</li> -<li>Source code cleanup</li> - -</ul> - -<p><strong>v1.3.1: -</strong></p> -<ul> -<li>Changed static class declaration to GCC 4.x compiler compatible syntax.</li> -<li>Enabled MMX/SSE-optimized routines also for GCC compilers. Earlier -the MMX/SSE-optimized routines were written in compiler-specific inline -assembler, now these routines are migrated to use compiler intrinsic -syntax which allows compiling the same MMX/SSE-optimized source code with -both Visual C++ and GCC compilers. </li> -<li>Set floating point as the default sample format and added switch to -the GNU configure script for selecting the other sample format.</li> - -</ul> - -<p><strong>v1.3.0: -</strong></p> -<ul> - <li>Fixed tempo routine output duration inaccuracy due to rounding -error </li> - <li>Implemented separate processing routines for integer and -floating arithmetic to allow improvements to floating point routines -(earlier used algorithms mostly optimized for integer arithmetic also -for floating point samples) </li> - <li>Fixed a bug that distorts sound if sample rate changes during the -sound stream </li> - <li>Fixed a memory leak that appeared in MMX/SSE/3DNow! optimized -routines </li> - <li>Reduced redundant code pieces in MMX/SSE/3DNow! optimized -routines vs. the standard C routines.</li> - <li>MMX routine incompatibility with new gcc compiler versions </li> - <li>Other miscellaneous bug fixes </li> -</ul> -<p><strong>v1.2.1: </strong></p> -<ul> - <li>Added automake/autoconf scripts for GNU -platforms (in courtesy of David Durham)</li> - <li>Fixed SCALE overflow bug in rate transposer -routine.</li> - <li>Fixed 64bit address space bugs.</li> - <li>Created a 'soundtouch' namespace for -SAMPLETYPE definitions.</li> -</ul> -<p><strong>v1.2.0: </strong></p> -<ul> - <li>Added support for 32bit floating point sample -data type with SSE/3DNow! optimizations for Win32 platform (SSE/3DNow! optimizations currently not supported in GCC environment)</li> - <li>Replaced 'make-gcc' script for GNU environment -by master Makefile</li> - <li>Added time-stretch routine configurability to -SoundTouch main class</li> - <li>Bugfixes</li> -</ul> -<p><strong>v1.1.1: </strong></p> -<ul> - <li>Moved SoundTouch under lesser GPL license (LGPL). This allows using SoundTouch library in programs that aren't -released under GPL license. </li> - <li>Changed MMX routine organiation so that MMX optimized routines are now implemented in classes that are derived from -the basic classes having the standard non-mmx routines. </li> - <li>MMX routines to support gcc version 3. </li> - <li>Replaced windows makefiles by script using the .dsw files </li> -</ul> -<p><strong>v1.01: </strong></p> -<ul> - <li>"mmx_gcc.cpp": Added "using namespace std" and -removed "return 0" from a function with void return value to fix -compiler errors when compiling the library in Solaris environment. </li> - <li>Moved file "FIFOSampleBuffer.h" to "include" -directory to allow accessing the FIFOSampleBuffer class from external -files. </li> -</ul> -<p><strong>v1.0: </strong></p> -<ul> - <li>Initial release </li> -</ul> -<p> </p> -<h3>5.2. SoundStretch application Change -History </h3> - -<p><strong>1.4.0:</strong></p> -<ul> -<li>Moved BPM detection routines from SoundStretch application into SoundTouch - library</li> -<li>Allow using standard input/output pipes as audio processing input/output - streams</li> - -</ul> - -<p><strong>v1.3.0:</strong></p> -<ul> - <li>Simplified accessing WAV files with floating -point sample format. - </li> -</ul> -<p><strong>v1.2.1: </strong></p> -<ul> - <li>Fixed 64bit address space bugs.</li> -</ul> -<p><strong>v1.2.0: </strong></p> -<ul> - <li>Added support for 32bit floating point sample -data type</li> - <li>Restructured the BPM routines into separate -library</li> - <li>Fixed big-endian conversion bugs in WAV file -routines (hopefully :)</li> -</ul> -<p><strong>v1.1.1: </strong></p> -<ul> - <li>Fixed bugs in WAV file reading & added -byte-order conversion for big-endian processors. </li> - <li>Moved SoundStretch source code under 'example' -directory to highlight difference from SoundTouch stuff. </li> - <li>Replaced windows makefiles by script using the .dsw files </li> - <li>Output file name isn't required if output -isn't desired (e.g. if using the switch '-bpm' in plain format only) </li> -</ul> -<p><strong>v1.1:</strong></p> -<ul> - <li>Fixed "Release" settings in Microsoft Visual -C++ project file (.dsp) </li> - <li>Added beats-per-minute (BPM) detection routine -and command-line switch "-bpm" </li> -</ul> -<p><strong>v1.01: </strong></p> -<ul> - <li>Initial release </li> -</ul> -<hr> -<h2 >6. Acknowledgements </h2> -<p >Kudos for these people who have contributed to development or submitted -bugfixes since -SoundTouch v1.3.1: </p> -<ul> - <li>Arthur A</li> - <li>Richard Ash</li> - <li>Stanislav Brabec</li> - <li>Christian Budde</li> - <li>Brian Cameron</li> - <li>Jason Champion</li> - <li>Patrick Colis</li> - <li>Justin Frankel</li> - <li>Jason Garland</li> - <li>Takashi Iwai</li> - <li>Paulo Pizarro</li> - <li>RJ Ryan</li> - <li>John Sheehy</li> -</ul> -<p >Moral greetings to all other contributors and users also!</p> -<hr> -<h2 >7. LICENSE </h2> -<p>SoundTouch audio processing library<br> -Copyright (c) Olli Parviainen</p> -<p>This library is free software; you can -redistribute it and/or modify it under the terms of the GNU -Lesser General Public License version 2.1 as published by the Free Software -Foundation.</p> -<p>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.</p> -<p>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</p> -<hr> -<!-- -$Id: README.html 81 2009-12-28 20:51:18Z oparviai $ ---> -</body> -</html> +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> +<head> + <title>SoundTouch library README</title> + <meta http-equiv="Content-Type" + content="text/html; charset=windows-1252"> + <meta http-equiv="Content-Language" content="en-us"> + <meta name="author" content="Olli Parviainen"> + <meta name="description" + content="Readme file for SoundTouch audio processing library"> + <meta name="GENERATOR" content="Microsoft FrontPage 4.0"> + <meta name="ProgId" content="FrontPage.Editor.Document"> + <style> <!-- .normal { font-family: Arial } + --></style> +</head> +<body class="normal"> +<hr> +<h4 style="color:red">Note: Some of the SoundTouch files included in OpenMPT repository are modified versions +of the original SoundTouch files (check OpenMPT.txt for details). +This readme, excluding this note, is the original SoundTouch readme. +</h4> +<h1>SoundTouch audio processing library v1.6.0 </h1> +<p class="normal">SoundTouch library Copyright © Olli Parviainen +2001-2011 </p> +<hr> +<h2>1. Introduction </h2> +<p>SoundTouch is an open-source audio processing library that allows +changing the sound tempo, pitch and playback rate parameters +independently from each other, i.e.:</p> +<ul> + <li> Sound tempo can be increased or decreased while maintaining the +original pitch </li> + <li> Sound pitch can be increased or decreased while maintaining the +original tempo </li> + <li> Change playback rate that affects both tempo and pitch at the +same time </li> + <li> Choose any combination of tempo/pitch/rate</li> +</ul> +<h3>1.1 Contact information </h3> +<p>Author email: oparviai 'at' iki.fi </p> +<p>SoundTouch WWW page: <a href="http://www.surina.net/soundtouch">http://www.surina.net/soundtouch</a></p> +<hr> +<h2>2. Compiling SoundTouch</h2> +<p>Before compiling, notice that you can choose the sample data format +if it's desirable to use floating point sample data instead of 16bit +integers. See section "sample data format" for more information.</p> +<h3>2.1. Building in Microsoft Windows</h3> +<p>Project files for Microsoft Visual C++ 6.0 and Visual C++ .NET are +supplied with the source code package.<br> +</p> +<p> Please notice that SoundTouch library uses processor-specific +optimizations for Pentium III and AMD processors. Visual Studio .NET +and later versions supports the required instructions by default, but +Visual Studio 6.0 requires a processor pack upgrade to be installed in +order to support these optimizations. The processor pack upgrade can be +downloaded from Microsoft site at this URL:</p> +<p><a href="http://msdn.microsoft.com/en-us/vstudio/aa718349.aspx">http://msdn.microsoft.com/en-us/vstudio/aa718349.aspx</a></p> +<p>If the above URL is unavailable or removed, go to <a + href="http://msdn.microsoft.com/"> http://msdn.microsoft.com</a> and +perform a search with keywords "processor pack". </p> +<p>To build the binaries with Visual C++ compiler, either run +"make-win.bat" script, or open the appropriate project files in source +code directories with Visual Studio. The final executable will appear +under the "SoundTouch\bin" directory. If using the Visual Studio IDE +instead of the make-win.bat script, directories bin and lib may need to +be created manually to the SoundTouch package root for the final +executables. The make-win.bat script creates these directories +automatically. </p> +<h3>2.2. Building in Gnu platforms</h3> +<p>The SoundTouch library compiles in practically any platform +supporting GNU compiler (GCC) tools. SoundTouch have been tested with +gcc version 4.4.5 at latest, but it shouldn't be very specific about +the gcc +version. Assembler-level performance optimizations for GNU platform are +currently available in x86 platforms only, and they are automatically +disabled and replaced with standard C routines in other processor +platforms.</p> +<p>To build and install the binaries, run the following commands in the +SoundTouch/ directory:</p> +<table border="0" cellpadding="0" cellspacing="4"> + <tbody> + <tr> + <td style="vertical-align: top;"> + <pre>./bootstrap -</pre> + </td> + <td style="vertical-align: top;">Creates "configure" file with +local autoconf/automake toolset.<br> + </td> + </tr> + <tr valign="top"> + <td> + <pre>./configure -</pre> + </td> + <td> + <p>Configures the SoundTouch package for the local environment. +Notice that "configure" file is not available before running the +"./bootstrap" command as above.<br> + </p> + </td> + </tr> + <tr valign="top"> + <td> + <pre>make -</pre> + </td> + <td> + <p>Builds the SoundTouch library & SoundStretch utility.</p> + </td> + </tr> + <tr valign="top"> + <td> + <pre>make install -</pre> + </td> + <td> + <p>Installs the SoundTouch & BPM libraries to <b>/usr/local/lib</b> +and SoundStretch utility to <b>/usr/local/bin</b>. Please notice that +'root' privileges may be required to install the binaries to the +destination locations.</p> + </td> + </tr> + </tbody> +</table> +<h4><b>2.2.1 Required GNU tools</b> </h4> +<p> <span style="font-weight: bold;">Bash shell</span>, <span + style="font-weight: bold;">GNU C++ compiler</span>, <span + style="font-weight: bold;">libtool</span>, <span + style="font-weight: bold;">autoconf</span> and <span + style="font-weight: bold;">automake</span> tools +are required for compiling the SoundTouch library. These are usually +included with the GNU/Linux distribution, but if not, install these +packages first. For example, Ubuntu Linux can acquire and install +these with the following command:</p> +<pre><b>sudo apt-get install automake autoconf libtool build-essential</b></pre> +<h4><b>2.2.2 Problems with GCC compiler compatibility</b></h4> +<p>At the release time the SoundTouch package has been tested to +compile in GNU/Linux platform. However, in past it's happened that new +gcc versions aren't necessarily compatible with the assembler settings +used in the optimized routines. <b>If you have problems getting the +SoundTouch library compiled, try disabling the optimizations as a </b><b>workaround</b> +by editing the file "include/STTypes.h" and removing the following +definition there:</p> +<blockquote> + <pre>#define ALLOW_OPTIMIZATIONS 1</pre> +</blockquote> +<h4><b>2.2.3 Problems with configure script or build process</b> </h4> +<p>Incompatibilities between various GNU toolchain versions may cause +errors when running the "configure" script or building the source +codes, if your GNU tool versions are not compatible with the versions +used for preparing the SoundTouch kit. </p> +<p>To resolve the issue, regenerate the configure scripts with your +local tool set by running the "<b>./bootstrap</b>" script included in +the SoundTouch source code kit. After that, run the <b>configure</b> +script and <b>make</b> as usually.</p> +<h4><b>2.2.4 Compiler issues with non-x86 processors</b></h4> +<p>SoundTouch library works also on non-x86 processors.</p> +<p>However, in case that you get compiler errors when trying to compile +for non-Intel processor, edit the file "<b>source\SoundTouch\Makefile.am</b>" +and +remove the "<b>-msse2</b>" flag on the <b>AM_CXXFLAGS </b>line:</p> +<pre><b>AM_CXXFLAGS=-O3 -fcheck-new -I../../include # Note: -msse2 flag removed!</b></pre> +<p>After that, run "<b>./bootstrap</b>" script, and then run <b>configure</b> +and <b>make</b> again.</p> +<hr> +<h2>3. About implementation & Usage tips</h2> +<h3>3.1. Supported sample data formats</h3> +<p>The sample data format can be chosen between 16bit signed integer +and 32bit floating point values, the default is 32bit floating point. </p> +<p> In Windows environment, the sample data format is chosen in file +"STTypes.h" by choosing one of the following defines:</p> +<ul> + <li> <span style="font-weight: bold;">#define +SOUNDTOUCH_INTEGER_SAMPLES</span> for 16bit signed integer </li> + <li> <span style="font-weight: bold;">#define </span><span + style="font-weight: bold;">SOUNDTOUCH_</span><span + style="font-weight: bold;">FLOAT_SAMPLES</span> for 32bit floating +point</li> +</ul> +<p> In GNU environment, the floating sample format is used by default, +but integer sample format can be chosen by giving the following switch +to the configure script: </p> +<blockquote> + <pre>./configure --enable-integer-samples</pre> +</blockquote> +<p>The sample data can have either single (mono) or double (stereo) +audio channel. Stereo data is interleaved so that every other data +value is for left channel and every second for right channel. Notice +that while it'd be possible in theory to process stereo sound as two +separate mono channels, this isn't recommended because processing the +channels separately would result in losing the phase coherency between +the channels, which consequently would ruin the stereo effect.</p> +<p>Sample rates between 8000-48000H are supported.</p> +<h3>3.2. Processing latency</h3> +<p>The processing and latency constraints of the SoundTouch library are:</p> +<ul> + <li> Input/output processing latency for the SoundTouch processor is +around 100 ms. This is when time-stretching is used. If the rate +transposing effect alone is used, the latency requirement is much +shorter, see section 'About algorithms'. </li> + <li> Processing CD-quality sound (16bit stereo sound with 44100H +sample rate) in real-time or faster is possible starting from +processors equivalent to Intel Pentium 133Mh or better, if using the +"quick" processing algorithm. If not using the "quick" mode or if +floating point sample data are being used, several times more CPU power +is typically required.</li> +</ul> +<h3>3.3. About algorithms</h3> +<p>SoundTouch provides three seemingly independent effects: tempo, +pitch and playback rate control. These three controls are implemented +as combination of two primary effects, <em>sample rate transposing</em> +and <em>time-stretching</em>.</p> +<p><em>Sample rate transposing</em> affects both the audio stream +duration and pitch. It's implemented simply by converting the original +audio sample stream to the desired duration by interpolating from +the original audio samples. In SoundTouch, linear interpolation with +anti-alias filtering is used. Theoretically a higher-order +interpolation provide better result than 1st order linear +interpolation, but in audio application linear interpolation together +with anti-alias filtering performs subjectively about as well as +higher-order filtering would.</p> +<p><em>Time-stretching </em>means changing the audio stream duration +without affecting it's pitch. SoundTouch uses WSOLA-like +time-stretching routines that operate in the time domain. Compared to +sample rate transposing, time-stretching is a much heavier operation +and also requires a longer processing "window" of sound samples used by +the processing algorithm, thus increasing the algorithm input/output +latency. Typical i/o latency for the SoundTouch time-stretch algorithm +is around 100 ms.</p> +<p>Sample rate transposing and time-stretching are then used together +to produce the tempo, pitch and rate controls:</p> +<ul> + <li> <strong>'Tempo'</strong> control is implemented purely by +time-stretching. </li> + <li> <strong>'Rate</strong>' control is implemented purely by sample +rate transposing. </li> + <li> <strong>'Pitch</strong>' control is implemented as a +combination of time-stretching and sample rate transposing. For +example, to increase pitch the audio stream is first time-stretched to +longer duration (without affecting pitch) and then transposed back to +original duration by sample rate transposing, which simultaneously +reduces duration and increases pitch. The result is original duration +but increased pitch.</li> +</ul> +<h3>3.4 Tuning the algorithm parameters</h3> +<p>The time-stretch algorithm has few parameters that can be tuned to +optimize sound quality for certain application. The current default +parameters have been chosen by iterative if-then analysis (read: "trial +and error") to obtain best subjective sound quality in pop/rock music +processing, but in applications processing different kind of sound the +default parameter set may result into a sub-optimal result.</p> +<p>The time-stretch algorithm default parameter values are set by the +following #defines in file "TDStretch.h":</p> +<blockquote> + <pre>#define DEFAULT_SEQUENCE_MS AUTOMATIC<br>#define DEFAULT_SEEKWINDOW_MS AUTOMATIC<br>#define DEFAULT_OVERLAP_MS 8</pre> +</blockquote> +<p>These parameters affect to the time-stretch algorithm as follows:</p> +<ul> + <li> <strong>DEFAULT_SEQUENCE_MS</strong>: This is the default +length of a single processing sequence in milliseconds which determines +the how the original... [truncated message content] |