squeezelite-esp32 icon indicating copy to clipboard operation
squeezelite-esp32 copied to clipboard

Recent esp-idf development, A2DP sink with extra codecs

Open lightdot opened this issue 11 months ago • 11 comments

When researching I noticed this recent esp-idf development:

ESP32 A2DP sink with extra codecs

Using v5.1.4-a2dp-codecs branch from esp-idf, support added for:

AAC aptX aptX-LL aptX-HD LDAC Opus 05 LC3plus HR

If esp-idf v5 is compatible, hopefully this could be used to move beyond just SBC Bluetooth codec.

lightdot avatar Jan 20 '25 18:01 lightdot

v5 and beyond are HIGHY incompatible and require a boatload of changes on network and BT. Can't do that for now

philippe44 avatar Feb 17 '25 21:02 philippe44

@philippe44, I'm pondering slowly working through the code and migrating it into platformio and esp-idf latest.

Has this been looked at before and abandoned, or is it something that will take a lot of work but likely possible? Any sage words much appreciated!

emlynmac avatar Mar 04 '25 21:03 emlynmac

As said, the network, AFAIR was a nightmare and I gave up

philippe44 avatar Mar 04 '25 22:03 philippe44

@philippe44 and @lightdot, I've started down the rabbit hole here: https://github.com/emlynmac/squeezelite-esp32/tree/esp-idf-5.4

Will keep plugging at it.

emlynmac avatar Mar 05 '25 21:03 emlynmac

@emlynmac, you are working on a very old code base so I would not recommend.

The underlying platform has changed quite a bit in the current development environment, which I have not yet been able to bring to a level that I can push as a new branch. The biggest change has to do with how settings are stored and used throughout the system, leveraging protobuffers and automated source code generation. This also came with a network stack refactoring that will open the door to multi-access point config, roaming, etc.

The configuration subsystem was also refactored to allow storing some hardware specific configurations as an "overlay" that is applied on top of the "user" config. The system loads user config, which includes the hardware platform type/name and then checks if there's a hardware/platform specific config file that should be loaded. This ensures that user have freedom to configure things while also ensuring that hard wired options like GPIOs, DAC name, etc aren't affected.

Unless someone comes with some serious arguments for using PlatformIO, we shouldn't move away from the current build system as doing so opens another big can of worms.

Since this is a significant refactoring effort that will require quite a bit of testing, I am not against also upgrading to V5 at the same time, but this will have to start from the new code base and not the "old" one.

Note that the refactored version used esp-idf 4.4.6.

sle118 avatar Mar 18 '25 18:03 sle118

@emlynmac, you are working on a very old code base so I would not recommend.

The underlying platform has changed quite a bit in the current development environment, which I have not yet been able to bring to a level that I can push as a new branch. The biggest change has to do with how settings are stored and used throughout the system, leveraging protobuffers and automated source code generation. This also came with a network stack refactoring that will open the door to multi-access point config, roaming, etc.

Since this is a significant refactoring effort that will require quite a bit of testing, I am not against also upgrading to V5 at the same time, but this will have to start from the new code base and not the "old" one.

Note that the refactored version used esp-idf 4.4.6.

Is your branch available? I've already got a fair way into migrating the 4.3 -> 5.4. Lots of changes!

emlynmac avatar Mar 18 '25 18:03 emlynmac

@emlynmac Would you be interested in bringing the project to the next level? Quite a few things were gutted out from the new branch, especially around the web interface as wanted to better modularize and leverage the new capabilities of the protobuf tooling I created and which should streamline the communications between a web UI and the backend. So current state is that most of the config has to be done via telnet.

Another big challenge of the project was managing the limited space on Flash. So ideally, recovery should be trimmed to be as small as possible. The new branch has made some progress in that direction, since all the web UI artefacts are stored on the SPIFFS rather than being compiled in the target binary. The added benefit is that it is possible to upgrade the UI as a separate activity and to make recovery/app mode present the same experience to the user.

Ah, and also it is worth mentionning that I have started levergaging the test automation platform that is shipped with the esp-idf. This helps target testing of some very specific components that would otherwise be cumbersome to fully validate.

I am pretty sure that many of the changes you've made so far would be transposable to the new code base.

sle118 avatar Mar 18 '25 18:03 sle118

@sle118 I am interested, hence the start on my fork. I'm unclear as to how much time I'll be able to put towards, but slow is good. Highlights from the work on the 5.4 port so far include:

  • mbedTLS 2->3, needs a RNG for things...
  • I2S driver is reworked...
  • Networking is changed significantly, might require a different arch to be optimal
  • Ethernet also affected, I've disabled those for now as I have no way to test.
  • Compiler is stricter; lots of updates to logging %d -> %ld

I'm also seeing a lot of traction in the rust community for ESP-IDF, so wondering if it might be a plan to start fresh and bring functionality across. https://docs.esp-rs.org/book/tooling/visual-studio-code.html

emlynmac avatar Mar 18 '25 21:03 emlynmac

Oh, the rust... Unless I am mistaken, this is much more radical than migrating to 5.x and implies a order of magnitude more work in the end. I doubt that @philippe44 would enjoy or even choose to participate, but I'll leave it up to him to answer.

I will try to push the latest code to a new branch, perhaps tonight.

sle118 avatar Mar 18 '25 21:03 sle118

Just my 2 cents on rust... I'm no expert there but I've used it a bit up to making some accepted contribution for librespot (direct ogg interface). I can't say that I'm a big fan but beyond starting and endless discussion wrt this language benefits, I don't think the rewrite is even possible. First it's a huge amount of work for no new features. Then, and this is the most important argument, the reason why you have so many features on this app (all audio codecs, equalizer, spdif, display with spectrum ...) is because everything has been optimized in C to fit the CPU and memory capabilities and believe me, that was very painful. So a rust implementation will not fit, unless you want to limit yourself to a s3 platform and maybe just lose all the benefit of s3 and go back to regular esp32 capability/level just for the fun of using rust.

philippe44 avatar Mar 19 '25 05:03 philippe44

@emlynmac I have pushed the current code to the following https://github.com/sle118/squeezelite-esp32/tree/refactoring

The code was originally branched out in october of 2023. This means there are likely changes that were made to the current release branch that aren't included in the new branch. Some of the changes will be irrelevant because of the refactoring, but some changes could be bug fixes that will eventually need to be retrofitted. There are also a few things I'll need to clean up under the targets folder (e.g. bureau-oled which is a personel hand crafted device).

The code definitely doesn't currently build under the 5.X branch. Do you want to take a look? I think many of the changes you made in your branch would still apply to this refactored code.

This is the first time I share the code so hopefully the build files are working on development machines other than mine.

Most of the device specific configuration sits under the spiffs_src/device_name/config.json. Each file is a subset of the protocol buffer structure that is specific to a given device. For example, the esp32-a1s board build around the es8388a CODEC has the following configuration: { "gpios": { "redLED": { "gpio": { "pin": 22, "level": "LOW" }, "brightness": 50, "led_type": "GPIO" }, "greenLED": { "gpio": { "pin": 19, "level": "LOW" }, "brightness": 50, "led_type": "GPIO" }, "amp": { "pin": 21, "level": "HIGH" }, "jack": { "pin": 39, "level": "LOW" } }, "dev": { "dac": { "bck": 27, "ws": 25, "dout": 26, "din": -1, "model": "ES8388", "i2c": { "port": "PORT0", "speed": 400000, "sda": 33, "scl": 32 }, "addr": 16, "jack_mutes_amp": false }, "root_button_profile": "default", "buttons_profiles": [ { "profile_name": "default", "buttons": [ { "gpio": {"pin":5}, "normal": { "pressed": { "type":"A_TOGGLE" } } }, { "gpio": {"pin":18}, "pull": true, "shifter": 5, "normal": { "pressed": { "type":"A_VOLUP" } }, "shifted": { "pressed": { "type":"A_NEXT" } } }, { "gpio": {"pin":23}, "pull": true, "shifter": 5, "normal": { "pressed": { "type":"A_VOLDOWN" } }, "shifted": { "pressed": { "type":"A_PREV" } } } ] } ] } }.

The build process takes each one of the config.json file and encodes them to a small bin file that the esp32 can decode at boot time. I haven't completed the squeezeamp config.json file yet (shame on me) but you'll find enough examples to see how things go.

You will also notice that we're not making nvs call from all over the place anymore. Instead, the build system generates multiple header files for structures that get instantiated as a single structure sys_config* platform. That structure contains all the configuration and is available at all time to retrieve data when needed.

In addition to the platform configuration structure, we also get a system state sys_state_data* sys_state that persists runting system state information.

Note that all the config structure headers are generated during the build and as such, the first round of the cmake work has to complete for them to show up and be found by intellisense and other code assistants. A number of other artefacts are generated as well for javascript, python, etc.

sle118 avatar Mar 19 '25 19:03 sle118