1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 10:38:11 +00:00

Piano: Rewrite application

Goals:
- Switch to a more typical LibGUI arrangement
- Separate GUI (MainWidget) and audio (AudioEngine)
- Improve on existing features while retaining the same feature set

Improvements:
- Each GUI element is a separate widget
- The wave (WaveWidget) scales with the window
- The piano roll (RollWidget) scales horizontally and scrolls vertically
- The piano (KeysWidget) fits as many notes as possible
- The knobs (KnobsWidget) are now sliders
- All mouse and key events are handled in constant time
- The octave can be changed while playing notes
- The same note can be played with the mouse, keyboard and roll at the
  same time, and the volume of the resulting note is scaled accordingly
- Note frequency constants use the maximum precision available in a
  double
This commit is contained in:
William McPherson 2020-01-31 03:02:45 +11:00 committed by Andreas Kling
parent ddefb95b21
commit 4a36a51618
17 changed files with 1647 additions and 762 deletions

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2019-2020, William McPherson <willmcpherson2@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -24,8 +25,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "Music.h"
#include "PianoWidget.h"
#include "AudioEngine.h"
#include "MainWidget.h"
#include <LibAudio/AClientConnection.h>
#include <LibCore/CFile.h>
#include <LibDraw/PNGLoader.h>
@ -39,34 +40,36 @@
int main(int argc, char** argv)
{
GApplication app(argc, argv);
auto audio_client = AClientConnection::construct();
audio_client->handshake();
AudioEngine audio_engine;
auto window = GWindow::construct();
auto main_widget = MainWidget::construct(audio_engine);
window->set_main_widget(main_widget);
window->set_title("Piano");
window->set_rect(100, 100, 512, 512);
auto piano_widget = PianoWidget::construct();
window->set_main_widget(piano_widget);
window->show();
window->set_rect(90, 90, 840, 600);
window->set_icon(load_png("/res/icons/16x16/app-piano.png"));
window->show();
LibThread::Thread sound_thread([piano_widget = piano_widget.ptr()] {
LibThread::Thread audio_thread([&] {
auto audio = CFile::construct("/dev/audio");
if (!audio->open(CIODevice::WriteOnly)) {
dbgprintf("Can't open audio device: %s", audio->error_string());
return 1;
}
FixedArray<Sample> buffer(sample_count);
for (;;) {
u8 buffer[4096];
piano_widget->fill_audio_buffer(buffer, sizeof(buffer));
audio->write(buffer, sizeof(buffer));
CEventLoop::current().post_event(*piano_widget, make<CCustomEvent>(0));
audio_engine.fill_buffer(buffer);
audio->write(reinterpret_cast<u8*>(buffer.data()), buffer_size);
CEventLoop::current().post_event(*main_widget, make<CCustomEvent>(0));
CEventLoop::wake();
}
});
sound_thread.start();
audio_thread.start();
auto menubar = make<GMenuBar>();