Уважаемые посетители! Форум CQHAM.RU существует исключительно за счет показа рекламы. Мы будем благодарны, если Вы не будете блокировать рекламу на нашем Форуме. Просим внести cqham.ru в список исключений для Вашего блокировщика рекламы.
Показано с 1 по 4 из 4

Тема: Цифровое АРУ с помощью stm32f429

  1. #1
    Моя реализация потоковой АРУ в цифровых трактах.
    Эмуляция всего внутри процессора. Выход через ЦАП на звуковуху.
    Нажмите на изображение для увеличения. 

Название:	Снимок экрана 2020-10-11 в 14.45.45.png 
Просмотров:	175 
Размер:	544.4 Кб 
ID:	344372

    запись по этой картинке здесь

    https://drive.google.com/file/d/16t-...ew?usp=sharing

    Программа обработки фрэйма


    if (tim > 0)tim--;
    for (int i = 0; i < FRAME_SIZE; i++) {
    a = (pFirOutTemp[i] < 0) ? -1.0f * (pFirOutTemp[i]) : pFirOutTemp[i];
    nowAgc = 1 / a;
    if (nowAgc <= agcLevel) {
    agcLevel = nowAgc;
    tim = 6;
    } else {
    if (tim == 0) agcLevel += 0.02f;
    }
    pFirOutTemp[i] *= agcLevel;
    }


  2. #2
    Аватар для Евгений240
    Регистрация
    20.12.2009
    Адрес
    г. Ростов на Дону.
    Сообщений
    15,630
    Позывной
    RX6LAO
    Я, как и многие сидящие здесь старперы ничего не понял.
    Лучше расскажите по какому алгоритму это всё работает.
    73. Евгений.

  3. #3
    Идут фреймы (у меня размер фрейма 1024 байт 32бита) с АЦП с определенной частотой (у меня 24000Гц) эти фремы заполняются.
    Далее я их принимаю в память и начинаю обрабатывать. Накладываю FIR фильтр далее АРУ (эта) и далее , что получилось, напрямик в ЦАП и с ЦАПа на звуковую карту.
    В файле сгенерирован тон переменной амплитуды (случайной амплитуды) и шум. И вот можно оценить эффективность работы АРУ

  4. #4
    Новая версия ару
    Теперь съедает питчики
    Код:
    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
    }

  5. Спасибо от ua3ycv

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Похожие темы

  1. Цифровое радиовещание в России?
    от VladiGeo в разделе Для начинающих
    Ответов: 36
    Последнее сообщение: 13.02.2023, 07:20
  2. Цифровое TV в России DVB-T (цифровое эфирное телевидение)
    от petr96 в разделе Цифровые виды связи Новые технологии в электронике и связи
    Ответов: 55
    Последнее сообщение: 13.12.2022, 18:46
  3. Цифровое вещание
    от ut5eqr в разделе Цифровые виды связи Новые технологии в электронике и связи
    Ответов: 12
    Последнее сообщение: 09.01.2012, 17:54
  4. Цифровое QSO
    от NIKKS1 в разделе Для начинающих
    Ответов: 7
    Последнее сообщение: 23.05.2010, 16:58
  5. Цифровое Аудио и SSB
    от VE3YXO в разделе Цифровые виды связи Новые технологии в электронике и связи
    Ответов: 4
    Последнее сообщение: 05.04.2010, 06:22

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •