Commit graph

18 commits

Author SHA1 Message Date
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
Tim Schumacher dfc57c0dd9 SoundPlayer: Don't offset the seek bar with the last seek value
The audio loader plugins already do this internally, if we do this a
second time the seek bar will just end up getting rendered at the wrong
place.
2023-01-19 11:42:32 +01:00
kleines Filmröllchen 3f59356c79 LibAudio: Rename ConnectionFromClient to ConnectionToServer
The automatic nomenclature change for IPC sockets got this one wrong.
2022-07-19 11:17:45 +01:00
kleines Filmröllchen ab49fcfb7c LibAudio+Userland: Remove Audio::LegacyBuffer
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-05-03 23:09:20 +02:00
kleines Filmröllchen 49b087f3cd LibAudio+Userland: Use new audio queue in client-server communication
Previously, we were sending Buffers to the server whenever we had new
audio data for it. This meant that for every audio enqueue action, we
needed to create a new shared memory anonymous buffer, send that
buffer's file descriptor over IPC (+recfd on the other side) and then
map the buffer into the audio server's memory to be able to play it.
This was fine for sending large chunks of audio data, like when playing
existing audio files. However, in the future we want to move to
real-time audio in some applications like Piano. This means that the
size of buffers that are sent need to be very small, as just the size of
a buffer itself is part of the audio latency. If we were to try
real-time audio with the existing system, we would run into problems
really quickly. Dealing with a continuous stream of new anonymous files
like the current audio system is rather expensive, as we need Kernel
help in multiple places. Additionally, every enqueue incurs an IPC call,
which are not optimized for >1000 calls/second (which would be needed
for real-time audio with buffer sizes of ~40 samples). So a fundamental
change in how we handle audio sending in userspace is necessary.

This commit moves the audio sending system onto a shared single producer
circular queue (SSPCQ) (introduced with one of the previous commits).
This queue is intended to live in shared memory and be accessed by
multiple processes at the same time. It was specifically written to
support the audio sending case, so e.g. it only supports a single
producer (the audio client). Now, audio sending follows these general
steps:
- The audio client connects to the audio server.
- The audio client creates a SSPCQ in shared memory.
- The audio client sends the SSPCQ's file descriptor to the audio server
  with the set_buffer() IPC call.
- The audio server receives the SSPCQ and maps it.
- The audio client signals start of playback with start_playback().
- At the same time:
  - The audio client writes its audio data into the shared-memory queue.
  - The audio server reads audio data from the shared-memory queue(s).
  Both sides have additional before-queue/after-queue buffers, depending
  on the exact application.
- Pausing playback is just an IPC call, nothing happens to the buffer
  except that the server stops reading from it until playback is
  resumed.
- Muting has nothing to do with whether audio data is read or not.
- When the connection closes, the queues are unmapped on both sides.

This should already improve audio playback performance in a bunch of
places.

Implementation & commit notes:
- Audio loaders don't create LegacyBuffers anymore. LegacyBuffer is kept
  for WavLoader, see previous commit message.
- Most intra-process audio data passing is done with FixedArray<Sample>
  or Vector<Sample>.
- Improvements to most audio-enqueuing applications. (If necessary I can
  try to extract some of the aplay improvements.)
- New APIs on LibAudio/ClientConnection which allows non-realtime
  applications to enqueue audio in big chunks like before.
- Removal of status APIs from the audio server connection for
  information that can be directly obtained from the shared queue.
- Split the pause playback API into two APIs with more intuitive names.

I know this is a large commit, and you can kinda tell from the commit
message. It's basically impossible to break this up without hacks, so
please forgive me. These are some of the best changes to the audio
subsystem and I hope that that makes up for this :yaktangle: commit.

:yakring:
2022-04-21 13:55:00 +02:00
kleines Filmröllchen cb0e95c928 LibAudio+Everywhere: Rename Audio::Buffer -> Audio::LegacyBuffer
With the following change in how we send audio, the old Buffer type is
not really needed anymore. However, moving WavLoader to the new system
is a bit more involved and out of the scope of this PR. Therefore, we
need to keep Buffer around, but to make it clear that it's the old
buffer type which will be removed soon, we rename it to LegacyBuffer.
Most of the users will be gone after the next commit anyways.
2022-04-21 13:55:00 +02:00
Idan Horowitz 086969277e Everywhere: Run clang-format 2022-04-01 21:24:45 +01:00
Itamar 3a71748e5d Userland: Rename IPC ClientConnection => ConnectionFromClient
This was done with CLion's automatic rename feature and with:
find . -name ClientConnection.h
    | rename 's/ClientConnection\.h/ConnectionFromClient.h/'

find . -name ClientConnection.cpp
    | rename 's/ClientConnection\.cpp/ConnectionFromClient.cpp/'
2022-02-25 22:35:12 +01:00
Lenny Maiorani 160bda7228 Applications: Use default constructors/destructors
https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#cother-other-default-operation-rules

"The compiler is more likely to get the default semantics right and
you cannot implement these functions better than the compiler."
2022-02-14 22:06:55 +00:00
kleines Filmröllchen c748c0726a SoundPlayer: Don't enqueue samples depending on the GUI loop
Previously, SoundPlayer would read and enqueue samples in the GUI loop
(through a Timer). Apart from general problems with doing audio on the
GUI thread, this is particularly bad as the audio would lag or drop out
when the GUI lags (e.g. window resizes and moves, changing the
visualizer). As Piano does, now SoundPlayer enqueues more audio once the
audio server signals that a buffer has finished playing. The GUI-
dependent decoding is still kept as a "backup" and to start the entire
cycle, but it's not solely depended on. A queue of buffer IDs is used to
keep track of playing buffers and how many there are. The buffer
overhead, i.e. how many buffers "too many" currently exist, is currently
set to its absolute minimum of 2.
2022-01-02 22:18:37 +01:00
kleines Filmröllchen 59601b67a0 SoundPlayer: Remove resolved FIXME
I already resolved this some time ago but apparently forgot about it :^)
2022-01-02 22:18:37 +01:00
Leandro Pereira 3126b78903 SoundPlayer: Fix inconsistencies and code duplication
This is a first pass at refactoring SoundPlayer so that the View widget
is decoupled from the player itself.

In doing so, this fixed a couple of issues, including possibly
inconsistent states (e.g. player could be paused and stopped at the
same time).

With the change, Player actually controls the show, and calls methods
overriden by its subclasses to perform actions, such as update the Seek
bar; the hard work of massaging the raw data is done by the Player
class, so subclasses don't need to reimplement any of these things.

This also removes some copies of playlist management code that happened
to be copied+pasted inside callbacks of buttons -- it now lives inside
a neatly packaged Playlist class, and the Player only asks for the next
song to play.

In addition, the menu bar has been slightly rearranged.
2021-10-25 23:37:18 +02:00
kleines Filmröllchen d049626f40 Userland+LibAudio: Make audio applications support dynamic sample rate
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-27 23:35:27 +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
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 fd126578d9 SoundPlayer: Add samplerate variable to visualizations
also fix conflict
2021-03-27 10:20:55 +01:00
Cesar Torres f9e4bff487 SoundPlayer: Reduce sample buffer size and add a sample load event 2021-03-27 10:20:55 +01:00
Andreas Kling dc28c07fa5 Applications: Move to Userland/Applications/ 2021-01-12 12:05:23 +01:00
Renamed from Applications/SoundPlayer/PlaybackManager.h (Browse further)