Commit Graph

54 Commits

Author SHA1 Message Date
kleines Filmröllchen
195d6d006f LibAudio: Resample FLAC audio data
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-18 18:16:48 +02:00
kleines Filmröllchen
d7ca60b998 LibAudio: Resample with integer ratios instead of floats
Floating-point ratios are inherently imprecise, and can lead to
unpredictable or nondeterministic behavior when resampling and expecting
a certain number of resulting samples. Therefore, the resampler now uses
integer ratios, with almost identical but fully predictable behavior.

This also introduces the reset() function that the FLAC loader will use
in the future.
2021-08-18 18:16:48 +02:00
kleines Filmröllchen
ba622cffe4 LibAudio: Fix overflow on 24-bit FLAC LPC data
When computing sample values from a linear predictor, the repeated
multiplication and addition can lead to very large values that may
overflow a 32-bit integer. This was never discovered with 16-bit FLAC
test files used to create and validate the first version of the FLAC
loader. However, 24-bit audio, especially with large LPC shifts, will
regularly exceed and overflow i32. Therefore, we now use 64 bits
temporarily. If the resulting value is too large for 32 bits, something
else has gone wrong :^)

This fixes playback noise on 24-bit FLACs.
2021-08-17 00:16:00 +02:00
kleines Filmröllchen
c974be91ab LibAudio: Rescale integer samples correctly in FLAC loader
The FLAC samples are signed, so we need to rescale them not by their bit
depth, but by half of the bit depth. For example, a 24-bit sample
extends from -2^23 to 2^23-1, and therefore needs to be rescaled by 2^23
to conform to the [-1, 1] double sample range.
2021-08-17 00:16:00 +02:00
kleines Filmröllchen
442aa48a61 LibAudio: Use size_t in loops
This is more idiomatic :^)
2021-08-17 00:16:00 +02:00
Karol Kosek
91c9d9ee88 LibAudio: Make playing lossy flacs more truthful
Playing a lossy flac file resulted in hearing something
you'd not like to play.  Instead of your lovely bass, you had sounds
as if you put a CD-ROM disc to a CD player.

It turned out that the size for making signed values was too big,
making all the values unsigned.

I've used lossyWav[1] (the posix port[2] to be exact)
to generate such files.

[1]: https://wiki.hydrogenaud.io/index.php?title=LossyWAV
[2]: https://github.com/MoSal/lossywav-for-posix
2021-08-06 23:50:10 +02:00
Karol Kosek
837803531a LibAudio: Fix calculation of wasted bits-per-sample
The value was always zero.
2021-08-06 23:50:10 +02:00
Karol Kosek
2ecd115176 LibAudio: Make read samples signed when decoding fixed FLAC subframes
Prior this change, decoding fixed subframes produced "unpleasant
crackling noices".

While the type doesn't appear so often when using the default settings,
encoding files in flac(1) with --fast option uses fixed subframes
almost every time.

This also applies the logic to the constant subframes,
which isn't so important, as the type is generally for the silence,
but let's use it as well to avoid inconsistency.
2021-08-06 23:50:10 +02:00
Karol Kosek
e500b39e47 LibAudio: Use an existing file stream when parsing a FLAC header
Before this change the file stream was generated two times:
one time in the parse_header(), and another time for the whole class
in the constructor.

The previous commit moved the m_stream initialization before
executing the parse_header function, so we can now reuse that here.
2021-08-04 11:00:27 +02:00
Karol Kosek
81261bc169 LibAudio: Initialize m_stream before parsing a FLAC header
Before this change opening the file in the system resulted in crash
caused by assertion saying:

  SoundPlayer(32:32): ASSERTION FAILED: m_ptr
  ../.././AK/OwnPtr.h:139
  [#0 SoundPlayer(32:32)]: Terminating SoundPlayer(32) due to signal 6
  [#0 FinalizerTask(4:4)]: 0xdeadc0de

The issue was that 845d403b8c started
using m_stream in the parse_header() function, but that variable wasn't
initialized if the Loader plugin was created using a file path
(which is used everywhere except for the fuzz testing),
resulting in a crash mentioned above.
2021-08-04 11:00:27 +02:00
Andrew Kaster
845d403b8c LibAudio: Handle stream errors in FlacLoader
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-08-02 09:05:28 +02:00
Karol Kosek
8c2be4b3dc LibAudio: Implement loaded_samples() in the FLAC Loader
This makes aplay show current playback position.
2021-07-22 22:57:05 +02:00
Karol Kosek
01e1e2c2c5 LibAudio: Read custom block sizes and sample rates as big endian
This fixes stucking in a loop at the end of the file, as
(a) custom block sizes are usually placed there, as the remaining
size might not be simply calculated as a power of two, and
(b) the number of bytes to read was incorrect (the program said
the block size was 32525, where flac -a said it's actually 3200).

Unfortunately, I couldn't trigger the bug for the sample rates,
so it may be not true, but I'd doubt it, giving the fact that flac
almost everywhere uses big endian numbers.
2021-07-22 22:57:05 +02:00
Karol Kosek
69c7b66f06 LibAudio: Don't read too much bytes in FLAC
This fixes crash when reading the end of the file.

The logic is mostly borrowed from WavLoader.
2021-07-22 22:57:05 +02:00
Karol Kosek
3c62b661f4 LibAudio: Fix UTF-8 decoding logic in FLAC decoding :^)
The problem here was that the multi-byte UTF-8 encoded characters
were taking one byte too much, misaligning the data completely
and eventually crashing the program on the 128th frame.

This change reduces the for loop by one, as it has been already
calculated from the start_byte variable.
2021-07-21 22:12:44 +02:00
Karol Kosek
9c71e43c3f LibAudio: Check if zero-bit padding is actually zero
This might allow the program to return an error a bit quicker.
2021-07-21 22:12:44 +02:00
Hendiadyoin1
ed46d52252 Everywhere: Use AK/Math.h if applicable
AK's version should see better inlining behaviors, than the LibM one.
We avoid mixed usage for now though.

Also clean up some stale math includes and improper floatingpoint usage.
2021-07-19 16:34:21 +04:30
kleines Filmröllchen
f634949d26 LibAudio: Use new Vector formatter 2021-07-13 17:40:07 +02:00
Karol Kosek
0c7a319e6b LibAudio: Set variable type for decoding fixed subframes in FLAC
This fixes an crash caused by using the type from
FlacSubframeHeader::order (unsigned 8-bit), which after overflowing
the integer, converting it back to u32, and decrementing by one
resulted in accessing an array waaay out of bounds.
2021-07-12 23:32:50 +02:00
kleines Filmröllchen
9d00db618d LibAudio: Add ClientConnection::async_enqueue()
async_enqueue() is a wrapper over the async_enqueue_buffer() call
to AudioServer. This allows users to asyncronously enqueue audio
samples, when the program requires non-blocking audio streaming.

This also makes ClientConnection use east-const everywhere.
2021-07-05 19:33:55 +02:00
kleines Filmröllchen
c8ced9f11d LibAudio: Improve latency on audio queue failures
We don't know what is a good time to wait after an audio buffer fails to
be processed by AudioServer. However, it seems like decreasing the wait
time to 10ms after such a failure should improve latency and has not
caused issues in my testing. After all, 10ms is quite some time in audio
sample magnitudes.
2021-07-05 19:33:55 +02: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
kleines Filmröllchen
184a9e7e67 LibAudio: Make ResampleHelper templated for different sample types
Previously, ResampleHelper was fixed on handling double's, which makes
it unsuitable for the upcoming FLAC loader that needs to resample
integers. For this reason, ResampleHelper is templated to support
theoretically any type of sample, though only the necessary i32 and
double are templated right now.

The ResampleHelper implementations are moved from WavLoader.cpp to
Buffer.cpp.

This also improves some imports in the WavLoader files.
2021-06-25 20:48:14 +04:30
kleines Filmröllchen
488de12ed4 LibAudio: Make LoaderPlugin::error_string return String&
Previously, error_string() returned char* which is bad Serenity style
and caused issues when other error handling methods were tried. As both
WavLoader and (future) FLAC loader store a String internally for the
error message, it makes sense to return a String reference instead.
2021-06-25 20:48:14 +04:30
kleines Filmröllchen
d599a14545 LibAudio: Add the Int32 sample format
The signed 32-bit PCM sample format is required for the FLAC standard.
2021-06-25 20:48:14 +04:30
Nick Miller
9a2c80c791 SoundPlayer: Handle any input file sample rate
This commit addresses two issues:
1. If you play a 96 KHz Wave file, the slider position is incorrect,
   because it is assumed all files are 44.1 KHz.
2. For high-bitrate files, there are audio dropouts due to not
   buffering enough audio data.

Issue 1 is addressed by scaling the number of played samples by the
ratio between the source and destination sample rates.

Issue 2 is addressed by buffering a certain number of milliseconds
worth of audio data (instead of a fixed number of bytes).
This makes the the buffer size independent of the source sample rate.

Some of the code is redesigned to be simpler. The code that did the
book-keeping of which buffers need to be loaded and which have been
already played has been removed. Instead, we enqueue a new buffer based
on a low watermark of samples remaining in the audio server queue.

Other small fixes include:
1. Disable the stop button when playback is finished.
2. Remove hard-coded instances of 44100.
3. Update the GUI every 50 ms (was 100), which improves visualizations.
2021-06-21 03:13:59 +04:30
Nick Miller
34a3d08e65 LibAudio: Sleep less when the audio buffer is full
When using `aplay` to play audio files with a sample rate of 96000,
there were occasional one-second gaps in playback. This is
because the Audio::ClientConnection sleeps for a full second when
the audio buffer is full.

One second is too long to sleep, especially for high-bitrate files.
Changing the sleep to a more reasonable value like 100 ms ensures
we attempt to enqueue again before the audio buffer runs empty.
2021-06-21 03:13:59 +04:30
Nick Miller
dec9ed066d LibAudio: Avoid reading past the end of sample data
Prior code in `WavLoader::get_more_samples()` would attempt to
read the requested number of samples without actually checking
whether that many samples were remaining in the stream.
This was the cause of an audible pop at the end of a track, due
to reading non-audio data that is sometimes at the end of a Wave file.

Now we only attempt to read up to the end of sample data, but no
further.

Also, added comments to clarify the meaning of "sample", and how it
should be independent of the number of channels.
2021-06-21 03:13:59 +04:30
Nick Miller
2b789adc16 LibAudio: Add support for WAVE_FORMAT_EXTENSIBLE
This enables support for playing float32 and float64
WAVE_FORMAT_EXTENSIBLE files.

The PCM data format is encoded in the
first two bytes of the SubFormat GUID inside of the
WAVE_FORMAT_EXTENSIBLE `fmt` chunk.

Also, fixed the RIFF header size check to allow up to
maximum_wav_size (currently defined as 1 GiB).
The RIFF header size is the size of the entire
file, so it should be checked against the largest Wave size.
2021-06-09 22:58:44 +04:30
Nick Miller
23d5b99fbf LibAudio: Make Loader::seek() treat its input as a sample index
This fixes a bug where if you try to play a Wave file a second
time (or loop with `aplay -l`), the second time will be pure
noise.

The function `Audio::Loader::seek` is meant to seek to a specific
audio sample, e.g. seek(0) should go to the first audio sample.
However, WavLoader was interpreting seek(0) as the beginning
of the file or stream, which contains non-audio header data.

This fixes the bug by capturing the byte offset of the start of the
audio data, and offseting the raw file/stream seek by that amount.
2021-06-09 17:30:08 +04:30
Nick Miller
ed5777eb0a LibAudio: WavLoader: Avoid reading partial samples
When samples are requested in `Audio::Loader::get_more_samples`,
the request comes in as a max number of bytes to read.

However, the requested number of bytes may not be an even multiple
of the bytes per sample of the loaded file. If this is the case, and
the bytes are read from the file/stream, then
the last sample will be a partial/runt sample, which then offsets
the remainder of the stream, causing white noise in playback.

This bug was discovered when trying to play 24-bit Wave files, which
happened to have a sample size that never aligned with the number
of requested bytes.

This commit fixes the bug by only reading a multiple of
"bytes per sample" for the loaded file.
2021-06-08 00:38:54 +04:30
Nick Miller
3938b56577 LibAudio+LibCore: Remove unnecessary IODeviceStreamReader.h
IODeviceStreamReader isn't pulling its weight.
It's essentially a subset of InputFileStream with only one user
(WavLoader).

This refactors WavLoader to use InputFileStream instead.
2021-06-08 00:38:54 +04:30
Andreas Kling
a345a1f4a1 Userland: Mark subclasses of IPC::{Client,Server}Connection final 2021-05-23 09:53:55 +02:00
Andreas Kling
c1c252ddb2 LibIPC: Remove unnecessary IPC::ServerConnection::handshake()
This is no longer used by any of our IPC pairs.
2021-05-23 09:53:55 +02:00
Andreas Kling
5424372d50 AudioServer: Remove unnecessary greet() message 2021-05-23 09:53:55 +02:00
Ali Mohammad Pur
a91a49337c LibCore+Everywhere: Move OpenMode out of IODevice
...and make it an enum class so people don't omit "OpenMode".
2021-05-12 11:00:45 +01:00
Gunnar Beutner
eb21aa65d1 Userland: Make IPC results with one return value available directly
This changes client methods so that they return the IPC response's
return value directly - instead of the response struct - for IPC
methods which only have a single return value.
2021-05-03 21:14:40 +02:00
Gunnar Beutner
5bb79ea0a7 Userland: Update IPC calls to use proxies
This updates all existing code to use the auto-generated client
methods instead of post_message/send_sync.
2021-05-03 21:14:40 +02:00
Gunnar Beutner
065040872f Userland: Change IPC funcs to use plain arguments instead of a struct
Instead of having a single overloaded handle method each method gets
its own unique method name now.
2021-05-03 21:14:06 +02:00
Gunnar Beutner
6cf59b6ae9 Everywhere: Turn #if *_DEBUG into dbgln_if/if constexpr 2021-05-01 21:25:06 +02:00
kleines Filmröllchen
563cc17a50 LibAudio: Support 32 and 64-bit float WAV files
LibAudio's WavLoader plugin for loading WAV files now supports loading
audio files with 32-bit float or 64-bit float samples.

By supporting these new non-int sample formats, Audio::Buffer now stores
the sample format (out of a list of supported formats) instead of the
raw bit depth. (The bit depth is easily calculated with
pcm_bits_per_sample)
2021-04-26 19:08:40 +02:00
Andreas Kling
b91c49364d AK: Rename adopt() to adopt_ref()
This makes it more symmetrical with adopt_own() (which is used to
create a NonnullOwnPtr from the result of a naked new.)
2021-04-23 16:46:57 +02:00
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
Cesar Torres
0d5e1e9df1 Everywhere: rename 'Sample' type to 'Frame'
Because it's what it really is. A frame is composed of 1 or more samples, in
the case of SerenityOS 2 (stereo). This will make it less confusing for
future mantainability.
2021-03-27 10:20:55 +01:00
Idan Horowitz
00f1cb924b LibAudio: decrease WavLoader's size limit to a more reasonable size
A 4 GiB wav (current size limit) is very unreasonable, and larger
than oss-fuzz's 2.5 GiB per-process memory limit.
2021-03-16 18:40:42 +01:00
Luke
152af3a297 LibAudio: Move format and BPS checks before VERIFYs in WAV loader
It was accidentally checking the format/bits per sample too late,
which would crash with the assertion.
2021-03-01 11:09:09 +01:00
Luke
69df86c1d6 LibAudio: Use handle_any_error in WAV loader
It was using has_any_error, which causes an assertion failure when
destroying the stream. Instead, use handle_any_error, as the
WAV loader does handle errors.
2021-03-01 11:09:09 +01:00
Andreas Kling
5d180d1f99 Everywhere: Rename ASSERT => VERIFY
(...and ASSERT_NOT_REACHED => VERIFY_NOT_REACHED)

Since all of these checks are done in release builds as well,
let's rename them to VERIFY to prevent confusion, as everyone is
used to assertions being compiled out in release.

We can introduce a new ASSERT macro that is specifically for debug
checks, but I'm doing this wholesale conversion first since we've
accumulated thousands of these already, and it's not immediately
obvious which ones are suitable for ASSERT.
2021-02-23 20:56:54 +01:00
Andreas Kling
1ce03f4f34 LibIPC: Stop sending client ID to clients
The client ID is not useful to normal clients anymore, so stop telling
everyone what their ID is.
2021-02-01 11:32:00 +01:00
asynts
eea72b9b5c Everywhere: Hook up remaining debug macros to Debug.h. 2021-01-25 09:47:36 +01:00