diff --git a/app/audio/audiovisualwaveform.cpp b/app/audio/audiovisualwaveform.cpp index 4b44dd06a..22e169a2f 100644 --- a/app/audio/audiovisualwaveform.cpp +++ b/app/audio/audiovisualwaveform.cpp @@ -17,11 +17,9 @@ along with this program. If not, see . ***/ -#if defined(__x86_64__) || defined(_M_X64) -#define x86_64 -#endif +#include -#ifdef x86_64 +#ifdef Q_PROCESSOR_X86_64 #include #endif @@ -293,23 +291,38 @@ AudioVisualWaveform::Sample AudioVisualWaveform::SumSamples(const float *samples return summed_samples; } -#ifdef x86_64 -void min_max_sse(float *a, int start, int end, float &min_val, float &max_val) { - // for time being just assume that length is always mod 4 - __m128 max = _mm_loadu_ps(a + start); // load the first 4 - __m128 min = _mm_loadu_ps(a + start); // load the first 4 - for(int i = 4; i < end; i+=4) - { - __m128 cur = _mm_loadu_ps(a + start + i); - max = _mm_max_ps(max, cur); - min = _mm_min_ps(min, cur); - } - for (int i = 0; i < 3; i++) { - max = _mm_max_ps(max, _mm_shuffle_ps(max, max, 0x93)); - min = _mm_min_ps(min, _mm_shuffle_ps(min, min, 0x93)); - } - _mm_store_ss(&max_val, max); - _mm_store_ss(&min_val, min); +#ifdef Q_PROCESSOR_X86_64 +void min_max_sse(float *a, int start, int end, float &min_val, float &max_val) +{ + // load the first 4 elements of 'a' into min and max (they are 4 * 32 = 128 bits) + __m128 max = _mm_loadu_ps(a + start); + __m128 min = _mm_loadu_ps(a + start); + + // loop over 'a' and compare current elements with min and max 4 by 4. + // we need to make sure we don't read out of boundaries should 'a' lenght be not mod. 4 + for(int i = 4; i < end-4; i+=4) { + __m128 cur = _mm_loadu_ps(a + start + i); + max = _mm_max_ps(max, cur); + min = _mm_min_ps(min, cur); + } + // so we read the last 4 (or less) elements in a safe manner. + __m128 cur = _mm_loadu_ps(a + end - 4); + max = _mm_max_ps(max, cur); + min = _mm_min_ps(min, cur); + // this potentially overlaps up to the last 3 elements but it's not an issue. + + // min and max will contain 4 min and max. To get the absolute min and max + // we need to compare the 4 values over themselves by shuffling each time. + for (int i = 0; i < 3; i++) { + max = _mm_max_ps(max, _mm_shuffle_ps(max, max, 0x93)); + min = _mm_min_ps(min, _mm_shuffle_ps(min, min, 0x93)); + } + // now min and max contain 4 identical items each representing min and max value respectively. + + // and we store the first one into a float variable. + _mm_store_ss(&max_val, max); + _mm_store_ss(&min_val, min); + // I bet you don't find annotated low level code very often. } #endif @@ -318,7 +331,7 @@ AudioVisualWaveform::Sample AudioVisualWaveform::SumSamples(SampleBufferPtr samp int channels = samples->audio_params().channel_count(); AudioVisualWaveform::Sample summed_samples(channels); - #ifdef x86_64 + #ifdef Q_PROCESSOR_X86_64 for (int channel=0; channelaudio_params().channel_count(); channel++) { min_max_sse(samples->data(channel), start_index, length, summed_samples[channel].min, summed_samples[channel].max); }