Преобразование коротких в Float и наоборот с использованием NEON SIMD

android arm simd neon

826 просмотра

1 ответ

Я обрабатываю аудио буферы в Android, у меня есть следующие настройки:

  1. получить системный обратный вызов с коротким буфером
  2. конвертировать короткий буфер в плавающий буфер
  3. сделать DSP с плавающим буфером
  4. преобразовать плавающий буфер в короткий буфер
  5. доставить короткий буфер в систему

Я хочу уменьшить задержку шагов 2 и 4, коротких, чтобы плавать и плавать для коротких конверсий. (оставив в стороне задержку в 3-DSP, так как я позабочусь об этом позже).

Итак, я хотел бы использовать NEON SIMD для расчета нескольких значений одновременно.

На данный момент у меня есть 2 и 4 следующий код:

#define CONV16BIT 32768
#define CONVMYFLT (1./32768.)
static int i;
float * floatBuffer;
short * shortInBuffer;
short * shortOutBuffer;

...(malloc and init buffers method)

...(inside callback) 
//2- short to float
for(i = 0; i < bufferSize; i++) {
    floatBuffer[i] = (float) (shortInBuffer[i] * CONVMYFLT);
}

...(do dsp)

//4- float to short
for(i = 0; i < bufferSize; i++) {
    shortOutBuffer[i] = (short) (floatBuffer[i] * CONV16BIT);
}

Я считаю, что для использования NEON мне нужны следующие шаги:

(для короткой части)

  1. Загрузите 16-битные шорты из короткого буфера
  2. Преобразуйте их в 32-разрядные целые числа
  3. Конвертируйте их, чтобы плавать
  4. Умножьте их на CONVMYFLT
  5. Храните их в буфере с плавающей точкой

Нашел эту информацию в этом посте (выбранный ответ)

__m128 factor = _mm_set1_ps(1.0f / value);
for (int i = 0; i < W*H; i += 8)
{
    //  Load 8 16-bit ushorts.
    //  vi = {a,b,c,d,e,f,g,h}
    __m128i vi = _mm_load_si128((const __m128i*)(source + i));

    //  Convert to 32-bit integers
    //  vi0 = {a,0,b,0,c,0,d,0}
    //  vi1 = {e,0,f,0,g,0,h,0}
    __m128i vi0 = _mm_cvtepu16_epi32(vi);
    __m128i vi1 = _mm_cvtepu16_epi32(_mm_unpackhi_epi64(vi,vi));

    //  Convert to float
    __m128 vf0 = _mm_cvtepi32_ps(vi0);
    __m128 vf1 = _mm_cvtepi32_ps(vi1);

    //  Multiply
    vf0 = _mm_mul_ps(vf0,factor);
    vf1 = _mm_mul_ps(vf1,factor);

    //  Store
    _mm_store_ps(destination + i + 0,vf0);
    _mm_store_ps(destination + i + 4,vf1);
}

Однако это SIMD для Intel SSE4.1, а не для NEON.

Какая будет эквивалентная реализация для NEON в Android? (было трудно понять суть NEON)

Обновление 1 Из ответа fsheikh я смог построить это: - Я смог получить int16_t из системного обратного вызова - и все мои размеры буфера кратны 8:

int16x8_t i16v;
int32x4_t i32vl, i32vh;
float32x4_t f32vl, f32vh;
for(i = 0; i < bufferSize; i += 8) {
    //load 8 16-bit lanes on vector
    i16v = vld1q_s16((const int16x8_t*) int16_t_inBuffer[i]);
    // convert into 32-bit signed integer
    i32vl = vmovl_s16 (i16v);
    i32vh = vmovl_s16 (vzipq_s16(i16v, i16v).val[0]);
    //convert to 32-bit float
    f32vl = vcvtq_f32_s32(i32vl);
    f32vh = vcvtq_f32_s32(i32vh);
    //multiply by scalar
    f32vl = vmulq_n_f32(f32vl, CONVMYFLT);
    f32vh = vmulq_n_f32(f32vh, CONVMYFLT);
    //store in float buffer
    vst1q_f32(floatBuffer[i], f32vl);
    vst1q_f32(floatBuffer[i + 4], f32vh);
}

Должно ли это работать правильно? У меня есть сомнения по поводу того, что я должен использовать нижнюю или верхнюю часть чередующегося вектора, возвращаемого vmovl_s16:

i32vh = vmovl_s16 (vzipq_s1 6 (i16v, i16v) .val [0]); или же

i32vh = vmovl_s16 (vzipq_s16 (i16v, i16v) .val [1]);

Автор: alexm Источник Размещён: 18.09.2019 11:03

Ответы (1)


3 плюса

Получив версию SSE, вы можете использовать список встроенных функций GCC ARM NEON для переноса макросов SSE в NEON. https://gcc.gnu.org/onlinedocs/gcc-4.6.4/gcc/ARM-NEON-Intrinsics.html

Так, например:

// Load unsigned short
uint16x4_t vld1_u16 (const uint16_t *)

// Convert to unsigned int
uint32x4_t vmovl_u16 (uint16x4_t) 

// Convert to float
float32x4_t vcvtq_f32_s32 (int32x4_t)

// Multiply floats with a scalar
float32x4_t vmulq_n_f32 (float32x4_t, float32_t) 

// Store results into a float buffer
void vst1q_f32 (float32_t *, float32x4_t)
Автор: fsheikh Размещён: 18.05.2017 05:20
Вопросы из категории :
32x32