From 62c95a5de87674562273073de86ab09438997ff8 Mon Sep 17 00:00:00 2001 From: Goldenkrew3000 Date: Sat, 25 Oct 2025 22:05:03 +1000 Subject: [PATCH] Added frontend pitch and volume control --- src/gui/gui_entry.cpp | 22 ++++++++++++++++++-- src/gui/gui_entry.hpp | 2 +- src/main.c | 2 +- src/player/player.c | 48 +++++++++++++++++++++++++++++++++++-------- src/player/player.h | 5 +++++ 5 files changed, 67 insertions(+), 12 deletions(-) diff --git a/src/gui/gui_entry.cpp b/src/gui/gui_entry.cpp index 2a6af68..36d7e7e 100644 --- a/src/gui/gui_entry.cpp +++ b/src/gui/gui_entry.cpp @@ -23,7 +23,7 @@ bool bAudioSettingsShow = false; void showLikedSongs(); void showAudioSettings(); -int qt_gui_entry(int argc, char** argv) { +int gui_entry() { // Initialize SDL if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0) { printf("SDL could not be initialized: %s\n", SDL_GetError()); @@ -196,20 +196,38 @@ void showLikedSongs() { } float in_volume_val = 0; +float out_volume_val = 0; +float pitch_val = 0; bool hasInVolumeFirstRun = false; void showAudioSettings() { ImGui::Begin("Audio Settings"); if (!hasInVolumeFirstRun) { in_volume_val = OSSPlayer_GstECont_InVolume_Get(); + out_volume_val = OSSPlayer_GstECont_OutVolume_Get(); + pitch_val = configObj->audio_pitch_cents / 100.0f; // Cents to semitones hasInVolumeFirstRun = true; } + ImGui::Text("In Vol / Out Vol"); + // Idk what that field is, styling?, Size, Storage, Low, High - if (ImGui::VSliderFloat("##v", ImVec2(35, 160), &in_volume_val, 0.0f, 1.0f)) { + if (ImGui::VSliderFloat("##invol", ImVec2(35, 160), &in_volume_val, 0.0f, 1.0f)) { // Data has changed OSSPlayer_GstECont_InVolume_set(in_volume_val); } + ImGui::SameLine(); + + if (ImGui::VSliderFloat("##outvol", ImVec2(35, 160), &out_volume_val, 0.0f, 1.0f)) { + OSSPlayer_GstECont_OutVolume_set(out_volume_val); + } + + ImGui::SameLine(); + + if (ImGui::VSliderFloat("##pitch", ImVec2(35, 160), &pitch_val, -6.00f, 6.00f)) { + OSSPlayer_GstECont_Pitch_Set(pitch_val * 100.0f); // Convert semitones to cents + } + ImGui::End(); } diff --git a/src/gui/gui_entry.hpp b/src/gui/gui_entry.hpp index dd7200a..4cf2e36 100644 --- a/src/gui/gui_entry.hpp +++ b/src/gui/gui_entry.hpp @@ -11,7 +11,7 @@ extern "C" { #endif // __cplusplus -int qt_gui_entry(int argc, char** argv); +int gui_entry(); #ifdef __cplusplus } diff --git a/src/main.c b/src/main.c index 785ec3b..2269c68 100644 --- a/src/main.c +++ b/src/main.c @@ -68,7 +68,7 @@ int main(int argc, char** argv) { discordrpc_struct_deinit(&discordrpc); // Launch QT frontend - qt_gui_entry(argc, argv); + gui_entry(); // Cleanup and exit configHandler_Free(&configObj); diff --git a/src/player/player.c b/src/player/player.c index 2ed41bd..6ef69c5 100644 --- a/src/player/player.c +++ b/src/player/player.c @@ -22,7 +22,7 @@ extern configHandler_config_t* configObj; static int rc = 0; -GstElement *pipeline, *playbin, *filter_bin, *conv_in, *conv_out, *in_volume, *equalizer, *pitch, *reverb; +GstElement *pipeline, *playbin, *filter_bin, *conv_in, *conv_out, *in_volume, *equalizer, *pitch, *reverb, *out_volume; GstPad *sink_pad, *src_pad; GstBus* bus; guint bus_watch_id; @@ -216,6 +216,7 @@ int OSSPlayer_GstInit() { // Calf Studio Plugins Reverb reverb = gst_element_factory_make(configObj->lv2_reverb_filter_name, "reverb"); } + out_volume = gst_element_factory_make("volume", "out-volume"); // TODO: Make better error messages for here, and exit out early if (!equalizer) { logger_log_error(__func__, "Could not initialize equalizer."); @@ -229,8 +230,8 @@ int OSSPlayer_GstInit() { // Add and link elements to the filter bin // TODO: Check creation and dynamic as per config - gst_bin_add_many(GST_BIN(filter_bin), conv_in, in_volume, equalizer, conv_out, NULL); - gst_element_link_many(conv_in, in_volume, equalizer, conv_out, NULL); + gst_bin_add_many(GST_BIN(filter_bin), conv_in, in_volume, equalizer, pitch, out_volume, conv_out, NULL); + gst_element_link_many(conv_in, in_volume, equalizer, pitch, out_volume, conv_out, NULL); sink_pad = gst_element_get_static_pad(conv_in, "sink"); src_pad = gst_element_get_static_pad(conv_out, "src"); gst_element_add_pad(filter_bin, gst_ghost_pad_new("sink", sink_pad)); @@ -240,7 +241,7 @@ int OSSPlayer_GstInit() { // Setup playbin3 (Configure audio plugins and set user agent) g_object_set(playbin, "audio-filter", filter_bin, NULL); - g_signal_connect (playbin, "source-setup", G_CALLBACK(gst_playbin3_sourcesetup_callback), NULL); + g_signal_connect(playbin, "source-setup", G_CALLBACK(gst_playbin3_sourcesetup_callback), NULL); // Add playbin3 to the pipeline gst_bin_add(GST_BIN(pipeline), playbin); @@ -248,6 +249,9 @@ int OSSPlayer_GstInit() { // Initialize in-volume (Volume before the audio reaches the plugins) g_object_set(in_volume, "volume", 0.175, NULL); + // Initialize out-volume (Volume after the audio plugins) + g_object_set(out_volume, "volume", 1.00, NULL); + // Initialize equalizer if (configObj->audio_equalizer_enable) { printf("Initializing %d equalizer bands...\n", configObj->audio_equalizer_graphCount); @@ -296,7 +300,7 @@ int OSSPlayer_GstInit() { g_object_set(equalizer, fl_name, freq, NULL); g_object_set(equalizer, fr_name, freq, NULL); } else { - printf("EQ band %d - F: %.2f / G: %.2f / Q: 4.36\n", i + 1, (float)configObj->audio_equalizer_graph[i].frequency, gain); + printf("EQ band %d - F: %.2f(Nfp) / G: %.2f / Q: 4.36\n", i + 1, (float)configObj->audio_equalizer_graph[i].frequency, gain); g_object_set(equalizer, fl_name, (float)configObj->audio_equalizer_graph[i].frequency, NULL); g_object_set(equalizer, fr_name, (float)configObj->audio_equalizer_graph[i].frequency, NULL); } @@ -315,9 +319,11 @@ int OSSPlayer_GstInit() { } // Initialize pitch - - - + if (configObj->audio_pitch_enable) { + float scaleFactor = OSSPlayer_CentsToPSF(configObj->audio_pitch_cents); + printf("Pitch Cents: %.2f, Scale factor: %.6f\n", configObj->audio_pitch_cents, scaleFactor); + g_object_set(pitch, "pitch", scaleFactor, NULL); + } // Initialize reverb } @@ -348,6 +354,7 @@ char* OSSPlayer_QueuePopFront() { /* * Gstreamer Element Control Functions */ +// TODO: Consolidate volume functions? float OSSPlayer_GstECont_InVolume_Get() { gdouble vol; g_object_get(in_volume, "volume", &vol, NULL); @@ -358,6 +365,25 @@ void OSSPlayer_GstECont_InVolume_set(float val) { g_object_set(in_volume, "volume", val, NULL); } +float OSSPlayer_GstECont_OutVolume_Get() { + gdouble vol; + g_object_get(out_volume, "volume", &vol, NULL); + return (float)vol; +} + +void OSSPlayer_GstECont_OutVolume_set(float val) { + g_object_set(out_volume, "volume", val, NULL); +} + +float OSSPlayer_GstECont_Pitch_Get() { + // +} + +void OSSPlayer_GstECont_Pitch_Set(float cents) { + float psf = OSSPlayer_CentsToPSF(cents); + g_object_set(pitch, "pitch", psf, NULL); +} + /* * Utility Functions */ @@ -370,3 +396,9 @@ float OSSPlayer_PitchFollow(float freq, float semitone) { // Calculate new EQ frequency from semitone adjustment return freq * pow(2.0, semitone / 12.0); } + +float OSSPlayer_CentsToPSF(float cents) { + // Convert Cents to a Pitch Scale Factor + float semitone = cents / 100.0; + return pow(2, (semitone / 12.0f)); +} diff --git a/src/player/player.h b/src/player/player.h index 61b404a..2f7ef9d 100644 --- a/src/player/player.h +++ b/src/player/player.h @@ -19,9 +19,14 @@ char* OSSPlayer_QueuePopFront(); float OSSPlayer_GstECont_InVolume_Get(); void OSSPlayer_GstECont_InVolume_set(float val); +float OSSPlayer_GstECont_OutVolume_Get(); +void OSSPlayer_GstECont_OutVolume_set(float val); +float OSSPlayer_GstECont_Pitch_Get(); +void OSSPlayer_GstECont_Pitch_Set(float cents); float OSSPlayer_DbLinMul(float db); float OSSPlayer_PitchFollow(float freq, float semitone); +float OSSPlayer_CentsToPSF(float cents); #ifdef __cplusplus }