Hi, sorry for the late reply, a couple of days ago I finally received the I2C display, so I was able to do some more work on the project. Quick reaction to previous discussion:
1) b) increasing wifi throughput - the pertinent section of the ESP-IDF docs is
this, but like I said, I don't expect this to have a significant impact.. There's a table listing a couple of different configuration presets (they call them "ranks"), and as can be seen there, if you were to max out everything as the "iperf" preset does, you could get to a TCP RX rate of some 63 Mbps, but it would eat up a huge amount of memory; the second best TCP RX result was using the "RX priority" preset, which can achieve around 48 Mbps, whereas the default preset yields 40 Mbps - so there is a 20% improvement
in theory (although I'm pretty sure you would actually only get those numbers in lab conditions, if then). And apparently the "RX priority" preset actually uses a tiny little bit
less memory than the default. So it might not hurt to try it, but it might also help only a little, if at all..
4) touchend - I actually ended up designing and coding for a mechanical switch, because I want the main play button to have tactile response, but yeah, I think this is still worth looking into..
Allright, and now for the new stuff:
α) I got everything to work! I've ordered a PCB for my project, and meanwhile I put everything together on a breadboard and after some tweaking it actually works. Amazing.
β) I ran into an issue where a fast-enough button press with a long enough debounce time didn't end up calling the onRelease() callback, which I'm using to cancel a long-press timer I have on one of the buttons. If I'm not mistaken, it's a limitation of the current implementation; it probably doesn't matter too much, but it may be worth looking into if you were to consider implementing the "touchend" event.
γ) I've tried switching to PlatformIO, both as an IDE for writing code and as a build pipeline - and it turns out that something in the PlatformIO build pipeline is causing my firmware to eat like 30kB of extra RAM from the get-go. My firmware starts with wifi off, and long-pressing one of the buttons is supposed to toggle it; this worked well previously, but suddenly it started failing (there was an error being logged about failing to allocate the expected number of RX buffers, or something like that). I didn't suspect the build pipeline at first, but after eliminating all the other changes I've made since the last successful build it was the only thing that could cause it.. and sure enough, rebuilding again using Arduino CLI got me a working firmware. I've no idea why that is.. Maybe PlatformIO includes some more debugging facilities even in release builds, or maybe it got a slightly different version of some library or something like that.. but yeah. I don't mind terribly, but it was an interesting thing to observe.
δ) Oh, yeah, ESP-IDF stuff is definitely available, that's what I'm using for the long-press timer - and just now, browsing the docs randomly, I discovered that it includes
a pretty capable HTTP server implementation - maybe WVR could drop the (seemingly unmaintained) AsyncTCP and ESPAsyncWebServer dependencies.. I'll definitely look into this, as it would be relevant for other projects I have in mind. It supports async requests and responses, as well as websockets, so it looks promising.
Regarding the "librarification" of WVR, I'm starting to see the outlines of a couple of things. At least I think the parts dealing with audio management might have sensible solutions.. There would need to be three parts to this, I think:
- A wav storage layer - a generic API allowing the storage and retrieval of PCM data to and from the eMMC - probably as a single flat indexed list; ideally it would allow storing application-defined metadata along with the wav files (so the WVR firmware could store e.g. loop start and end points here). From the playback point of view, this would need to provide a method which would read PCM data into a buffer given a file index, an offset, and a buffer length. It could also abstract away the handling of mono files - just pass it a separate L and R output buffer, and it would either fill each with data from the respective PCM channels, or fill both with the same data when the file is mono.
- An audio playback layer - which would use one or more input buffers for each audio channel, and it would handle summing them and sending them to the DAC. It'd be awesome if the number of output channels could be configurable - as in, if you could use it with e.g. multiple DACs to handle multi-channel output. It could handle global volume & mute (ideally on a per-channel basis). This would encapsulate the RTOS task; the user would just provide a callback to fill the input buffers.
- An application-specific "glue" layer, which would implement the callback for the playback layer using the storage layer. In the default WVR firmware, this would be where MIDI notes are converted to storage layer indices, pruning is resolved, ASR loops are applied etc - basically most of what the current wav player task does, except for the stuff abstracted away into the other two layers.
In my ideal world, all of this would be implemented as classes & wouldn't use any global state.. ;-)
By the way, have you heard of the ESP Audio Development Framework, a.k.a.
ESP-ADF? I haven't, until recently. It looks like it might be pretty powerful..
Cheers!
Dan