Ktoś korzystał z biblioteki libmad?

Eksperymentuję właśnie z biblioteką z programowym dekodowaniem MP3 za pomocą biblioteki popularnej libmad. W tej chwili testy wykonuję na Raspberry Pi Pico, ale docelowo będę ją także próbował odpalić na STM32.

Z pozoru korzystanie z biblioteki nie jest skomplikowane. Wystarczy wywołać funkcję mad_decoder_init() z kilkoma parametrami - m.in. adresem struktury przechowującej stan dekodera oraz wskaźnikami do funkcji, które będą wywoływane w określonych sytuacjach (pobieranie danych, obsługa błędu, zapis zdekodowanych danych audio PCM itp.). Następnie należy wywołać funkcję mad_decoder_run(), która będzie w odpowiednich chwilach wywoływała podane funkcje.

Każda z funkcji zwraca enuma określającego co dekoder ma robić dalej: kontynuować pracę (MAD_FLOW_CONTINUE), zignorować ramkę (MAD_FLOW_IGNORE), przerwać dekodowanie i zwrócić błąd (MAD_FLOW_BREAK) lub zakończyć pracę (MAD_FLOW_STOP).

Przykład wykorzystania biblioteki można zobaczyć tutaj:

formatting link
W powyższym przykładzie cały plik jest dekodownay natychmiast. Ze względu na niewielką ilość pamięci w MCU oczywiście nie mogę sobie na to pozwolić. Jedynym rozwiązaniem jest dekodowanie kawałka pliku w momencie, gdy w buforze PCM zaczyna brakować miejsca.

Funkcje pobierające wyglądają u mnie następująco:

formatting link
Jak widać w funkcji pobierającej dane postanowiłem wykorzystać wskaźniki przekazywane do niej przez wskaźnik do struktury *stream (bufend i next_frame). Za ich pomocą dane odpowiadające kolejnej ramce przenosiłem na początek bufora, a resztę miejsca wypełniałem kolejnym danymi z pliku.

Wyszedłem z założeni, że jeśli funkcję mad_output_callback() zakończę zwracając MAD_FLOW_STOP, to przy kolejnym wywołaniu mad_decoder_run() biblioteka wznowi pracę tam gdzie skończyła i kolejne wywołanie mad_input_callback() otrzyma wskaźnik do kolejnej ranki.

Niestety, ten prosty plan rozbił się o fakt, że te dane są tracone.

Ktoś z was orientuje się może jak wstrzymać dekodowanie do momentu kiedy kolejna porcja danych PCM będzie potrzebna?

Reply to
Atlantis
Loading thread data ...

Ok, odpowiadam sam sobie gdyby ktoś kiedyś miał podobny problem. Udało mi się dojść do tego, że biblioteka ma ma dwa API: niskopoziomowe i wysokopoziomowe. To pierwsze teoretycznie pozwala na obsłużenie procesu dekodowania serią wywołań w pętli głównej, ale w tym celu trzeba by sobie cały to proces napisać, używając niskopoziomowych funkcji wedle swoich potrzeb. Znacznie prostsze w obsłudze jest API wysokopoziomowe, gdzie właściwie trzeba tylko przygotować kilka funkcji callback - obsługa banalna, ale niestety - to rozwiązanie było pisane z myślą o pracy w systemie z wielozadaniowością, więc jego odpalenie bezpośrednio na krzemie nie pozwoli na wykonywanie innych operacji.

Najprostsze (choć nie najbardziej optymalne) rozwiązanie to zastosowanie FreeRTOS i przeznaczenie osobnego tasku na dekodowanie MP3. Tak właśnie ostatecznie zrobiłem.

Reply to
Atlantis

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.