steindevices / ESP32-LyraT-DSP

A cheap (around $20) DSP built using the Espressif ESP32-Lyrat development board.
MIT License
13 stars 2 forks source link

Can the filters be changed once loaded? #4

Closed hhemmati81 closed 10 months ago

hhemmati81 commented 11 months ago

I am using the filters as an equalizer and have setup and API where I can send command to change the equalizer. If I try to set the filter in my API it doesn't do anything.

I was changing them by assigning new filters to filter_def_t FREQ_Filters[] = {new filters}

steindevices commented 11 months ago

Hello Hamed,

There isn't a mechanism currently in the code to change the filters dynamically. The filters are compiled into the DSP and there isn't an interface to send new filter settings to the DSP.

Out of curiosity, how are you attempting to set the filters through your API to the DSP? Have you modified my code to support this functionality? Is so, I can probably direct you to what additional changes to make to the DSP code to reload the filters on demand.

hhemmati81 commented 11 months ago

So far I have extended it to include a webserver and API paths. Then I send post commands to the webserver and if the command is for changing filters then I pass the following as a test

filter_def_t FREQ_Filters[] = {
                        {0, DSP_FILTER_PEAK_EQ, 60, 2.0, 3.0},
                        {0, DSP_FILTER_PEAK_EQ, 80, 5.0, 2.0},
                        {0, DSP_FILTER_PEAK_EQ, 100, 5.0, 2.0},
                        {0, DSP_FILTER_PEAK_EQ, 120, 5.0, 2.0},
                        {0, DSP_FILTER_PEAK_EQ, 140, 5.0, 2.0},
                    };

then stop the filters and run again but it always runs the original filters.

steindevices commented 11 months ago

If I am understanding correctly, bear in mind that the text you are sending is 'C' code that the API would need to replace in the existing config file and then recompile the source and reboot the DSP.

I'm curious what happens to the text you send to the web server. What do you do with it at the web server end? Where does it go?

steindevices commented 11 months ago

Ok. Just so I understand, is your web server embedded in the DSP code and so you are updating the config settings dynamically? If that is the case, I can probably point you in the right direction.

hhemmati81 commented 11 months ago

Here is my webserver code. The dsp_commands() work but the filter doesn't.

#include "ESPAsyncWebServer.h"
#include "dsp_process.h"

AsyncWebServer server(80);

static void setupWebServer()
{
    server.on("/eq", HTTP_GET, [](AsyncWebServerRequest *request)
              {
            if(request->hasArg("setEQ")){
                String param = request->arg("setEQ");
                if(param.equals("disable")){
                    Serial.println("disable dsp");
                    dsp_command('d');
                } else if(param.equals("rock")){
                    Serial.println("filter set to rock");
                    filter_def_t FREQ_Filters[] = {
                        {0, DSP_FILTER_PEAK_EQ, 60, 2.0, 3.0},
                        {0, DSP_FILTER_PEAK_EQ, 80, 5.0, 2.0},
                        {0, DSP_FILTER_PEAK_EQ, 100, 5.0, 2.0},
                        {0, DSP_FILTER_PEAK_EQ, 120, 5.0, 2.0},
                        {0, DSP_FILTER_PEAK_EQ, 140, 5.0, 2.0},
                    };
                    dsp_command('s');
                    dsp_command('r');
                } else if(param.equals("voice")){
                    Serial.println("filter set to voice");
                } 
            }
            request->send(200, "text/plain", "EQ commands"); });

    server.begin();
    Serial.println("Web server started");
}

and then set up the webserver in the main.cpp if the wifi is on. When you go to the deviceIP/eq?setEQ=rock then the webserver runs the code for changing the filter.

hhemmati81 commented 11 months ago

I am a web and mobile engineer so C has been challenging to understand.

steindevices commented 11 months ago

Ah. Ok. I misunderstood, I thought you had set up an external web server to act as an interface. My bad.

steindevices commented 11 months ago

Ok. So to reset the filters dynamically, you will need to make a few changes to your code. Basically, you just need to re-initialize the filters. Let me look into the code changes you'll need.

Will get back to you in a bit.

steindevices commented 11 months ago

Hamed,

What I will do is create a function that you can call in your code to reset the filters. That is probably the easiest way to go and also would be a good addition to the DSP. Just give me a day or two to add it.

One thing though is that my code does not currently have the ability to store updated settings. So if the DSP is restarted, you would need to run the API each time at startup to set your filters. Alternatively, once you had the filters set up the way you wanted, you could recompile them into the DSP via the config file. Does that work for you?

hhemmati81 commented 11 months ago

Yeah that should be perfect. Thanks for the work done on this. I was using Wrover-E for our project and the sound was pretty boxy even with a nice i2S amp. With this DSP chip and the filters I have been able to improve it significantly.

On that note is the onboard amp disabled? I am able to get sound from the headphone jack and my i2s Amp but I get nothing if I just plug a speaker in the L or R jacks.

steindevices commented 11 months ago

I didn't have a need for the amplifier on board so I haven't enabled it in my code. May be a simple change.

I don't recall if the both the line out and amp can be enabled at the same time as that may be a limitation of the ES8388 chip on the ESP32-Lyrat board. If not, I could add a command switch. Will let you know.

steindevices commented 10 months ago

Hamed,

I am looking at this now but have a question. Are you looking at loading up the DSP with a permanent set of filters, or are you looking for the the ability to change them dynamically on an ongoing basis?

hhemmati81 commented 10 months ago

A permanent set of filters is fine for my purpose as long as I can select which one should be loaded. Dynamic EQ would be nice but not necessary.

steindevices commented 10 months ago

Hamed,

I have added a new function in dsp_filter.cpp called dsp_update_filters(). Please pull down the new code.

In your example, to do what you want you would use the code below. The first parameter of the function is the new filter table, the second is the TOTAL number of filters. To change the filters on the fly, update the values in the table with your code and then call the function with the same table each time you want to change the equalization (e.g. from rock to classical). Note that it is important that you specify that the table is static as in my definition below.

Also, I have added an example of how this is called with a new command line 'u' in dsp_process.cpp. Take a look at the dsp_command() function in the source.

P.S.: You will probably want to define filters for BOTH channels (L=0, R=1) which is why I have specified 10 filters over your 5.

Hope this helps.

Any questions or issues, let me know.

      static filter_def_t FREQ_Filters[] = {
             {0, DSP_FILTER_PEAK_EQ, 60, 2.0, 3.0},
             {0, DSP_FILTER_PEAK_EQ, 80, 5.0, 2.0},
             {0, DSP_FILTER_PEAK_EQ, 100, 5.0, 2.0},
             {0, DSP_FILTER_PEAK_EQ, 120, 5.0, 2.0},
             {0, DSP_FILTER_PEAK_EQ, 140, 5.0, 2.0},
             {1, DSP_FILTER_PEAK_EQ, 60, 2.0, 3.0},
             {1, DSP_FILTER_PEAK_EQ, 80, 5.0, 2.0},
             {1, DSP_FILTER_PEAK_EQ, 100, 5.0, 2.0},
             {1, DSP_FILTER_PEAK_EQ, 120, 5.0, 2.0},
             {1, DSP_FILTER_PEAK_EQ, 140, 5.0, 2.0}             
             };

      dsp_update_filters( FREQ_Filters, 10 );
steindevices commented 10 months ago

By the way, if you would prefer to use different filter tables for different equalizations, you can do that instead. So you could have a table called ROCK_Filters[], JAZZ_Filters[], CLASSICAL_Filters[], etc. Then in your code you would call the function with the appropriate table.

hhemmati81 commented 10 months ago

This is working great. I am able to change the filters on the fly from API commands. Thanks for adding the new function.

Now all I need to figure out is the Wifi Provisioning.

steindevices commented 10 months ago

Closed as per user comment.