1717
1818#include < array>
1919#include < algorithm>
20+ #include < cmath>
2021#include " audio.h"
2122#include " audio_decoder_midi.h"
2223#include " midisequencer.h"
2324#include " output.h"
25+ #include " utils.h"
2426
2527using namespace std ::chrono_literals;
2628
@@ -38,6 +40,7 @@ constexpr int samples_per_play = 64 / sample_divider;
3840
3941static const uint8_t midi_set_reg_param_upper = 0x6 ;
4042static const uint8_t midi_control_volume = 0x7 ;
43+ static const uint8_t midi_control_pan = 0xA ;
4144static const uint8_t midi_event_control_change = 0xB ;
4245static const uint8_t midi_set_reg_param_lower = 0x26 ;
4346static const uint8_t midi_control_all_sound_off = 0x78 ;
@@ -66,6 +69,10 @@ static uint32_t midimsg_volume(uint8_t channel, uint8_t volume) {
6669 return midimsg_make (midi_event_control_change, channel, midi_control_volume, volume);
6770}
6871
72+ static uint32_t midimsg_pan (uint8_t channel, uint8_t pan) {
73+ return midimsg_make (midi_event_control_change, channel, midi_control_pan, pan);
74+ }
75+
6976static uint32_t midimsg_reset_all_controller (uint8_t channel) {
7077 return midimsg_make (midi_event_control_change, channel, midi_control_reset_all_controller, 0 );
7178}
@@ -112,6 +119,7 @@ AudioDecoderMidi::AudioDecoderMidi(std::unique_ptr<MidiDecoder> mididec)
112119 : mididec(std::move(mididec)) {
113120 seq = std::make_unique<midisequencer::sequencer>();
114121 channel_volumes.fill (127 );
122+ midi_requested_channel_pans.fill (64 );
115123 music_type = " midi" ;
116124}
117125
@@ -175,14 +183,14 @@ void AudioDecoderMidi::Resume() {
175183 }
176184}
177185
178- int AudioDecoderMidi::GetVolume () const {
186+ StereoVolume AudioDecoderMidi::GetVolume () const {
179187 // When handled by Midi messages fake a 100 otherwise the volume is adjusted twice
180188
181189 if (!mididec->SupportsMidiMessages ()) {
182- return static_cast < int >( log_volume) ;
190+ return log_volume;
183191 }
184192
185- return 100 ;
193+ return { 100 , 100 } ;
186194}
187195
188196void AudioDecoderMidi::SetVolume (int new_volume) {
@@ -195,9 +203,7 @@ void AudioDecoderMidi::SetVolume(int new_volume) {
195203 mididec->SendMidiMessage (msg);
196204 }
197205
198- if (!mididec->SupportsMidiMessages ()) {
199- log_volume = AdjustVolume (volume * 100 .0f );
200- }
206+ ApplyLogVolume ();
201207}
202208
203209void AudioDecoderMidi::SetFade (int end, std::chrono::milliseconds duration) {
@@ -214,6 +220,16 @@ void AudioDecoderMidi::SetFade(int end, std::chrono::milliseconds duration) {
214220 delta_volume_step = (fade_volume_end - volume) / fade_steps;
215221}
216222
223+ void AudioDecoderMidi::SetBalance (int new_balance) {
224+ AudioDecoderBase::SetBalance (new_balance);
225+ ApplyLogVolume ();
226+
227+ for (int channel = 0 ; channel < 16 ; channel++) {
228+ uint32_t msg = midimsg_pan (channel, ChannelPan (midi_requested_channel_pans[channel]));
229+ mididec->SendMidiMessage (msg);
230+ }
231+ }
232+
217233bool AudioDecoderMidi::Seek (std::streamoff offset, std::ios_base::seekdir origin) {
218234 assert (!tempo.empty ());
219235
@@ -251,9 +267,7 @@ void AudioDecoderMidi::Update(std::chrono::microseconds delta) {
251267 }
252268 if (fade_steps > 0 && mtime - last_fade_mtime > 0 .1s) {
253269 volume = Utils::Clamp<float >(volume + delta_volume_step, 0 .0f , 1 .0f );
254- if (!mididec->SupportsMidiMessages ()) {
255- log_volume = AdjustVolume (volume * 100 .0f );
256- }
270+ ApplyLogVolume ();
257271 for (int i = 0 ; i < 16 ; i++) {
258272 uint32_t msg = midimsg_volume (i, static_cast <uint8_t >(channel_volumes[i] * volume * global_volume));
259273 mididec->SendMidiMessage (msg);
@@ -392,6 +406,9 @@ void AudioDecoderMidi::midi_message(int, uint_least32_t message) {
392406 channel_volumes[channel] = value2;
393407 // Send the modified volume to midiout
394408 message = midimsg_volume (channel, static_cast <uint8_t >(value2 * volume * global_volume));
409+ } else if (event_type == midi_event_control_change && value1 == midi_control_pan) {
410+ midi_requested_channel_pans[channel] = value2;
411+ message = midimsg_pan (channel, ChannelPan (value2));
395412 }
396413 if (midimsg_validate (message)) {
397414 mididec->SendMidiMessage (message);
@@ -480,3 +497,23 @@ int AudioDecoderMidi::MidiTempoData::GetSamples(std::chrono::microseconds mtime_
480497 int ticks_since_last = static_cast <int >(ticks_per_us * delta.count ());
481498 return samples + static_cast <int >(ticks_since_last * samples_per_tick);
482499}
500+
501+ void AudioDecoderMidi::ApplyLogVolume () {
502+ if (!mididec->SupportsMidiMessages ()) {
503+ float base_gain = AdjustVolume (volume);
504+ int balance = GetBalance ();
505+ float left_gain = 1 .f , right_gain = 1 .f ;
506+ constexpr float pan_exp = 0 .5012f ;
507+ if (balance <= 50 ) {
508+ right_gain = std::pow (pan_exp, (50 - balance) / 10 .f );
509+ } else {
510+ left_gain = std::pow (pan_exp, (balance - 50 ) / 10 .f );
511+ }
512+ log_volume.left_volume = base_gain * left_gain;
513+ log_volume.right_volume = base_gain * right_gain;
514+ }
515+ }
516+
517+ int AudioDecoderMidi::ChannelPan (int desired_pan) const {
518+ return Utils::Clamp (desired_pan + ((GetBalance () - 50 ) * 2 ), 0 , 127 );
519+ }
0 commit comments