Автор Тема: Цифровая АРУ 0...1  (Прочитано 52817 раз)

0 Пользователей и 7 Гостей просматривают эту тему.

Оффлайн ra0ahc

  • Hero Member
  • *****
  • Сообщений: 4872
  • Сергей, RD6AH
Re: Цифровая АРУ 0...1
« Ответ #135 : Ноябрь 15, 2020, 09:09:16 am »
Ну вот пока , что удалось на розовом шуме сделать. С компрессией. Все питчи автоматом съедает.
Да да, я знаю, у меня ничего не получится )))

Оффлайн Игорь 2

  • Administrator
  • *****
  • Сообщений: 20749
Re: Цифровая АРУ 0...1
« Ответ #136 : Ноябрь 15, 2020, 11:00:17 am »
нужно сигнал на лимиттер садить иногда.

У меня, напомню, совсем короткие пички (типа, до 2 мс, точное время уже не помню) именно на лимитер и садятся, отрабатывать их АРУ смысла не вижу никакого..  dontt44 pl33
Ничего невозможного нет

Оффлайн ra0ahc

  • Hero Member
  • *****
  • Сообщений: 4872
  • Сергей, RD6AH
Re: Цифровая АРУ 0...1
« Ответ #137 : Ноябрь 15, 2020, 02:06:45 pm »
Я вообщем то все понимаю, но только не могу до конца понять от куда этот хвост появляется ?  no88 Собственно с ним и борюсь уже три дня.

Ну вот какой участок осциллограммы дает этот хвост?
Да да, я знаю, у меня ничего не получится )))

Оффлайн Игорь 2

  • Administrator
  • *****
  • Сообщений: 20749
Re: Цифровая АРУ 0...1
« Ответ #138 : Ноябрь 15, 2020, 02:38:33 pm »
Любое амплитудное вмешательство в исходник расширяет его спектр, и тем сильнее, чем с большей частотой (большей крутизной) Вы осуществляете регулирование, от этого уйти нельзя, это по определению.
Если стоит лимитер, или скоростная АРУ, рубящая пички, НЧ фильтр за ней очень полезен, гляньте, к примеру, на модуль 0913... 123123 pl33
Ничего невозможного нет

Оффлайн ra0ahc

  • Hero Member
  • *****
  • Сообщений: 4872
  • Сергей, RD6AH
Re: Цифровая АРУ 0...1
« Ответ #139 : Ноябрь 15, 2020, 03:06:16 pm »
У меня стоит фильтр 300-ого порядка после ару
Да да, я знаю, у меня ничего не получится )))

Оффлайн Relayer

  • Hero Member
  • *****
  • Сообщений: 1006
  • UR5FFR
Re: Цифровая АРУ 0...1
« Ответ #140 : Ноябрь 15, 2020, 03:08:31 pm »
стоит фильтр 300-ого порядка после ару
Зачем так много? Уменьшите порядок до разумного :)
В любой схеме есть как минимум одна ненужная деталь :)

Оффлайн ra0ahc

  • Hero Member
  • *****
  • Сообщений: 4872
  • Сергей, RD6AH
Re: Цифровая АРУ 0...1
« Ответ #141 : Ноябрь 15, 2020, 03:08:55 pm »
Основной 800-ого порядка
Да да, я знаю, у меня ничего не получится )))

Оффлайн ra0ahc

  • Hero Member
  • *****
  • Сообщений: 4872
  • Сергей, RD6AH
Re: Цифровая АРУ 0...1
« Ответ #142 : Ноябрь 15, 2020, 03:29:39 pm »
Любое амплитудное вмешательство в исходник расширяет его спектр
Даже если от 0 до 0 я это делаю?
Я определяю начало периода и конец (через 1мс) тоже 0 или около того, и только потом умножаю на коэффициент.
Причем когда я это делаю на увеличение амплитуды то все ок хвоста нет, а на уменьшение почти всегда. Либо где-то не увидел не стыковку амплитуд либо еще что.
Да да, я знаю, у меня ничего не получится )))

Оффлайн Игорь 2

  • Administrator
  • *****
  • Сообщений: 20749
Re: Цифровая АРУ 0...1
« Ответ #143 : Ноябрь 15, 2020, 03:40:52 pm »
Я определяю начало периода и конец (через 1мс) тоже 0 или около того, и только потом умножаю на коэффициент.

А какая разница? Это же, фактически, АМ со всеми вытекающими.  cr123
Ничего невозможного нет

Оффлайн ra0ahc

  • Hero Member
  • *****
  • Сообщений: 4872
  • Сергей, RD6AH
Re: Цифровая АРУ 0...1
« Ответ #144 : Ноябрь 15, 2020, 03:54:21 pm »
Вот пример в котором алгоритм цепляется за питчики и запускает задержку и второй - это с поглощением питчиков. 

Смотрим на водопад  123123

Ну вот как раз "лимиттер" дает на водопаде лес.
Да да, я знаю, у меня ничего не получится )))

Оффлайн Игорь 2

  • Administrator
  • *****
  • Сообщений: 20749
Re: Цифровая АРУ 0...1
« Ответ #145 : Ноябрь 15, 2020, 05:01:35 pm »
Это обычный шум?  cr123
Ничего невозможного нет

Оффлайн ra0ahc

  • Hero Member
  • *****
  • Сообщений: 4872
  • Сергей, RD6AH
Re: Цифровая АРУ 0...1
« Ответ #146 : Ноябрь 15, 2020, 06:52:42 pm »
Это розовый шум!! и на него ару ох сильно реагирует.
Да да, я знаю, у меня ничего не получится )))

Оффлайн ra0ahc

  • Hero Member
  • *****
  • Сообщений: 4872
  • Сергей, RD6AH
Re: Цифровая АРУ 0...1
« Ответ #147 : Ноябрь 15, 2020, 06:55:39 pm »
Сделал !!!
Новая версия. Работает даже если стробировать сигнал около 1 !!! Без дельты. С дельтой вооще огонь  cr123

float32_t max = 0.49975586f; //максималка от -0.5 до +0.5 примерно для 12 бит
uint16_t count = 100;
float32_t pit1 = -1;
float32_t pit2 = 0;
uint8_t stopGoingUp = 0;
float32_t rmsPik = 0;
float32_t rmsFrame = 0;

void agcDo(float32_t *buffer) {

    float32_t agcMetrTemp = 0;

    if (tim > 0)tim--; //уменьшение задержки
    stopGoingUp = 0;

    for (uint16_t i = 0; i < FRAME_SIZE; i++) {
        float32_t a;
        //a = (buffer[i] < 0.0f) ? -1.0f * buffer[i] : buffer[i];// adc V
        a = fabsf(buffer[i]);
        // seach min
        if (a > 0)nowAgc = max / a;
        else nowAgc = max / 0.000005f;


        uint16_t upIdx = i;
        float32_t pikBuf = -1;
        uint8_t exit = 1;
        uint8_t exitYN = 0;
        uint16_t wait = 48;// 1msec
        int direction = 0;//напрвление вниз (отрицательная синусоида)

        if (buffer[i] > 0) direction = 1;//напрвление вверх (положительная синусоида)
        if (buffer[i] == 0) exit = 0; //пропустим поиск пика в блоке

        while (exit) { //поиск пика в блоке от 0 до 0
            exit = 0;//выходим
            float32_t p1 = fabsf(buffer[upIdx]);//feature
            if (upIdx < FRAME_SIZE) {
                if (direction) {//+++++++++++++++++++++++++++++
                    //если условие остановило в ++ то добиваем его до 0
                    if ((buffer[upIdx] >= 0 && !exitYN) || (upIdx - i < wait)) {
                        upIdx++;
                        if (p1 > pikBuf) {
                            pikBuf = p1;
                        }
                        exit = 1;//не выходим
                    }
                    //если условие остановило в -- то добиваем его до 0 и выходим
                    if (((buffer[upIdx] < 0)) && (upIdx - i >= wait)) {
                        upIdx++;
                        exitYN = 1; //не дадим пред условию сработать
                        if (p1 > pikBuf) {
                            pikBuf = p1;
                        }
                        exit = 1;//не выходим
                    }

                } else { //------------------------
                    //going up
                    //если условие остановило в -- то добиваем его до 0 и выходим
                    if ((buffer[upIdx] <= 0 && !exitYN) || (upIdx - i < wait)) {
                        upIdx++;
                        if (p1 > pikBuf) {
                            pikBuf = p1;
                        }
                        exit = 1;//не выходим
                    }
                    //если условие остановило в ++ то добиваем его до 0
                    if (((buffer[upIdx] > 0)) && (upIdx - i >= wait)) {
                        upIdx++;
                        exitYN = 1; //не дадим пред условию сработать
                        if (p1 > pikBuf) {
                            pikBuf = p1;
                        }
                        exit = 1;//не выходим
                    }

                }
                //добавим блок если в нем есть глобальный пик (выброс)
                if (upIdx - i >= wait && max / pikBuf < agcLevel) {
                    if (256 + upIdx < FRAME_SIZE) wait = 256;
                }
            }
        }//while

        if (upIdx > i) { //если блок не пустой то...
            float32_t locNowAgc;
            //проверка на 0
            if (pikBuf != 0) {
                locNowAgc = max / pikBuf;//максимальное значение
            } else locNowAgc = max / 0.00005f;
//типа среднее значение . исползуется для отката .
            rmsPik = (rmsPik + pikBuf) / 2.0f;

            //agcLevel == текущий уровень ару
            if (locNowAgc < agcLevel) { // всплеск или питч V, идем вниз ..........................
                 stopGoingUp=0;
                //заполним блок
                if (i) {
                    for (uint16_t z = i; z <= upIdx; z++) {
                        buffer[z] *= locNowAgc;//применить новый коэфф
                    }
                } else {//механизм сочленения с пред фреймом ...ждем первого нуля
                    if (buffer[0] > 0) direction = 1;//напрвление вверх (положительная синусоида)
                    exit = 1;
                    uint16_t idx0 = 0;
                    while (exit) {
                        exit = 0;//выходим
                        if (direction) {//+++++++++++++++++++++++++++++
                            if (buffer[idx0] > 0) {
                                idx0++;
                                exit = 1;//не выходим
                            }
                        } else { //------------------------
                            //going up
                            if (buffer[idx0] < 0) {
                                idx0++;
                                exit = 1;//не выходим
                            }
                        }
                    }//while
                    for (uint16_t z = 0; z <= upIdx; z++) {
                        if (z <= idx0)buffer[z] *= agcLevel;//применить старый коэфф
                        else buffer[z] *= locNowAgc;//применить новый коэфф
                    }
                }


                if ((pit2< pit1 &&  pit1 > pikBuf ) ) {//смотрим следующий питч если
                    agcLevel -= (agcLevel - locNowAgc) / 5;
                } else {
                   // agcLevel = locNowAgc;
                    agcLevel -= (agcLevel - locNowAgc) / 2;
                }
                if ((pit2< pit1 &&  pit1 < pikBuf )) {//смотрим следующий питч если
                   // agcLevel = locNowAgc;
                    agcLevel -= (agcLevel - locNowAgc) / 1;
                }
                pit2 = pit1;
                pit1 = pikBuf;

                tim = 30;//задежка отпускания



//                }

            } else {//идем вверх/////////////////////////////////////////////////////////////////////

                float32_t cc ;

                if (tim == 0) {//подождали и начинаем
                    cc = agcLevel + (locNowAgc - agcLevel) / 600;
                    //проверим можем нет еще откатить
                    if (rmsFrame * cc < max - 0.0f && !stopGoingUp) {//дельта отката 0.4
                        agcLevel = cc;
                    } else stopGoingUp=1; //остановить откат
                }
                //заполним полупериод
                for (uint16_t z = i; z <= upIdx; z++) {
                    buffer[z] *= agcLevel;//применить новый коэфф
                }
            }
            i = upIdx; // след цикл будет стратовать от upIdx

        } else { //это ситуация редкая но тоже надо . сделано по классике одного замера

            if (nowAgc < agcLevel) { // всплеск V
                agcLevel -= (agcLevel - nowAgc) / 2;
               // tim = 10;//задежка отпускания
            }
            float32_t f = a * agcLevel;
            //контроль вылета в out
            if (f > max) {//out
                if (buffer[i] >= 0) buffer[i] = max;//max
                else buffer[i] = -max;//max
                // agcLevel = 1;
            } else
                buffer[i] *= agcLevel;

        }

        if (a > agcMetrTemp) agcMetrTemp = a; //s-meter макс V
    }//for
    rmsFrame=(rmsFrame+rmsPik)/2.0f; // глобальный меж фреймовый средничок  нужен для отката до какого-то уровня.
    agcMetr = agcMetrTemp; //s-meter
}
« Последнее редактирование: Ноябрь 15, 2020, 07:04:28 pm от ra0ahc »
Да да, я знаю, у меня ничего не получится )))

Оффлайн ra0ahc

  • Hero Member
  • *****
  • Сообщений: 4872
  • Сергей, RD6AH
Re: Цифровая АРУ 0...1
« Ответ #148 : Ноябрь 15, 2020, 06:58:31 pm »
вот алгоритм убирания питчиков


                if ((pit2< pit1 &&  pit1 > pikBuf ) ) {//смотрим следующий питч если
                    agcLevel -= (agcLevel - locNowAgc) / 5;
                } else {
                    agcLevel -= (agcLevel - locNowAgc) / 2;
                }
                if ((pit2< pit1 &&  pit1 < pikBuf )) {//смотрим следующий питч если
                    agcLevel -= (agcLevel - locNowAgc) / 1;
                }
                pit2 = pit1;
                pit1 = pikBuf;

pit1 pit2 - это глобальные амплитуды всплесков, которые требуют занижать амплитуду
agcLevel - самая главная переменная в ару !
pikBuf - текущий пик
locNowAgc - значение лимиттера по которому был опущен пик
Да да, я знаю, у меня ничего не получится )))

Оффлайн ra0ahc

  • Hero Member
  • *****
  • Сообщений: 4872
  • Сергей, RD6AH
Re: Цифровая АРУ 0...1
« Ответ #149 : Ноябрь 15, 2020, 07:08:59 pm »
Очень много контроля и самое главное был косяк: пропуск применения главного множителя, отсюда и сигнал ломался. Сейчас тоже проскакиваю нестыковки. Скорей всего межфреймомые дела. И достаточно редко. И ару ОЧЕНЬ не любит низкие частоты 150Гц и ниже. Запустил музыку и ару посчитало, что низы - это ступенька.  cr123
Да да, я знаю, у меня ничего не получится )))