Moin. Ich habe mal eine Frage zur Geschwindigkeit eines ESP32: Wenn man mehrere Audio-Streams in eine Datei auf einer SD-Karte packen möchte, was schafft der ESP32 an Daten zu lesen, zu splitten und dadurch einen dieser Streams über sein I2S Audio-Interface auszugeben? Angenommen, man nimmt zwei Streams mit 48kHz 16bit Stereo, dann kommt einer davon auf 48.000 x 2bytes (16bit) x 2 Kanäle = 192kbyte/s. Mal zwei Streams sind das schon 384kbyte/s. Wenn man die Streams in Frames zu sagen wir 25ms aufteilt, sind das 4,8kbyte Audio-Daten pro Stream (zwei Streams 9,6kbyte), aber man muss pro Sekunde 40 dieser Frames an das I2S-Interface schicken. Bevor ich das nun ausprobiere und am Ende enttäuscht feststelle, daß es nicht geht, frage ich lieber mal nach: Ist der ESP32 schnell genug, 40mal pro Sekunde 9,6kbyte aus einer Datei von einer SD-Karte zu lesen, daraus 4,8kbyte Daten zu extrahieren und diese an das I2S-Interface zu schicken? Es wäre schön, wenn jemand da Erfahrungswerte aus der Praxis hat. Alle Bibliotheken, die ich dazu auf die Schnelle gefunden habe, benutzen irgendwelche Subroutinen, die das Lesen der Daten von der SD-Karte und die Ausgabe auf dem I2C-Interface alles alleine machen. Das ist natürlich super simpel, bietet aber nicht die Möglichkeit, eigene Datenformate zu nutzen und schleust alle Daten wenn man das so sagen möchte, an der CPU vorbei. Ich würde das gerne mit der Arduino-Plattform probieren, gibts da entsprechende Funktionen, um die DMA-Fähigkeit des I2C-Interfaces zu nutzen bzw. einen Audio-Puffer unterbrechungsfrei aufzufüllen, so daß es zu keinen Störgeräuschen beim Audio kommt? Etwas ähnliches hatte ich vor langer Zeit schon mit dem 486er bzw. Pentium und einer Soundblaster-Karte probiert, einen eigenen WAV-Player zu basteln. Da waren die Frames am Ende glaube ich 64kbyte lang und die Soundkarte hat sich die Daten per DMA geholt, aber der Rechner war trotz Assembler nicht schnell genug, am Ende eines DMA-Transfers neue Daten in den Puffer zu schreiben und einen neuen DMA-Transfer zu starten. Das führte zu Störgeräuschen durch die kurze Pause und man musste den DMA-Transfer so konfigurieren, daß er automatisch wiederholt wird und dann immer eine Hälfte des Puffers updaten während die andere abgespielt wurde. Keine Ahnung, ob der ESP32 was ähnliches kann, so daß die Daten unterbrechungsfrei zum I2S-Interface kommen, obwohl sie in Stücken in den Puffer kopiert werden.
Grundsätzlich, also mit ESP-IDF, ist das gar kein Problem. Mit Arduino kenne ich mich nicht aus, aber da muss man halt darauf achten, dass man keine der doch häufiger vorkommenden schlechten Bibliotheken benutzt. Du hast aber nicht geschrieben, ob die Hardware bereits vorgegeben ist oder noch ausgewählt werden kannst. Da gibt es dann natürlich auch noch Stellschrauben: - Ist der ursprüngliche ESP32 gemeint oder kann es auch ein ESP32-S3 oder ESP32-P4 sein? - Wird PSRAM als Puffer genutzt? - Falls ja, mit welcher Taktfrequenz läuft der PSRAM (bei P4 bis zu 200MHz)? - Wie ist die SD-Karte angeschlossen (SPI, 1Bit, 4Bit) Ich denke, selbst im ungünstigsten Fall sollte das reichen, aber wenn Du noch die Hardware auswählen kannst, dann musst Du Dir sowieso keine Gedanken machen.
Der potentielle Flaschenhals dürfte die SD-Karte sein. Zwar versprechen deren Hersteller Wunderdinge in Sachen Geschwindigkeit, die harte Realität sieht aber meist sehr anders aus - und hier kommt die Anbindung der SD-Karte nochmal ganz deutlich zum Tragen.
Bei der Auswahl der Hardware bin ich absolut flexibel, das Projekt wenn man es überhaupt schon so nennen will, ist noch im Ideen-Stadium. Ich hatte nur den ESP32 im Auge, weil ich damit (und mit der Arduino-Plattform) ein gutes Benutzer-Interface hinkriege (WLAN). Also es darf ruhig eine leistungsstarke ESP32-Variante sein, da nehme ich gerne Vorschläge an, sollte aber von der Arduino-Plattform unterstützt werden. So wie ich das mitbekommen habe, gibts da bei neuen Modellen gerne mal Probleme. > - Ist der ursprüngliche ESP32 gemeint oder kann es auch > ein ESP32-S3 oder ESP32-P4 sein? Wenn der -S3 oder -P4 von der Arduino-Plattform unterstützt wird und man das Modul vielleicht sogar bastelfreundlich wie die ursprünglichen ESP32 (-WROOM) bekommt, dann darf es auch gerne ein -S3 oder -P4 sein. Ich werde mal schauen, was diese beiden Varianten besser können als der ursprüngliche ESP32. Edit: Gerade gelesen, der -P4 hat kein WiFi mehr, damit ist der eigentlich raus. > - Wird PSRAM als Puffer genutzt? Meinst Du nicht, daß das interne RAM des ESP32 ausreicht wenn man mit 25ms langen Audio-Frames arbeitet? Oder ist das zu langsam? > - Falls ja, mit welcher Taktfrequenz läuft der PSRAM > (bei P4 bis zu 200MHz)? Wenn nötig, dann nehme ich 200Mhz - aber müsste dann irgendwie bereits im ESP32-Modul verbaut sein, weil 200Mhz krieg ich mit einer Bastelplatine bestimmt nicht so locker zusammen. > - Wie ist die SD-Karte angeschlossen (SPI, 1Bit, 4Bit) Gerne 4 Bit, wenn das das WLAN-Modul, das I2S-Interface und ein SPI/UART-Interface nicht behindert.
:
Bearbeitet durch User
Ich hab das mal schnell mit dem Arduino-Zeugs für Dich ausprobiert: Als Richtwert für eine untere Grenze habe ich ein altes ESP32 Modul genommen und die SD-Karte mit SPI angesteuert. Die SD-Karte ist eine SanDisk 32GB SDHC(UHS-I 10). Formatiert war sie mit FAT32. Damit komme ich auf 432kB/s. Das liegt schon über den von Dir geforderten 375kB/s. Mit dem SDIO 4Bit Modus kommst Du dann auf ein Vielfaches.
Was möchtest Du erreichen? Wieviel Musik möchtest Du speichern?
:
Bearbeitet durch User
@Richie Danke Dir für Deine Mühe, das stimmt doch schon mal zuversichtlich. Also die grundlegende Idee ist, in einer WAV-ähnlichen Datei sowas wie Subchannel-Daten abzulegen, die dann synchron mit einem Audio-Inhalt zur Verfügung stehen, oder eben auch zwei (oder mehrere) Audio-Streams. So eine Datei zu basteln ist eigentlich trivial, vor allem wenn man eine konstante Frame-Länge benutzt. Damit kann man diese Datei aber nicht mehr einfach so an Standard-Bibliotheken übergeben und dem ESP32 einfach sagen "Spiel mal diese Datei von der SD-Karte ab", sondern man muss die Daten einlesen, die Datenströme splitten und dann den Audio-Inhalt so über das I2S-Interface ausgeben, daß dabei der Audio-Puffer nicht leerläuft und es keine Störgeräusche gibt. Im Moment denke ich am meisten über den Standard-ESP32 nach, also die ursprüngliche Variante. Da bekäme man zwei 240Mhz-Cores, man könnte den zeitkritischen Programmteil (der die Daten in Echtzeit lesen, verarbeiten und das I2S füttern muss) auf einem Core laufen lassen und das WLAN-User-Interface-Gedöns auf dem anderen Core. Leider weiß ich im Moment noch nicht viel über das I2S-Interfache, also was es kann... wie lang der Audio-Puffer sein kann und ob man den aktuellen Füllstand des Audio-Puffers irgendwo her ermitteln kann. Eine Alternative wäre evtl. - falls man zwei Dateien von der SD-Karte gleichzeitig lesen kann - die Streams in verschiedenen Dateien abzulegen. Wenn die Standard-Audio-Bibliotheken in schneller Folge und ausreichend hoher Auflösung die aktuelle Spielzeit übermitteln können, dann könnte man die Subchannel-Daten aus einer anderen Datei lesen und über die Spielzeit synchronisieren. Nachteil: mehrere Dateien, Vorteil: man braucht sich praktisch nicht um den zeitkritischen Audio-Kram zu kümmern.
Mit die SD_MMC library (1bit) und eine standard ESP32 geht bei mir noch etwas schneller : SD_MMC Read speed= 679 ms/MB Write speed= 1414 ms/MB s Daneben ist die richtige audio library auch wichtig, shau mal hier : https://github.com/pschatzmann/arduino-audio-tools Auch hilfsreich (yt Andreas Spiess) : https://www.youtube.com/watch?v=a936wNgtcRA
Danke für die Tipps! Die Youtube-Videos habe ich durch, die waren mehr oder weniger der Auslöser für die "Idee". Leider findet man immer nur Beispiele, die ausschließlich die Libs, aber nicht die Schnittstellen direkt verwenden, so daß man z.B. gar nicht ohne weiteres herausbekommt, wie man das I2S-Interface des ESP32 unterbrechungsfrei mit WAV-Daten füttern muss, also ob das einen Puffer hat und wie groß der ist. Das über was ich da nachgedacht habe war etwas mehr als I2S_Play(sd_card_file);forget_about_the_rest;
:
Bearbeitet durch User
Ben B. schrieb: > Alle Bibliotheken, die ich dazu auf die Schnelle gefunden habe, war da earlephilhower/ESP8266Audio mit darunter?
Hier könntest die relevanten Teile rausnehmen: https://github.com/schreibfaul1/ESP32-audioI2S 90% oder mehr könnte für deinen Zeck aber weg. Wenn ich mich recht erinnere: Puffergröße und Anzahl kann in Grenzen im Code definiert werden. Wenn ein Puffer voll ist geht der an die I2s-Einheit und wird per DMA abgespielt. Gesamtpuffergröße halt so wählen, dass es bei Latenzen der SD Karte nicht stockt. Aber auch nicht zu viel, weil du sonst nicht schnell reagieren kannst falls du weiterschalten willst oder ausfaden etc. Was in den Puffer geschrieben ist kann nicht geändert werden. 2 Puffer sind eher zu wenig. Erst wenn ein Puffer komplett voll ist kann er abgespielt werden und erst wenn ein Puffer komplett geleert ist kannst du wieder was reinschreiben: Puffer 1 wird abgespielt, noch 1 Sample. Puffer 2 ist voll. Dann kannst nichts nachfüllen. Also nächster Task. Dann kommst frühestens nach 1 ms wieder in den Nachfülltask und der muss den dann freien Puffer 1 vollmachen bevor Puffer 2 zu Ende gespielt ist. Da laufen 4 oder 8 Puffer gleichmäßiger.
Ben B. schrieb: > Danke für die Tipps! > > Die Youtube-Videos habe ich durch, die waren mehr oder weniger der > Auslöser für die "Idee". Leider findet man immer nur Beispiele, die > ausschließlich die Libs, aber nicht die Schnittstellen direkt verwenden, > so daß man z.B. gar nicht ohne weiteres herausbekommt, wie man das > I2S-Interface des ESP32 unterbrechungsfrei mit WAV-Daten füttern muss, > also ob das einen Puffer hat und wie groß der ist. Das über was ich da > nachgedacht habe war etwas mehr > als I2S_Play(sd_card_file);forget_about_the_rest; Ich habe vor vielen Jahren auf ESP32-Basis einen Player für meine Tochter gebaut. Die Hauptfunktion war das Abspielen von MP3-Dateien als Dateien und per Internet-Stream. Genutzt habe ich das esp-idf. Ich habe allerdings keine SD-Karten verwendet, sondern USB-Sticks (davon hatte ich aus einer Werbeaktion noch knapp 100 Stück übrig...). Angeschlossen habe ich das über den ch372-Chip mit seiner kruden API, da der ESP32 im Gegensatz zum S2 oder S3 heute keine USB-Schnittstelle hat. Das Ganze funktioniert aber bis heute einwanfrei. Die Dateien oder Streams werden beim Abspielen vom USB-Stick eingelesen, per Helix-Decoder dekodiert, in einen Ringpuffer geschrieben und dann per i2s_write an die esp-idf API übergeben, die das dann per DMA ausgibt. Das Ganze findet in einer Schleife statt. i2s_write blockiert den Task, bis wieder Platz im DMA-Puffer ist. Die API hat sich allerdings geändert, die 5er gab es damals noch nicht. Der Ringpuffer ist deutlich größer als die an die API übergebenen Datenhäppchen, um den "Jitter" beim Einlesen vom USB-Stick abzufangen. Das Ganze funktioniert problemlos, es ist auch noch genug Zeit übrig, um z.B. die Lautstärke der eingelesenen Daten zu verändern oder anderes damit zu machen. Ausgegeben wird das dann über einen PCM1502A. Es reicht übrigens ein Puffer.
Eigentlich müsste das ESP32-A1S AudioKit für diese Anwendung passen. Es hat ja den DAC und den SD-Kartenslot gleich eingebaut. Ich habe mal vor ein paar Jahren eines gekauft aber zugegebenermaßen nie zum laufen bekommen. Ich habe alle möglichen Methoden ausprobiert, aber ein Ton kam nie aus dem Lautsprecher. Ich vermute mein Board hat einfach einen Defekt.
Christoph M. schrieb: > Eigentlich müsste das ESP32-A1S AudioKit für diese Anwendung passen. Ich hab' auf genauso einem Ding "Squeezelite" installiert. https://github.com/sle118/squeezelite-esp32 Läuft; man muss nur darauf achten, daß man, wenn man kein "LMS" verwendet, das Autoreset-Feature deaktiviert, siehe Kommentar am Ende von https://github.com/sle118/squeezelite-esp32#additional-configuration-notes-from-the-web-ui Ich nutze das Ding als Airplay-Empfänger.
Harald K. schrieb: > Läuft; man muss nur darauf achten, daß man, wenn man kein "LMS" Bei mir scheitert es an der grundlegenden Initialisierung des I2C Codecs. Scheinbar hat sich beim ESP32-AS1 die interne Pinbelegung des I2C-Interface zum Codec über die verschiedenen Modulversionen geändert. Leider findet aber der I2C Scanner (siehe Code) mit allen gezeigten Pinvarianten die ich in verschiedenen Foren und Dokumenten gefunden habe, kein I2C Device.
Ich glaube das Thema war I2S‑DMA Ringbuffer, nicht I2C.
Christoph M. schrieb: > Bei mir scheitert es an der grundlegenden Initialisierung des I2C > Codecs. I2C? Falsche Fährte; Du willst I2S nutzen. Das sind zwei komplett unterschiedliche Schnittstellen; I2C ist für Audioausgabe viel zu langsam.
Harald K. schrieb: > Christoph M. schrieb: >> Bei mir scheitert es an der grundlegenden Initialisierung des I2C >> Codecs. > > I2C? Falsche Fährte; Du willst I2S nutzen. > > Das sind zwei komplett unterschiedliche Schnittstellen; I2C ist für > Audioausgabe viel zu langsam. Was meinst Du wohl, wie der DAC/Codec konfiguriert wird? Sicher nicht über I2S... Natürlich läuft das über I2C. Also: Falsche Fährte; Du willst I2C nutzen.
Harald K. schrieb: > I2C? Falsche Fährte; Du willst I2S nutzen. Ja. Aber erst will man den Codec über I2C konfigurieren. edit: Ich sehe gerade, Richie war schneller.
:
Bearbeitet durch User
Will man das? Wohl nur für externe Hardware die über I2C konfigurierbar ist. Für den PCM1502A sicher nicht.
:
Bearbeitet durch User
Richie schrieb: > Was meinst Du wohl, wie der DAC/Codec konfiguriert wird? > Sicher nicht über I2S... Die I2S-Dinge, die ich bislang verwendet habe, die habe ich nicht via I2C konfiguriert, sondern mit ein paar Jumpern bzw. Lötbrücken. Ich gebe zu, mit dem auf dem Audiokit hab' ich mich nicht weiter beschäftigt; Squeezelite funktioniert, ohne daß ich mir da irgendwas ansehen musste. Da mich Audioeingänge auch nicht interessiert haben, habe ich nur einen I2S-DAC genutzt, wie z.B. PCM1502, den es günstig auf netten "breakout boards" gibt. https://www.adafruit.com/product/6250
Alexander schrieb: > Will man das? Wohl nur für externe Hardware die über I2C konfigurierbar > ist. Für den PCM1502A sicher nicht. Um den ging es hier aber nicht. Sondern um per I2C konfigurierbare Codecs...
Eigentlich ging es um ein eigenes kleines Containerformat das mehrere Audio‑Streams enthält die über DMA laufen sollen. Das können auch Daten-Streams sein. Wo liest Du da irgendwo was von Codecs?
Alexander schrieb: > Eigentlich ging es um ein eigenes kleines Containerformat das mehrere > Audio‑Streams enthält die über DMA laufen sollen. Gleich im ersten Post steht: >Ich habe mal eine Frage zur Geschwindigkeit eines ESP32: Und als Hardware dafür nimmt man am besten ein Board, das dafür gemacht ist und alle Komponenten integriert hat. Dafür sollte das ESP32-A1S Board mit integriertem I2C konfigurierbarem Audio-Codec und auf dem Board befindlichem SD-Kartenslot ziemlich geeignet sein.
Dafür reicht schon ein nackter ESP32 mit seinem DAC.
Alexander schrieb: > Dafür reicht schon ein nackter ESP32 mit seinem DAC. Klingt halt bescheiden. Deswegen nimmt man einen externen DAC. Ein "codec" ist in diesem Kontext ein Stück Hardware, nämlich die Kombination aus einem DAC und einem ADC, der für Audiozwecke via I2S angebunden wird.
Zur Klangqualität kann ich nichts sagen, hatte nur einen Transistor mit PC Speaker dran. Aus Gründen der Lautstärke hab ich dann so einen Mono Verstärker angeschlossen. Hab noch welche da gegen Porto. Alexander schrieb: > https://www.aliexpress.com/item/1005001981842370.html
Alexander schrieb: > Zur Klangqualität kann ich nichts sagen, hatte nur einen Transistor mit > PC Speaker dran. Mir ging es um Musik, nicht irgendwelches Gequäke.
Für audiophile Anwendungsfälle wäre ein ESP32 wohl meine letzte Wahl.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.

