From 419ee8fd7cc23b044a7fa0db1125c3d81d3f37c1 Mon Sep 17 00:00:00 2001 From: illyum <90023277+itzilly@users.noreply.github.com> Date: Fri, 9 Aug 2024 00:58:20 -0600 Subject: [PATCH] Add audio playback to gui --- main.cpp | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 80 insertions(+), 4 deletions(-) diff --git a/main.cpp b/main.cpp index 9779ef6..5fccf62 100644 --- a/main.cpp +++ b/main.cpp @@ -10,7 +10,8 @@ #include #include #include - +#define MINIAUDIO_IMPLEMENTATION +#include "miniaudio.h" #include "tinyfiledialogs.h" @@ -31,6 +32,11 @@ float bpm = 120.0f; // Default BPM float zoom_level = 1.0f; // Zoom level float pan_offset = 0.0f; // Pan offset +// audio stuff +ma_sound sound; +ma_engine engine; +bool audioLoaded = false; + const int num_channels = 512; unsigned char buffer[num_channels] = { 0 }; @@ -87,6 +93,11 @@ int main() { return 1; } + if (ma_engine_init(NULL, &engine) != MA_SUCCESS) { + std::cerr << "Failed to initialize audio engine." << std::endl; + return -1; + } + GLFWwindow* window = initOpenGL(); if (!window) { CloseHandle(hSerial); @@ -126,6 +137,8 @@ int main() { glfwTerminate(); CloseHandle(hSerial); + ma_engine_uninit(&engine); + return 0; } @@ -195,6 +208,28 @@ void loadMarkersFromFile(const std::string& filename) { } } +void loadAndPlayAudio(const std::string& filename) { + if (audioLoaded) { + ma_sound_uninit(&sound); + } + + if (ma_sound_init_from_file(&engine, filename.c_str(), MA_SOUND_FLAG_STREAM, NULL, NULL, &sound) == MA_SUCCESS) { + audioLoaded = true; + ma_sound_start(&sound); + } + else { + std::cerr << "Failed to load audio file: " << filename << std::endl; + } +} + +std::string OpenAudioFileDialog() { + const char* filterPatterns[2] = { "*.mp3", "*.wav" }; + const char* filename = tinyfd_openFileDialog("Select an audio file", "", 2, filterPatterns, NULL, 0); + if (filename) { + return std::string(filename); + } + return ""; +} GLFWwindow* initOpenGL() { if (!glfwInit()) { @@ -276,6 +311,13 @@ void renderImGui() { } } + if (ImGui::Button("Load Audio File")) { + std::string filename = OpenAudioFileDialog(); + if (!filename.empty()) { + loadAndPlayAudio(filename); + } + } + // Create sliders for the first three DMX channels ImGui::SliderInt("Channel 1", &channel1, 0, 255); @@ -290,13 +332,45 @@ void renderImGui() { // Allow user to set the total duration of the timeline and BPM ImGui::SliderFloat("Timeline Duration (seconds)", &timeline_duration, 1.0f, 300.0f); ImGui::SliderFloat("BPM", &bpm, 30.0f, 240.0f); + ImGui::SameLine(); + ImGui::SetNextItemWidth(50); + if (ImGui::InputFloat("##BPMInput", &bpm, 0.0f, 0.0f, "%.1f")) { + if (bpm < 30.0f) bpm = 30.0f; + if (bpm > 240.0f) bpm = 240.0f; + } + // Play/Pause button if (ImGui::Button(is_playing ? "Pause" : "Play")) { is_playing = !is_playing; if (is_playing) { playback_start_time = static_cast(glfwGetTime()) - timeline_position; + if (audioLoaded) { + ma_uint64 frameCount; + ma_sound_get_length_in_pcm_frames(&sound, &frameCount); + + // Calculate the frame to seek to based on the timeline position + ma_uint64 targetFrame = static_cast((timeline_position / timeline_duration) * frameCount); + ma_sound_seek_to_pcm_frame(&sound, targetFrame); + + ma_sound_start(&sound); + } } + else { + if (audioLoaded) { + ma_sound_stop(&sound); + } + } + } + + // Stop Music button + ImGui::SameLine(); + if (ImGui::Button("Stop Music")) { + if (audioLoaded) { + ma_sound_stop(&sound); + } + is_playing = false; + timeline_position = 0.0f; } // Time Slider (Timeline Position) @@ -356,23 +430,25 @@ void renderImGui() { current_time = static_cast(glfwGetTime()) - playback_start_time; timeline_position = current_time; - // Trigger markers during playback for (const auto& marker : markers) { float marker_time = std::get<0>(marker) * timeline_duration; - if (current_time >= marker_time && current_time < marker_time + 0.025f) { // Slight tolerance for timing precision + if (current_time >= marker_time && current_time < marker_time + 0.025f) { buffer[0] = std::get<1>(marker); buffer[1] = std::get<2>(marker); buffer[2] = std::get<3>(marker); } } - // Stop playback when the timeline reaches the end if (timeline_position >= timeline_duration) { is_playing = false; timeline_position = timeline_duration; + if (audioLoaded) { + ma_sound_stop(&sound); + } } } + // Display added markers with their RGB values and time for (const auto& marker : markers) { float marker_time = std::get<0>(marker) * timeline_duration;