Конвейерная обработка алгоритма 1D с использованием C на плате разработки DSP - PullRequest
2 голосов
/ 17 ноября 2011

Плата DSP, которую я сейчас использую, это DSK6416 от Spectrum Digital, и я внедряю алгоритм свертки в C для свертывания входных выборок голоса с предварительно записанным массивом импульсных характеристик. Цель состоит в том, чтобы говорить в микрофон и выводить обработанный эффект, чтобы мы звучали так, как будто говорим в той среде, где получается массив импульсных характеристик.

Задача, с которой я сейчас сталкиваюсь, заключается в том, чтобы выполнить свертку вживую и поддерживать темп входной и выходной скорости функции прерывания на 8 кГц.

Вот моя идея мозгового штурма:

Моя текущая неэффективная реализация, которая не работает, выглядит следующим образом:

Прерывание остановит процесс свертки, выведет индекс и возобновит свертку на частоте 8 кГц или 1/8 кГц.

Однако полная итерация свертки выполняется намного медленнее, чем 1/8 кГц секунд. Поэтому, когда прерывание хочет вывести данные из выходного массива, данные еще не готовы.

Моя идеальная реализация алгоритма быстрой конвейерной свертки:

У нас будет много процессов свертки, работающих в фоновом режиме, при выводе завершенных с течением времени. Параллельно будет работать много труб.

Если я использую конвейерный подход, нам нужно иметь N = 10000 конвейерных процессов, работающих в фоновом режиме ...

Теперь у меня есть идея (по крайней мере, я думаю, что могу, я могу ошибаться), я понятия не имею, как реализовать это на плате DSK с использованием языка программирования C, потому что C не поддерживает ориентацию объекта.

Ниже приведен псевдокод для нашей реализации C:

#include <stdio.h>
#include "DSK6416_AIC23.h"
Uint32 fs=DSK6416_AIC23_FREQ_48KHZ;        //set sampling rate
#define DSK6416_AIC23_INPUT_MIC 0x0015
#define DSK6416_AIC23_INPUT_LINE 0x0011
Uint16 inputsource=DSK6416_AIC23_INPUT_MIC; // select input

//input & output parameters declaration
#define MAX_SIZE 10000
Uint32 curr_input;
Int16 curr_input2;
short input[1];
short impulse[MAX_SIZE ];
short output[MAX_SIZE ];
Int16 curr_output;

//counters declaration
Uint32 a, b, c, d;      //dip switch counters
int i, j, k;            //convolution iterations
int x;                  //counter for initializing output;                                     

interrupt void c_int11()         //interrupt running at 8 kHz
{
    //Reads Input
    //Start new pipe
    //Outputs output to speaker
}

void main()
{

//Read Impulse.txt into impulse array

    comm_intr();
    while(1)
    {

    if (DIP switch pressed)
    {
            //convolution here (our current inefficient convolution algorithm)
            //Need to run multiple of the same process in the background in parallel.

    for (int k = 0; k < MAX_SIZE; k++)
    {
        if (k==MAX_SIZE-1 && i == 0)  // special condition overwriting element at i = MAX_SIZE -1
        {
            output[k] = (impulse[k]*input[0]); 
        }
        else if (k+i < MAX_SIZE) // convolution from i to MAX_SIZE
        {
            output[k+i] += (impulse[k]*input[0]); 
        }

        else if (k+i-MAX_SIZE != i-1)  // convolution from 0 to i-2
        {
            output[k+i-MAX_SIZE] += (impulse[k]*input[0]); 
        }
        else   // overwrite element at i-1
        {
            output[i-1] = (impulse[k]*input[0]); 
        }
    }

    }

    else //if DIP switch is not pressed
    {
            DSK6416_LED_off(0);
            DSK6416_LED_off(1);
            DSK6416_LED_off(2);
            DSK6416_LED_off(3);
            j = 0; 
            curr_output = input[1];
            output_sample(curr_output);  //outputs unprocessed dry voice
    }
    } //end of while
    fclose(fp);
}

Есть ли способ реализовать конвейер в коде C для компиляции на аппаратной плате DSP, чтобы мы могли одновременно выполнять несколько итераций свертки в фоновом режиме?

Я нарисовал несколько картинок, но я новичок в этой доске, поэтому не могу публиковать картинки.

Пожалуйста, дайте мне знать, если вам нужны мои изобразительные идеи, чтобы помочь вам помочь мне ~

Любая помощь по реализации этого кода очень ценится!

Ответы [ 2 ]

3 голосов
/ 17 ноября 2011

Вам, вероятно, нужно обрабатывать данные кусками некоторых N выборок. Пока один блок обрабатывается вводом / выводом в обработчике прерываний ЦАП / АЦП, другой обрабатывается где-то в main (). Главное здесь - убедиться, что ваша обработка фрагмента из N выборок занимает меньше времени, чем прием / передача N выборок.

Вот как это может выглядеть во времени (все вещи на каждом шаге (кроме шага 1) происходят «параллельно»):

  1. buf1 = buf3 = нули, buf2 = что-нибудь
  2. ISR: ЦАП отправляет buf1, АЦП получает buf2; main (): обрабатывает buf3
  3. ISR: ЦАП отправляет buf3, АЦП получает buf1; main (): обрабатывает buf2
  4. ISR: ЦАП отправляет buf2, АЦП получает buf3; main (): процессы buf1

Повторять бесконечно с шага 2.

Кроме того, вы можете реализовать свою свертку в сборке для дополнительной скорости. Я бы посмотрел некоторые заметки приложения TI или что-то не для реализации. Возможно, он доступен и в какой-то библиотеке.

Вы можете также рассмотреть возможность свертки через Fast Fourier Transform.

0 голосов
/ 19 ноября 2011

Ваш DSP имеет только столько циклов ЦП, доступных в секунду. Вам необходимо проанализировать свой алгоритм, чтобы определить, сколько циклов ЦП требуется для обработки каждой выборки в среднем. Это должно быть меньше количества циклов ЦП между выборками. Никакое количество конвейерной обработки или ориентации объекта не поможет, если у вас нет алгоритма, который в среднем выполняет достаточно небольшое количество циклов на выборку.

...