Игорь 2

Трансиверы, передатчики, РПУ => Software Defined Radio (SDR) => Тема начата: ra0ahc от Октябрь 11, 2020, 09:30:28 pm

Название: Авто нотч
Отправлено: ra0ahc от Октябрь 11, 2020, 09:30:28 pm
Пока я не совсем понимаю как оно работает.


void arm_lms_norm_init_f32   (   arm_lms_norm_instance_f32 *    S ,
uint16_t    numTaps ,
float32_t *    pCoeffs ,
float32_t *    pState ,
float32_t    му ,
uint32_t    размер блока
)      
Параметры
[в]   S   указывает на экземпляр структуры фильтра LMS с плавающей запятой
[в]   numTaps   количество коэффициентов фильтра
[в]   pCoeffs   указывает на буфер коэффициентов
[в]   pState   указывает на буфер состояния
[в]   му   размер шага, который управляет обновлениями коэффициентов фильтра
[в]   размер блока   количество образцов для обработки
Возврат
никто
Детали
pCoeffs указывает на массив коэффициентов фильтра, хранящихся в обратном во времени порядке:
   {b [numTaps-1], b [numTaps-2], b [N-2], ..., b [1], b
Начальные коэффициенты фильтра служат отправной точкой для адаптивного фильтра. pStateуказывает на массив numTaps+blockSize-1выборок длины , где blockSize- количество входных выборок, обработанных каждым вызовом arm_lms_norm_f32().


void arm_lms_norm_f32   (   arm_lms_norm_instance_f32 *    S ,
const float32_t *    pSrc ,
float32_t *    pRef ,
float32_t *    pOut ,
float32_t *    pErr ,
uint32_t    размер блока
)      
Параметры
[в]   S   указывает на экземпляр структуры нормализованного фильтра LMS с плавающей запятой
[в]   pSrc   указывает на блок входных данных
[в]   pRef   указывает на блок справочных данных
[вне]   pOut   указывает на блок выходных данных
[вне]   pErr   указывает на блок данных об ошибке
[в]   размер блока   количество образцов для обработки
Название: Re: Авто нотч
Отправлено: Relayer от Октябрь 11, 2020, 09:59:00 pm
А что в качестве референса использовать? Шум белый?
Нет никакого референса. Рассматривайте LMS как простой линейный предсказатель невысокого порядка. Даете ему на вход синус плюс чегото там еще - он адаптируется к самому простому сигналу - синусу. Вычитаете - остается все остальное (шум, речь и тп)
Название: Re: Авто нотч
Отправлено: Relayer от Октябрь 11, 2020, 10:02:04 pm
Вот код для LMS. Семплрейт 24к. Параметры: Order=25, Delay=20, Leakage=1E-5, AdaptationRate=0.002
Может использоваться как шумодв если FMode = fmDeNoise, но хреново и надо другие параметры. С параметрами которые я написал хорошо работает как автонотч. В случае другого семплрейт параметры возможно придется менять. order так точно можно будет уменьшить
procedure TDSPLMSFilter.ApplyFilter(bf: TBuffer);
var px: PFloat32;
    i,j,idl,sz,mask,dl: integer;
    sum,sum_sq,df: double;
begin
  dl:=Delay;
  mask:=Length(DelayLine)-1;
  df:=1-Leakage*AdaptationRate;
  bf_Write(bf);
  px:=bf_Data(bf);
  sz:=Length(taps)-1;
  idl:=idelay;
  for j:=1 to bf.Size do begin
    DelayLine[idl]:=px^;
    DelayLineSqr[idl]:=px^*px^;
    sum:=0; sum_sq:=0;
    for i:=0 to sz do begin
      sum:=sum+DelayLine[(idl+i+1+dl) and mask]*taps[i];
      sum_sq:=sum_sq+DelayLineSqr[(idl+i+1+dl) and mask];
    end;
    if FMode = fmDeNoise then begin
      px^:=sum;
      sum:=DelayLine[idl]-sum;
    end else begin
      sum:=DelayLine[idl]-sum;
      px^:=sum;
    end;
    // LMS update
    sum:=sum*AdaptationRate/(sum_sq+1E-10);
    for i:=0 to sz do
      taps[i]:=taps[i]*df+sum*DelayLine[(idl+i+1+dl) and mask];
    //
    Inc(px);
    idl:=(idl-1) and mask;
  end;
  idelay:=idl;
end;

function TDSPLMSFilter.Redesign(SampleRate: integer; var DelayLen: integer): Boolean;
begin
  taps:=nil;
  Result:=False;
  if Order > 0 then begin
    SetLength(taps,Order);
    FillChar(taps[0],Length(taps)*SizeOf(TFloat32),0);
    DelayLen:=Order+Delay+10{Gap};
    SetLength(DelayLineSqr,RoundToPower2(DelayLen)*2);
    FillChar(DelayLineSqr[0],Length(DelayLineSqr)*SizeOf(TFloat32),0);
    Result:=True;
  end;
end;
Название: Re: Авто нотч
Отправлено: Relayer от Октябрь 11, 2020, 10:08:02 pm
Млин, можно как-то запретить форматирование? Этож ппц какой-то - съедает квадратные скобки с индексами. Что за форумный движок такой кривой?!?!?
Название: Re: Авто нотч
Отправлено: zenit от Октябрь 12, 2020, 08:03:52 am
Млин, можно как-то запретить форматирование?
Попробуйте вставлять текст как код.
вот так для примера- смайлики в игноре  :)  ;)  :D
Название: Re: Авто нотч
Отправлено: ra0ahc от Октябрь 12, 2020, 09:00:39 am
void DMA2_Stream5_IRQHandler(void) {
    /* USER CODE BEGIN DMA2_Stream5_IRQn 0 */
    //////////////////////////////////////////////////B-RX
    // saiRxBankNowNumber++;

    if ((DMA2->HISR & DMA_HISR_TCIF5) != 0) {

        uint8_t b = (uint8_t) ((hdma_sai1_b.Instance->CR & DMA_SxCR_CT) != 0);
        if (b != 0)
            saiRxBankNowNumber = 0;
        else
            saiRxBankNowNumber = 1;

        arm_fir_f32(&S_dsp, (float *) &saiRxBank[saiRxBankNowNumber], (float32_t *) pFirOutTemp, FRAME_SIZE);
        uint16_t y = 0;
        float32_t a;
        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 = 2;
            } else {
                if (tim == 0) agcLevel += 0.02f;
            }
            pFirOutTemp[i] *= agcLevel;
        }


        arm_fir_f32(&S_dsp_temp, (float *) pFirOutTemp, (float32_t *) pFirOut, FRAME_SIZE);

        for (int i = 1; i < FRAME_SIZE; i += 2) {
            pOutDac[dacTxBankNawNumber][y] = (uint32_t) (2048 + pFirOut[i - 1] * 300);
            pOutDac[dacTxBankNawNumber][y] |= ((uint32_t) (2048 + pFirOut[i] * 300)) << 16;
            y++;
        }
        mayk = 2;


    }
    /* USER CODE END DMA2_Stream5_IRQn 0 */
    HAL_DMA_IRQHandler(&hdma_sai1_b);
    /* USER CODE BEGIN DMA2_Stream5_IRQn 1 */

    /* USER CODE END DMA2_Stream5_IRQn 1 */
}
Название: Re: Авто нотч
Отправлено: ra0ahc от Октябрь 12, 2020, 09:02:38 am
Спасибо Андрею за код
Спасибо Зениту за совет
 lol22
Название: Re: Авто нотч
Отправлено: Relayer от Октябрь 12, 2020, 09:07:33 am
Не могу поправить пост. Короче там съело taps [ i ] везде
Название: Re: Авто нотч
Отправлено: ra0ahc от Октябрь 12, 2020, 01:54:33 pm
начилась рабочая неделя.... dontt44
Название: Re: Авто нотч
Отправлено: GenaSPB от Октябрь 12, 2020, 09:49:29 pm
Посмотрел у UA3REO.
Там перед началом обработки очередного блока семплов просто проверяется на наличие НЕ ЧИСЕЛ в ранее накомленнвх коэффициентов
Название: Re: Авто нотч
Отправлено: ra0ahc от Октябрь 13, 2020, 05:17:42 pm
Ну вот, что я сделал и не заработало. НЕ удивительно, в слепую делаю, то чего не понимаю .

и так
сперва делаю ini
// arrays
__IO float32_t pOutLms[FRAME_SIZE];//out array
__IO float32_t lmsRef[FRAME_SIZE];// reference
__IO float32_t lmsErr[FRAME_SIZE];// error
 

ини и заполнение lmsRef синусом массива длиной FRAME_SIZE (1024)
LMS_FILTER_AP_NUM=40

//lms
//https://www.keil.com/pack/doc/CMSIS/DSP/html/group__LMS__NORM.html
//LMS_FILTER_AP_NUM=40
    arm_lms_norm_init_f32(&Slms, LMS_FILTER_AP_NUM, (float32_t *) firCoeff32, &firStateF32lms[0], 20, FRAME_SIZE);

    float32_t phaseRef = 0;
    float32_t pi2=2.0f * pi;
    delta =  (pi2 * 1000) / 24000;//1000Hz
    //заполнение референсного массива синусом
    for (int i = 0; i < FRAME_SIZE; i += 1) {
        lmsRef[i] = arm_sin_f32(phaseRef);
        phaseRef += delta;
        if (phaseRef >= pi2) phaseRef -=pi2;
    }


Теперь в прерывании:

....
       arm_lms_norm_f32(&Slms,(float32_t *)pFirOutTemp,(float32_t *)lmsRef,(float32_t *)pOutLms,(float32_t *)lmsErr,FRAME_SIZE);
....

Ну и на выходе фигня
Название: Re: Авто нотч
Отправлено: ra0ahc от Октябрь 13, 2020, 05:45:26 pm
arm_lms_norm_init_f32

здесь есть
-   размер шага, который управляет обновлениями коэффициентов фильтра
поставил 2 , что то там заплясало поработало сколько то и в аут улетело.

arm_lms_norm_init_f32(&Slms, LMS_FILTER_AP_NUM, (float32_t *) firCoeff32, &firStateF32lms[0], 2, FRAME_SIZE);


и еще, что делать с массивом Error?
Название: Re: Авто нотч
Отправлено: Relayer от Октябрь 13, 2020, 05:47:46 pm
Так надо видеть и понимать что внутри arm_lms_norm_f32 делается. Не понимаю почему вы не хотите написать код "с нуля" - там не так сложно
Название: Re: Авто нотч
Отправлено: ra0ahc от Октябрь 13, 2020, 05:51:12 pm
"с нуля" -
Потому-что не понимаю, нет опыта. Я даже на листе не смогу описать этот процесс
Название: Re: Авто нотч
Отправлено: ra0ahc от Октябрь 13, 2020, 05:58:11 pm
Геннадий как вы запустили "это"?
Название: Re: Авто нотч
Отправлено: GenaSPB от Октябрь 13, 2020, 06:40:43 pm
Мы срисовали откуда то...
Название: Re: Авто нотч
Отправлено: ra0ahc от Октябрь 14, 2020, 06:37:53 pm
Исправил mu с 2 на 0.0001
Как то заработало. Каряво конечно, но хоть так пока. Шум теперь постоянно. Во времени артефакты всякие вылазят.

Сильно все во времени растянуто. Тон когда появляется то система его начинает гасить крайне медленно.
На фото лучший вариант.
Тональник у меня подается и исчезает по 1 сек, от него остается яма, когда его нет.
Название: Re: Авто нотч
Отправлено: ra0ahc от Октябрь 14, 2020, 07:32:51 pm
Ну понятно, что я все не правильно делаю.
Название: Re: Авто нотч
Отправлено: ra0ahc от Октябрь 14, 2020, 09:01:18 pm
Запустил. Надо было референс обновлять.

Красные точки это появление тональника.
Название: Re: Авто нотч
Отправлено: ra0ahc от Октябрь 14, 2020, 09:06:33 pm
Тест работы авто нотч

https://drive.google.com/file/d/1zLI6Nf6rTqPYlmVtQIBQwNlEY4gQ4s7Q/view?usp=sharing
Название: Re: Авто нотч
Отправлено: ra0ahc от Октябрь 14, 2020, 09:15:07 pm
У UA3REO не спрашивал разрешения, надеюсь он не обидится.
 
https://github.com/XGudron/UA3REO-DDC-Transceiver/tree/master/STM32/Src


#include "auto_notch.h"
#include <arm_math.h>

// Private variables
static AN_Instance RX1_AN_instance = {0}; // filter instances for two receivers

// initialize the automatic notch filter
void InitAutoNotchReduction(void)
{
    arm_lms_norm_init_f32(&RX1_AN_instance.lms2_Norm_instance, AUTO_NOTCH_TAPS,RX1_AN_instance.lms2_normCoeff_f32 , RX1_AN_instance.lms2_stateF32, AUTO_NOTCH_STEP, AUTO_NOTCH_BLOCK_SIZE);
AUTO_NOTCH_STEP, AUTO_NOTCH_BLOCK_SIZE);
    arm_fill_f32(0.0f, RX1_AN_instance.lms2_reference, AUTO_NOTCH_REFERENCE_SIZE);
    arm_fill_f32(0.0f, RX1_AN_instance.lms2_normCoeff_f32, AUTO_NOTCH_TAPS);
}

// start automatic notch filter
void processAutoNotchReduction(float32_t *buffer)
{
    AN_Instance *instance = &RX1_AN_instance;

    for (uint32_t i = 0; i < AUTO_NOTCH_REFERENCE_SIZE; i++)
        if (isnanf(instance->lms2_reference[i]))
            InitAutoNotchReduction();

    arm_copy_f32(buffer, &instance->lms2_reference[instance->reference_index_new], AUTO_NOTCH_BLOCK_SIZE);   // save the data to the reference buffer
    arm_lms_norm_f32(&instance->lms2_Norm_instance, buffer, &instance->lms2_reference[instance->reference_index_old], instance->lms2_errsig2, buffer, AUTO_NOTCH_BLOCK_SIZE); // start LMS filter

    instance->reference_index_old += AUTO_NOTCH_BLOCK_SIZE;   // move along the reference buffer
    if (instance->reference_index_old >= AUTO_NOTCH_REFERENCE_SIZE)
        instance->reference_index_old = 0;

    instance->reference_index_new = instance->reference_index_old + AUTO_NOTCH_BLOCK_SIZE;
    if (instance->reference_index_new >= AUTO_NOTCH_REFERENCE_SIZE)
        instance->reference_index_new = 0;
}


.h
от красного зависит качество фильтра
от зеленого скорость

#define AUTO_NOTCH_TAPS 40              // filter order
#define AUTO_NOTCH_STEP 0.0005f   

#define AUTO_NOTCH_BLOCK_SIZE 1024   // block size for processing
#define AUTO_NOTCH_TAPS 40   // filter order
#define AUTO_NOTCH_REFERENCE_SIZE (AUTO_NOTCH_BLOCK_SIZE * 2) // size of the reference buffer
#define AUTO_NOTCH_STEP 0.0005f   // LMS algorithm step

typedef struct // filter instance
{
    arm_lms_norm_instance_f32 lms2_Norm_instance;
    float32_t lms2_stateF32[AUTO_NOTCH_TAPS + AUTO_NOTCH_BLOCK_SIZE - 1];
    float32_t lms2_normCoeff_f32[AUTO_NOTCH_TAPS];
    float32_t lms2_reference[AUTO_NOTCH_REFERENCE_SIZE];
    float32_t lms2_errsig2[AUTO_NOTCH_BLOCK_SIZE];
    uint_fast16_t reference_index_old;
    uint_fast16_t reference_index_new;
} AN_Instance;

// Public methods
extern void InitAutoNotchReduction(void);    // initialize the automatic notch filter
extern void processAutoNotchReduction(float32_t *buffer); // start automatic notch filter

Название: Re: Авто нотч
Отправлено: ra0ahc от Октябрь 14, 2020, 09:21:13 pm
Морзянка взрывает мозг
Нужна задержка.