Кто любит RISC в жизни, заходим, не стесняемся.
Ответить

Re: Куплю исходники для STM32

Пн ноя 29, 2021 20:25:30

Eddy_Em писал(а):А 20мс — это 50ГЦ!
Частота, соответствующая i-му отсчету в массиве после Фурье, F(i) = i/(N * dt) = i * f/ N.
1*6800/256 = 26,5625Гц, где 256 выборок при частоте дискретизации 6,8кГц
2*6800/256 = 53,125Гц
3*6800/256 = 79,6875Гц

В чем проблема?

Re: Куплю исходники для STM32

Пн ноя 29, 2021 20:39:30

Согласен, в парадигме конкретной теории это так.
Но на Фурье ссылаться в наше время нейросетей несколько опрометчиво. Фурье лица не распознавал и ничего для этого не предложил и предложить не может.
Я тут набрел на решение, в парадигме которого эти соотношения кажутся мягко сказать сильно устаревшими.

Добавлено after 10 minutes 30 seconds:
Найквист ничего не может поделать со схемой бланкирования. А вы все про выборки. Если просто не делать выборку во время ожидаемой помехи (например об этом известно заранее) Найквист оказывается бессилен яки младенец. И его теория идет лесом.

Вы просто не в курсе последних достижений цифровой фильтрации.
Еще раз. Кант вновь оказался прав, критикуя математиков за мистический формализм.
Последний раз редактировалось astrahard Пн ноя 29, 2021 20:44:11, всего редактировалось 2 раз(а).

Re: Куплю исходники для STM32

Пн ноя 29, 2021 20:40:36

Eddy_Em писал(а): если мы будем оцифровывать данные с частотой в 6800Гц, то сможем измерить максимум 3400Гц. И то, хреново! Желательно хотя бы 13.6кГц. А еще лучше - больше.
Какое условие - такое решение.
И мне с высокой горки на ..., пусть хоть > 5-го порядка ставит фильтр на входе.

Re: Куплю исходники для STM32

Пн ноя 29, 2021 20:46:29

Да я уже понял, что кроме формального решения не спросишь. Ладно, просто почитал о существующем и о будущем и сравнил.

Я вот почитал Stack Overflow там молодежь уже и Марковские цепи на свалку отправила, сообразительные! оказались.
И, тоже решил поискать свежие решения.
Последний раз редактировалось astrahard Пн ноя 29, 2021 21:01:04, всего редактировалось 1 раз.

Re: Куплю исходники для STM32

Пн ноя 29, 2021 21:00:42

Ну, на STM32F0, нейросеть ... давайте вперед, а я посмотрю.
Уже одни пытались посчитать синус быстрее 4 пня в месте с атлоном.

Re: Куплю исходники для STM32

Пн ноя 29, 2021 21:01:52

Кстати умножение пня уже ускорили кратно. Вы не слышали?

Ничто не вечно под луной!

Re: Куплю исходники для STM32

Пн ноя 29, 2021 21:24:22

astrahard, Миром правят идеи, а критерий истины в общественной практике. Как связаны идеи с практикой отражено в романе Персига "Дзен и искусство..."
Почитайте и сами сделаете свои фильтры, мои уже работают на ЖД, где измеряют уровни частот управления в рельсовых цепях. Цифровые фильтры любят дробную математику, лучше сразу использовать stm32H7**, стоит до 10$.

Re: Куплю исходники для STM32

Пн ноя 29, 2021 21:26:40

Кстати, да: идеалом вообще будет выкинуть нахрен STM32 и купить за 15 баксов Orange PI zero. И нехай себе считает ☺
Там вообще баш-скрипта с sox'ом хватит в простейшем случае!.. В случае чуть сложней - читаем, делаем БПФ, не парясь о вычислительных мощах, да выводим куда нужно результаты.

Re: Куплю исходники для STM32

Пн ноя 29, 2021 21:37:47

linkov1959, Nuhertz Filter Solutions?

Да, очень толковая прога, лучшая по фильтрам.

Re: Куплю исходники для STM32

Вт ноя 30, 2021 09:10:29

И так, сошлись на том что нужен более мощный компутер. А как же тогда справлялись на Атмега?
Ведь у вас и так stm32, 32 битный МК, в сравнении с 8 битной Атмега, а вам вычислительные моща подавай.

А известно ли вам, что у вас даже нет на борту полосовых фильтров? К примеру хотя бы такой MSGEQ7.

Для определения 9,6кГц, не буду вдаваться в подробные цифры, необходимо всего 16 отсчетов с какой-то постоянной дискретизацией.
Для 2,4 - 4,8кГц - надо 32 отсчета.
Для 1,2 - 1,6 кГц - 64 отсчета.
Для 400 - 800 Гц - 256 отсчетов.
Для 75 - 300Гц - 512 отсчетов.

Повторяю, у вас, на борту нету полосовых фильтров, значит вам эти отсчеты надо набрать. А на это время надо.
Какой бы вы мощный компутер не взяли, выше этой планки вы не прыгните, вы ограничены.

Сколько там stm32 имеет аналоговых входов? 16?
Поставьте на входы этих каналов 16 полосовых фильтров, и будет самый быстрый спектро анализатор.

Добавлено after 26 minutes 20 seconds:
Мощностей вам не хватает:
ДПФ для 9 частот, на расчет 2мс, ADC - 13,2мс, 256 отсчетов, на 32МГц
ДПФ для 12 частот, на расчет 4мс, ADC - 26,6мс, 512 отсчетов, на 32МГц

Да куда с добром мощностей, раз 5 можно посчитать пока ADC отсчеты накапливает.

Re: Куплю исходники для STM32

Вт ноя 30, 2021 15:53:52

"о сколько нам расчетов чудных..."
вот из свеженького: 2P2Z, 3P3Z

Re: Куплю исходники для STM32

Вт ноя 30, 2021 16:29:51

КИХ просит много памяти и MAC операций. Если для звука, бери биквадратные фильтры с расчетами коэффициентов для Lowshelf, peak и highshelf фильтров.
Плюс в том, что три вышеназванных фильтра пропускают весь сигнал, с подавлением или усилением выбранной полосы. Одна полоса - это пять MAC операций. Для пятиполосного это будет 25 операций. Хороший КИХ на одну полосу может сожрать больше сотни операций. Эквалайзеры для звука именно на Biquad фильтрах и реализуются.

Дарю свой, не совсем оптимизированный код.
Работает на STM32F407. Параметры аудиопотоков - 48кГц, 24 бит, стерео

СпойлерСобственно, обработчик потока:
Код:
////////////////////////////////////////////////////////////////////////////////
// Biquad signal processing function
void DSP_Bq_Process(BiquadFilter* flt, int32_t* leftSample, int32_t* rightSample)
{
    // Left input data shift
    flt->leftInZ[2] = flt->leftInZ[1];
    flt->leftInZ[1] = flt->leftInZ[0];
    flt->leftInZ[0] = *leftSample;
           
    // Right input data shift
    flt->rightInZ[2] = flt->rightInZ[1];
    flt->rightInZ[1] = flt->rightInZ[0];
    flt->rightInZ[0] = *rightSample;
           
    //-- Processing left
    float tmpLch = flt->leftInZ[0] * flt->bqB[0];    // MAC Add
    tmpLch += flt->leftInZ[1] * flt->bqB[1];         // MAC Add
    tmpLch += flt->leftInZ[2] * flt->bqB[2];         // MAC Add
    tmpLch -= flt->leftOutZ[0] * flt->bqA[1];        // MAC Substract
    tmpLch -= flt->leftOutZ[1] * flt->bqA[2];        // MAC Substract
   
    //-- Processing right
    float tmpRch = flt->rightInZ[0] * flt->bqB[0];   // MAC Add
    tmpRch += flt->rightInZ[1] * flt->bqB[1];        // MAC Add
    tmpRch += flt->rightInZ[2] * flt->bqB[2];        // MAC Add
    tmpRch -= flt->rightOutZ[0] * flt->bqA[1];       // MAC Substract
    tmpRch -= flt->rightOutZ[1] * flt->bqA[2];       // MAC Substract
   
    // Left out data shift
    flt->leftOutZ[1] = flt->leftOutZ[0];
    flt->leftOutZ[0] = tmpLch;
   
    // Right out data shift
    flt->rightOutZ[1] = flt->rightOutZ[0];
    flt->rightOutZ[0] = tmpRch;
   
    // Convert and store final result
    *leftSample = (int32_t)tmpLch;
    *rightSample = (int32_t)tmpRch;
}

Дескриптор полосы эквалайзера:
Код:
// Biquad filter instanse
typedef struct _BiquadFilter
{
    float frequency;
    float param;
    float gain;
    uint8_t type;
   
    float bqA[3];
    float bqB[3];
    float leftInZ[3];
    float rightInZ[3];
    float leftOutZ[2];
    float rightOutZ[2];
}BiquadFilter;


Калькулятор коэффициентов.
Заполняем в дескрипторе поля желаемыми параметрами (frequency, param, gain, type),
скармливаем дескриптор этой функции и она посчитает коэффициенты.
Код:
////////////////////////////////////////////////////////////////////////////////
// Biquad filter coefficients calculate
void DSP_CalcBiquad(BiquadFilter* flt)
{
    // Calculating reference values
    float gainAbs = pow(10, (flt->gain / 40) );
    float omega = 2 * PI * (flt->frequency / MAIN_SAMPLERATE);
    float sinOmega = sin(omega);
    float cosOmega = cos(omega);
    // Patch need
    float alpha = sinOmega / (2 * flt->param);
    float beta = sqrt(gainAbs + gainAbs);
   
    // Calculating coefficients
    switch (flt->type)
    {
    default:
    case LOWSHELF:
        flt->bqB[0] = gainAbs * ((gainAbs + 1) - (gainAbs - 1) * cosOmega + beta * sinOmega);
        flt->bqB[1] = 2 * gainAbs * ((gainAbs - 1) - (gainAbs + 1) * cosOmega);
        flt->bqB[2] = gainAbs * ((gainAbs + 1) - (gainAbs - 1) * cosOmega - beta * sinOmega);
        flt->bqA[0] = (gainAbs + 1) + (gainAbs - 1) * cosOmega + beta * sinOmega;
        flt->bqA[1] = -2 * ((gainAbs - 1) + (gainAbs + 1) * cosOmega);
        flt->bqA[2] = (gainAbs + 1) + (gainAbs - 1) * cosOmega - beta * sinOmega;
        break;
       
    case PEAK:
        flt->bqB[0] = 1 + (alpha * gainAbs);
        flt->bqB[1] = -2 * cosOmega;
        flt->bqB[2] = 1 - (alpha * gainAbs);
        flt->bqA[0] = 1 + (alpha / gainAbs);
        flt->bqA[1] = -2 * cosOmega;
        flt->bqA[2] = 1 - (alpha / gainAbs);
        break;
   
    case HIGHSHELF:
        flt->bqB[0] = gainAbs * ((gainAbs + 1) + (gainAbs - 1) * cosOmega + beta * sinOmega);
        flt->bqB[1] = -2 * gainAbs * ((gainAbs - 1) + (gainAbs + 1) * cosOmega);
        flt->bqB[2] = gainAbs * ((gainAbs + 1) + (gainAbs - 1) * cosOmega - beta * sinOmega);
        flt->bqA[0] = (gainAbs + 1) - (gainAbs - 1) * cosOmega + beta * sinOmega;
        flt->bqA[1] = 2 * ((gainAbs - 1) - (gainAbs + 1) * cosOmega);
        flt->bqA[2] = (gainAbs + 1) - (gainAbs - 1) * cosOmega - beta * sinOmega;
        break;
   
    case LOWPASS:
        flt->bqB[0] = (1 - cosOmega) / 2;
        flt->bqB[1] = 1 - cosOmega;
        flt->bqB[2] = (1 - cosOmega) / 2;
        flt->bqA[0] = 1 + alpha;
        flt->bqA[1] = -2 * cosOmega;
        flt->bqA[2] = 1 - alpha;
        break;
       
    case BANDPASS:
        flt->bqB[0] = alpha;
        flt->bqB[1] = 0;
        flt->bqB[2] = -alpha;
        flt->bqA[0] = 1 + alpha;
        flt->bqA[1] = -2 * cosOmega;
        flt->bqA[2] = 1 - alpha;
        break;
   
    case HIGHPASS:
        flt->bqB[0] = (1 + cosOmega) / 2;
        flt->bqB[1] = -(1 + cosOmega);
        flt->bqB[2] = (1 + cosOmega) / 2;
        flt->bqA[0] = 1 + alpha;
        flt->bqA[1] = -2 * cosOmega;
        flt->bqA[2] = 1 - alpha;
        break;
       
    case NOTCH:
        flt->bqB[0] = 1;
        flt->bqB[1] = -2 * cosOmega;
        flt->bqB[2] = 1;
        flt->bqA[0] = 1 + alpha;
        flt->bqA[1] = -2 * cosOmega;
        flt->bqA[2] = 1 - alpha;
        break;
    }
   
    // Prescale flter constants
    flt->bqB[0] /= flt->bqA[0];
    flt->bqB[1] /= flt->bqA[0];
    flt->bqB[2] /= flt->bqA[0];
    flt->bqA[1] /= flt->bqA[0];
    flt->bqA[2] /= flt->bqA[0];
}


В такой реализации STM32F407 спокойно пережевывает 10 полос эквалайзера.

Пример (из моего лабораторного кода):
Спойлер
Код:
////////////////////////////// BIQUAD filters //////////////////////////////////
// Filter parameters
uint8_t bqEn = 1;

BiquadFilter LowShelf =
{
    .frequency = 75.0f,
    .param = 1.5f,
    .gain = 8.0f,
    .type = LOWSHELF
};

BiquadFilter MidPeak =
{
    .frequency = 5500.0f,
    .param = 1.4f,
    .gain = -3.0f,
    .type = PEAK
};

BiquadFilter HighShelf =
{
    .frequency = 10000.0f,
    .param = 1.5f,
    .gain = 6.0f,
    .type = HIGHSHELF
};


    // Calculate filters
    DSP_CalcBiquad(&LowShelf);
    DSP_CalcBiquad(&MidPeak);
    DSP_CalcBiquad(&HighShelf);

////////////////////////////////////////////////////////////////////////////////
// DSP precess main function
int DSP_Process(pDspBufPoint buff, uint32_t samplNum)
{
   
    for(int i = 0; i < samplNum; i++)
    {
        //---------- Volume control ----------//
        buff->leftCh[i] *= (leftVol);
        buff->rightCh[i] *= (rightVol);
       
       
       
        //---------- Biquad filters ----------//
        if(bqEn != 0)
        {
            DSP_Bq_Process(&LowShelf, &buff->leftCh[i], &buff->rightCh[i]);
            DSP_Bq_Process(&MidPeak, &buff->leftCh[i], &buff->rightCh[i]);
            DSP_Bq_Process(&HighShelf, &buff->leftCh[i], &buff->rightCh[i]);
        }
       
       
        // Signed saturation limit on 24 bit with SSAT instruction
        buff->leftCh[i] = __SSAT(buff->leftCh[i], 24);
        buff->rightCh[i] = __SSAT(buff->rightCh[i], 24);
    }// DSP cycle
    return 0;
}
Последний раз редактировалось DX168B Вт ноя 30, 2021 16:44:29, всего редактировалось 1 раз.

Re: Куплю исходники для STM32

Вт ноя 30, 2021 16:43:53

Надо прислушаться. это колокол, фильтр высоких частот (срез низких частот), фильтр низких частот.
Точно, то что надо, спасибо большое.
Ответить