Commit graph

18 commits

Author SHA1 Message Date
kleines Filmröllchen
264cc76ab4 LibAudio: Move audio stream buffering into the loader
Before, some loader plugins implemented their own buffering (FLAC&MP3),
some didn't require any (WAV), and some didn't buffer at all (QOA). This
meant that in practice, while you could load arbitrary amounts of
samples from some loader plugins, you couldn't do that with some others.
Also, it was ill-defined how many samples you would actually get back
from a get_more_samples call.

This commit fixes that by introducing a layer of abstraction between the
loader and its plugins (because that's the whole point of having the
extra class!). The plugins now only implement a load_chunks() function,
which is much simpler to implement and allows plugins to play fast and
loose with what they actually return. Basically, they can return many
chunks of samples, where one chunk is simply a convenient block of
samples to load. In fact, some loaders such as FLAC and QOA have
separate internal functions for loading exactly one chunk. The loaders
*should* load as many chunks as necessary for the sample count to be
reached or surpassed (the latter simplifies loading loops in the
implementations, since you don't need to know how large your next chunk
is going to be; a problem for e.g. FLAC). If a plugin has no problems
returning data of arbitrary size (currently WAV), it can return a single
chunk that exactly (or roughly) matches the requested sample count. If a
plugin is at the stream end, it can also return less samples than was
requested! The loader can handle all of these cases and may call into
load_chunk multiple times. If the plugin returns an empty chunk list (or
only empty chunks; again, they can play fast and loose), the loader
takes that as a stream end signal. Otherwise, the loader will always
return exactly as many samples as the user requested. Buffering is
handled by the loader, allowing any underlying plugin to deal with any
weird sample count requirement the user throws at it (looking at you,
SoundPlayer!).

This (not accidentally!) makes QOA work in SoundPlayer.
2023-03-13 13:25:42 +01:00
kleines Filmröllchen
0b421a3764 LibAudio: Implement the Quite Okay Audio format
Brought to you by the inventor of QOI, QOA is a lossy audio codec that
is, as the name says, quite okay in compressing audio data reasonably
well without frequency transformation, mostly introducing some white
noise in the background. This implementation of QOA is fully compatible
with the qoa.h reference implementation as of 2023-02-25. Note that
there may be changes to the QOA format before a specification is
finalized, and there is currently no information on when that will
happen and which changes will be made.

This implementation of QOA can handle varying sample rate and varying
channel count files. The reference implementation does not produce these
files and cannot handle them, so their implementation is untested.

The QOA loader is capable of seeking in constant-bitrate streams.

QOA links:
https://phoboslab.org/log/2023/02/qoa-time-domain-audio-compression
https://github.com/phoboslab/qoa
2023-03-10 04:07:14 -07:00
Tim Schumacher
8464da1439 AK: Move Stream and SeekableStream from LibCore
`Stream` will be qualified as `AK::Stream` until we remove the
`Core::Stream` namespace. `IODevice` now reuses the `SeekMode` that is
defined by `SeekableStream`, since defining its own would require us to
qualify it with `AK::SeekMode` everywhere.
2023-01-29 19:16:44 -07:00
Linus Groh
3a9225608a LibAudio: Remove try_ prefix from fallible LoaderPlugin methods 2023-01-28 22:41:36 +01:00
Linus Groh
ee0297d9ec LibAudio: Remove try_ prefix from fallible LoaderPlugin methods 2023-01-28 22:41:36 +01:00
Tim Schumacher
312a41fddf LibAudio: Use NonnullOwnPtr to keep track of LoaderPlugin streams
This doesn't have any immediate uses, but this adapts the code a bit
more to `Core::Stream` conventions (as most functions there use
NonnullOwnPtr to handle streams) and it makes it a bit clearer that this
pointer isn't actually supposed to be null. In fact, MP3LoaderPlugin
and FlacLoaderPlugin apparently forgot to check for that completely
before starting to decode data.
2022-12-05 17:49:47 +01:00
Tim Schumacher
c57be0f474 LibAudio: Switch LoaderPlugin to a more traditional constructor pattern
This now prepares all the needed (fallible) components before actually
constructing a LoaderPlugin object, so we are no longer filling them in
at an arbitrary later point in time.
2022-12-05 17:49:47 +01:00
Tim Schumacher
3cf93d0dd2 LibAudio: Stop passing Bytes by reference
`Bytes` is very slim, so the memory and/or performance gains from
passing it by reference isn't that big, and it passing it by value is
more compatible with xvalues, which is handy for things like
`::try_create(buffer.bytes())`.
2022-12-05 17:49:47 +01:00
kleines Filmröllchen
f54462c424 LibAudio: Revert to using buffered file reading
This was slowing down FLACLoader below realtime. The real solution is
still to use mapped files but that has to wait until a larger refactor.
2022-11-13 19:18:00 +00:00
Lucas CHOLLET
c837a1a8de LibAudio: Factorize stream initialisation to base class LoaderPlugin
All actual plugins follow the same logic to initialize their stream,
this commit factorizes all of this to their base class: `LoaderPlugin`.
2022-10-14 23:11:23 +02:00
Lucas CHOLLET
754b129f4a LibAudio: Allow the MP3 plugin to be constructed from a byte buffer 2022-10-14 23:11:23 +02:00
Arne Elster
7223b593cb LibAudio: Add basic MP3 Decoder
This is a basic MPEG-1 layer 3 audio decoder. It supports all
sample rates and stereo modes except for freeformat.
2022-02-26 16:01:26 +01:00
kleines Filmröllchen
8a92573732 LibAudio: Convert FlacLoader to use new Core::Stream APIs :^)
For this change to work "easily", Loader can't take const ByteBuffer's
anymore, which is fine for now.
2022-01-22 01:13:42 +03:30
kleines Filmröllchen
96d02a3e75 LibAudio: New error propagation API in Loader and Buffer
Previously, a libc-like out-of-line error information was used in the
loader and its plugins. Now, all functions that may fail to do their job
return some sort of Result. The universally-used error type ist the new
LoaderError, which can contain information about the general error
category (such as file format, I/O, unimplemented features), an error
description, and location information, such as file index or sample
index.

Additionally, the loader plugins try to do as little work as possible in
their constructors. Right after being constructed, a user should call
initialize() and check the errors returned from there. (This is done
transparently by Loader itself.) If a constructor caused an error, the
call to initialize should check and return it immediately.

This opportunity was used to rework a lot of the internal error
propagation in both loader classes, especially FlacLoader. Therefore, a
couple of other refactorings may have sneaked in as well.

The adoption of LibAudio users is minimal. Piano's adoption is not
important, as the code will receive major refactoring in the near future
anyways. SoundPlayer's adoption is also less important, as changes to
refactor it are in the works as well. aplay's adoption is the best and
may serve as an example for other users. It also includes new buffering
behavior.

Buffer also gets some attention, making it OOM-safe and thereby also
propagating its errors to the user.
2021-11-28 13:33:51 -08:00
Andreas Kling
8b1108e485 Everywhere: Pass AK::StringView by value 2021-11-11 01:27:46 +01:00
kleines Filmröllchen
22d7e57955 LibAudio: Implement a basic FLAC loader
This commit adds a loader for the FLAC audio codec, the Free Lossless
Audio codec by the Xiph.Org foundation. LibAudio will automatically
read and parse FLAC files, so users do not need to adjust.

This implementation is bare-bones and needs to be improved upon.
There are many bugs, verbatim subframes and any kind of seeking is
not supported. However, stereo files exported by libavcodec on
highest compression setting seem to work well.
2021-06-25 20:48:14 +04:30
Brian Gianforcaro
1682f0b760 Everything: Move to SPDX license identifiers in all files.
SPDX License Identifiers are a more compact / standardized
way of representing file license information.

See: https://spdx.dev/resources/use/#identifiers

This was done with the `ambr` search and replace tool.

 ambr --no-parent-ignore --key-from-file --rep-from-file key.txt rep.txt *
2021-04-22 11:22:27 +02:00
Andreas Kling
13d7c09125 Libraries: Move to Userland/Libraries/ 2021-01-12 12:17:46 +01:00
Renamed from Libraries/LibAudio/Loader.cpp (Browse further)