diff --git a/include/Menus/AudioMenu.hpp b/include/Menus/AudioMenu.hpp index c5f2c2d..0386cdb 100755 --- a/include/Menus/AudioMenu.hpp +++ b/include/Menus/AudioMenu.hpp @@ -16,6 +16,8 @@ enum AudioMenuOutAction{ AUDIO_MENU_VOLUME_INC, AUDIO_MENU_MAX_LATENCY_DEC, AUDIO_MENU_MAX_LATENCY_INC, + AUDIO_MENU_OUTPUT_DEC, + AUDIO_MENU_OUTPUT_INC, AUDIO_MENU_RESTART, }; diff --git a/include/Menus/OptionSelectionMenu.hpp b/include/Menus/OptionSelectionMenu.hpp index 900a269..2d0ccf9 100755 --- a/include/Menus/OptionSelectionMenu.hpp +++ b/include/Menus/OptionSelectionMenu.hpp @@ -54,6 +54,7 @@ protected: void prepare_options(); void base_prepare(float menu_scaling_factor, int view_size_x, int view_size_y); std::string setTextOptionInt(int index, int value); + std::string setTextOptionString(int index, std::string value); std::string setTextOptionBool(int index, bool value); std::string setTextOptionFloat(int index, float value, int num_decimals = 1); diff --git a/include/audio_data.hpp b/include/audio_data.hpp index a7f4157..ba586bf 100755 --- a/include/audio_data.hpp +++ b/include/audio_data.hpp @@ -4,14 +4,19 @@ #include #define MAX_MAX_AUDIO_LATENCY 10 +enum AudioOutputType {AUDIO_OUTPUT_STEREO, AUDIO_OUTPUT_MONO, AUDIO_OUTPUT_END}; + class AudioData { public: void reset(); - void set_max_audio_latency(int new_value); + void change_max_audio_latency(bool is_change_positive); + void change_audio_output_type(bool is_change_positive); void change_audio_volume(bool is_change_positive); void change_audio_mute(); void request_audio_restart(); bool check_audio_restart_request(); + AudioOutputType get_audio_output_type(); + std::string get_audio_output_name(); int get_max_audio_latency(); int get_final_volume(); bool has_text_to_print(); @@ -25,15 +30,19 @@ private: int volume; int max_audio_latency; bool mute; + AudioOutputType output_type; bool restart_request = false; bool text_updated; std::string text; + void set_max_audio_latency(int new_value); + void set_audio_output_type(int new_value); void set_audio_volume(int new_volume); void set_audio_mute(bool new_mute); void update_text(std::string text); const std::string max_audio_latency_str = "max_audio_latency"; const std::string volume_str = "volume"; const std::string mute_str = "mute"; + const std::string output_type_str = "audio_output_type"; }; #endif diff --git a/source/Menus/AudioMenu.cpp b/source/Menus/AudioMenu.cpp index 00b8d88..fd76442 100755 --- a/source/Menus/AudioMenu.cpp +++ b/source/Menus/AudioMenu.cpp @@ -27,6 +27,11 @@ static const AudioMenuOptionInfo audio_max_latency_option = { .is_inc = true, .dec_str = "-", .inc_str = "+", .inc_out_action = AUDIO_MENU_MAX_LATENCY_INC, .out_action = AUDIO_MENU_MAX_LATENCY_DEC}; +static const AudioMenuOptionInfo audio_output_type_option = { +.base_name = "Audio Output", .false_name = "", +.is_inc = true, .dec_str = "<", .inc_str = ">", .inc_out_action = AUDIO_MENU_OUTPUT_INC, +.out_action = AUDIO_MENU_OUTPUT_DEC}; + static const AudioMenuOptionInfo audio_restart_option = { .base_name = "Restart Audio", .false_name = "", .is_inc = false, .dec_str = "", .inc_str = "", .inc_out_action = AUDIO_MENU_NO_ACTION, @@ -36,6 +41,7 @@ static const AudioMenuOptionInfo* pollable_options[] = { &audio_volume_option, &audio_mute_option, &audio_max_latency_option, +&audio_output_type_option, &audio_restart_option, }; @@ -123,6 +129,9 @@ void AudioMenu::prepare(float menu_scaling_factor, int view_size_x, int view_siz case AUDIO_MENU_MAX_LATENCY_DEC: this->labels[index]->setText(this->setTextOptionInt(real_index, audio_data->get_max_audio_latency())); break; + case AUDIO_MENU_OUTPUT_DEC: + this->labels[index]->setText(this->setTextOptionString(real_index, audio_data->get_audio_output_name())); + break; case AUDIO_MENU_MUTE: this->labels[index]->setText(this->setTextOptionBool(real_index, audio_data->get_mute())); break; diff --git a/source/Menus/OptionSelectionMenu.cpp b/source/Menus/OptionSelectionMenu.cpp index dd7176b..96a0315 100755 --- a/source/Menus/OptionSelectionMenu.cpp +++ b/source/Menus/OptionSelectionMenu.cpp @@ -217,6 +217,10 @@ std::string OptionSelectionMenu::setTextOptionInt(int index, int value) { return this->get_string_option(index, DEFAULT_ACTION) + ": " + std::to_string(value); } +std::string OptionSelectionMenu::setTextOptionString(int index, std::string value) { + return this->get_string_option(index, DEFAULT_ACTION) + ": " + value; +} + std::string OptionSelectionMenu::setTextOptionBool(int index, bool value) { if(value) return this->get_string_option(index, DEFAULT_ACTION); diff --git a/source/WindowScreen_Menu.cpp b/source/WindowScreen_Menu.cpp index a05b4b7..3848815 100755 --- a/source/WindowScreen_Menu.cpp +++ b/source/WindowScreen_Menu.cpp @@ -1177,10 +1177,16 @@ void WindowScreen::poll(bool do_everything) { this->audio_data->change_audio_volume(true); break; case AUDIO_MENU_MAX_LATENCY_DEC: - this->audio_data->set_max_audio_latency(this->audio_data->get_max_audio_latency() - 1); + this->audio_data->change_max_audio_latency(false); break; case AUDIO_MENU_MAX_LATENCY_INC: - this->audio_data->set_max_audio_latency(this->audio_data->get_max_audio_latency() + 1); + this->audio_data->change_max_audio_latency(true); + break; + case AUDIO_MENU_OUTPUT_DEC: + this->audio_data->change_audio_output_type(false); + break; + case AUDIO_MENU_OUTPUT_INC: + this->audio_data->change_audio_output_type(true); break; case AUDIO_MENU_MUTE: this->audio_data->change_audio_mute(); diff --git a/source/audio.cpp b/source/audio.cpp index 2804f8d..cccc710 100755 --- a/source/audio.cpp +++ b/source/audio.cpp @@ -10,6 +10,13 @@ // Number of consecutive failures to restart the audio when switching output. #define AUDIO_FAILURE_THRESHOLD 20 +// Test for audio panning issues +//#define AUDIO_PANNING_TEST + +#ifdef AUDIO_PANNING_TEST +static int greatest_diff = 0; +#endif + Sample::Sample(sf::Int16 *bytes, std::size_t size, float time) : bytes(bytes), size(size), time(time) {} //============================================================================ @@ -97,6 +104,30 @@ bool Audio::onGetData(sf::SoundStream::Chunk &data) { samples.pop(); } + if(this->audio_data->get_audio_output_type() == AUDIO_OUTPUT_MONO) + for(int i = 0; i < data.sampleCount; i++) { + int sum = ((int)buffer[i * 2]) + buffer[(i * 2) + 1]; + if(sum >= 32768) + sum += 1; + else if((sum < 0) && (sum > -32768)) + sum += 1; + int avg = sum >> 1; + buffer[i * 2] = avg; + buffer[(i * 2) + 1] = avg; + } + + #ifdef AUDIO_PANNING_TEST + int max_diff = 0; + for(int i = 0; i < data.sampleCount; i++) { + int diff = abs(buffer[i * 2] - buffer[(i * 2) + 1]); + if(diff > max_diff) + max_diff = diff; + } + if(max_diff > greatest_diff) + greatest_diff = max_diff; + printf("Current diff: %d - Greatest measured diff: %d\n", max_diff, greatest_diff); + #endif + // Basically, look into how low the time between calls of the function is curr_time = std::chrono::high_resolution_clock::now(); clock_time_start = curr_time; diff --git a/source/audio_data.cpp b/source/audio_data.cpp index db47624..f6e2136 100755 --- a/source/audio_data.cpp +++ b/source/audio_data.cpp @@ -4,17 +4,29 @@ void AudioData::reset() { this->volume = 50; this->mute = false; this->max_audio_latency = 2; + this->output_type = AUDIO_OUTPUT_STEREO; this->restart_request = false; this->text_updated = false; } +void AudioData::change_max_audio_latency(bool is_change_positive) { + int change = 1; + if(!is_change_positive) + change = -1; + int initial_max_audio_latency = this->max_audio_latency; + this->set_max_audio_latency(this->max_audio_latency + change); + if(this->max_audio_latency != initial_max_audio_latency) + this->update_text("Max Audio Latency: " + std::to_string(this->max_audio_latency)); +} -void AudioData::set_max_audio_latency(int new_value) { - if(new_value > MAX_MAX_AUDIO_LATENCY) - new_value = MAX_MAX_AUDIO_LATENCY; - if(new_value <= 0) - new_value = 1; - this->max_audio_latency = new_value; +void AudioData::change_audio_output_type(bool is_change_positive) { + int change = 1; + if(!is_change_positive) + change = -1; + AudioOutputType initial_audio_output_type = this->output_type; + this->set_audio_output_type(this->output_type + change); + if(this->output_type != initial_audio_output_type) + this->update_text("Audio Output: " + this->get_audio_output_name()); } void AudioData::change_audio_volume(bool is_change_positive) { @@ -65,6 +77,27 @@ std::string AudioData::text_to_print() { return this->text; } +AudioOutputType AudioData::get_audio_output_type() { + return this->output_type; +} + +std::string AudioData::get_audio_output_name() { + std::string chosen_str = ""; + switch(this->output_type) { + case AUDIO_OUTPUT_STEREO: + chosen_str = "Stereo"; + break; + case AUDIO_OUTPUT_MONO: + chosen_str = "Mono"; + break; + default: + this->output_type = AUDIO_OUTPUT_STEREO; + chosen_str = "Stereo"; + break; + } + return chosen_str; +} + int AudioData::get_max_audio_latency() { return this->max_audio_latency; } @@ -106,6 +139,10 @@ bool AudioData::load_audio_data(std::string key, std::string value) { this->set_max_audio_latency(std::stoi(value)); return true; } + if (key == this->output_type_str) { + this->set_audio_output_type(std::stoi(value)); + return true; + } return false; } @@ -114,9 +151,26 @@ std::string AudioData::save_audio_data() { out_str += this->mute_str + "=" + std::to_string(this->mute) + "\n"; out_str += this->volume_str + "=" + std::to_string(this->volume) + "\n"; out_str += this->max_audio_latency_str + "=" + std::to_string(this->max_audio_latency) + "\n"; + out_str += this->output_type_str + "=" + std::to_string(this->output_type) + "\n"; return out_str; } +void AudioData::set_max_audio_latency(int new_value) { + if(new_value > MAX_MAX_AUDIO_LATENCY) + new_value = MAX_MAX_AUDIO_LATENCY; + if(new_value <= 0) + new_value = 1; + this->max_audio_latency = new_value; +} + +void AudioData::set_audio_output_type(int new_value) { + if(new_value >= AUDIO_OUTPUT_END) + new_value = 0; + if(new_value < 0) + new_value = AUDIO_OUTPUT_END - 1; + this->output_type = static_cast(new_value); +} + void AudioData::set_audio_volume(int new_volume) { if(new_volume < 0) new_volume = 0;