Пока я не совсем понимаю как оно работает.
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 указывает на блок данных об ошибке
[в] размер блока количество образцов для обработки
Авто нотч
43024 просмотров, 22 ответов — стр. 1 из 2
11 октября 2020 г. в 09:30#1
11 октября 2020 г. в 09:59#2
А что в качестве референса использовать? Шум белый?Нет никакого референса. Рассматривайте LMS как простой линейный предсказатель невысокого порядка. Даете ему на вход синус плюс чегото там еще - он адаптируется к самому простому сигналу - синусу. Вычитаете - остается все остальное (шум, речь и тп)
11 октября 2020 г. в 10:02#3
Вот код для 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;
Может использоваться как шумодв если 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;
11 октября 2020 г. в 10:08#4
Млин, можно как-то запретить форматирование? Этож ппц какой-то - съедает квадратные скобки с индексами. Что за форумный движок такой кривой?!?!?
12 октября 2020 г. в 08:03#5
Млин, можно как-то запретить форматирование?Попробуйте вставлять текст как код.
Код: [Выделить]вот так для примера- смайлики в игноре

12 октября 2020 г. в 09:00#6
Код: [Выделить]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 */
}
/* 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 */
}
12 октября 2020 г. в 09:02#7
Спасибо Андрею за код
Спасибо Зениту за совет

Спасибо Зениту за совет
12 октября 2020 г. в 09:07#8
Не могу поправить пост. Короче там съело taps [ i ] везде
12 октября 2020 г. в 01:54#9
начилась рабочая неделя....
12 октября 2020 г. в 09:49#10
Посмотрел у UA3REO.
Там перед началом обработки очередного блока семплов просто проверяется на наличие НЕ ЧИСЕЛ в ранее накомленнвх коэффициентов
Там перед началом обработки очередного блока семплов просто проверяется на наличие НЕ ЧИСЕЛ в ранее накомленнвх коэффициентов
13 октября 2020 г. в 05:17#11
Ну вот, что я сделал и не заработало. НЕ удивительно, в слепую делаю, то чего не понимаю .
и так
сперва делаю 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);
....
Ну и на выходе фигня
и так
сперва делаю 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);
....
Ну и на выходе фигня
13 октября 2020 г. в 05:45#12
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?
здесь есть
- размер шага, который управляет обновлениями коэффициентов фильтра
поставил 2 , что то там заплясало поработало сколько то и в аут улетело.
arm_lms_norm_init_f32(&Slms, LMS_FILTER_AP_NUM, (float32_t *) firCoeff32, &firStateF32lms[0], 2, FRAME_SIZE);
и еще, что делать с массивом Error?
13 октября 2020 г. в 05:47#13
Так надо видеть и понимать что внутри arm_lms_norm_f32 делается. Не понимаю почему вы не хотите написать код "с нуля" - там не так сложно
13 октября 2020 г. в 05:51#14
"с нуля" -Потому-что не понимаю, нет опыта. Я даже на листе не смогу описать этот процесс
13 октября 2020 г. в 05:58#15
Геннадий как вы запустили "это"?