vult-dsp / vult

Vult is a transcompiler well suited to write high-performance DSP code
https://vult-dsp.github.io/vult
Other
490 stars 25 forks source link

How to create a (zeroed) array of 5000 samples? #17

Closed cristiano-belloni closed 7 years ago

cristiano-belloni commented 7 years ago

Hi, I'm taking the first steps with Vult. I'm creating a simple instrument which involves the initialisation of an array long 5000 samples. I don't really care if it's full of zeroes or random values, since I fill it using a mem counter, but I should be able to get and set on it.

What I'm doing is:

and start(freq: int) @[init] {
   impulse = 44100 / 100;
   y: array(real, 5000) = [];
   N: real = floor(44100.0 / freq);
}

and earlier:

fun processor() {
    mem N;
    mem impulse;
    mem n;
    mem y;
    ...
    val yn = get(y, n);
    val yn1 = get(y, n + 1);
    out = xn + (yn + yn1 % N) / 2.0;
    _ = set(y, n, out);
  ...
}

But the compiler comes back with This expression has type (array, 0) but (array, 5000) was expected. Which makes sense as a response to my javascript-y initialisation, I guess, but do I need to specify all the 5000 values (or 10k or 50k) on initialisation? Is there a shorthand for this?

modlfo commented 7 years ago

You should remove the initialization ( = []) as follows:

and start(freq: int) @[init] {
   impulse = 44100 / 100;
   y: array(real, 5000);
   N: real = floor(44100.0 / freq);
}

That should initialize the array with zeros. The type checker complains because the expression [] is of size zero.

modlfo commented 7 years ago

But put the type in the declaration of y. When you do:

mem y: array(real, 5000);
modlfo commented 7 years ago

Here I have an example of a delay https://github.com/modlfo/vult/blob/master/examples/web/delay.vult

In the delay function I'm declaring the buffer as follows mem buffer : array(real,30000);. The declaration will initialize the array with the given size and filled with zeros.

cristiano-belloni commented 7 years ago

Tanks for your response. If I do y: array(real, 5000); I get an error saying This is not a valid statement in the form a = b If I do mem y: array(real, 5000); it's ok, but then I have to put another mem y in the processor function, and that confuses me. I guess part of the problem is that I don't know how to use start functions.

What I have now is:

fun processor() {
    mem N;
    mem impulse;
    mem n;
    mem y;
    val xn;
    ...
}
and start(freq: int) @[init] {
   impulse = 44100 / 100;
   mem y: array(real, 5000);
   N = floor(44100.0 / real(freq));
}

Does it make any sense?

cristiano-belloni commented 7 years ago

I mean, the reference says:

fun counter() {
   mem count = count + 1;
   return count;
}
and start() @[init] {
   count = 10;  // the first value of count will be 10
}

so I thought all the declarations should be in the counter and the initialisations in the start @[init] function. Does it work declaring stuff in both?

modlfo commented 7 years ago

I recommend you to write it as follows:

fun processor() {
    mem N;
    mem impulse;
    mem n;
    mem y: array(real, 5000);
    val xn;
    ...
}
and start(freq: int) @[init] {
   impulse = 44100 / 100;
   N = floor(44100.0 / real(freq));
}

It is legal to have multiple mem declarations of the same name. The compiler considers them as the same as long as the types match. For example mem x:

fun foo() {
   mem x : array(real, 5000);
}
and bar() {
   mem x;
}

Both x are actually the same array (memory location).

Regarding the start functions, the compiler will initialize to zero all declared variables (including arrays) as long as it knows the type. For example, if you give the function:

fun foo(){
   mem x : int;
   mem y : real;
   mem z : array(real,3);
}

x is initialized to 0, y to 0.0 and z to [0.0, 0.0, 0.0]. When you provide a function with the attribute @[init], you can specify a start value for any of the mem variables. For example:

fun foo(){
   mem x : int;
   mem y : real;
   mem z : array(real,3);
}
and bar() @[init] {
   x = 1;
   z = [1.0, 2.0, 3.0];
}

The mem variables are special and they can be declared anywhere in a chain of functions. For example the following code is equivalent to the previous:

fun foo(){
   mem y : real;
}
and bar() @[init] {
   mem x = 1;
   mem z = [1.0, 2.0, 3.0];
}
cristiano-belloni commented 7 years ago

That makes sense. Thanks for the amazing support!

modlfo commented 7 years ago

Thanks for the report. I will try to clarify those points in the language reference or by adding small examples. Feel free to let me know anything that is not clear, to try to document it better.

cristiano-belloni commented 7 years ago

One small error is the get and set documentation in the array section (both lines say get). I would PR that, but I have no access to cloning until Sunday. However, I will probably keep on asking help in the next days :) Many thanks!

modlfo commented 7 years ago

Fixed. Thank you!