drflac.library 1.0
==================
drflac.library is a port of dr_flac 0.13.4 by David Reid
(https://github.com/mackron/dr_libs), the compact single file FLAC
decoder, as a classic AmigaOS shared library. It decodes:
- native FLAC and Ogg-encapsulated FLAC
- 4 to 32 bits per sample, 1 to 8 channels, any sample rate
- output as 32 bit, 16 bit or float PCM
- fast seeking (seek table, binary search or brute force)
- metadata: Vorbis comments (tags), pictures (cover art),
cue sheets, seek tables
The library offers the complete dr_flac API under the original names,
so code written for dr_flac.h usually compiles unchanged against
<proto/drflac.h>. It is reentrant: any number of tasks may decode at
the same time, one decoder per task. Callers do not need a large
stack - if less than needed is free, the library switches to a
private stack for the duration of the call.
For programs that should not depend on a shared library, the archive
also contains dr_flac as a static link library (libdrflac.a) for all
five CPUs.
dr_flac version: development state 0.13.4 (commit dfe8377 of
1.9.2026). It contains all fixes made after the 0.13.3 release
(overflows in picture parsing, bounds checks, seek fixes).
Installation
------------
Copy the library for your CPU to LIBS:
CPU copy
68000 / 68010 Libs/68000/drflac.library
68020 Libs/68020/drflac.library
68030 Libs/68030/drflac.library
68040 with FPU Libs/68040/drflac.library
68060 with FPU Libs/68060/drflac.library
68LC040 / 68EC060 (no FPU) Libs/68030/drflac.library
68080 (Vampire) Libs/68020/drflac.library
for example
Copy drflac/Libs/68030/drflac.library LIBS:
"Version drflac.library FULL" shows which build is installed. A build
that does not match the CPU/FPU fails to open instead of crashing.
Only the 68060 build avoids the 64 bit form of MULS.L, which a 68060
does not implement: any other build would trap into 68060.library on
files that need 64 bit prediction.
Decoding itself is pure integer arithmetic. Floating point is only
used for float output and for binary search seeking. The 68000-68030
builds do this via mathieeesingbas, mathieeedoubbas and
mathieeedoubtrans.library (part of every Workbench 2.04+), which use
an FPU automatically if one is present. The 68040/68060 builds use the
FPU directly.
Tools
-----
C/flactest LIB=Libs/68020/drflac.library FILE=file.flac [QUIET]
Checks a file with every open and read function against the MD5
sum in the FLAC file, also 16 bit and float output and seeking,
and reports the speed. German output; runs on any CPU.
Speed
-----
Measured on a 68080 (Vampire V4, Kickstart 3.2), percent of real time,
16 bit output:
Build 16 bit 44.1 kHz 24 bit 96 kHz 16 bit 48 kHz
stereo stereo 5.1
68000 957 % 438 % 573 %
68020 1704 % 785 % 829 %
68030 1698 % 789 % 829 %
68040/FPU 1660 % 785 % 826 %
68060/FPU 1666 % 566 % 847 %
The 68080 is none of the target CPUs; the numbers only show the order
of magnitude. Real 68000-68060 CPUs have not been measured.
For programmers
---------------
SDK/include/proto/drflac.h include this one
SDK/include/libraries/drflac.h types and constants (from dr_flac.h)
SDK/include/clib/, inline/ prototypes, GCC inline calls
SDK/include/fd/, SDK/sfd/ interface description
SDK/include/dr_flac.h header for the static libdrflac.a
SDK/lib/680x0/libdrflac.a dr_flac as static link library
SDK/examples/ sources of flactest
#include <proto/exec.h>
#include <proto/drflac.h>
struct Library *DrFlacBase = OpenLibrary(DRFLACNAME, 1);
drflac *pFlac = drflac_open_file("Music:Track.flac", NULL);
while (drflac_read_pcm_frames_s16(pFlac, 4096, buffer) > 0) ...
drflac_close(pFlac);
Differences to dr_flac.h:
- The four functions with 64 bit parameters exist in the library as
drflac_amiga_read_pcm_frames_s32/_s16/_f32() (frame count as
ULONG) and drflac_amiga_seek_to_pcm_frame(pFlac, hi, lo).
<proto/drflac.h> wraps them under the original names and
signatures (define DRFLAC_NO_COMPAT_WRAPPERS to turn that off).
- drflac_open_file() uses dos.library and AmigaDOS paths; the caller
must be a process. The wchar_t (_w) functions do not exist.
- Memory comes from AllocVec() unless you pass allocation callbacks.
Free the results of drflac_open_*_and_read_*() with drflac_free().
- Callbacks (read, seek, tell, metadata, allocator) are called with
the normal C convention (arguments on the stack). Programs using
the small data model need __saveds on their callbacks.
Supported and tested with GCC (bebbo's m68k-amigaos-gcc). dr_flac
needs 64 bit integers (long long), so SAS/C 6 cannot use the headers.
Full documentation (German): README.md.
Static linking (bebbo GCC, libnix)
----------------------------------
SDK/lib/680x0/libdrflac.a contains dr_flac itself with the original
API of SDK/include/dr_flac.h (64 bit parameters, no wrappers). Use the
variant matching your -m680x0 option and link with libnix:
m68k-amigaos-gcc -m68020 -mcrt=nix20 -ISDK/include -o player \
player.c SDK/lib/68020/libdrflac.a -lm
#include <dr_flac.h> /* without DR_FLAC_IMPLEMENTATION */
Memory comes from malloc(), drflac_open_file() uses libnix stdio.
Built with the large data model (no -fbaserel) and without wchar_t
functions. There is no automatic stack switch in the static library:
opening needs about 5 KB of stack, the drflac_open_*_and_read_*()
functions about 17 KB, so give your program enough, for example
unsigned long __stack = 65536;
Big endian fix
--------------
dr_flac read the little endian fields of Ogg page headers without
byte swapping, so Ogg-FLAC never opened on big endian CPUs like the
68k (every page failed its CRC check). This port contains a fix; it
changes nothing on little endian machines.
68000/68060 speedup
-------------------
The LPC prediction needs 64 bit intermediate results for most files,
even 16 bit ones. The 68000 has no 32 bit multiply and the 68060 does
not implement the 64 bit form of MULS.L, so every filter tap called a
libgcc helper. Since the coefficients have at most 15 bits, the 68000
and 68060 builds now form each product from two MULS.W instead. The
decoded samples are bit identical; the 68020, 68030 and 68040 builds
are unchanged by this. Measured on a 68080, 16 bit stereo: 68000
build 205% -> 491% of real time, 68060 build 324% -> 535%. On a real
68060 the gain is larger still: the old code used the 64 bit MULU.L
form inside __muldi3, which the 68060 has to emulate in software.
Faster LPC prediction
---------------------
Two more patches speed up all variants (decoded samples stay bit
identical):
- 0003: dr_flac chose the 64 bit prediction path from a rough
worst case estimate, so most 16 bit files took the slow path.
It now checks the actual coefficients (like libFLAC 1.4) and uses
32 bit arithmetic whenever the result provably fits.
- 0004 (68020-68060): BFFFO for counting leading zeros in the Rice
decoder, and a small assembler loop that adds the 32 bit
prediction in a second pass over the decoded residuals.
Measured on a 68080 (Vampire V4), 68020 variant, 16 bit output:
16 bit stereo 1051% -> 1704%, 24 bit stereo 742% -> 785%, 16 bit
5.1 477% -> 829% of real time.
Tested
------
* Vampire V4 Standalone, 68080, Kickstart 3.2 (28.10.2026): all five
builds with seven test files (16 and 24 bit, 5.1, mono, embedded
cover, seek table, Ogg-FLAC), 16 checks each. Decoded samples
match the MD5 sum in the FLAC files; 16 bit and float output,
seeking, decoding from memory, own callbacks and allocators and
error cases are checked as well
* the automatic stack switch with only 4 KB of task stack, on the
same machine with an earlier build (5.10.2026)
* static libdrflac.a: all five builds with three files (seek table,
24 bit, Ogg-FLAC)
* 35 generated files (noise and near full scale signals, LPC order
up to 32) with the 68000, 68020 and 68060 builds; on a PC they
decode bit identically to unmodified dr_flac
Not yet tested on real 68000-68060 hardware. Reports welcome.
History
-------
1.0 (28.10.2026) first release
License
-------
dr_flac is public domain (Unlicense) or MIT No Attribution, at your
choice; so are drflac.library and the Amiga specific files. See
LICENSE. README.md has the details: API differences, stack use, how
the library was built and tested, and the changes made to dr_flac.
|