2121#include " audio_decoder_midi.h"
2222#include " midisequencer.h"
2323#include " output.h"
24+ #include " utils.h"
2425
2526using namespace std ::chrono_literals;
2627
@@ -38,6 +39,7 @@ constexpr int samples_per_play = 64 / sample_divider;
3839
3940static const uint8_t midi_set_reg_param_upper = 0x6 ;
4041static const uint8_t midi_control_volume = 0x7 ;
42+ static const uint8_t midi_control_pan = 0xA ;
4143static const uint8_t midi_event_control_change = 0xB ;
4244static const uint8_t midi_set_reg_param_lower = 0x26 ;
4345static const uint8_t midi_control_all_sound_off = 0x78 ;
@@ -66,6 +68,10 @@ static uint32_t midimsg_volume(uint8_t channel, uint8_t volume) {
6668 return midimsg_make (midi_event_control_change, channel, midi_control_volume, volume);
6769}
6870
71+ static uint32_t midimsg_pan (uint8_t channel, uint8_t pan) {
72+ return midimsg_make (midi_event_control_change, channel, midi_control_pan, pan);
73+ }
74+
6975static uint32_t midimsg_reset_all_controller (uint8_t channel) {
7076 return midimsg_make (midi_event_control_change, channel, midi_control_reset_all_controller, 0 );
7177}
@@ -175,14 +181,15 @@ void AudioDecoderMidi::Resume() {
175181 }
176182}
177183
178- int AudioDecoderMidi::GetVolume () const {
184+ std::pair< int , int > AudioDecoderMidi::GetVolume () const {
179185 // When handled by Midi messages fake a 100 otherwise the volume is adjusted twice
180186
181187 if (!mididec->SupportsMidiMessages ()) {
182- return static_cast <int >(log_volume);
188+ const auto & [left, right] = log_volume;
189+ return std::pair (static_cast <int >(left), static_cast <int >(right));
183190 }
184191
185- return 100 ;
192+ return { 100 , 100 } ;
186193}
187194
188195void AudioDecoderMidi::SetVolume (int new_volume) {
@@ -195,9 +202,7 @@ void AudioDecoderMidi::SetVolume(int new_volume) {
195202 mididec->SendMidiMessage (msg);
196203 }
197204
198- if (!mididec->SupportsMidiMessages ()) {
199- log_volume = AdjustVolume (volume * 100 .0f );
200- }
205+ SetLogVolume ();
201206}
202207
203208void AudioDecoderMidi::SetFade (int end, std::chrono::milliseconds duration) {
@@ -214,6 +219,19 @@ void AudioDecoderMidi::SetFade(int end, std::chrono::milliseconds duration) {
214219 delta_volume_step = (fade_volume_end - volume) / fade_steps;
215220}
216221
222+ void AudioDecoderMidi::SetBalance (int new_balance) {
223+ AudioDecoderBase::SetBalance (new_balance);
224+ SetLogVolume ();
225+
226+ uint8_t pan = Utils::Clamp (last_known_midi_pan + ((GetBalance () - 50 ) * 2 ), 0 , 127 );
227+ for (int channel = 0 ; channel < 16 ; channel++) {
228+ uint32_t msg = midimsg_pan (channel, pan);
229+ mididec->SendMidiMessage (msg);
230+ }
231+
232+ Output::Warning (" setting balance to {}" , new_balance);
233+ }
234+
217235bool AudioDecoderMidi::Seek (std::streamoff offset, std::ios_base::seekdir origin) {
218236 assert (!tempo.empty ());
219237
@@ -251,9 +269,7 @@ void AudioDecoderMidi::Update(std::chrono::microseconds delta) {
251269 }
252270 if (fade_steps > 0 && mtime - last_fade_mtime > 0 .1s) {
253271 volume = Utils::Clamp<float >(volume + delta_volume_step, 0 .0f , 1 .0f );
254- if (!mididec->SupportsMidiMessages ()) {
255- log_volume = AdjustVolume (volume * 100 .0f );
256- }
272+ SetLogVolume ();
257273 for (int i = 0 ; i < 16 ; i++) {
258274 uint32_t msg = midimsg_volume (i, static_cast <uint8_t >(channel_volumes[i] * volume * global_volume));
259275 mididec->SendMidiMessage (msg);
@@ -392,6 +408,12 @@ void AudioDecoderMidi::midi_message(int, uint_least32_t message) {
392408 channel_volumes[channel] = value2;
393409 // Send the modified volume to midiout
394410 message = midimsg_volume (channel, static_cast <uint8_t >(value2 * volume * global_volume));
411+ } else if (event_type == midi_event_control_change && value1 == midi_control_pan) {
412+ // See #2585 for details on MIDI values processed by RPG_RT
413+ last_known_midi_pan = value2;
414+ uint8_t pan = Utils::Clamp (value2 + ((GetBalance () - 50 ) * 2 ), 0 , 127 );
415+ Output::Warning (" want={} changed={} balance={}" , value2, pan, GetBalance ());
416+ message = midimsg_pan (channel, pan);
395417 }
396418 if (midimsg_validate (message)) {
397419 mididec->SendMidiMessage (message);
@@ -480,3 +502,17 @@ int AudioDecoderMidi::MidiTempoData::GetSamples(std::chrono::microseconds mtime_
480502 int ticks_since_last = static_cast <int >(ticks_per_us * delta.count ());
481503 return samples + static_cast <int >(ticks_since_last * samples_per_tick);
482504}
505+
506+ void AudioDecoderMidi::SetLogVolume () {
507+ if (!mididec->SupportsMidiMessages ()) {
508+ int balance = GetBalance ();
509+ float left_gain = 1 .f , right_gain = 1 .f ;
510+ if (balance <= 50 ) {
511+ right_gain = balance / 50 .f ;
512+ } else {
513+ left_gain = (100 - balance) / 50 .f ;
514+ }
515+ log_volume.first = AdjustVolume (volume * left_gain);
516+ log_volume.second = AdjustVolume (volume * right_gain);
517+ }
518+ }
0 commit comments