3

I am writing a data mashing function where I'm modifying audio data over time for a sort of dynamic bit-crusher audio filter. It is convenient for me to use static variables because their values carry over between function calls and this helps me achieve some interesting time-based effects by incrementing and so forth across rendering callbacks.

For example, one effect uses a sin function to modulate some sound effect over time. Like so:

void mangle(float * data, int n) {

   static bool direction = false;

   static float bottom = 0;
   static float top = n;
   static float theta = 0;

   theta += 5;

// data = sin(theta) etc..

So I wish theta to be initialized once and than modified over time. Likewise, top wants to be static variable because I modify it later in the function also. In addition, top should take on the value of parameter n because n changes based on program state. But when I go to assign n to top, I get the compiler error

Initializer element is not a compile-time constsant.

Is there a way to assign a parameter to a static variable? Is there another way to accomplish what I want without static variables? I am aware I could use instance variables but I find that to be too much.

1
  • Sounds good, as long as you understand that your filter is not thread-safe. Commented Feb 17, 2016 at 10:17

4 Answers 4

5

static variables are initialized before the program execution begins, so you cannot use a variable value to initialize a static variable. You'll need a compile-time constant value to initialize the static variable.

Quoting C11 standard, chapter §6.2.4, Storage durations of objects (emphasis mine)

[..] or with the storage-class specifier static, has static storage duration. Its lifetime is the entire execution of the program and its stored value is initialized only once, prior to program startup.

However, you can always assign a new value to the static variable.

That said, coming to the initialization part, as per chapter §6.7.9,

If an object that has static or thread storage duration is not initialized explicitly, then
- ...
- if it has arithmetic type, it is initialized to (positive or unsigned) zero
- ...

so, you need not initialize the static floats explicitly to 0. You can assign any value, whatsoever later in the code.

Sign up to request clarification or add additional context in comments.

Comments

1

In your case, top is a local static variable.

It is like global static variable and global variable that they all have static storage duration and they have value before the code startup.

The reason you have error similar to this case:

int a;
int b = a; \\initializer is not a constant

int main() {
...
}

With your purpose, use top as a global variable is a right way to go.

1 Comment

so the static aspect is actually not critical here?
1

What you should do is create a struct that holds the data that is needed across calls and pass a pointer to the struct to the function. If you wnat to get fancy, you can create functions that allocate, initialize and free such a struct (and the user of the functions never needs to know what the contents of the struct are.

Something like:

struct mangle_t {
    bool direction;
    float bottom;
    float top;
    float theta;
};

struct mangle_t* mangle_open(void)
{
    struct mangle_t* m = malloc(sizeof *m);

    if (m) {
        memset(m, 0, sizeof *m);
    }

    return m;
}

void mangle_close(struct mangle_t* m)
{
    free(m);
}



void mangle(struct mangle_t* m, float * data, int n) {

    m->top = n;
    m->theta += 5;

}

As far as assigning a parameter to a static variable, you can just perofrm the assignment like any other variable (however, not as an initialization in the variable's declaration - that only happens once).

9 Comments

So I was actually able to get the behavior I wanted by doing static float top; and then top = n This gets me all the persistent state that lets me do time based manipulation with no need for structs or extra complexity. Caller always just passes in a value for n.
Yes - using static for persistent state is easier, but it doesn't scale - they have many of the same problems that global variables do. If your needs are simple, then using statics might be good enough. I'm not saying that you need to move away from static variables for your current implementation, but keep this technique in mind whenever you want to use static variables to keep persistent context as it may be the solution when your application gets more complex (such as needing to process multiple audio streams concurrently or something).
Also keep in mind that you don't necessarily need to go to the complexity of having full blown open/close or init/free functions - those just provide a mechanism for hiding data & implementation details. generally that's desirable, but again your own specific can take precedence. You could always just have a struct (or variable if the persistent state is that minimal) that the caller manages ownership and initialization of.
Yeah I could imagine one way the complexity would not scale is if the static variables are not name-spaced. Is that the case? In other words, if I use a static int called theta in dspFunction1 and I have several dspFunctions all which need to keep track of a theta variable would they collide given the name theta?
Also, with regards to structs. Is there a way to have the function entirely manage the struct. Like create the struct as a static entity and malloc memory to it and just free it at program end or something? I guess that is the same scenario as using regular static local variables but at least it encapsulates the names within a struct.
|
1

I'm not sure if you want to initialize top once and then keep it, but if so, this is what I would do:

void mangle(float *data, int n) {
    static float top = -1; // Assuming that n will never be -1
    if (top == -1)
        top = n;
    // .....
}

If you don't need to keep the value of top over function calls, there is no need to declare it static.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.