snapclient
snapclient copied to clipboard
Using the MAX98357A
Hey, I'm pretty stuck right now on implementing this snapclient on my own hardware.
I'm using a MAX98357A based on this example.
Currenlty all configuration of audio devices isn't working. (I tried all devices on the "Custom Audio Board").
After research (I'm a complete noob when it comes to audio streaming) I found out that I have to add my own driver for the Audio HAL module. But I have no idea how to get this, or how to write my own.
Is it possible to stream the audio using this library?: https://github.com/schreibfaul1/ESP32-audioI2S
Or this library: https://github.com/earlephilhower/ESP8266Audio (as it supports more audio codecs)
Or ist there a pretty basic solution to stream PCM audio directly to my I2S board?
Thanks a lot for your help. I'm pretty much locked in as I bought a lot of these boards for a multiroom audio solution, and a only found out about this project as I noticed that an Icecast server wont be enough)
@Aragur You probably should study the files in https://github.com/jorgenkraghjakobsen/snapclient/tree/master/components/custom_board/pcm51xx as a reference. Copy it as a new board and rename everything to reflect your codec. All the i2c stuff can be removed as you don't need it. You'll probably end up with some empty functions and some gpio configuration. Study the datasheet of your codec for details on it's initialization and configure esp's i2s interface in accordance. I am not sure how this specific codec will work out as it hasn't a mclk signal but it should probably work without issues. You realize that you bought a mono IC? You would need two to get a stereo signal, again study the datasheet for details.
I didn't take a closer look, but I think the linked libraries are of no use here.
Regards Karl
@Aragur I actually added a TI PCM5102A board several weeks ago and just confirmed today this also works with a MAX98357A, so you should be able to use this out of the box. In fact, this should work with about any pure I2S DAC without I2C communication/setup requirements.
You can even connect SD_MODE the same way as the X(SMT) pin on PCM5102A boards to have power down/mute capability on the board (plus a resistor if you want to mix stereo channels instead of only using the left channel, see datasheet).
See my code in https://github.com/majoreffort/snapclient/blob/NETCONN/components/custom_board/pcm5102a/pcm5102a.c Note: this is based on @CarlosDerSeher's fork NETCONN branch.
Not sure if I should make a pull request to this repo or your fork @CarlosDerSeher ?
Thanks for all your effort.
@majoreffort By using your NETCONN branch I cannot connect to my server anymore.
Anyhting I can do to fix this?
SC: can't connect to remote 192.168.178.51:1704, err -13
So now I got it working by porting the changes to this codebase. My audio signal is pretty bad as my ring buff has an error all the time reading audio data. I'm using a PCM stream as Opus is crashing my board directly on initialization. Here is a part of my log:
I (1762) I2S: I2S interface master setup
I (1772) I2S: Setup i2s dma and interface
Setup ringbuffer using internal ram - only space for 150ms - Snapcast buffer_ms parameter ignored
Ringbuffer ok
I (1782) SNAPCAST: ... allocated socket
I (1812) SNAPCAST: ... connected
I (1832) SNAPCAST: Buffer length: 150
I (1832) SNAPCAST: Ringbuffer size:28800
I (1832) SNAPCAST: Latency: 0
I (1832) SNAPCAST: Mute: 0
I (1832) SNAPCAST: Setting volume: 100
I (1842) SNAPCAST: Received codec header message
I (1842) SNAPCAST: Codec : pcm , Size: 44
I (1872) I2S: 150 49 syncing ...
I (1892) I2S: 150 69 syncing ...
I (1912) I2S: 150 89 syncing ...
I (1932) I2S: 150 109 syncing ...
I (1952) I2S: 150 129 syncing ...
I (1972) I2S: 150 149 syncing ...
I (1992) I2S: 150 169 syncing ...
I (1992) I2S: 150 169 SYNCED
I (1992) I2S: Chunk :3840 152 ms
I (2072) I2S: Error readding audio from ring buf : read 1940 of 3840 , missing 1900
I (2072) I2S: Read the next 1900
I (2242) I2S: Error readding audio from ring buf : read 40 of 3840 , missing 3800
I (2242) I2S: Read the next 3800
I (2402) I2S: Error readding audio from ring buf : read 1992 of 3840 , missing 1848
I (2402) I2S: Read the next 1848
I (2572) I2S: Error readding audio from ring buf : read 92 of 3840 , missing 3748
I (2572) I2S: Read the next 3748
I (2732) I2S: Error readding audio from ring buf : read 2044 of 3840 , missing 1796
I (2732) I2S: Read the next 1796
I (2902) I2S: Error readding audio from ring buf : read 144 of 3840 , missing 3696
I (2902) I2S: Read the next 3696
I (3062) I2S: Error readding audio from ring buf : read 2096 of 3840 , missing 1744
I (3062) I2S: Read the next 1744
I (3232) I2S: Error readding audio from ring buf : read 196 of 3840 , missing 3644
I (3232) I2S: Read the next 3644
I (3392) I2S: Error readding audio from ring buf : read 2148 of 3840 , missing 1692
I (3392) I2S: Read the next 1692
I (3562) I2S: Error readding audio from ring buf : read 248 of 3840 , missing 3592
I (3562) I2S: Read the next 3592
I (3722) I2S: Error readding audio from ring buf : read 2200 of 3840 , missing 1640
I (3722) I2S: Read the next 1640
I (3872) I2S: Chunk :3840 42 ms
I (3892) I2S: Error readding audio from ring buf : read 300 of 3840 , missing 3540
I (3892) I2S: Read the next 3540
I (4042) I2S: Error readding audio from ring buf : read 2252 of 3840 , missing 1588
I (4042) I2S: Read the next 1588
I (4212) I2S: Error readding audio from ring buf : read 352 of 3840 , missing 3488
I (4212) I2S: Read the next 3488
I (4382) I2S: Error readding audio from ring buf : read 2304 of 3840 , missing 1536
I (4382) I2S: Read the next 1536
I (4552) I2S: Error readding audio from ring buf : read 404 of 3840 , missing 3436
I (4552) I2S: Read the next 3436
I (4712) I2S: Error readding audio from ring buf : read 2356 of 3840 , missing 1484
I (4712) I2S: Read the next 1484
I (4892) I2S: Error readding audio from ring buf : read 456 of 3840 , missing 3384
I (4892) I2S: Read the next 3384
I (5052) I2S: Error readding audio from ring buf : read 2408 of 3840 , missing 1432
I (5052) I2S: Read the next 1432
This is the crash when using opus: (Returning error -7 which translates to OPUS_ALLOC_FAIL)
I (1762) I2S: I2S interface master setup
I (1772) I2S: Setup i2s dma and interface
Setup ringbuffer using internal ram - only space for 150ms - Snapcast buffer_ms parameter ignored
Ringbuffer ok
I (1782) SNAPCAST: ... allocated socket
I (1982) SNAPCAST: ... connected
I (2002) SNAPCAST: Buffer length: 1000
I (2002) SNAPCAST: Ringbuffer size:192000
I (2002) SNAPCAST: Latency: 0
I (2002) SNAPCAST: Mute: 0
I (2012) SNAPCAST: Setting volume: 100
I (2012) SNAPCAST: Received codec header message
I (2022) SNAPCAST: Opus sampleformat: 48000:16:2
I (2022) SNAPCAST: Failed to init opus coder
E (2032) FreeRTOS: FreeRTOS Task "http_get_task" should not return, Aborting now!
abort() was called at PC 0x4008d02b on core 1
0x4008d02b: vPortTaskWrapper at /Users/giesel/Library/esp/esp-idf/components/freertos/port/xtensa/port.c:172
Backtrace:0x40081697:0x3ffda4b0 0x40089b75:0x3ffda4d0 0x40090736:0x3ffda4f0 0x4008d02b:0x3ffda560
0x40081697: panic_abort at /Users/giesel/Library/esp/esp-idf/components/esp_system/panic.c:393
0x40089b75: esp_system_abort at /Users/giesel/Library/esp/esp-idf/components/esp_system/system_api.c:112
0x40090736: abort at /Users/giesel/Library/esp/esp-idf/components/newlib/abort.c:46
0x4008d02b: vPortTaskWrapper at /Users/giesel/Library/esp/esp-idf/components/freertos/port/xtensa/port.c:172
Thanks for all your effort.
@majoreffort By using your NETCONN branch I cannot connect to my server anymore. Anyhting I can do to fix this?
SC: can't connect to remote 192.168.178.51:1704, err -13
I use mDNS autodiscovery which works fine for me. But I just double checked and have the same issue when trying to use a fixed address. So if you're able to use mDNS that should work. Maybe create a separate issue in CarlosDerSeher's repo for this?
As for the buffering: If you don't have a WROVER module with SPI RAM you really should use the fork from CarlosDerSeher, as he did an excellent job reworking the sync implementation to work with longer buffers.
I use mDNS autodiscovery which works fine for me. But I just double checked and have the same issue when trying to use a fixed address. So if you're able to use mDNS that should work. Maybe create a separate issue in CarlosDerSeher's repo for this?
Thanks for your fast anser. Do you have a guide how to setup mDNS? I cannot find any documentation on this topic.
@majoreffort
Not sure if I should make a pull request to this repo or your fork @CarlosDerSeher ?
to me it seems like @jorgenkraghjakobsen has abandoned the project, also there is quite some divergence of the repos. You are welcome doing a pull request to my repo, though it shouldn't be a problem to do the same for this repo too as the custom board component is the same for both repositories. You probably will have to make a separte checkout of jorgen's repo and add your changes and do a pull request just for these.
@Aragur mDNS should be activated at the snapserver side and is the default (as far as I know). Also you really should use my fork if you need syncing between clients to work.
@CarlosDerSeher thanks a lot I now got it working. But is Opus currently not supported on your branch im getting this error:
I (00:02:44.132) SC: Lookup snapcast service on network
I (00:02:47.222) SC: Found 192.168.178.88:1704
I (00:02:47.227) SC: netconn connected
I (00:02:47.229) SC: netconn sent hello message
I (00:02:47.234) SC: Buffer length: 1000
I (00:02:47.234) SC: Latency: 0
I (00:02:47.235) SC: Mute: 0
I (00:02:47.239) SC: Setting volume: 100
I (00:02:47.244) SC: OPUS not implemented yet
Guru Meditation Error: Core 1 panic'ed (IllegalInstruction). Exception was unhandled.
Memory dump at 0x400d7740: b469a51a 1df50406 000000f0
0x400d7740: http_get_task at /Users/giesel/Projects/Private/KiSpi/snapclient-fork2/main/main.c:585
Core 1 register dump:
PC : 0x400d7747 PS : 0x00060130 A0 : 0x00000000 A1 : 0x3ffcb8d0
0x400d7747: http_get_task at /Users/giesel/Projects/Private/KiSpi/snapclient-fork2/main/main.c:2682
A2 : 0x3ffb4520 A3 : 0x00000000 A4 : 0x3ffb4518 A5 : 0x3ffb451c
A6 : 0x00000004 A7 : 0x3f401f38 A8 : 0x800d5e01 A9 : 0x3ffcb880
A10 : 0x00000003 A11 : 0x3f401f38 A12 : 0x3f4026b4 A13 : 0x3ffb3f20
A14 : 0x3f401f38 A15 : 0x3ffcb890 SAR : 0x00000004 EXCCAUSE: 0x00000000
EXCVADDR: 0x00000000 LBEG : 0x400014fd LEND : 0x4000150d LCOUNT : 0xffffffff
Backtrace:0x400d7744:0x3ffcb8d0
0x400d7744: http_get_task at /Users/giesel/Projects/Private/KiSpi/snapclient-fork2/main/main.c:588
ELF file SHA256: 3dceee4d40b274fa
If Opus is not implemented yet what codec should be used than? Because PCM uses lot's of the bandwith. (@majoreffort is opus working on your side?)
Using ogg
or opus
results in an error.
Using flac
or pcm
playback is working with some crackling noises and lot's of errors printed to the console:
E (01:41:37.683) PLAYER: Failed to allocate IRAM memory for pcm chunk payload
@Aragur As the log says OPUS is not implemented yet. Use flac instead. Also if you are using NETCONN branch you should lower the buffer length on the server to something below 750ms. Also see https://github.com/CarlosDerSeher/snapclient/issues/2#issuecomment-974759877_
Ah and I just remembered now that I did another modification to flac to reduce overall RAM usage, in file components/flac/flac/src/libFLAC/bitreader.c I set FLAC__BITREADER_DEFAULT_CAPACITY from static const uint32_t FLAC__BITREADER_DEFAULT_CAPACITY = 65536u / FLAC__BITS_PER_WORD; to static const uint32_t FLAC__BITREADER_DEFAULT_CAPACITY = (65536u / 4) / FLAC__BITS_PER_WORD; Maybe this will help with out of sync too?
You'll have to do that too as I didn't have time to update the documentation or add a patch as I don't know how to integrate it automatically for the flac submodule. Maybe one of you guys have an idea on how to do that?
@CarlosDerSeher Thanks for your answer. Okay, so that was what I was reading but I thought this was a bug, that opus should be implemented :) So I tested it by ignoring the logs for about 2 hours and I had with 1000ms Buffer and without the modification no syncing issues. Two questions:
- What does reducing the buffer do for audio quality? Is there anything you can hear by reducing it to 750ms?
- What das modifing the
FLAC__BITREADER_DEFAULT_CAPACITY
do? Does it cut the audio quality by 4 in your example?
If the buffer is too long this can result in skipped frames and isn't handled yet. So you will eventually get out of sync. Errors like E (01:41:37.683) PLAYER: Failed to allocate IRAM memory for pcm chunk payload
indicate lost frames which could be audible as crackling noise. You really should reduce the buffer length and try find the best value for your wifi situation where these errors completely go away. Reducing the buffer length has no effect on quality, as long as there are not too much retransmissions for the tcpip connection on your wifi channel. For me 500ms were more than enough.
Reducing FLAC__BITREADER_DEFAULT_CAPACITY
has no effect on audio quality but maximum RAM usage. It just means flac's callbacks need to be called more often to get data which results in higher CPU load of the esp32
As a side note: If you have spi ram on your module you could also try use the master branch. I think opus is implemented there though I didn't do any work there for quite some time and don't know how stable it is. Another user reported in #9 it works though
@CarlosDerSeher I don't have a module with spi ram (only the WROM module). Currently without the flac modification my chip get's pretty hot. Isn't a higher CPU load heating the chip up even more?
what do you mean by pretty hot? I never had problems with high temperature can you still touch the module then you are definitely ok
what do you mean by pretty hot? I never had problems with high temperature can you still touch the module then you are definitely ok
Okay so I measured it. The chip is not getting over 40°C so everything should be fine :)