summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibAudio/FlacLoader.h
AgeCommit message (Collapse)Author
2023-03-19LibAudio: Use specified bit depth directlykleines Filmröllchen
We report a rounded up PCM sample format to the outside, but use the exact bit depth as specified in header and frames. This makes the three FLAC spec tests with a a bit depth of 20 pass.
2023-03-19LibAudio: Improve FLAC seekingkleines Filmröllchen
"Improve" is an understatement, since this commit makes all FLAC files seek without errors, mostly with high accuracy, and partially even fast: - A new generic seek table type is introduced, which keeps an always-sorted list of seek points, which allows it to use binary search and fast insertion. - Automatic seek points are inserted according to two heuristics (distance between seek points and minimum seek precision), which not only builds a seek table for already-played sections of the file, but improves seek precision even for files with an existing seek table. - Manual seeking by skipping frames works properly now and is still used as a last resort.
2023-03-13LibAudio: Detect and read FLAC metadatakleines Filmröllchen
FLAC uses the very simple vorbis comment metadata format, which we can now read most standard and non-standard fields from.
2023-03-13LibAudio: Move audio stream buffering into the loaderkleines Filmröllchen
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-02-13LibCore: Remove `Stream.h`Tim Schumacher
2023-01-29AK: Move memory streams from `LibCore`Tim Schumacher
2023-01-29AK: Move bit streams from `LibCore`Tim Schumacher
2023-01-29AK: Move `Stream` and `SeekableStream` from `LibCore`Tim Schumacher
`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-28LibAudio: Remove `try_` prefix from fallible LoaderPlugin methodsLinus Groh
2023-01-10LibCore: Rename InputBitStream.h to BitStream.hTim Schumacher
We won't just be defining readable streams here from now on, but also writable streams.
2022-12-06AK+Everywhere: Rename String to DeprecatedStringLinus Groh
We have a new, improved string type coming up in AK (OOM aware, no null state), and while it's going to use UTF-8, the name UTF8String is a mouthful - so let's free up the String name by renaming the existing class. Making the old one have an annoying name will hopefully also help with quick adoption :^)
2022-12-05LibAudio: Use `NonnullOwnPtr` to keep track of LoaderPlugin streamsTim Schumacher
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-05LibAudio: Switch LoaderPlugin to a more traditional constructor patternTim Schumacher
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-11-13LibAudio: Make `FlacLoaderPlugin` destructor virtualLucas CHOLLET
2022-11-13LibAudio: Parse the picture metadata blockLucas CHOLLET
2022-10-14LibAudio: Factorize stream initialisation to base class `LoaderPlugin`Lucas CHOLLET
All actual plugins follow the same logic to initialize their stream, this commit factorizes all of this to their base class: `LoaderPlugin`.
2022-10-14LibAudio: Remove the last occurrence of `Core::File` in the Flac pluginLucas CHOLLET
The design is deeply inspired from what is done in the Wav plugin.
2022-10-14LibAudio: Get rid of unused method `Loader::file()`Lucas CHOLLET
`aplay` and two files of `SoundPlayer` were relying on the include of `LibCore/File.h` by `Loader.h`.
2022-06-23LibAudio: Add spec comments to the FlacLoaderkleines Filmröllchen
This way the FlacLoader can be more easily understood by someone that doesn't already know the format inside out.
2022-05-03LibAudio+Userland: Remove Audio::LegacyBufferkleines Filmröllchen
The file is now renamed to Queue.h, and the Resampler APIs with LegacyBuffer are also removed. These changes look large because nobody actually needs Buffer.h (or Queue.h). It was mostly transitive dependencies on the massive list of includes in that header, which are now almost all gone. Instead, we include common things like Sample.h directly, which should give faster compile times as very few files actually need Queue.h.
2022-04-01Everywhere: Run clang-formatIdan Horowitz
2022-03-26FlacLoader: Use seektable for performing seek operationsMax Trussell
As a fallback, we perform primitive seek if there's no seektable. Co-authored-by: kleines Filmröllchen <filmroellchen@serenityos.org>
2022-03-26FlacLoader: Parse SEEKTABLE headerMax Trussell
Populates m_seektable attribute with FlacSeekPoints. For more information see: https://datatracker.ietf.org/doc/html/draft-ietf-cellar-flac#section-11.13 Co-authored-by: kleines Filmröllchen <filmroellchen@serenityos.org>
2022-01-22LibAudio: Convert FlacLoader to use new Core::Stream APIs :^)kleines Filmröllchen
For this change to work "easily", Loader can't take const ByteBuffer's anymore, which is fine for now.
2022-01-14LibAudio: Expose the format name from the loader pluginskleines Filmröllchen
The format of these names is "Full Abbreviation (.fileformat)". For example: "FLAC (.flac)", "RIFF WAVE (.wav)", "MPEG Layer III (.mp3)", "Vorbis (.ogg)" The reasoning is that the container and therefore the file ending may differ significantly from the actual format, and the format should be given as unambiguously as possible and necessary.
2022-01-14Everywhere: Use my new serenityos.org e-mail :^)kleines Filmröllchen
2022-01-02LibAudio: Remove frame-wise copys from FlacLoaderkleines Filmröllchen
Previously, FlacLoader would read the data for each frame into a separate vector, which are then combined via extend() in the end. This incurs an avoidable copy per frame. By having the next_frame() function write into a given Span, there's only one vector allocated per call to get_more_samples(). This increases performance by at least 100% realtime, as measured by abench, from about 1200%-1300% to (usually) 1400% on complex test files.
2021-12-17LibAudio: Don't unnecessarily copy the passed decode bufferkleines Filmröllchen
2021-12-17LibAudio: Add an adjustable buffer size to FlacLoaderkleines Filmröllchen
This makes it easier to fine-tune the optimal input buffer size.
2021-11-28LibAudio: New error propagation API in Loader and Bufferkleines Filmröllchen
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-28LibAudio: Avoid frequent read() calls in FLAC residual decodekleines Filmröllchen
Decoding the residual in FLAC subframes is by far the most I/O-heavy operation in FLAC decoding, as the residual data makes up the majority of subframe data in LPC subframes. As the residual consists of many Rice-encoded numbers with different bit sizes for differently large numbers, the residual decoder frequently reads only one or two bytes at a time. As we use a normal FileInputStream, that directly translates to many calls to the read() syscall. We can see that the I/O overhead while FLAC decoding is quite large, and much time is spent in the read() syscall's kernel code. This is optimized by using a Buffered<FileInputStream> instead, leading to 4K blocks being read at once and a large reduction in I/O overhead. Benchmarking with the new abench utility gives a 15-20% speedup on identical files, usually pushing FLAC decoding to 10-15x realtime speed on common sample rates.
2021-11-15Audio: Fix code smells and issues found by static analysiskleines Filmröllchen
This fixes all current code smells, bugs and issues reported by SonarCloud static analysis. Other issues are almost exclusively false positives. This makes much code clearer, and some minor benefits in performance or bug evasion may be gained.
2021-11-11Everywhere: Pass AK::StringView by valueAndreas Kling
2021-11-08LibAudio: Rename Audio::Frame -> Audio::SampleDavid Isaksson
"Frame" is an MPEG term, which is not only unintuitive but also overloaded with different meaning by other codecs (e.g. FLAC). Therefore, use the standard term Sample for the central audio structure. The class is also extracted to its own file, because it's becoming quite large. Bundling these two changes means not distributing similar modifications (changing names and paths) across commits. Co-authored-by: kleines Filmröllchen <malu.bertsch@gmail.com>
2021-08-27Userland+LibAudio: Make audio applications support dynamic sample ratekleines Filmröllchen
All audio applications (aplay, Piano, Sound Player) respect the ability of the system to have theoretically any sample rate. Therefore, they resample their own audio into the system sample rate. LibAudio previously had its loaders resample their own audio, even though they expose their sample rate. This is now changed. The loaders output audio data in their file's sample rate, which the user has to query and resample appropriately. Resampling code from Buffer, WavLoader and FlacLoader is removed. Note that these applications only check the sample rate at startup, which is reasonable (the user has to restart applications when changing the sample rate). Fully dynamic adaptation could both lead to errors and will require another IPC interface. This seems to be enough for now.
2021-08-18LibAudio: Resample FLAC audio datakleines Filmröllchen
FlacLoader initialized, but never used its resampler; this is now fixed and all subframes are resampled before decorrelation occurs. FLAC files with non-44100-Hz sample rates now play properly.
2021-08-02LibAudio: Handle stream errors in FlacLoaderAndrew Kaster
The FlacLoader already has numerous checks for invalid data reads and for invalid stream states, but it never actually handles the stream errors on the stream object. By handling them properly we can actually run FuzzFlacLoader for longer than a few seconds before it hits the first assertion :^).
2021-07-22LibAudio: Implement loaded_samples() in the FLAC LoaderKarol Kosek
This makes aplay show current playback position.
2021-06-25LibAudio: Implement a basic FLAC loaderkleines Filmröllchen
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.