summaryrefslogtreecommitdiff
path: root/Applications/Piano
diff options
context:
space:
mode:
authorWilliam McPherson <willmcpherson2@gmail.com>2020-02-07 00:32:46 +1100
committerAndreas Kling <kling@serenityos.org>2020-02-06 19:13:53 +0100
commitb7d190bd108cf9f67abb2181e36ede0a3218c597 (patch)
treee6fe80a3a23c0d27a15389b30ee4f345f53b299c /Applications/Piano
parent5dc014b26106259a03b16310da5d9f3cdf3a10c3 (diff)
downloadserenity-b7d190bd108cf9f67abb2181e36ede0a3218c597.zip
Piano: Add export action
This is a pretty rudimentary WAV export function for Piano.
Diffstat (limited to 'Applications/Piano')
-rw-r--r--Applications/Piano/AudioEngine.cpp18
-rw-r--r--Applications/Piano/AudioEngine.h1
-rw-r--r--Applications/Piano/main.cpp30
3 files changed, 49 insertions, 0 deletions
diff --git a/Applications/Piano/AudioEngine.cpp b/Applications/Piano/AudioEngine.cpp
index 8eec8938d8..c3ada8eb28 100644
--- a/Applications/Piano/AudioEngine.cpp
+++ b/Applications/Piano/AudioEngine.cpp
@@ -125,6 +125,24 @@ void AudioEngine::fill_buffer(FixedArray<Sample>& buffer)
swap(m_front_buffer_ptr, m_back_buffer_ptr);
}
+void AudioEngine::reset()
+{
+ memset(m_front_buffer.data(), 0, buffer_size);
+ memset(m_back_buffer.data(), 0, buffer_size);
+ m_front_buffer_ptr = &m_front_buffer;
+ m_back_buffer_ptr = &m_back_buffer;
+
+ m_delay_buffers.clear();
+
+ memset(m_note_on, 0, sizeof(m_note_on));
+ memset(m_power, 0, sizeof(m_power));
+ memset(m_envelope, 0, sizeof(m_envelope));
+
+ m_time = 0;
+ m_current_column = 0;
+ m_previous_column = horizontal_notes - 1;
+}
+
// All of the information for these waves is on Wikipedia.
double AudioEngine::sine(size_t note)
diff --git a/Applications/Piano/AudioEngine.h b/Applications/Piano/AudioEngine.h
index e722e0cfd0..72d3e17a13 100644
--- a/Applications/Piano/AudioEngine.h
+++ b/Applications/Piano/AudioEngine.h
@@ -40,6 +40,7 @@ public:
~AudioEngine();
const FixedArray<Sample>& buffer() const { return *m_front_buffer_ptr; }
+ void reset();
Switch roll_note(int y, int x) const { return m_roll_notes[y][x]; }
int current_column() const { return m_current_column; }
int octave() const { return m_octave; }
diff --git a/Applications/Piano/main.cpp b/Applications/Piano/main.cpp
index 4be57b21c2..18b0e3d02e 100644
--- a/Applications/Piano/main.cpp
+++ b/Applications/Piano/main.cpp
@@ -28,11 +28,14 @@
#include "AudioEngine.h"
#include "MainWidget.h"
#include <LibAudio/ClientConnection.h>
+#include <LibAudio/WavWriter.h>
#include <LibCore/File.h>
#include <LibGUI/GAboutDialog.h>
#include <LibGUI/GAction.h>
#include <LibGUI/GApplication.h>
+#include <LibGUI/GFilePicker.h>
#include <LibGUI/GMenuBar.h>
+#include <LibGUI/GMessageBox.h>
#include <LibGUI/GWindow.h>
#include <LibThread/Thread.h>
@@ -53,6 +56,10 @@ int main(int argc, char** argv)
window->set_icon(Gfx::Bitmap::load_from_file("/res/icons/16x16/app-piano.png"));
window->show();
+ Audio::WavWriter wav_writer;
+ Optional<String> save_path;
+ bool need_to_write_wav = false;
+
LibThread::Thread audio_thread([&] {
auto audio = Core::File::construct("/dev/audio");
if (!audio->open(Core::IODevice::WriteOnly)) {
@@ -66,6 +73,17 @@ int main(int argc, char** argv)
audio->write(reinterpret_cast<u8*>(buffer.data()), buffer_size);
Core::EventLoop::current().post_event(*main_widget, make<Core::CustomEvent>(0));
Core::EventLoop::wake();
+
+ if (need_to_write_wav) {
+ need_to_write_wav = false;
+ audio_engine.reset();
+ while (audio_engine.current_column() < horizontal_notes - 1) {
+ audio_engine.fill_buffer(buffer);
+ wav_writer.write_samples(reinterpret_cast<u8*>(buffer.data()), buffer_size);
+ }
+ audio_engine.reset();
+ wav_writer.finalize();
+ }
}
});
audio_thread.start();
@@ -77,6 +95,18 @@ int main(int argc, char** argv)
GUI::Application::the().quit(0);
return;
}));
+ app_menu->add_action(GUI::Action::create("Export", { Mod_Ctrl, Key_E }, [&](const GUI::Action&) {
+ save_path = GUI::FilePicker::get_save_filepath("Untitled", "wav");
+ if (!save_path.has_value())
+ return;
+ wav_writer.set_file(save_path.value());
+ if (wav_writer.has_error()) {
+ GUI::MessageBox::show(String::format("Failed to export WAV file: %s", wav_writer.error_string()), "Error", GUI::MessageBox::Type::Error);
+ wav_writer.clear_error();
+ return;
+ }
+ need_to_write_wav = true;
+ }));
menubar->add_menu(move(app_menu));
auto help_menu = GUI::Menu::construct("Help");