Add audio playback to gui
This commit is contained in:
parent
e3228fa03d
commit
419ee8fd7c
84
main.cpp
84
main.cpp
@ -10,7 +10,8 @@
|
|||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#define MINIAUDIO_IMPLEMENTATION
|
||||||
|
#include "miniaudio.h"
|
||||||
#include "tinyfiledialogs.h"
|
#include "tinyfiledialogs.h"
|
||||||
|
|
||||||
|
|
||||||
@ -31,6 +32,11 @@ float bpm = 120.0f; // Default BPM
|
|||||||
float zoom_level = 1.0f; // Zoom level
|
float zoom_level = 1.0f; // Zoom level
|
||||||
float pan_offset = 0.0f; // Pan offset
|
float pan_offset = 0.0f; // Pan offset
|
||||||
|
|
||||||
|
// audio stuff
|
||||||
|
ma_sound sound;
|
||||||
|
ma_engine engine;
|
||||||
|
bool audioLoaded = false;
|
||||||
|
|
||||||
|
|
||||||
const int num_channels = 512;
|
const int num_channels = 512;
|
||||||
unsigned char buffer[num_channels] = { 0 };
|
unsigned char buffer[num_channels] = { 0 };
|
||||||
@ -87,6 +93,11 @@ int main() {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ma_engine_init(NULL, &engine) != MA_SUCCESS) {
|
||||||
|
std::cerr << "Failed to initialize audio engine." << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
GLFWwindow* window = initOpenGL();
|
GLFWwindow* window = initOpenGL();
|
||||||
if (!window) {
|
if (!window) {
|
||||||
CloseHandle(hSerial);
|
CloseHandle(hSerial);
|
||||||
@ -126,6 +137,8 @@ int main() {
|
|||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
CloseHandle(hSerial);
|
CloseHandle(hSerial);
|
||||||
|
|
||||||
|
ma_engine_uninit(&engine);
|
||||||
|
|
||||||
return 0;
|
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() {
|
GLFWwindow* initOpenGL() {
|
||||||
if (!glfwInit()) {
|
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
|
// Create sliders for the first three DMX channels
|
||||||
ImGui::SliderInt("Channel 1", &channel1, 0, 255);
|
ImGui::SliderInt("Channel 1", &channel1, 0, 255);
|
||||||
@ -290,14 +332,46 @@ void renderImGui() {
|
|||||||
// Allow user to set the total duration of the timeline and BPM
|
// 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("Timeline Duration (seconds)", &timeline_duration, 1.0f, 300.0f);
|
||||||
ImGui::SliderFloat("BPM", &bpm, 30.0f, 240.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
|
// Play/Pause button
|
||||||
if (ImGui::Button(is_playing ? "Pause" : "Play")) {
|
if (ImGui::Button(is_playing ? "Pause" : "Play")) {
|
||||||
is_playing = !is_playing;
|
is_playing = !is_playing;
|
||||||
if (is_playing) {
|
if (is_playing) {
|
||||||
playback_start_time = static_cast<float>(glfwGetTime()) - timeline_position;
|
playback_start_time = static_cast<float>(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<ma_uint64>((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)
|
// Time Slider (Timeline Position)
|
||||||
ImGui::SliderFloat("Timeline Position", &timeline_position, 0.0f, timeline_duration, "%.2f sec");
|
ImGui::SliderFloat("Timeline Position", &timeline_position, 0.0f, timeline_duration, "%.2f sec");
|
||||||
@ -356,22 +430,24 @@ void renderImGui() {
|
|||||||
current_time = static_cast<float>(glfwGetTime()) - playback_start_time;
|
current_time = static_cast<float>(glfwGetTime()) - playback_start_time;
|
||||||
timeline_position = current_time;
|
timeline_position = current_time;
|
||||||
|
|
||||||
// Trigger markers during playback
|
|
||||||
for (const auto& marker : markers) {
|
for (const auto& marker : markers) {
|
||||||
float marker_time = std::get<0>(marker) * timeline_duration;
|
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[0] = std::get<1>(marker);
|
||||||
buffer[1] = std::get<2>(marker);
|
buffer[1] = std::get<2>(marker);
|
||||||
buffer[2] = std::get<3>(marker);
|
buffer[2] = std::get<3>(marker);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop playback when the timeline reaches the end
|
|
||||||
if (timeline_position >= timeline_duration) {
|
if (timeline_position >= timeline_duration) {
|
||||||
is_playing = false;
|
is_playing = false;
|
||||||
timeline_position = timeline_duration;
|
timeline_position = timeline_duration;
|
||||||
|
if (audioLoaded) {
|
||||||
|
ma_sound_stop(&sound);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Display added markers with their RGB values and time
|
// Display added markers with their RGB values and time
|
||||||
for (const auto& marker : markers) {
|
for (const auto& marker : markers) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user