Загрузка данных


#include <stdint.h>
#include <stdio.h>

/**
 * Ресемплинг 16000 -> 8000 Гц
 * @param input  - входной массив (размер 2n)
 * @param output - выходной массив (размер n)
 * @param n_out  - количество выходных сэмплов (кратно 8)
 */
void resample_16to8_asm(const int16_t* input, int16_t* output, int n_out) {
    const int16_t* in_ptr = input;
    int16_t* out_ptr = output;
    int iterations = n_out / 8;

    if (iterations <= 0) return;

    asm volatile (
        "1:                                     \n\t"
        // 1. Загружаем 16 сэмплов (два 128-битных регистра)
        "ld1    {v0.8h, v1.8h}, [%[in]], #32    \n\t" 

        // 2. Вариант А: Просто децимация (берем каждый второй)
        // Пользуемся инструкцией UZP1 (Unzip), которая собирает четные элементы
        "uzp1   v2.8h, v0.8h, v1.8h             \n\t" 
        
        /* 
           Вариант Б: Децимация с усреднением (ФНЧ), чтобы не было алиасинга.
           Если нужен этот вариант, расскомментируйте код ниже, а uzp1 удалите:
           
           "uzp1   v2.8h, v0.8h, v1.8h   \n\t" // Четные сэмплы
           "uzp2   v3.8h, v0.8h, v1.8h   \n\t" // Нечетные сэмплы
           "srhadd v2.8h, v2.8h, v3.8h   \n\t" // Среднее между соседями
        */

        // 3. Сохраняем 8 сэмплов результата
        "st1    {v2.8h}, [%[out]], #16          \n\t"

        // 4. Цикл
        "subs   %w[count], %w[count], #1        \n\t"
        "b.ne   1b                              \n\t"

        : [in] "+r" (in_ptr), [out] "+r" (out_ptr), [count] "+r" (iterations)
        : 
        : "v0", "v1", "v2", "v3", "cc", "memory"
    );
}

int main() {
    // Вход: 16 сэмплов (16кГц)
    int16_t input[16] = {10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85};
    int16_t output[8];

    resample_16to8_asm(input, output, 8);

    printf("In (16kHz) -> Out (8kHz):\n");
    for (int i = 0; i < 8; i++) {
        printf("%d ", output[i]); // Ожидаем 10, 20, 30... (каждый второй)
    }
    printf("\n");

    return 0;
}