У меня есть этот код, чтобы получить уровни вывода звука в дБ в массив (peak_dB[8]) для использования в пикометре в реальном времени:
#include <emmintrin.h>
float channelsPeak[8] = { 0 };
float peak_dB[8] = { 0 };
__m128 log2_sse(__m128 x) {
// https://www.kvraudio.com/forum/viewtopic.php?p=7524831#p7524831
// 12-13ulp
const __m128 c0 = _mm_set1_ps(1.011593342e+01f);
const __m128 c1 = _mm_set1_ps(1.929443550e+01f);
const __m128 d0 = _mm_set1_ps(2.095932245e+00f);
const __m128 d1 = _mm_set1_ps(1.266638851e+01f);
const __m128 d2 = _mm_set1_ps(6.316540241e+00f);
const __m128 one = _mm_set1_ps(1.0f);
const __m128 multi = _mm_set1_ps(1.41421356237f);
const __m128i mantissa_mask = _mm_set1_epi32((1 << 23) - 1);
__m128i x_i = _mm_castps_si128(x);
__m128i spl_exp = _mm_castps_si128(_mm_mul_ps(x, multi));
spl_exp = _mm_sub_epi32(spl_exp, _mm_castps_si128(one));
spl_exp = _mm_andnot_si128(mantissa_mask, spl_exp);
__m128 spl_mantissa = _mm_castsi128_ps(_mm_sub_epi32(x_i, spl_exp));
spl_exp = _mm_srai_epi32(spl_exp, 23);
__m128 log2_exponent = _mm_cvtepi32_ps(spl_exp);
__m128 num = spl_mantissa;
num = _mm_add_ps(num, c1);
num = _mm_mul_ps(num, spl_mantissa);
num = _mm_add_ps(num, c0);
num = _mm_mul_ps(num, _mm_sub_ps(spl_mantissa, one));
__m128 denom = d2;
denom = _mm_mul_ps(denom, spl_mantissa);
denom = _mm_add_ps(denom, d1);
denom = _mm_mul_ps(denom, spl_mantissa);
denom = _mm_add_ps(denom, d0);
__m128 res = _mm_div_ps(num, denom);
res = _mm_add_ps(log2_exponent, res);
return res;
}
__m128 lin2db(__m128 x) {
const __m128 convert_10 = _mm_set1_ps(6.02059991328f);
return _mm_mul_ps(log2_sse(x), convert_10);
}
float getPeaks_dB(int cCount) { // cCount = enabled channels (1...8)
__m128 s1 = _mm_setzero_ps();
s1 = _mm_set_ps(channelsPeak[3], channelsPeak[2], channelsPeak[1], channelsPeak[0]); //channels 1-4
s1 = lin2db(s1);
_mm_store_ps(peak_dB, s1);
if(cCount > 4){
float t2[4] = { 0 };
__m128 s2 = _mm_setzero_ps();
s2 = _mm_set_ps(channelsPeak[7], channelsPeak[6], channelsPeak[5], channelsPeak[4]); // channels 5-8
s2 = lin2db(s2);
_mm_store_ps(t2, s2);
for (int i = 4; i < 8; i++){peak_dB[i] = t2[i-4];}
}
return 0;
}
где плавающие каналы пик[0..7] массив — хранилище для линейных уровней (0.0f..1.0f) восьми каналов, считываемых с устройства рендеринга звука (один вызов GetChannelsPeakValues ()), пик_дБ представляет собой массив из восьми элементов для хранения этого значения в формате дБ (для использования в некоторых последующих вычислениях и текстовом представлении) и lin2db — это приближение 20log10 (x) (быстрее (из-за меньшей точности), чем std :: log10), реализованное с использованием встроенных функций SSE.
В: Есть ли другие (лучшие) способы вставить данные из s2 в последние четыре элемента peak_dB (исключая AVX)? Я использую VS2013 и Обозреватель компилятора, компилятор, похоже, улучшает for-loop, используемый в коде сейчас, но, поскольку первая часть в пиковом_dB, хранимом с _mm_store_ps (peak_dB, s1), выглядит намного проще, просто интересно, есть ли способ сделать это без for-loop.
![Вставить массив[4] в массив[8] (C ++, SSE) [closed] TheFAQ.ru](https://thefaq.ru/wp-content/uploads/2023/01/logo-250.png)