How to indicate input size to dsp.BlockLMSFilter when using MATLAB Coder?

1 view (last 30 days)
I would like to use dsp.BlockLMSFilter in code that will be converted to C code via MATLAB Coder. I understand that Length and BlockSize of dsp.BlockLMSFilter must be entered as literals in the constructor for the object. I have tried to feed the object signals whose lengths are equal to an integer multiple of BlockSize, but I get a warning about variable input size when I run codegen, even if I have "released" the object beforehand. I have the same problem if I feed the signal to the object in successive BlockSize-length blocks.
Is there some way to assure a dsp.BlockLMSFilter object (in code that will be converted to C and compiled) that the size of the incoming signal is acceptable?
Suppose that x and d (in the simplified example below) are guaranteed to have lengths that are multiples of the BlockSize. How do I let the code generator know this? Is there an assert that might help?
function wts = example(x,d,mu) %#codegen
obj = dsp.BlockLMSFilter('Length',10,'BlockSize',10,'StepSizeSource','Input port');
[y,errs,wts] = obj(x,d,mu);
end
  2 Comments
David Fink
David Fink on 15 Jul 2021
What specific warning or error are you seeing, and what commands are you using to generate code?
Note - if using the MATLAB Coder App, you can convert this to a code generation script via:
Joe M
Joe M on 17 Jul 2021
Edited: Joe M on 18 Jul 2021
@David Fink Thank you for responding. My question is part of a much larger project, so I will illustrate with an artificial m-file that captures just this particular issue's behavior. Below I include
  • the m-file,
  • main.c,
  • my build-script,
  • and the error message.
For my m-file, I borrow some content from the documentaion for dsp.BlockLMSFIlter.
% myexample.m
function myexample(N) %#codegen
filt = dsp.FIRFilter('Numerator',fir1(10,[0.5, 0.75]));
x = randn(N*100,1);
t = (0:length(x)-1)'/length(x);
d = filt(x) + sin(2*pi*8*t);
blms = dsp.BlockLMSFilter('Length',10,'BlockSize',5,'StepSize',0.01);
[y, err, w] = blms(x, d);
fprintf("norm(d - err): %f\n", norm(d - err));
end
/* main.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "myexample_initialize.h"
#include "myexample_terminate.h"
void example( const int N );
int main(int argc, char * const argv[])
{
int N;
N = atoi( argv[1] );
myexample_initialize():
myexample( N );
myexample_terminate();
return 0;
}
% buildscript.m
u = coder.typeof(int32(1));
cfg = coder.config('exe');
cfg.Toolchain = 'Intel IPP | make (64-bit Linux)';
cfg.CustomSource = 'main.c';
cfg.CustomInclude = pwd;
codegen -report -config cfg -args { u } myexample;
When I run buildscript.m, I receive the following error message.
??? Reported by dsp.BlockLMSFilter: This system object (or its current configuration) does not support variable input sizes.
Error in ==> myexample Line 11 Column 1
Code generation failed: View Error Report
Error using codegen
Error in buildscript (line 9)
codegen -report -config cfg -args { u } myexample;

Sign in to comment.

Accepted Answer

Pranav Venuprasad
Pranav Venuprasad on 19 Jul 2021
The dsp.BlockLMSFilter object does not support variable input sizes as mentioned in the error message. This begavior is not specific to codegen. For example consider the code snippet below:
blms = dsp.BlockLMSFilter(10,5);
filt = dsp.FIRFilter;
filt.Numerator = fir1(10,[.5, .75]);
x = randn(1000,1); % Noise
d = filt(x) + sin(0:.05:49.95)'; % Noise + Signal
[y, err] = blms(x, d);
[y2, err2] = blms([x;x], [d;d]); % double the size of the input
The above snippet produces the following error even though the size of the input in the second step is a multiple of the "BlockSize" property of the dsp.BlockLMSFilter object.
Error using dsp.BlockLMSFilter/parenReference
Changing the size on input 1 is not allowed without first calling the release() method.
In codegen to lock the input frame size, you can provide the size of the input as a constant when compiling. In the example mentioned above, if the desired value of N is say 10, you can generate the C code using the following snippet
N = int32(10);
codegen myexample -args {coder.Constant(N)};
  2 Comments
Joe M
Joe M on 22 Jul 2021
Edited: Joe M on 22 Jul 2021
@Pranav Venuprasad: Thank you for the answer.
Unfortunately, a fixed signal-size is not an option for my work.
I wrote my own block LMS filter function, and I would like it to perform as much like the dsp.BlockLMSFilter system object as possible. This leads me to a question, for which I need to provide some background.
The MATLAB code that I inherited, uses a dsp.BlockLMSFilter object (named blms) and applies
for ii = 1:10
[y, err, w] = step(blms, x, d);
end
It is clear from my experiments that blms maintains an internal state, but even after reading the documentation I am unsure of the details. I suspect that the weights are part of the internal state, but I would like to know if there is more. Where can I find concrete answers?
Pranav Venuprasad
Pranav Venuprasad on 29 Jul 2021
The dsp.BlockLMSFilter object maintains the internal state according to the update equations provided in the following documentation page: https://www.mathworks.com/help/dsp/ref/blocklmsfilter.html#f3-1110408 . If you would like to create a custom functionality for Block LMS filtering with variable size inputs, you can use make use of the equations outlined on the above page for the same.

Sign in to comment.

More Answers (0)

Products


Release

R2021a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!