Knacksen bei opus files (insb. 48kHz) / vormals auch wav files

@sfields hilft es hier die Audio-Bibliothek zu aktualisieren?

lib_deps =
	https://github.com/schreibfaul1/ESP32-audioI2S.git#8ba3208
    ;https://github.com/schreibfaul1/ESP32-audioI2S.git#961b320 - unser aktueller DEV

Damit habe ich einen besseren Klang & keine Aussetzer mehr. Die Verbesserung gilt anscheinend nur für das OPUS-Format.

1 „Gefällt mir“

Super! Das Knacken ist weg.

Ist das jetzt absoluter Zufall? Egal, jedenfalls sehr schön. Danke.

Das ist kein Zufall, der Autor liest hier auch immer mal mit & verbessert die Audio-Bibliothek ständig. Also bedankt Euch bei @wolle :heart:
Der Audiotask läuft jetzt wohl etwas performanter & bremst unsere anderen Tasks weniger aus. Die Aktualisierung ist jetzt im DEV-Branch verfügbar.

3 „Gefällt mir“

Leider hilft das bei mir nicht. Die DEV vom 4.12.2023 ist die letzte die bei mir läuft, bei allen nachfolgenden habe ich wieder keinen Webzugriff.
@Wolle Hast du keine Lite-Version deiner Lib? MP3 in 128 und vielleicht ein paar weitere Formate für Radiostreams würden doch reichen. Viele Features sind für Kinder nicht relevant und wenn es das Verhalten der Box so stark beeinflusst sollte man es weglassen. Es handelt sich um eine Kinderbox, kein Spielzeug für Daddy.
Schön wenn man alles machen kann, aber das ist dann das falsche Projekt. Wer mehr will sollte sich das Webradio von @Wolle ansehen.

sehe ich nicht so.

Das ist gerade der derzeitige Vorteil der Lib, ich kann da reinwerfen was ich will (in gewissen Grenzen) und es wird abgespielt :smiley:
Dein Vorschlag würde alle dazu zwingen ihre Dateien in Format x oder y bereitzustellen…

1 „Gefällt mir“

@compactflash Wir aktualisieren die Audio-Bibliothek nicht, damit Papa möglichst viele neue Audioformate zur Verfügung hat, sondern weil viele MP3s vorher nicht abspielbar waren und Fehler wie z.B. die Darstellung der Coverbilder behoben wurden.

Leider gibt es derzeit noch ungelöste Probleme wie teils Knackser beim Abspielen, nicht reagierendes Webinterface und zu wenig Speicher ohne PSRAM (Lolin D32 ohne Pro). Diese betreffen hauptsächlich den DEV-Zweig, der genau dafür da ist, solche Probleme zu lösen. Ist halt auch schwierig einzugrenzen da wir begrenzte Debug-Möglichkeiten haben. Trotzdem sehe ich da den Weg nach vorn & nicht zurück.

3 „Gefällt mir“

@compactflash hat Recht, die Audiobibliothek ist in den letzten Jahren gewachsen und nicht alle Funktionen werden von euch genutzt (HLS Streams, Vorbis…). Unbenutzte Routinen sind immer inaktiv sind und verschwenden keine Zeit.
Das Problem der Knackgeräusche könnte im DMA liegen. Lt. Espressif ist die DMA Größe: dma_buffer_size = dma_frame_num * slot_num * slot_bit_width / 8, das sind (512 * 16 * 16 / 8) 16KB. Bei 44,1KHz, stereo und 16 Bit/Kanal reicht das für weniger als 0,093s. Der audio.loop() muss so schnell sein, und Verzögerungen in der Größenordnung nie auftreten, damit der DMA Speicher nicht leer läuft.

3 „Gefällt mir“

@wolle Vielen Dank für die Erklärungen!

Dann dürften wir beim Abspielen von Audio in der Loop auch kein vTaskDelay aufrufen. Hatte das schon mal testweise rausgenommen & konnte in einem Grenzfall das Knacken beheben:

Negative Auswirkungen konnte ich nicht feststellen, Neopixel, Web und die anderen Funktionen laufen wie gehabt. Was meint Ihr?

Wir reden hier laut @Wolle von 93 ms. Ich würde das delay vom 1 ms da auf jeden Fall drin lassen wollen solange es möglich ist um nicht in den Animation der LEDs hängen zu bleiben oder nicht mehr auf Buttons zu reagieren…
Aber vielleicht macht es auch keinen großen Unterschied.

Wenn diese 1ms ein Problem macht müssen wir meiner Meinung nach wo anders suchen…

Wenn das wirklich ein Problem ist wäre es vielleicht besser die Audio-loop komplett zu separieren, dass die ganzen anderen checks gar nicht mehr in dem task laufen. Die könnten größeren Einfluss als die 1 ms haben…

Ich habe auf die Schnelle mal eine Funktion runtergeschrieben, die Statistiken ausgibt:

Die kann man einfach z.B. so bei Zeile 245 in AudioPlayer.cpp integrieren und ganz oben im Loop unterhalb von for (;;) integrieren, indem man das Ganze z.B. aufruft mit AudioPlayer_LoopStats(100);.

Die 100 ist die Anzahl der Loops, die pro Iteration analysiert werden. Ausgegeben werden minTime, maxTime, avgTime und loopCount.

Das sieht im Leerlauf dann z.B. so aus:

D [12935] LoopStats: min: 11 max: 23 avg: 11 loops: 1200
D [14035] LoopStats: min: 11 max: 11 avg: 11 loops: 1300
D [15135] LoopStats: min: 11 max: 11 avg: 11 loops: 1400
D [16235] LoopStats: min: 11 max: 11 avg: 11 loops: 1500

Mit Webradio (192 kBit/s via http):

D [61061] LoopStats: min: 1 max: 24 avg: 5 loops: 6300
D [61629] LoopStats: min: 1 max: 25 avg: 5 loops: 6400
D [62198] LoopStats: min: 1 max: 25 avg: 5 loops: 6500

Mit mp3 (320 kBit/s):

D [538430] LoopStats: min: 1 max: 23 avg: 6 loops: 82800
D [539131] LoopStats: min: 1 max: 23 avg: 7 loops: 82900
D [539781] LoopStats: min: 1 max: 19 avg: 6 loops: 83000
D [540464] LoopStats: min: 1 max: 26 avg: 6 loops: 83100
D [541116] LoopStats: min: 1 max: 20 avg: 6 loops: 83200

Ich hoffe mal, dass mir dabei kein Denkfehler unterlaufen ist - vielleicht aber doch :rofl:. Die Variablen kann man sicherlich auch besser benennen. Aber grundsätzlich wirkt es erstmal plausibel und wenn man verschiedenen Kram macht, dann erhöht sich die Zeit teilweise. Also bis 44 ms habe ich gesehen.

Mit min kann man leider nicht viel anfangen. Man sieht nur, dass im Leerlauf ein 10ms-Delay greift, damit der Audiotask nicht alles Andere „platt macht“.

3 „Gefällt mir“

Also was man auf jeden Fall sehen kann: Das Webinterface alleine ist kein Problem (nur das initiale Öffnen erzeugt einen Peak), aber wenn man dort den Tab „Steuerung“ öffnet, dann hat das deutlichen Impact:

Webradio ohne Webinterface:

D [890189] LoopStats: min: 1 max: 24 avg: 6 loops: 137600
D [890805] LoopStats: min: 1 max: 25 avg: 6 loops: 137700
D [891394] LoopStats: min: 1 max: 25 avg: 5 loops: 137800
D [891965] LoopStats: min: 1 max: 25 avg: 5 loops: 137900
D [892536] LoopStats: min: 1 max: 19 avg: 5 loops: 138000
D [893117] LoopStats: min: 1 max: 23 avg: 5 loops: 138100
D [893693] LoopStats: min: 1 max: 23 avg: 5 loops: 138200

Webradio mit Webinterface:

D [932157] LoopStats: min: 1 max: 25 avg: 5 loops: 144500
D [932735] LoopStats: min: 1 max: 19 avg: 5 loops: 144600
D [933322] LoopStats: min: 1 max: 19 avg: 5 loops: 144700
D [933881] LoopStats: min: 1 max: 24 avg: 5 loops: 144800
D [934450] LoopStats: min: 1 max: 21 avg: 5 loops: 144900
D [935027] LoopStats: min: 1 max: 24 avg: 5 loops: 145000

Webradio mit Webinterface, bei dem der Tab „Steuerung“ geöffnet ist:

D [981998] LoopStats: min: 1 max: 32 avg: 6 loops: 152800
D [982674] LoopStats: min: 1 max: 25 avg: 6 loops: 152900
D [983269] LoopStats: min: 1 max: 19 avg: 5 loops: 153000
D [983982] LoopStats: min: 1 max: 33 avg: 7 loops: 153100
D [984662] LoopStats: min: 1 max: 25 avg: 6 loops: 153200
D [985287] LoopStats: min: 1 max: 24 avg: 6 loops: 153300
D [985962] LoopStats: min: 1 max: 33 avg: 6 loops: 153400
D [986672] LoopStats: min: 1 max: 33 avg: 7 loops: 153500
D [987264] LoopStats: min: 1 max: 25 avg: 5 loops: 153600

Hatte es Nachbarthread schon geschrieben, es gibt seit gestern einen PR der den Port-Expander Zugriff deutlich beschleunigt. Wenn ich den Code einsetze verschwindet auch das Krackseln. Kann jetzt Zufall sein aber ist für mich plausibel weil weniger Rechenzeit auf Core 1.
@biologist weil Du die Schleife grad laufen hast, verändert sich die Loopzeit zum Guten? Einfach Port.cpp durch diesen Code ersetzen.

Hmm, ja, ich denke das macht es etwas besser. 7 ms als avg-Zeit sind eher selten.
Webradio + Tab Steuerung:

D [207226] LoopStats: min: 1 max: 19 avg: 6 loops: 33400
D [207815] LoopStats: min: 1 max: 23 avg: 5 loops: 33500
D [208504] LoopStats: min: 1 max: 31 avg: 6 loops: 33600
D [209148] LoopStats: min: 1 max: 31 avg: 6 loops: 33700
D [209704] LoopStats: min: 1 max: 22 avg: 5 loops: 33800
D [210257] LoopStats: min: 1 max: 19 avg: 5 loops: 33900
D [210854] LoopStats: min: 1 max: 23 avg: 5 loops: 34000
D [211506] LoopStats: min: 1 max: 24 avg: 6 loops: 34100
D [212158] LoopStats: min: 1 max: 25 avg: 6 loops: 34200
D [212735] LoopStats: min: 1 max: 24 avg: 5 loops: 34300

Das ist jetzt mal SD + 320 kBit/s + Tab Steuerung (hatte ich vorher nicht getestet):

D [297640] LoopStats: min: 1 max: 32 avg: 7 loops: 47500
D [298363] LoopStats: min: 1 max: 34 avg: 7 loops: 47600
D [299096] LoopStats: min: 1 max: 24 avg: 7 loops: 47700
D [299722] LoopStats: min: 1 max: 19 avg: 6 loops: 47800
D [300486] LoopStats: min: 1 max: 32 avg: 7 loops: 47900
D [301233] LoopStats: min: 1 max: 32 avg: 7 loops: 48000
D [301907] LoopStats: min: 1 max: 32 avg: 6 loops: 48100
D [302656] LoopStats: min: 1 max: 28 avg: 7 loops: 48200
D [303403] LoopStats: min: 1 max: 25 avg: 7 loops: 48300
D [304171] LoopStats: min: 1 max: 32 avg: 7 loops: 48400

Nachtrag: Hier nochmal SD + 320 kBit/s + Tab Steuerung mit bisherigem Port.cpp

D [31426] LoopStats: min: 1 max: 32 avg: 7 loops: 3400
D [32169] LoopStats: min: 1 max: 32 avg: 7 loops: 3500
D [32843] LoopStats: min: 1 max: 22 avg: 6 loops: 3600
D [33555] LoopStats: min: 1 max: 33 avg: 7 loops: 3700
D [34303] LoopStats: min: 1 max: 26 avg: 7 loops: 3800
D [34979] LoopStats: min: 1 max: 21 avg: 6 loops: 3900
D [35721] LoopStats: min: 1 max: 33 avg: 7 loops: 4000
D [36506] LoopStats: min: 1 max: 33 avg: 7 loops: 4100

Also bei SD macht’s eher nix. Bei Webradio wohl schon.
Ist aber auch mehr so semi-quantitativ der Vergleich :slight_smile:

Ich bekomme die Verbesserung beim Abspielen von SD, bei Webstreams hatte ich noch nie Kracksler (selten mal HTTP-Dropouts aber das ist ja was anderes).
Die Port-Expander Optimierung halte ich für gelungen & das könnte hier zusätzlich helfen.

2 „Gefällt mir“

Der port-expander-PR ist auf jeden Fall sinnvoll, ich glaube aber, dass wir hier an der falschen Stelle unterwegs sind und nur die Auswirkungen bekämpfen.

Um tatsächlich die Performance weiter zu verbessern würde ich folgendes vorschlagen:

  • weitere Last-reduzierung in der main-loop (langsamer Sachen z.B nur alle 10 / 100 ms ausführen)
  • einen Task nur für die Audio-Loop (so stellen wir sicher, dass nichts dazwischen funken kann oder verzögert wird)
  • die Audio-loop ins IRAM packen, so dass wir dort nicht auf den MMU Cache angewiesen sind.

Weitere mögliche Schritte:

  • Prioritäten und delays sauber aufeinander abstimmen
  • Core0 optimieren um dort z.B. die LEDs wieder hin zu packen

Gibt es hier weitere Meinungen oder Anregungen?
Natürlich braucht es entsprechende Benchmarks um den Effekt der jeweiligen Änderung beurteilen zu können, hier können wir den Code von oben vielleicht noch bisschen erweitern und mit den Task-Stats kombinieren…

2 „Gefällt mir“

Ich habe noch nie mit PE compiliert und trotzdem die Probleme

Du hast von einer nicht reagierenden Weboberfläche berichtet. Das hängt zwar Alles miteinander zusammen, trotzdem sollten wir hier die Fehler unterscheiden. Hier geht es um Audio-Aussetzer. @compactflash hast Du Aussetzer?

Leider „bröselt“/„knackst“ es wieder. Habe gerade ein update des dev vom Stand 29.12.2023 (ohne Bröseln) auf 25.01.2024 (mit Bröseln) gemacht. Habe es mit unterschiedlichen Ständen der Audio-Bibliothek ausprobiert, hat nichts geändert.

Dann habe ich Stück für Stück die neusten Commits rausgeschmissen, bis ich einen Stand ohne Bröseln erhalten habe. Der Übeltäter ist wohl

ich habe diesen teils reverted und es bröselt nicht mehr:

Hier hat also CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=0 das Bröseln verursacht. Kann man daraus weitere Schlüsse ziehen, was z.B. letztlich Ursache des Bröseln ist und wie man dem am besten Abhilfe schaffen kann?

2 „Gefällt mir“

Soweit ich es richtig verstanden habe sorgt diese Einstellung dafür ab welcher Größe der Speicher im schnelleren SPI RAM allokiert wird oder im langsameren PSRAM.
Wird mehr Speicher im externen PSRAM allokiert haben wir automatisch mehr freien Heap-Speicher. Aber evt. auch Audio-Performance-Probleme.

Mit der Audiodatei „01 Fröhliche Weihnacht (Macht euch bereit).opus“ kann ich das Audioruckeln nachvollziehen und habe einige Werte durchprobiert:

Audioruckeln bei (Aktueller Master & DEV):

CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=0
D [726] Freier Heap-Speicher nach Setup-Routine: 140444

Fehlerfreie Wiedergabe ohne Ruckeln:

CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=4096
D [705] Freier Heap-Speicher nach Setup-Routine: 108180
CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=1024
D [674] Freier Heap-Speicher nach Setup-Routine: 119696
CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=256
D [716] Freier Heap-Speicher nach Setup-Routine: 123176

Der Wert CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=256 erscheint mir am Besten geeignet zu sein, fehlerfreie Wiedergabe + maximal verfügbarer Speicher. @sfields oder auch andere, könnt Ihr das so bestätigen?

1 „Gefällt mir“

Danke für die Rückmeldung. Habe jetzt mit CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=256 ca. 40 Dateien durchgehört. Das war alles in Ordnung.
Ohne dass ich den Paramater und seine Auswirkungen verstehe, scheint das also zu reichen. Vielen Dank.