summaryrefslogtreecommitdiff
path: root/Userland/Applications/SoundPlayer
AgeCommit message (Collapse)Author
2022-05-29SoundPlayer: Insert separator after play/stop and back/next buttonsLinus Groh
2022-05-29SoundPlayer: Replace two manual key event checks with action shortcutLinus Groh
2022-05-29SoundPlayer: Replace regular buttons with action-based toolbar buttonsLinus Groh
This looks nicer in every way imaginable.
2022-05-29Everywhere: Fix a bunch of typosLinus Groh
2022-05-07LibAudio+LibDSP: Switch samples to 32-bit float instead of 64-bit floatkleines Filmröllchen
This has been overkill from the start, and it has been bugging me for a long time. With this change, we're probably a bit slower on most platforms but save huge amounts of space with all in-memory sample datastructures.
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-21LibAudio+Userland: Use new audio queue in client-server communicationkleines Filmröllchen
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-21LibAudio+Everywhere: Rename Audio::Buffer -> Audio::LegacyBufferkleines Filmröllchen
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-01Everywhere: Run clang-formatIdan Horowitz
2022-03-29LibGUI: Add DoClamp option to AbstractSlider::set_value()Itamar
2022-03-25SoundPlayer: Don't crash when the reported buffer is unexpectedkleines Filmröllchen
It seems like this happens in quite some valid situations, so my initially sensible failsafe doesn't make sense. As the buffer system is hopefully gone soon, it won't be an issue in the future either way.
2022-03-25SoundPlayer: Fix jump to slider behavior for playback sliderkleines Filmröllchen
This was regressed at some point though I never saw it working. Basically, while jump to slider works correctly it doesn't even get actioned. While the user is clicking the slider it's very likely that a buffer finishes playing and the callback for that changes the slider value. This means that the user click just gets lost. There's some additional weird behavior where values are lost in even more cases, so an additional fix that is needed is to store the slider value in the AutoSlider while we're dragging and apply it on mouse up.
2022-03-18SoundPlayer: Fix read of uninitialized member variables on startupBrian Gianforcaro
I found these by running SoundPlayer under UserspaceEmulator. After boot we attempt to read from these values before they are initialized.
2022-03-14SoundPlayer: Implement logarithmic spectrum displaykleines Filmröllchen
Now that we have y-axis (gain) logarithmic display, we should also have x-axis (frequency) logarithmic display; that's how our ears work. This can be turned off with an option, but it generally looks much nicer.
2022-03-14SoundPlayer: Adjust peaking logic for bars visualizationkleines Filmröllchen
This should give us better peaks by also reducing the energy on lower frequency bars.
2022-03-14SoundPlayer: Use overlapping windows for bars visualizationkleines Filmröllchen
For DSP reasons I can't explain myself (yet, sorry), short-time Fourier transform (STFT) is much more accurate and aesthetically pleasing when the windows that select the samples for STFT overlap. This implements that behavior by storing the previous samples and performing windowed FFT over both it as well as the current samples. This gives us 50% overlap between windows, a common standard that is nice to look at.
2022-03-14SoundPlayer: Rework FFT visualizationArne Elster
The input to the FFT was distorted by the usage of fabs on the samples. It led to a big DC offset and a distorted spectrum. Simply removing fabs improves the quality of the spectrum a lot. The FFT input should be windowed to reduce spectral leakage. This also improves the visual quality of the spectrum. Also, no need to do a FFT of the whole buffer if we only mean to render 64 bars. A 8192 point FFT may smooth out fast local changes but at 44100 hz samplerate that's 200 ms worth of sound which significantly reduces FPS. A better approach for a fluent visualization is to do small FFTs at the current playing position inside the current buffer. There may be a better way to get the current playing position, but for now it's implemented as an estimation depending on how many frames where already rendered with the current buffer. Also I picked y-axis log scale as a default because there's usually a big difference in energy between low and high frequency bands. log scale looks nicer.
2022-03-14SoundPlayer: Auto refresh visualization widgetsArne Elster
Visualization widgets should only have to tell how many samples they need per frame and have a render method which receives all data relevant to draw the next frame.
2022-03-14SoundPlayer: Enable frequency energy adjustment by defaultkleines Filmröllchen
Although it's nice to have this as an option, it should be the default to adjust higher frequencies as they intrinsically have less energy than lower energies.
2022-03-14LibDSP: Generalize & improve FFTkleines Filmröllchen
Several related improvements to our Fast Fourier Transform implementation: - FFT now operates on spans, allowing it to use many more container types other than Vector. It's intended anyways that FFT transmutes the input data. - FFT is now constexpr, moving the implementation to the header and removing the cpp file. This means that if we have static collections of samples, we can transform them at compile time. - sample_data.data() weirdness is now gone.
2022-03-02SoundPlayer: Sort CMake sources alphabeticallyNícolas F. R. A. Prado
2022-03-02SoundPlayer: Draw album cover with correct aspect ratioNícolas F. R. A. Prado
Instead of drawing the album cover scaled to cover the whole visualization area, draw it resized to fit the area without altering the aspect ratio.
2022-03-02SoundPlayer: Rename NoVisualization to AlbumCoverVisualizationNícolas F. R. A. Prado
Since the NoVisualization widget now shows the album cover, it should be called AlbumCoverVisualization instead.
2022-03-02SoundPlayer: Display album cover in the NoVisualizationWidgetNícolas F. R. A. Prado
Display the album cover for the current playing song in the visualization area for the "None" Visualization. For now only "cover.png" and "cover.jpg" are looked for in the same directory for the album cover image. When no cover image is found the serenity background is shown instead as a fallback.
2022-03-02SoundPlayer: Add start_new_file() to VisualizationWidget's APINícolas F. R. A. Prado
This adds a new start_new_file() function to VisualizationWidget which is called when the player starts a new file, passing the filename of the file. This allows VisualizationWidget subclasses to do any setup needed when a new file is started.
2022-03-02SoundPlayer: Fix potential never-updated bars visualizationkleines Filmröllchen
When the bars visualization receives a new buffer, it checks if it needs a new buffer, which is only the case after it has repainted. However, after then setting m_is_using_last, which is the flag for this, it checks the buffer size of the passed buffer and returns if that is too small. This means that if the visualizer receives a buffer that is too small, and because of external circumstances the update doesn't run after the buffer modification routine, the m_is_using_last variable is stuck at true, which means that the visualization incorrectly believes that the passed buffer is old and we need not update. This simply fixes that by resetting m_is_using_last if the buffer we're passed is too small, because in that case, we're clearly not using the last buffer anymore. Note: This bug is not exposed by the current SoundPlayer behavior. It will become an issue with future changes, so we should fix it regardless.
2022-02-25Userland: Rename IPC ClientConnection => ConnectionFromClientItamar
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-14Applications: Use default constructors/destructorsLenny Maiorani
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-06Soundplayer: Use exp() instead of pow(E, n)Hendiadyoin1
2022-01-04Userland: Resolve -Woverloaded-virtual in LibGUI and SoundPlayerAndrew Kaster
Enable the warning project-wide. It catches when a non-virtual method creates an overload set with a virtual method. This might cause surprising overload resolution depending on how the method is invoked.
2022-01-02SoundPlayer: Don't enqueue samples depending on the GUI loopkleines Filmröllchen
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-02SoundPlayer: Remove resolved FIXMEkleines Filmröllchen
I already resolved this some time ago but apparently forgot about it :^)
2021-12-30LibGUI+SoundPlayer: Use 'decrease_slider_by_page_steps()' methodElyse
This method allow us to avoid repeating the pattern 'set_value(value() - page_step() * page_number)'.
2021-12-30LibGUI+SoundPlayer: Use 'increase_slider_by_page_steps()'Elyse
This method allow us to avoid repeating the pattern 'set_value(value() + page_step() * page_number)'.
2021-12-24SoundPlayer: Add a keyboard shortcut 'M' to mute the playerElyse
This shortcut let us mute/unmute the player, but it still doesn't update the volume slider because the actual volume widget can't display a muted state.
2021-12-24SoundPlayer: Add 'mute' methods to PlayerElyse
These methods allow us to mute/unmute the player without needing to modify the volume level that it has.
2021-12-24SoundPlayer: Sync startup loop and show playlist settings in GUIMax Trussell
This fix syncs up the AudioPlayer's internal state for showing playlist information with the AudioPlayer's GUI. Before, if the AudioPlayer was opened with a playlist file (.m3u or .m3u8) it would automatically show the playlist information in the GUI and set the loop mode to playlist, but the menu options would be unchecked. In order to hide the playlist information, the menu option would then have to be toggled twice -- once on and again off.
2021-12-04SoundPlayer: Port to LibMain :^)Elyse
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-24SoundPlayer+LibDSP: Move the FFT implementation to LibDSPkleines Filmröllchen
LibDSP can greatly benefit from this nice FFT implementation, so let's move it into the fitting library :^) Note that this now requires linking SoundPlayer against LibDSP. That's not an issue (LibDSP is rather small currently anyways), as we can probably make great use of it in the future anyways.
2021-11-13SoundPlayer: Add keyboard shortcuts for stop and volumeElyse
These shortcuts allow us to stop the player (key S) and adjust the volume level (key Up and key Down).
2021-11-13SoundPlayer: Make 'volume_slider' a member variableElyse
This change will allow us to modify the volume slider from any event inside the widget.
2021-11-13SoundPlayer: Allow volume output of up to 150%Elyse
Previously the volume slider could go up to 150% but the real output volume stayed the same between 100% and 150%.
2021-11-08SoundPlayer: Fix stack-use-after-scope when playing file in loop modeSimon Woertz
The path returned by GUI:FilePicker is stored on the stack when the callback is executed. The player only stored a StringView to the path however it should take ownership of the path instead since the path is accessed even after the file menu open action has returned.
2021-11-08LibGfx: Use ErrorOr<T> for Bitmap::try_load_from_file()Andreas Kling
This was used in a lot of places, so this patch makes liberal use of ErrorOr<T>::release_value_but_fixme_should_propagate_errors().
2021-11-04SoundPlayer: Allow playback progress slider jump to cursorElyse
This fix allows us to move the knob wherever we click inside the slider. The 'jump_to_cursor()' mechanism wasn't working properly because the player was overwriting the value we had just clicked.
2021-11-02Applications: Fix visibility of Object-derivative constructorsBen Wiederhake
Derivatives of Core::Object should be constructed through ClassName::construct(), to avoid handling ref-counted objects with refcount zero. Fixing the visibility means that misuses like this are more difficult.
2021-10-27Everywhere: Rename left/right-click to primary/secondaryFiliph Sandström
This resolves #10641.
2021-10-25SoundPlayer: Implement playlist shuffle modeLeandro Pereira
The shuffling algorithm uses a naïve bloom filter to provide random uniformity, avoiding items that were recently played. With 32 bits, double hashing, and an error rate of ~10%, this bloom filter should be able to hold around ~16 keys, which should be sufficient to give the illusion of fairness to the shuffling algorithm. This avoids having to shuffle the playlist itself (user might have spent quite a bit of time to sort them, so it's not a good idea to mess with it), or having to create a proxy model that shuffles (that could potentially use quite a bit of memory).
2021-10-25SoundPlayer: Make M3UParser more idiomaticLeandro Pereira
Let's use the nice APIs we have, and make the M3U parser a bit more readable, shorter, and resilient.