[#1] Quite OK Audio
Temat został mi podstępnie podsunięty na Discordzie... ale po kolei. Quite OK Audio to dość nowy (2023) format kompresji dźwięku. Jego założeniem było niewielkie skomplikowanie algorytmu, oraz prosta specyfikacja (mieści się na jednej stronie A4). Jakie podstawowe cechy ma ten format?
  • kompresuje strumienie 16-bitowe o dowolnym próbkowaniu i liczbie kanałów
  • jest stratny, podobnie jak np. MP3,
  • stopień kompresji jest stały i wynosi 5:1 (dla porównania MP3 @ 128 kbps ma około 10:1),
  • jakość po testach odsłuchowych mogę ocenić w okolicach powyższego MP3, może nawet minimalnie lepsza
  • dekodowanie jest w miarę szybkie, na razie moja 68020 @ 28 MHz osiąga 0,9 rzeczywistej szybkości, ale dekoder nie jest jeszcze zoptymalizowany i na razie testuję dekoder dla 68000, bez wykorzystania rozkazów 020.

Jeżeli chodzi o algorytm to jest to predykcja w dziedzinie czasu, więc można QOA umieścić pomiędzy ADPCM a FLAC, zarówno jeżeli chodzi o jakość, jak i wymagania co do mocy obliczeniowej.

Napisałem dekoder tego formatu i na początek narzędzie "QoaToAiff" konwertujące pliki QOA na nieskompresowane AIFF. Dlaczego użyłem słowa "napisałem"? Ponieważ sam dekoder jest od zera napisany w asemblerze M68k na podstawie specyfikacji, referencyjny dekoder zaś jest w C. Pewnie dałoby się go skompilować na Amidze wprost, ale ze szkodą dla szybkości.

Źródła mojego dekodera (i programu QoaToAiff) są na GitHubie, zaś skompilowany program na Aminecie.

Po dekoderze mam w planach player, na początek jako polecenie shella, a potem może coś z GUI. Nie zapomnę też o enkoderze, co prawda enkodowanie będzie sporo wolniejsze, ale do zrobienia. Rzecz jasna zawsze można enkodować na PC, tam - jak można się domyśleć - enkodowanie idzie jak przecinak i pięciominutowy kawałek kompresuje się sekundę albo i krócej.

Myślałem również o używaniu QOA do przechowywania np. audio w grach, niestety ten format pracuje tylko na 16 bitach. Można oczywiście skompresować dźwięk 8-bitowy dodając mu zera na młodszym bajcie, ale wtedy efektywna kompresja spadnie do 2,5:1. Zaletą QOA w takich zastosowaniach jest bardzo mały nagłówek (8 bajtów, identyfikator 'qoaf' i ilość sampli), którego można się zresztą pozbyć, i małe rozmiary kodu dekodera (660 bajtów jak ostatnio patrzyłem, ale jeszcze jest z czego zjechać). Stały (dla danej ilości kanałów) rozmiar ramki ułatwia też skakanie po strumieniu.

Asemblerowy kod dekodera ramki QOA będzie jeszcze podlegał optymalizacji, specjaliści od asemblera na EAB podsunęli mi szereg pomysłów, które będę benchmarkował i implementował. Dlatego QoaToAiff podaje czas pracy dekodera i szybkość w odniesieniu do czasu utworu. Oczywiście jeżeli tutaj ktoś ma pomysły na przyspieszenie kodu to chętnie poczytam.

Ostatnia aktualizacja: 13.04.2025 11:30:59 przez Krashan
20
[#2] Re: Quite OK Audio

@Krashan, post #1

Z ciekawosci zapytam, wiem ze to jest dosc swiezy format ale jak z popularnoscia, przyjal sie?

BTW. jesli da sie zrobic jako player do Deli-Trackera to bardzo bym prosil.
1
[#3] Re: Quite OK Audio

@Phibrizzo, post #2

Z ciekawosci zapytam, wiem ze to jest dosc swiezy format ale jak z popularnoscia, przyjal sie?
Jako popularny format do słuchania muzyki, nie sądzę. Przeciętny pecet spokojnie odtwarza MP3 czy AAC pojedynczymi procentami mocy procesora, z drugiej strony dla mających wysokie oczekiwania jakościowe jest FLAC, też nie będący wyzwaniem obliczeniowym dla współczesnych komputerów.
BTW. jesli da sie zrobic jako player do Deli-Trackera to bardzo bym prosil.
Nigdy nie robiłem, ale przyjrzę się.

Ostatnia aktualizacja: 13.04.2025 16:50:40 przez Krashan
2
[#4] Re: Quite OK Audio

@Phibrizzo, post #2

Jeśli cokolwiek to znaczy, to Godot Engine ostatnio dodał obsługę QOA do swoich assetów. Format pochodzi z mniej-więcej nowożytnego gamedevu i raczej tak zostanie. Nikt raczej nie będzie na pececie trzymał w tym swojej kolekcji muzyki, ale do gierek jak znalazł.

Ostatnia aktualizacja: 14.04.2025 11:38:13 przez teh_KaiN
3
[#5] Re: Quite OK Audio

@Krashan, post #1

Jutro powinna wjechać na Aminet wersja 0.2 narzędzia QoaToAiff. W niej przede wszystkim zbuforowałem operacje dyskowe, zarówno odczyt jak i zapis. Poskutkowało to zauważalnym przyspieszeniem całej konwersji. Na mojej A1200 z kartą ACA1221 i "dyskiem" w postaci karty SD w konwerterze wpiętym w standardowe IDE na płycie, operacje dyskowe zajmują około 20% całego czasu konwersji. Co ciekawe, zauważyłem, że przesadne zwiększenie buforów powoduje... spowolnienie. Nie wiem do końca dlaczego. Poprzestałem na optymalnym buforze miesczącym 8 ramek QOA, co dla plików stereo oznacza około 32 kB bufora odczytu i 160 kB zapisu.

Samo dekodowanie przyspieszyło minimalnie z 0,95 do 1,00 szybkości czasu rzeczywistego. To jeszcze trochę za mało na prawdziwe odtwarzanie, bo przecież trzeba czytać plik i kierować zdekodowane dane do Pauli. Czas na ciśnięcie asemblera, najpierw wersji 68000, a potem zobaczę co instrukcje 68020 mogą poprawić.

Przy okazji uporządkowałem raportowanie błędów konwersji, bo komunikaty błędów mimo, że były już w pliku programu, to nie były używane, za to można było otrzymać bardzo opisowy komunikat w stylu "wystąpił błąd numer 17". Teraz są już używane, a lokalizacja programu jest o krok.

Aha i dalej to całe 6536 bajtów pliku wykonywalnego, mimo, że przecież "w C++ nie da się pisać małych programów".

Co do rozmiaru, to też ciekaw jestem Waszej opinii o następującym dylemacie: cały program jest napisany w C++, ale procedura dekodująca jest w asemblerze. Jeżeli wersja tej procedury dedykowana procesorom 68020+ okaże się jakoś zauważalnie szybsza od kodu 68000 (raczej tak, ale to się okaże), to lepiej:
  • Zrobić dwie wersje programu: 000 i 020+ i wtedy również kod w C++ w tej drugiej wersji skompilować pod 020+. Niech użytkownik sobie skopiuje właściwą wersję. Oczywiście wersja 020+ odpalona na 000 nie będzie się wieszać, tylko wyświetli komunikat, że musisz awansować do amigowej burżuazji.
  • Zrobić jedną wersję. Nie kompilować kodu C++ pod 020, bo on przecież i tak nie jest krytyczny szybkościowo (owszem, nie jest). Umieścić w kodzie obie procedury dekodujące, sprawdzać procesor i automatycznie wybierać odpowiednią. Objętościowo, jedna procedura dekodująca to poniżej kilobajta, więc tyle nieużywanego na danej maszynie kodu balastowałoby sobie w pliku wykonywalnym.
4
[#6] Re: Quite OK Audio

@Krashan, post #5

Samo dekodowanie przyspieszyło minimalnie z 0,95 do 1,00 szybkości czasu rzeczywistego. To jeszcze trochę za mało na prawdziwe odtwarzanie, bo przecież trzeba czytać plik i kierować zdekodowane dane do Pauli.


To 030 50Mhz powinien już sobie z tym poradzić. Z czytaniem pliku, to jak ktoś ma 030 to pewnie i ma wystatczającą ilość Fastu, żeby cały plik zmieścić i zostaje tylko dekodowanie i kopiowanie do Chip. Nie wiem ile taki przeciętny plik może zajmować. Powiedzmy 4 minutowy? Z 10MB? Wiem, że chcesz to robić w czasie rzeczywistym, ale jeśli planujesz pisać jakiś mini player do tego, to taka opcja mogłaby się przydać. Są karty z kotrolerem IDE co wyciągają nawet 10MB/s. Przy kartach z 128MB czy 64MB te kilkanaście MB raczej by nie bolało.

Nawet przy szybkich procesorach 060, może pojawić się problem z odczytem danych z SD gdy w tle będzie się coś jeszcze kopiować. No ale to takie gdybanie bez empirycznego sprawdzenia.
[#7] Re: Quite OK Audio

@Krashan, post #5

Jesli zalezy na szybkosci dzialania to mozesz dekodowac od razu do chipu, anie do fastu jesli ma byc dla Pauli.
Wtedy zapis longwordowy ma sens, bo w zasadzie da sie wtedy pominac zapis do chipu przy dekodowaniu dla 68020.
W przypadku 68000 najszybszy raczej bedzie zapis wordowy, ewentualnie bajtowy, jesli bylyby potrzebne przesuniecia bajtow.
Wedlug mnie 2 (68000 i 68020) wersje sa lepsze niz 1 wersja. No chyba, ze wersja 68000 bedzie tylko niezauwazalnie wolniejsza niz wersja 68020, wtedy to raczej nie bedzie mialo sensu.
[#8] Re: Quite OK Audio

@Krashan, post #5

Co do rozmiaru, to też ciekaw jestem Waszej opinii o następującym dylemacie


Ja bym poszedł w drugie rozwiązanie, zwłaszcza że jak rozumiem mówimy tu różnicy w rozmiarze binarki wyrażonej w pojedynczych kilobajtach. Jedna wersja wydaje mi się prostsza zarówno z punktu widzenia programisty (utrzymanie i rozwój) , jak użytkownika (instalacja i użytkowanie).
1
[#9] Re: Quite OK Audio

@snifferman, post #6

Tak dla playera można dodać opcję prebuforowania nawet całego pliku w pamięci. QOA 44,1 kHz stereo ma przelicznik z grubsza 2 MB na minutę muzyki, więc przeciętnie będzie to od 6 do 10 MB. Dekoder może zapisywać próbki od razu do chip RAM w przypadku odtwarzania bezpośrednio Paulą (będzie oczywiście opcja AHI i wtedy lepiej bufor w faście).
1
[#10] Re: Quite OK Audio

@vojo, post #8

jak rozumiem mówimy tu różnicy w rozmiarze binarki wyrażonej w pojedynczych kilobajtach
Tak, a nawet poniżej kilobajta. Dekoder ramki QOA jest bardzo krótki.
[#11] Re: Quite OK Audio

@Krashan, post #5

Super sprawa. Fajnie byłoby to mieć jako prostą bibliotekę, żeby np. Można było nakłonić twórców AmigaAMPa albo HippoPlayera do implementacji formatu.
[#12] Re: Quite OK Audio

@alt_, post #11

Fajnie byłoby to mieć jako prostą bibliotekę
Będzie, ale najpierw optymalizacja dekodera, a potem go pomęczę data fuzzingiem. Wtedy można zapakować w bibliotekę, a nawet należy.
1
[#13] Re: Quite OK Audio

@Krashan, post #12

Burza mózgów na Discordzie i EAB dała efekt. Aktualnie na 68020@28 dekodowanie przyspieszyło o 15% z x1,00 do x1,18, przy czym to jest kod dla 68000. Okazuje się że nowe rozkazy 68020 w tym przypadku rewolucji nie robią. Napisany przeze mnie oddzielny kod dla 020 okazał się wolniejszy (x1,07), więc poszedł do kosza. Na razie to zostawiam, kiedyś może spróbuję się ponownie z tematem kodu dla 020+ modyfikując nieznacznie ten aktualny dla 68000.

Te wyniki dają jakąś szansę, że A1200 z najsłabszą kartą turbo (chyba, że ktoś nie dopłacił Jensowi do odblokowania zegara...) będzie odtwarzać 44,1 kHz stereo.
5
[#14] Re: Quite OK Audio

@Krashan, post #13

Czyli 030@50Mhz powinno sobie spokojnie poradzić?
1
[#15] Re: Quite OK Audio

@snifferman, post #14

Bez problemu.
3
[#16] Re: Quite OK Audio

@Krashan, post #13

Zakladajac, ze te moje dzisiejsze zmiany dzialaja, to na 68020 bodaj 6c szybciej powinno byc w glownej petli.
Sam kod mozna jeszcze troche skrocic, chyba o okolo 10 bajtow (calosc), ale to raczej nie bedzie miec wplywu na szybkosc, chyba ze akurat wtedy cos by sie wiecej w cache 68020 zmiescilo, ale w to watpie, bo nie wyglada mi na to, choc nie liczylem ile bajtow ma cala petla.
1
[#17] Re: Quite OK Audio

@alt_, post #11

już nawet o "extenszjonie" dla lamusów takich jak ja do Amos'a nawet nie piszę :) (plizzz)
[#18] Re: Quite OK Audio

@jimiche, post #17

już nawet o "extenszjonie" dla lamusów takich jak ja do Amos'a nawet nie piszę :) (plizzz)
Jest tylko jeden, jak to się teraz mówi, niuans. Bladego pojęcia nie mam o Amosie, o rozszerzeniach do niego już nie wspominając.
[#19] Re: Quite OK Audio

@alt_, post #11

Zastanawiałem się nad API takiej biblioteki pod kątem różnych zastosowań. Na przykład do tego, do czego ten format powstał, czyli trzymania dźwięków w grach (albo w plikach, albo w samym pliku wykonywalnym). Co prawda na Amidze najczęściej mamy dźwięki 8-bitowe, ale nawet jak weźmiemy taki dźwięk 8-bitowy, dodamy mu zera na młodszym bajcie i skompresujemy QOA, to kompresja jest 2,5:1, całkowicie poza zasięgiem kompresorów bezstratnych. A dla 8 bitów utrata jakości będzie w zasadzie zerowa. Robimy drobną modyfikację dekodera, żeby odrzucał dolny bajt i możemy wynik podać Pauli do odegrania.

Przy czym możemy kompresować audio o dowolnej częstotliwości próbkowania, algorytm jest całkowicie niewrażliwy na to, a format pozwala na zakres od 1 Hz do ponad 16 MHz (!). Możnaby nawet popakować sample w module protrackerowym z niezłym efektem objętościowym, tak myślę. Oczywiście rozpakowujemy przed graniem moda.

Kod dekodera ramki QOA zajmuje 598 bajtów. Jeżeli nie potrzebujemy obsługi ramek stereo, można 108 bajtów usunąć, czyli zostanie 480.
1
[#20] Re: Quite OK Audio

@Krashan, post #19

Dobrze by bylo jakbyt biblioteka zwracala tez pelne 16-to bitowe dane.
Np dla ktos chcialby odtwarzac na 14 bitach.
1
[#21] Re: Quite OK Audio

@Phibrizzo, post #20

Wiadomo. Będzie zestaw flag do ustalenia różnych postaci sygnału wyjściowego:
  • 8 czy 16 bitów
  • kanały stereo do dwóch osobnych buforów, czy z przeplotem
  • starszy i młodszy bajt razem, czy do oddzielnych buforów (bo tak się chyba odtwarza 14-bitowo na Pauli)
[#22] Re: Quite OK Audio

@Don_Adan, post #16

Wydaje mi sie, ze jeszcze minimum 4c dla 68020 da sie zyskac w petli, ale jak chcialem sprawdzic zrodla na GitHubie to mi jakies stare zrodla wyswietlalo z linku na EAB, a ja chcialem sprawdzic najnowsze.
[#23] Re: Quite OK Audio

@Don_Adan, post #22

jak chcialem sprawdzic zrodla na GitHubie to mi jakies stare zrodla wyswietlalo z linku na EAB

Tak jak tam pisałem, bezpośrednie linki do plików w repozytorium, w którym cały czas się coś dzieje, są słabe. Najlepiej po prostu wejść w projekt (ten link się nie zmienia) i doklikać się do kodu. Aktualnie jest tylko jeden branch w projekcie (main), co ułatwia sprawę.
[#24] Re: Quite OK Audio

@Krashan, post #23

Nie znam sie na GitHubie, ale jak tam wchodze klikajac to mam to co wczoraj, czyli:

EXT.L	d4
		ADD.L	d4,d5
		CMPI.L	#32767,d5
		BLE.S	noupper
		MOVE.W	#32767,d5
		BRA.S	clamped
noupper:	CMPI.L	#-32768,d5
		BGE.S	clamped
		MOVE.W	#-32768,d5


A to jest chyba pierwsza wersja kodu, choc podaje ze plik byl zmieniony 19 godzin temu.
Wiec albo nie potrafie znalezc ostatniej wersji kodu, albo wstawiles stary kod.
[#25] Re: Quite OK Audio

@Don_Adan, post #24

A co do kodu to da sie wywalic asr.w #4,d4 jak sie powiekszy tablice dwukrotnie, czyli z 256 do 512 bajtow.

MOVEQ   #28,d4
		AND.B	d0,d4                  ; extract encoded sample to d4
		MOVE.L	(a6,d4.w),D4         ; decode with lookup table
               move.w D4, A5
               swap D4 ; wartosc asr.w #4,D4

Na 68000 to bedzie szybsze, na 68020 byc moze tez.
Czy warto? Byc moze.

Ostatnia aktualizacja: 02.05.2025 15:32:45 przez Don_Adan
[#26] Re: Quite OK Audio

@Don_Adan, post #25

No i pomysl Thora, czyli bez zadnych skokow nie jest az taki zly, bo na 68020 to bodaj 14 cykli by bylo, o ile sie nie myle.
Wolny rejestr danych typu Dx.w (word) chyba daloby sie uzyskac stosujac jeden trick.
Ale to wszystko ma sens tylko wtedy jesli taka wersja bylaby szybsza niz ostatnia wersja z branchami.
[#27] Re: Quite OK Audio

@Don_Adan, post #24

Nie znam sie na GitHubie, ale jak tam wchodze klikajac to mam to co wczoraj
Tak bo dla mnie ostatecznym weryfikatorem są pomiary i okazało się, że ten sprytny kod bez skoków jest... wolniejszy. Jak to możliwe? Zrobiłem szybki hack referencyjnego dekodera na pececie, żeby mi zliczał ile razy robiony jest clamp. I okazuje się, że bardzo rzadko, nieraz tylko raz na kilkadziesiąt tysięcy próbek. Co to oznacza? Że trzeba optymalizować tę ścieżkę kodu, która jest wykonywana, gdy clampa nie ma. Z tą wiedzą do optymalizacji tego kawałka należy podejść inaczej.

Tak samo na pomiarach poległa optymalizacja aktualizacji wag. Pomysł, że zawsze odejmujemy, a jeżeli historia okaże się dodatnia, to dodajemy dwa razy, nie sprawdził się. Być może jest nierównowaga statystyczna wartości ujemnych i dodatnich, do sprawdzenia.

Ta wersja, która jest aktualnie na GitHubie jest najszybsza ze wszystkich proponowanych. Tzn. miałem jeszcze wersję która była minimalnie szybsza na 68000, ale z kolei minimalnie wolniejsza na 68020. Różnice w okolicach 1%, więc odrzuciłem.

Miałem też "rewolucyjną" wersję w której historię trzymałem w 2 rejestrach danych, zamiast 4 adresowych. Czyli zrobiło mi się nagle więcej wolnych rejestrów, ale cóż. Pomiary były dla niej bezwzględne, spadek szybkości o 10%.
2
[#28] Re: Quite OK Audio

@Krashan, post #27

Dla mnie wersja na GitHubie jest najwolniejsza, z tych ktore widzialem.
Byc moze to jest kwestia tego co tam jest teraz ustawione jako publiczne a co jako prywatne.
Ewentualnie trzeba byc zalogowanym na GitHuba zeby obejrzec najnowsza wersje "frame.s"
Bo o logowanie sie pyta jak wchodze z EAB.
To mozesz zrobic testy statystyczne za pomoca dodania instrukcji addq.l #1,Test1, addq.l #1, Test2 itd
i bedziesz wiedzial, co ile razy jest przecietnie wykonywany dany kod.
PC-et jest do tego niepotrzebny.
Byc moze najpierw trzeba dodac, a potem 2x odjac.
Optymalizacja statystystyczna moze byc uzyteczna w przypadku branchy, ale trzeba najpierw zrobic test wersje programu, zeby wiedziec jak czesto dany kod jest wykonywany. Najlepiej test na parunastu roznych pilkach.
[#29] Re: Quite OK Audio

@Don_Adan, post #28

Jako ciekawostkę dodam, że ten kodek jest wykorzystany w moim porcie W1peouta. Jeśli będzie łatwo zaimplementować tę amigową wersję QOA to użyję też w grze.
2
[#30] Re: Quite OK Audio

@Don_Adan, post #28

Dla mnie wersja na GitHubie jest najwolniejsza, z tych ktore widzialem.

Na jakiej maszynie zmierzone i jaki plik był dekodowany?

Powiem szczerze, że już mi się nie chce, bo te pomiary pochłaniają mnóstwo czasu, wolę się zabrać za player. Tam się i tak już nie ugra za dużo, bo decydujące są mnożenia, a ich się nie da pozbyć.
3
Na stronie www.PPA.pl, podobnie jak na wielu innych stronach internetowych, wykorzystywane są tzw. cookies (ciasteczka). Służą ona m.in. do tego, aby zalogować się na swoje konto, czy brać udział w ankietach. Ze względu na nowe regulacje prawne jesteśmy zobowiązani do poinformowania Cię o tym w wyraźniejszy niż dotychczas sposób. Dalsze korzystanie z naszej strony bez zmiany ustawień przeglądarki internetowej będzie oznaczać, że zgadzasz się na ich wykorzystywanie.
OK, rozumiem