mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-26 02:17:34 +09:00
Issue #451 part 1 - use OpenMP for SoundTouch
This commit is contained in:
parent
952767296d
commit
b66a74daf6
5 changed files with 48 additions and 18 deletions
|
|
@ -86,8 +86,11 @@ uint FIRFilter::evaluateFilterStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, ui
|
||||||
assert((length != 0) && (length == ilength) && (src != NULL) && (dest != NULL) && (filterCoeffs != NULL));
|
assert((length != 0) && (length == ilength) && (src != NULL) && (dest != NULL) && (filterCoeffs != NULL));
|
||||||
|
|
||||||
end = 2 * (numSamples - ilength);
|
end = 2 * (numSamples - ilength);
|
||||||
|
const SAMPLETYPE *coeffsStereo = filterCoeffsStereo;
|
||||||
|
|
||||||
#pragma omp parallel for
|
#if defined(_OPENMP)
|
||||||
|
#pragma omp parallel for default(none) shared(src, dest, end, ilength, coeffsStereo) private(j) schedule(static)
|
||||||
|
#endif
|
||||||
for (j = 0; j < end; j += 2)
|
for (j = 0; j < end; j += 2)
|
||||||
{
|
{
|
||||||
const SAMPLETYPE *ptr;
|
const SAMPLETYPE *ptr;
|
||||||
|
|
@ -98,8 +101,8 @@ uint FIRFilter::evaluateFilterStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, ui
|
||||||
|
|
||||||
for (int i = 0; i < ilength; i ++)
|
for (int i = 0; i < ilength; i ++)
|
||||||
{
|
{
|
||||||
suml += ptr[2 * i] * filterCoeffsStereo[2 * i];
|
suml += ptr[2 * i] * coeffsStereo[2 * i];
|
||||||
sumr += ptr[2 * i + 1] * filterCoeffsStereo[2 * i + 1];
|
sumr += ptr[2 * i + 1] * coeffsStereo[2 * i + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SOUNDTOUCH_INTEGER_SAMPLES
|
#ifdef SOUNDTOUCH_INTEGER_SAMPLES
|
||||||
|
|
@ -133,7 +136,10 @@ uint FIRFilter::evaluateFilterMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint
|
||||||
assert(ilength != 0);
|
assert(ilength != 0);
|
||||||
|
|
||||||
end = numSamples - ilength;
|
end = numSamples - ilength;
|
||||||
#pragma omp parallel for
|
const SAMPLETYPE *coeffs = filterCoeffs;
|
||||||
|
#if defined(_OPENMP)
|
||||||
|
#pragma omp parallel for default(none) shared(src, dest, end, ilength, coeffs) private(j) schedule(static)
|
||||||
|
#endif
|
||||||
for (j = 0; j < end; j ++)
|
for (j = 0; j < end; j ++)
|
||||||
{
|
{
|
||||||
const SAMPLETYPE *pSrc = src + j;
|
const SAMPLETYPE *pSrc = src + j;
|
||||||
|
|
@ -143,7 +149,7 @@ uint FIRFilter::evaluateFilterMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint
|
||||||
sum = 0;
|
sum = 0;
|
||||||
for (i = 0; i < ilength; i ++)
|
for (i = 0; i < ilength; i ++)
|
||||||
{
|
{
|
||||||
sum += pSrc[i] * filterCoeffs[i];
|
sum += pSrc[i] * coeffs[i];
|
||||||
}
|
}
|
||||||
#ifdef SOUNDTOUCH_INTEGER_SAMPLES
|
#ifdef SOUNDTOUCH_INTEGER_SAMPLES
|
||||||
sum >>= resultDivFactor;
|
sum >>= resultDivFactor;
|
||||||
|
|
@ -176,8 +182,11 @@ uint FIRFilter::evaluateFilterMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uin
|
||||||
int ilength = length & -8;
|
int ilength = length & -8;
|
||||||
|
|
||||||
end = numChannels * (numSamples - ilength);
|
end = numChannels * (numSamples - ilength);
|
||||||
|
const SAMPLETYPE *coeffs = filterCoeffs;
|
||||||
|
|
||||||
#pragma omp parallel for
|
#if defined(_OPENMP)
|
||||||
|
#pragma omp parallel for default(none) shared(src, dest, end, ilength, numChannels, coeffs) private(j) schedule(static)
|
||||||
|
#endif
|
||||||
for (j = 0; j < end; j += numChannels)
|
for (j = 0; j < end; j += numChannels)
|
||||||
{
|
{
|
||||||
const SAMPLETYPE *ptr;
|
const SAMPLETYPE *ptr;
|
||||||
|
|
@ -194,7 +203,7 @@ uint FIRFilter::evaluateFilterMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uin
|
||||||
|
|
||||||
for (i = 0; i < ilength; i ++)
|
for (i = 0; i < ilength; i ++)
|
||||||
{
|
{
|
||||||
SAMPLETYPE coef=filterCoeffs[i];
|
SAMPLETYPE coef=coeffs[i];
|
||||||
for (c = 0; c < numChannels; c ++)
|
for (c = 0; c < numChannels; c ++)
|
||||||
{
|
{
|
||||||
sums[c] += ptr[0] * coef;
|
sums[c] += ptr[0] * coef;
|
||||||
|
|
|
||||||
|
|
@ -306,25 +306,31 @@ int TDStretch::seekBestOverlapPositionFull(const SAMPLETYPE *refPos)
|
||||||
// over the permitted range.
|
// over the permitted range.
|
||||||
bestCorr = calcCrossCorr(refPos, pMidBuffer, norm);
|
bestCorr = calcCrossCorr(refPos, pMidBuffer, norm);
|
||||||
bestCorr = (bestCorr + 0.1) * 0.75;
|
bestCorr = (bestCorr + 0.1) * 0.75;
|
||||||
|
const int seekLen = seekLength;
|
||||||
|
const int nChannels = channels;
|
||||||
|
const SAMPLETYPE *midBuffer = pMidBuffer;
|
||||||
|
|
||||||
#pragma omp parallel for
|
#if defined(_OPENMP)
|
||||||
for (i = 1; i < seekLength; i ++)
|
#pragma omp parallel for default(none) shared(refPos, bestCorr, bestOffs, seekLen, nChannels, midBuffer) private(i) schedule(static)
|
||||||
|
#endif
|
||||||
|
for (i = 1; i < seekLen; i ++)
|
||||||
{
|
{
|
||||||
double corr;
|
double corr;
|
||||||
|
double localNorm;
|
||||||
// Calculates correlation value for the mixing position corresponding to 'i'
|
// Calculates correlation value for the mixing position corresponding to 'i'
|
||||||
#if defined(_OPENMP) || defined(ST_SIMD_AVOID_UNALIGNED)
|
#if defined(_OPENMP) || defined(ST_SIMD_AVOID_UNALIGNED)
|
||||||
// in parallel OpenMP mode, can't use norm accumulator version as parallel executor won't
|
// in parallel OpenMP mode, can't use norm accumulator version as parallel executor won't
|
||||||
// iterate the loop in sequential order
|
// iterate the loop in sequential order
|
||||||
// in SIMD mode, avoid accumulator version to allow avoiding unaligned positions
|
// in SIMD mode, avoid accumulator version to allow avoiding unaligned positions
|
||||||
corr = calcCrossCorr(refPos + channels * i, pMidBuffer, norm);
|
corr = calcCrossCorr(refPos + nChannels * i, midBuffer, localNorm);
|
||||||
#else
|
#else
|
||||||
// In non-parallel version call "calcCrossCorrAccumulate" that is otherwise same
|
// In non-parallel version call "calcCrossCorrAccumulate" that is otherwise same
|
||||||
// as "calcCrossCorr", but saves time by reusing & updating previously stored
|
// as "calcCrossCorr", but saves time by reusing & updating previously stored
|
||||||
// "norm" value
|
// "norm" value
|
||||||
corr = calcCrossCorrAccumulate(refPos + channels * i, pMidBuffer, norm);
|
corr = calcCrossCorrAccumulate(refPos + nChannels * i, midBuffer, norm);
|
||||||
#endif
|
#endif
|
||||||
// heuristic rule to slightly favour values close to mid of the range
|
// heuristic rule to slightly favour values close to mid of the range
|
||||||
double tmp = (double)(2 * i - seekLength) / (double)seekLength;
|
double tmp = (double)(2 * i - seekLen) / (double)seekLen;
|
||||||
corr = ((corr + 0.1) * (1.0 - 0.25 * tmp * tmp));
|
corr = ((corr + 0.1) * (1.0 - 0.25 * tmp * tmp));
|
||||||
|
|
||||||
// Checks for the highest correlation value
|
// Checks for the highest correlation value
|
||||||
|
|
@ -333,7 +339,9 @@ int TDStretch::seekBestOverlapPositionFull(const SAMPLETYPE *refPos)
|
||||||
// For optimal performance, enter critical section only in case that best value found.
|
// For optimal performance, enter critical section only in case that best value found.
|
||||||
// in such case repeat 'if' condition as it's possible that parallel execution may have
|
// in such case repeat 'if' condition as it's possible that parallel execution may have
|
||||||
// updated the bestCorr value in the mean time
|
// updated the bestCorr value in the mean time
|
||||||
#pragma omp critical
|
#if defined(_OPENMP)
|
||||||
|
#pragma omp critical(soundtouch_bestcorr)
|
||||||
|
#endif
|
||||||
if (corr > bestCorr)
|
if (corr > bestCorr)
|
||||||
{
|
{
|
||||||
bestCorr = corr;
|
bestCorr = corr;
|
||||||
|
|
@ -910,7 +918,9 @@ double TDStretch::calcCrossCorr(const short *mixingPos, const short *compare, do
|
||||||
if (lnorm > maxnorm)
|
if (lnorm > maxnorm)
|
||||||
{
|
{
|
||||||
// modify 'maxnorm' inside critical section to avoid multi-access conflict if in OpenMP mode
|
// modify 'maxnorm' inside critical section to avoid multi-access conflict if in OpenMP mode
|
||||||
#pragma omp critical
|
#if defined(_OPENMP)
|
||||||
|
#pragma omp critical(soundtouch_maxnorm)
|
||||||
|
#endif
|
||||||
if (lnorm > maxnorm)
|
if (lnorm > maxnorm)
|
||||||
{
|
{
|
||||||
maxnorm = lnorm;
|
maxnorm = lnorm;
|
||||||
|
|
|
||||||
|
|
@ -119,7 +119,9 @@ double TDStretchMMX::calcCrossCorr(const short *pV1, const short *pV2, double &d
|
||||||
if (norm > (long)maxnorm)
|
if (norm > (long)maxnorm)
|
||||||
{
|
{
|
||||||
// modify 'maxnorm' inside critical section to avoid multi-access conflict if in OpenMP mode
|
// modify 'maxnorm' inside critical section to avoid multi-access conflict if in OpenMP mode
|
||||||
#pragma omp critical
|
#if defined(_OPENMP)
|
||||||
|
#pragma omp critical(soundtouch_maxnorm)
|
||||||
|
#endif
|
||||||
if (norm > (long)maxnorm)
|
if (norm > (long)maxnorm)
|
||||||
{
|
{
|
||||||
maxnorm = norm;
|
maxnorm = norm;
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,11 @@ else:
|
||||||
# Windows need alloca renamed to _alloca
|
# Windows need alloca renamed to _alloca
|
||||||
DEFINES['alloca'] = '_alloca'
|
DEFINES['alloca'] = '_alloca'
|
||||||
|
|
||||||
|
# Use standardized OpenMP parallelization for SoundTouch hot loops.
|
||||||
|
if CONFIG['CC_TYPE'] == 'gcc':
|
||||||
|
CXXFLAGS += ['-fopenmp']
|
||||||
|
OS_LIBS += ['gomp']
|
||||||
|
|
||||||
DEFINES['BUILDING_SOUNDTOUCH'] = 1
|
DEFINES['BUILDING_SOUNDTOUCH'] = 1
|
||||||
|
|
||||||
# We allow warnings for third-party code that can be updated from upstream.
|
# We allow warnings for third-party code that can be updated from upstream.
|
||||||
|
|
|
||||||
|
|
@ -250,9 +250,13 @@ uint FIRFilterSSE::evaluateFilterStereo(float *dest, const float *source, uint n
|
||||||
assert((length % 8) == 0);
|
assert((length % 8) == 0);
|
||||||
assert(filterCoeffsAlign != NULL);
|
assert(filterCoeffsAlign != NULL);
|
||||||
assert(((ulongptr)filterCoeffsAlign) % 16 == 0);
|
assert(((ulongptr)filterCoeffsAlign) % 16 == 0);
|
||||||
|
const uint filterLength = length;
|
||||||
|
const float *coeffsAlign = filterCoeffsAlign;
|
||||||
|
|
||||||
// filter is evaluated for two stereo samples with each iteration, thus use of 'j += 2'
|
// filter is evaluated for two stereo samples with each iteration, thus use of 'j += 2'
|
||||||
#pragma omp parallel for
|
#if defined(_OPENMP)
|
||||||
|
#pragma omp parallel for default(none) shared(source, dest, count, filterLength, coeffsAlign) private(j) schedule(static)
|
||||||
|
#endif
|
||||||
for (j = 0; j < count; j += 2)
|
for (j = 0; j < count; j += 2)
|
||||||
{
|
{
|
||||||
const float *pSrc;
|
const float *pSrc;
|
||||||
|
|
@ -263,11 +267,11 @@ uint FIRFilterSSE::evaluateFilterStereo(float *dest, const float *source, uint n
|
||||||
|
|
||||||
pSrc = (const float*)source + j * 2; // source audio data
|
pSrc = (const float*)source + j * 2; // source audio data
|
||||||
pDest = dest + j * 2; // destination audio data
|
pDest = dest + j * 2; // destination audio data
|
||||||
pFil = (const __m128*)filterCoeffsAlign; // filter coefficients. NOTE: Assumes coefficients
|
pFil = (const __m128*)coeffsAlign; // filter coefficients. NOTE: Assumes coefficients
|
||||||
// are aligned to 16-byte boundary
|
// are aligned to 16-byte boundary
|
||||||
sum1 = sum2 = _mm_setzero_ps();
|
sum1 = sum2 = _mm_setzero_ps();
|
||||||
|
|
||||||
for (i = 0; i < length / 8; i ++)
|
for (i = 0; i < filterLength / 8; i ++)
|
||||||
{
|
{
|
||||||
// Unroll loop for efficiency & calculate filter for 2*2 stereo samples
|
// Unroll loop for efficiency & calculate filter for 2*2 stereo samples
|
||||||
// at each pass
|
// at each pass
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue