summaryrefslogtreecommitdiff
path: root/Applications/Piano
diff options
context:
space:
mode:
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");