1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-18 15:05:09 +00:00
Commit graph

255 commits

Author SHA1 Message Date
Sam Atkins
0a9fa85e86 LibAudio: Use ReadonlyBytes instead of Bytes for buffer parameters
Bytes will implicitly cast to StringView, but not to ReadonlyBytes. That
means that if you call
`Audio::Loader::create_plugin(mapped_file->bytes())`
it will silently use the `create_plugin(StringView path)` overload.

Reading audio data does not require that data to be writable, so let's
use ReadonlyBytes for it and avoid the footgun.
2023-07-20 08:02:12 +01:00
Timothy Flynn
c911781c21 Everywhere: Remove needless trailing semi-colons after functions
This is a new option in clang-format-16.
2023-07-08 10:32:56 +01:00
kleines Filmröllchen
111fd1e5fe LibAudio: Optimize FlacLoader by avoiding allocations
- Pre-allocate and reuse sample decompression buffers. In many FLAC
  files, the amount of samples per frame is either constant or the
  largest frame will be hit within the first couple of frames. Also,
  during audio output, we need to move and combine the samples from the
  decompression buffers into the final output buffers anyways. Avoiding
  the reallocation of these large buffers provides an improvement from
  16x to 18x decode speed on strongly compressed but otherwise usual
  input.
- Leave a FIXME for a similar improvement that can be made in the
  residual decoder.
- Pre-allocate audio chunks if frame size is known.
- Use reasonable inline capacities in several places where we know the
  maximum or usual capacity needed.
2023-07-06 19:13:36 +01:00
Zaggy1024
ddb7b59af0 LibAudio: Always add a seek point once the FLAC header has parsed 2023-07-06 14:27:57 +01:00
Zaggy1024
9d5819e9e2 LibAudio: Seek accurately to the target frame in the FLAC loader
Instead of using a seek tolerance value to get close enough to the
target, we can skip frames forward until we pass the target, then seek
back to the previous frame. That puts us in a position to immediately
decode the frame containing the target sample.
2023-07-06 14:27:57 +01:00
Zaggy1024
f2d9280342 LibAudio: Skip FLAC samples even if already close to seek target
Previously, the FLAC loader would not skip samples to reach its seek
target if it saw that the current sample in the loader is closer to the
target than the seek point it finds. This prevents seeking forward when
there are no seek points past the current position.
2023-07-06 14:27:57 +01:00
Zaggy1024
ee1903e641 LibAudio: Always insert a seek point at sample 0 if not present
Previously, the calculation of the distance to the previous seekpoint
would always behave as if a seek point existed at sample 0, meaning
that it would never place a seek point there. If we instead treat it as
the maximum distance if no sample is present, a seek point will be
placed.
2023-07-06 14:27:57 +01:00
Zaggy1024
a8dc97d95d LibAudio: Don't return a seek point if it is after the desired sample
If the seek table was incomplete, without any seek points available
before the target point, `SeekTable::seek_point_before()` would instead
return the first seek point after the target. Check whether the seek
point is before the target before returning it.
2023-07-06 14:27:57 +01:00
kleines Filmröllchen
8258618caf LibAudio: Mix multi-channel files more properly
We downsample multi-channel files into stereo for now, which at least
makes the other channels listenable. The new multi-channel downmix
helper is intended to be used for other formats with the same or similar
channel arrangement, such as QOA.
2023-07-06 10:44:42 +01:00
kleines Filmröllchen
fc70d88367 LibAudio: Handle unknown-sized streams better
Especially FLAC had an issue here before, but the loader infrastructure
itself wouldn't handle end of stream properly if the "available samples"
information didn't match up.
2023-07-06 10:44:42 +01:00
kleines Filmröllchen
e9e95b1899 LibAudio: Fix escaped partitions
A missing sign extension and a wrong data type broke these before.
2023-07-06 10:44:42 +01:00
Nico Weber
5619bb3e04 LibAudio: Stop using and remove LOADER_TRY
It's no longer needed now that this code uses ErrorOr instead of Result.

Ran:

    rg -lw LOADER_TRY Userland/Libraries/LibAudio \
        | xargs sed -i '' 's/LOADER_TRY/TRY/g'

...and then manually fixed up Userland/Libraries/LibAudio/LoaderError.h
to not redefine TRY but instead remove the now-unused LOADER_TRY,
and ran clang-format.
2023-07-04 13:24:17 -06:00
kleines Filmröllchen
a75377d014 LibAudio: Perform seekpoint comparison without subtraction
For very large seekpoint indices, the casts necessary for the "simple"
subtraction comparison will yield wrong and overflowing results.
Therefore, we perform the seekpoint comparison manually instead.
2023-07-04 12:47:08 +02:00
kleines Filmröllchen
e82bee86dd LibAudio: Account for 0xFF start byte in FLAC UTF-8 decoder
This specialized UTF-8 decoder is more powerful than a normal UTF-8
decoder anyways, but it couldn't account for the never spec-compliant
0xff start byte. This commit makes that byte behave as expected if
taking UTF-8 to its extreme, even if it is a little silly and likely not
relevant for real applications.
2023-07-04 12:47:08 +02:00
kleines Filmröllchen
8bc56c7fb0 LibAudio: Prevent FLAC Rice partitions getting smaller than 1 sample
This would cause an integer underflow leading to us trying to allocate
over 4GB for residual samples.
2023-07-04 12:47:08 +02:00
kleines Filmröllchen
952c633a65 LibAudio: Fix 32-bit/64-bit mixup in FLAC sign extend
The bit magic for two's complement sign extension was only sign
extending to 32-bit signed. This issue was exposed by the last commit,
where now we actually use the 64-bit return value.
2023-07-04 12:47:08 +02:00
kleines Filmröllchen
59c7ce3d54 LibAudio: Prevent integer overflows in intermediate FLAC calculations
Since we can have up to 32 bits of input data, multiplications may need
up to 63 bits. This was accounted for in some places, but by far not in
all, and oss-fuzz found multiple integer overflows. We now use i64 in
all of the decoding, since we need to rescale samples to float later on
anyways. If a final sample value ends up out of range (and the range can
be a maximum of 32 bits), we may get samples past 1, but that then is a
non-compliant input file, and using over-range samples (and most likely
clipping audio) is considerably less weird than overflowing and
glitching audio.
2023-07-04 12:47:08 +02:00
kleines Filmröllchen
9bece0d0da LibAudio: Prevent multiple kinds of buffer overruns in FLAC picture load
The fuzzer found one heap buffer overflow here due to confusion between
u32* and u8* (the given size is for bytes, but we used it for 32-bit
elements, quadrupling it), and it looks like there's an opportunity for
several more. This commit modernizes the picture loader by using
String's built-in stream loader, and also adds several spec-compliance
checks: The MIME type must be ASCII in a specific range, and the picture
description must be UTF-8.
2023-07-04 12:47:08 +02:00
kleines Filmröllchen
ab9c18c176 LibAudio: Don't try to resample FLAC frames with sample rate 0
Although this sample rate is more or less bogus, we might as well not
crash.
2023-07-04 12:47:08 +02:00
kleines Filmröllchen
2e9e0dfe61 LibAudio: Check that LPC order is smaller than subframe sample count
An LPC predictor (fixed or not) contains as many warm-up samples as its
order. Therefore, the corresponding subframe must have at least this
many samples.

This turns this fuzzer-found crash into a handleable format error.
2023-07-04 12:47:08 +02:00
kleines Filmröllchen
6cddee98a9 LibAudio: Don't overread MP3 granule samples if big_values is too large
There are at most 576 granule samples/frequency lines, but the side data
can specify that the big_values granule type take up to 1024 samples.
The spec says in 2.4.3.4.6 that we should always stop reading Huffman
data once we have 576 samples, so that is what this change does. I also
add some useful spec comments while I'm here.
2023-07-02 02:15:32 +02:00
kleines Filmröllchen
53785a9206 LibAudio: Handle bitstream errors in MP3 Huffman decode 2023-07-02 02:15:32 +02:00
kleines Filmröllchen
b4fbd30b70 AudioServer+Userland: Decouple client sample rates from device rate
This change was a long time in the making ever since we obtained sample
rate awareness in the system. Now, each client has its own sample rate,
accessible via new IPC APIs, and the device sample rate is only
accessible via the management interface. AudioServer takes care of
resampling client streams into the device sample rate. Therefore, the
main improvement introduced with this commit is full responsiveness to
sample rate changes; all open audio programs will continue to play at
correct speed with the audio resampled to the new device rate.

The immediate benefits are manifold:
- Gets rid of the legacy hardware sample rate IPC message in the
  non-managing client
- Removes duplicate resampling and sample index rescaling code
  everywhere
- Avoids potential sample index scaling bugs in SoundPlayer (which have
  happened many times before) and fixes a sample index scaling bug in
  aplay
- Removes several FIXMEs
- Reduces amount of sample copying in all applications (especially
  Piano, where this is critical), improving performance
- Reduces number of resampling users, making future API changes (which
  will need to happen for correct resampling to be implemented) easier

I also threw in a simple race condition fix for Piano's audio player
loop.
2023-07-01 23:27:24 +01:00
kleines Filmröllchen
5f1dbbaaa6 LibAudio: Extract loader stream creation from the plugins
This removes a lot of duplicated stream creation code from the plugins,
and also simplifies the way that the appropriate plugin is found. This
mirrors the ImageDecoderPlugin design and necessitates new sniffing
methods on the loaders.
2023-06-27 15:28:22 +01:00
kleines Filmröllchen
dfd48ab643 LibAudio: Extract MP3 synchronize to static helper function
This comes in handy when we want to sniff an MP3 file with a stream
outside of the loader.
2023-06-27 15:28:22 +01:00
kleines Filmröllchen
03fac609ee AudioServer+Userland: Separate audio IPC into normal client and manager
This is a sensible separation of concerns that mirrors the WindowServer
IPC split. On the one hand, there is the "normal" audio interface, used
for clients that play audio, which is the primary service of
AudioServer. On the other hand, there is the management interface,
which, like the WindowManager endpoint, provides higher-level control
over clients and the server itself.

The reasoning for this split are manifold, as mentioned we are mirroring
the WindowServer split. Another indication to the sensibility of the
split is that no single audio client used the APIs of both interfaces.
Also, useless audio queues are no longer created for managing clients
(since those don't even exist, just like there's no window backing
bitmap for window managing clients), eliminating any bugs that may occur
there as they have in the past.

Implementation-wise, we just move all the APIs and implementations from
the old AudioServer into the AudioManagerServer (and respective clients,
of course). There is one point of duplication, namely the hardware
sample rate. This will be fixed in combination with per-client sample
rate, eliminating client-side resampling and the related update bugs.
For now, we keep one legacy API to simplify the transition.

The new AudioManagerServer also gains a hardware sample rate change
callback to have exact symmetry on the main server parameters (getter,
setter, and callback).
2023-06-25 00:16:44 +02:00
kleines Filmröllchen
de17cd018e LibAudio: Add accessor to "real" PCM sample format of loader 2023-06-22 21:45:54 +02:00
kleines Filmröllchen
cd2e890304 LibAudio: Handle all integer PCM sample formats "correctly" in WavWriter
WavWriter needs a TON of modernization work, but for now this commit
just tackles two FIXMEs by converting samples correctly into all
supported integer PCM formats. The supported formats are only signed
16-bit and unsigned 8-bit for now, but can be expanded later. At least
we don't produce horrible speaker-destroying noise when writing any
other format.
2023-06-22 21:45:54 +02:00
Daniel
b10c87d31e LibAudio: Remove redundant checks in WavLoader
- Max size of a wav is u32::MAX, so file/data size will never be larger
2023-06-20 09:12:17 +02:00
Timothy Flynn
3a4e64bdbd LibAudio: Add a forwarding header 2023-06-13 06:14:01 +02:00
Timothy Flynn
936ec94f81 AK+LibAudio+AudioServer: Silence very noisy debug statements by default
These are spammed quite heavily on the debug console, especially at the
end of audio playback.
2023-06-13 06:14:01 +02:00
kleines Filmröllchen
9e496a96a6 LibAudio: Load WAV metadata
This is quite straightforward with our new RIFF infrastructure.
2023-05-31 16:23:07 +02:00
kleines Filmröllchen
70970b2fa9 LibAudio: Modernize WAV loader
With this, the WAV loader is a completely modern LibAudio loader:
- Own type header for RIFF data structures
- custom stream read functions for the types
- Final removal of legacy I/O error checking
- clearer error messages
- clean handling of header chunks

The latter will allow proper handling of other chunks (before "data") in
the future, such as metadata :^)
2023-05-31 16:23:07 +02:00
kleines Filmröllchen
213025f210 AK: Rename Time to Duration
That's what this class really is; in fact that's what the first line of
the comment says it is.

This commit does not rename the main files, since those will contain
other time-related classes in a little bit.
2023-05-24 23:18:07 +02:00
kleines Filmröllchen
3b8ccd123b LibAudio: Compute and verify FLAC frame header checksums
This is currently not a failure condition, but we will print out a
message to the console informing the user of a potential corrupted file.
2023-05-18 22:23:15 +02:00
Lucas CHOLLET
8c34959b53 AK: Add the Input word to input-only buffered streams
This concerns both `BufferedSeekable` and `BufferedFile`.
2023-05-09 11:18:46 +02:00
Andreas Kling
7035a19645 LibAudio: Wait for enqueuer thread to start before poking its event loop 2023-04-26 19:17:04 +01:00
Jelle Raaijmakers
0f22dfa634 LibAudio: Make WavWriter check if a file was set during destruction
`WavWriter` can be constructed without a file, which should probably be
made impossible at some point. For now, let's not crash `Piano` when you
close the application.
2023-04-25 15:34:14 +02:00
Andreas Kling
9601b516b8 LibCore: Remove awkward EventLoop::wake_once() API
This was used in exactly one place, to avoid sending multiple
CustomEvents to the enqueuer thread in Audio::ConnectionToServer.

Instead of this, we now just send a CustomEvent and wake the enqueuer
thread. If it wakes up and has multiple CustomEvents, they get delivered
and ignored in no time anyway. Since they only get ignored if there's
no work to be done, this seems harmless.
2023-04-25 14:48:40 +02:00
Tim Schumacher
708387b850 LibAudio: Use read_until_filled to fill a buffer from a Stream
This has the advantage of recognizing when the Stream reaches EOF and
avoids an endless loop.
2023-04-12 14:02:56 -04:00
Cameron Youell
7734eba03f Piano+LibAudio: Port to Core::File 2023-04-09 20:58:54 -06:00
kleines Filmröllchen
1ee2091b2d LibAudio: Support FLAC files with unknown amount of samples
This is a special case of the sample count field in the header which we
treated as a format error before. Now we just take care to check stream
EOF before reading chunks.

This makes the final FLAC spec test pass, making us one of the most
compliant loaders! :^)
2023-03-19 14:15:35 +00:00
kleines Filmröllchen
b2a018ee59 LibAudio: Use specified bit depth directly
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-19 14:15:35 +00:00
kleines Filmröllchen
27d9ed0224 LibAudio: Use new generic seek table for MP3
MP3 had the exact same data structure, except less readable and less
efficient.
2023-03-19 00:28:02 +00:00
kleines Filmröllchen
0cd0565abc LibAudio: Improve FLAC seeking
"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-19 00:28:02 +00:00
Timothy Flynn
6070875564 LibAudio: Update stream APIs used when reading audio metadata 2023-03-13 12:46:42 -04:00
kleines Filmröllchen
a8963a270f LibAudio: Detect and read FLAC metadata
FLAC uses the very simple vorbis comment metadata format, which we can
now read most standard and non-standard fields from.
2023-03-13 12:35:17 -04:00
kleines Filmröllchen
d8e8ddedf3 LibAudio: Add a generic audio metadata container
This container has several design goals:
- Represent all common and relevant metadata fields of audio files in a
  unified way.
- Allow perfect recreation of any metadata format from the in-memory
  structure. This requires that we allow non-detected fields to reside
  in an "untyped" miscellaneous collection.

Like with pictures, plugins are free to store their metadata into the
m_metadata field whenever they read it. It is recommended that this
happens on loader creation; however failing to read metadata should not
cause an error in the plugin.
2023-03-13 12:35:17 -04:00
kleines Filmröllchen
d1dd753a95 LibAudio: Add a formatter for LoaderError 2023-03-13 12:35:17 -04:00
Tim Schumacher
ae51c1821c Everywhere: Remove unintentional partial stream reads and writes 2023-03-13 15:16:20 +00:00