diff --git a/Plugins/MIDI/MIDI/SFPlayer.cpp b/Plugins/MIDI/MIDI/SFPlayer.cpp index 890879cbe..9a7475a1b 100644 --- a/Plugins/MIDI/MIDI/SFPlayer.cpp +++ b/Plugins/MIDI/MIDI/SFPlayer.cpp @@ -12,42 +12,24 @@ #define _countof(x) (sizeof((x))/sizeof(((x)[0]))) -static const uint8_t sysex_gm_reset[] = { 0xF0, 0x7E, 0x7F, 0x09, 0x01, 0xF7 }; -static const uint8_t sysex_gm2_reset[]= { 0xF0, 0x7E, 0x7F, 0x09, 0x03, 0xF7 }; -static const uint8_t sysex_gs_reset[] = { 0xF0, 0x41, 0x10, 0x42, 0x12, 0x40, 0x00, 0x7F, 0x00, 0x41, 0xF7 }; -static const uint8_t sysex_xg_reset[] = { 0xF0, 0x43, 0x10, 0x4C, 0x00, 0x00, 0x7E, 0x00, 0xF7 }; - -static bool is_gs_reset(const unsigned char * data, unsigned long size) -{ - if ( size != _countof( sysex_gs_reset ) ) return false; - - if ( memcmp( data, sysex_gs_reset, 5 ) != 0 ) return false; - if ( memcmp( data + 7, sysex_gs_reset + 7, 2 ) != 0 ) return false; - if ( ( ( data[ 5 ] + data[ 6 ] + 1 ) & 127 ) != data[ 9 ] ) return false; - if ( data[ 10 ] != sysex_gs_reset[ 10 ] ) return false; - - return true; -} - SFPlayer::SFPlayer() : MIDIPlayer() { - _synth = 0; + _synth[0] = 0; + _synth[1] = 0; + _synth[2] = 0; uInterpolationMethod = FLUID_INTERP_DEFAULT; - reset_drums(); - - synth_mode = mode_gm; - _settings = new_fluid_settings(); - fluid_settings_setnum(_settings, "synth.gain", 1.0); + fluid_settings_setnum(_settings, "synth.gain", 0.2); fluid_settings_setnum(_settings, "synth.sample-rate", 44100); - fluid_settings_setint(_settings, "synth.midi-channels", 48); + fluid_settings_setint(_settings, "synth.midi-channels", 16); } SFPlayer::~SFPlayer() { - if (_synth) delete_fluid_synth(_synth); + for (unsigned int i = 0; i < 3; ++i) + if (_synth[i]) delete_fluid_synth(_synth[i]); if (_settings) delete_fluid_settings(_settings); } @@ -55,7 +37,8 @@ void SFPlayer::setInterpolationMethod(unsigned method) { shutdown(); uInterpolationMethod = method; - if ( _synth ) fluid_synth_set_interp_method( _synth, -1, method ); + for (unsigned int i = 0; i < 3; ++i) + if ( _synth[i] ) fluid_synth_set_interp_method( _synth[i], -1, method ); } void SFPlayer::send_event(uint32_t b) @@ -67,9 +50,10 @@ void SFPlayer::send_event(uint32_t b) int cmd = b & 0xF0; int chan = b & 0x0F; int port = (b >> 24) & 0x7F; + fluid_synth_t* _synth = this->_synth[0]; if ( port && port < 3 ) - chan += port * 16; + _synth = this->_synth[port]; switch (cmd) { @@ -83,28 +67,8 @@ void SFPlayer::send_event(uint32_t b) break; case 0xB0: fluid_synth_cc(_synth, chan, param1, param2); - if ( param1 == 0 || param1 == 0x20 ) - { - unsigned bank = channel_banks[ chan ]; - if ( param1 == 0x20 ) bank = ( bank & 0x3F80 ) | ( param2 & 0x7F ); - else bank = ( bank & 0x007F ) | ( ( param2 & 0x7F ) << 7 ); - channel_banks[ chan ] = bank; - if ( synth_mode == mode_xg ) - { - if ( bank == 16256 ) drum_channels [chan] = 1; - else drum_channels [chan] = 0; - } - else if ( synth_mode == mode_gm2 ) - { - if ( bank == 15360 ) - drum_channels [chan] = 1; - else if ( bank == 15488 ) - drum_channels [chan] = 0; - } - } break; case 0xC0: - if ( drum_channels [chan] ) fluid_synth_bank_select(_synth, chan, 16256 /*DRUM_INST_BANK*/); fluid_synth_program_change(_synth, chan, param1); break; case 0xD0: @@ -123,49 +87,33 @@ void SFPlayer::send_event(uint32_t b) mSysexMap.get_entry( n, data, size, port ); if (port >= 3) port = 0; - if ( ( size == _countof( sysex_gm_reset ) && !memcmp( data, sysex_gm_reset, _countof( sysex_gm_reset ) ) ) || - ( size == _countof( sysex_gm2_reset ) && !memcmp( data, sysex_gm2_reset, _countof( sysex_gm2_reset ) ) ) || - is_gs_reset( data, size ) || - ( size == _countof( sysex_xg_reset ) && !memcmp( data, sysex_xg_reset, _countof( sysex_xg_reset ) ) ) ) - { - fluid_synth_system_reset( _synth ); - reset_drums(); - synth_mode = ( size == _countof( sysex_xg_reset ) ) ? mode_xg : - ( size == _countof( sysex_gs_reset ) ) ? mode_gs : - ( data [4] == 0x01 ) ? mode_gm : - mode_gm2; - } - else if ( synth_mode == mode_gs && size == 11 && - data [0] == 0xF0 && data [1] == 0x41 && data [3] == 0x42 && - data [4] == 0x12 && data [5] == 0x40 && (data [6] & 0xF0) == 0x10 && - data [10] == 0xF7) - { - if (data [7] == 2) - { - // GS MIDI channel to part assign - gs_part_to_ch [ ( port * 16 ) + ( data [6] & 15 ) ] = data [8]; - } - else if ( data [7] == 0x15 ) - { - // GS part to rhythm allocation - unsigned int drum_channel = gs_part_to_ch [ ( port * 16 ) + ( data [6] & 15 ) ]; - if ( drum_channel < 16 ) - { - drum_channels [ ( port * 16 ) + drum_channel ] = data [8]; - if ( port == 0 ) - { - drum_channels [ 16 + drum_channel ] = data [8]; - drum_channels [ 32 + drum_channel ] = data [8]; - } - } - } - } + fluid_synth_sysex(_synth[port], (const char *)data, size, NULL, NULL, NULL, 0); } } void SFPlayer::render(float * out, unsigned long count) { - fluid_synth_write_float(_synth, count, out, 0, 2, out, 1, 2); + unsigned long done = 0; + memset(out, 0, sizeof(float) * 2 * count); + while (done < count) + { + float buffer[512 * 2]; + unsigned long todo = count - done; + unsigned long i; + if (todo > 512) todo = 512; + for (unsigned long j = 0; j < 3; ++j) + { + memset(buffer, 0, sizeof(buffer)); + fluid_synth_write_float(_synth[j], todo, buffer, 0, 2, buffer, 1, 2); + for (i = 0; i < todo; ++i) + { + out[i * 2 + 0] += buffer[i * 2 + 0]; + out[i * 2 + 1] += buffer[i * 2 + 1]; + } + } + out += todo * 2; + done += todo; + } } void SFPlayer::setSoundFont( const char * in ) @@ -182,25 +130,29 @@ void SFPlayer::setFileSoundFont( const char * in ) void SFPlayer::shutdown() { - if (_synth) delete_fluid_synth(_synth); - _synth = 0; + for (unsigned int i = 0; i < 3; ++i) + { + if (_synth[i]) delete_fluid_synth(_synth[i]); + _synth[i] = 0; + } } bool SFPlayer::startup() { - if ( _synth ) return true; + if ( _synth[0] && _synth[1] && _synth[2] ) return true; fluid_settings_setnum(_settings, "synth.sample-rate", uSampleRate); - _synth = new_fluid_synth(_settings); - if (!_synth) + for (unsigned int i = 0; i < 3; ++i) { - _last_error = "Out of memory"; - return false; + _synth[i] = new_fluid_synth(_settings); + if (!_synth[i]) + { + _last_error = "Out of memory"; + return false; + } + fluid_synth_set_interp_method( _synth[i], -1, uInterpolationMethod ); } - fluid_synth_set_interp_method( _synth, -1, uInterpolationMethod ); - reset_drums(); - synth_mode = mode_gm; if (sSoundFontName.length()) { std::string ext; @@ -209,12 +161,15 @@ bool SFPlayer::startup() ext.assign( sSoundFontName.begin() + dot + 1, sSoundFontName.end() ); if ( !strcasecmp( ext.c_str(), "sf2" ) || !strcasecmp( ext.c_str(), "sf3" ) ) { - if ( FLUID_FAILED == fluid_synth_sfload( _synth, sSoundFontName.c_str(), 1) ) + for (unsigned i = 0; i < 3; ++i) { - shutdown(); - _last_error = "Failed to load SoundFont bank: "; - _last_error += sSoundFontName; - return false; + if ( FLUID_FAILED == fluid_synth_sfload( _synth[i], sSoundFontName.c_str(), 1) ) + { + shutdown(); + _last_error = "Failed to load SoundFont bank: "; + _last_error += sSoundFontName; + return false; + } } } else if ( !strcasecmp( ext.c_str(), "sflist" ) ) @@ -244,13 +199,16 @@ bool SFPlayer::startup() temp = path; temp += name; } - if ( FLUID_FAILED == fluid_synth_sfload( _synth, temp.c_str(), 1 ) ) + for (unsigned i = 0; i < 3; ++i) { - fclose( fl ); - shutdown(); - _last_error = "Failed to load SoundFont bank: "; - _last_error += temp; - return false; + if ( FLUID_FAILED == fluid_synth_sfload( _synth[i], temp.c_str(), 1 ) ) + { + fclose( fl ); + shutdown(); + _last_error = "Failed to load SoundFont bank: "; + _last_error += temp; + return false; + } } } fclose( fl ); @@ -266,12 +224,15 @@ bool SFPlayer::startup() if ( sFileSoundFontName.length() ) { - if ( FLUID_FAILED == fluid_synth_sfload(_synth, sFileSoundFontName.c_str(), 1) ) + for (unsigned i = 0; i < 3; ++i) { - shutdown(); - _last_error = "Failed to load SoundFont bank: "; - _last_error += sFileSoundFontName; - return false; + if ( FLUID_FAILED == fluid_synth_sfload(_synth[i], sFileSoundFontName.c_str(), 1) ) + { + shutdown(); + _last_error = "Failed to load SoundFont bank: "; + _last_error += sFileSoundFontName; + return false; + } } } @@ -280,33 +241,6 @@ bool SFPlayer::startup() return true; } -void SFPlayer::reset_drums() -{ - static const uint8_t part_to_ch[16] = { 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15 }; - - memset( drum_channels, 0, sizeof( drum_channels ) ); - drum_channels [9] = 1; - drum_channels [9+16] = 1; - drum_channels [9+32] = 1; - - memcpy( gs_part_to_ch, part_to_ch, sizeof( gs_part_to_ch ) ); - memcpy( gs_part_to_ch+16, part_to_ch, sizeof( gs_part_to_ch ) ); - memcpy( gs_part_to_ch+32, part_to_ch, sizeof( gs_part_to_ch ) ); - - memset( channel_banks, 0, sizeof( channel_banks ) ); - - if ( _synth ) - { - for ( unsigned i = 0; i < 48; ++i ) - { - if ( drum_channels [i] ) - { - fluid_synth_bank_select( _synth, i, 16256 /*DRUM_INST_BANK*/); - } - } - } -} - const char * SFPlayer::GetLastError() const { if ( _last_error.length() ) return _last_error.c_str(); diff --git a/Plugins/MIDI/MIDI/SFPlayer.h b/Plugins/MIDI/MIDI/SFPlayer.h index 69ff96f60..ea2f5669b 100644 --- a/Plugins/MIDI/MIDI/SFPlayer.h +++ b/Plugins/MIDI/MIDI/SFPlayer.h @@ -39,25 +39,11 @@ private: std::string _last_error; fluid_settings_t * _settings; - fluid_synth_t * _synth; + fluid_synth_t * _synth[3]; std::string sSoundFontName; std::string sFileSoundFontName; unsigned uInterpolationMethod; - - enum - { - mode_gm = 0, - mode_gm2, - mode_gs, - mode_xg - } - synth_mode; - - void reset_drums(); - uint8_t drum_channels[48]; - uint8_t gs_part_to_ch[48]; - unsigned short channel_banks[48]; }; #endif /* SFPlayer_h */