Update FluidSynth code, changing default gain, and letting it handle SysEx messages on its own
parent
9c58f67c48
commit
1a95c234b2
|
@ -12,42 +12,24 @@
|
||||||
|
|
||||||
#define _countof(x) (sizeof((x))/sizeof(((x)[0])))
|
#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()
|
SFPlayer::SFPlayer() : MIDIPlayer()
|
||||||
{
|
{
|
||||||
_synth = 0;
|
_synth[0] = 0;
|
||||||
|
_synth[1] = 0;
|
||||||
|
_synth[2] = 0;
|
||||||
uInterpolationMethod = FLUID_INTERP_DEFAULT;
|
uInterpolationMethod = FLUID_INTERP_DEFAULT;
|
||||||
|
|
||||||
reset_drums();
|
|
||||||
|
|
||||||
synth_mode = mode_gm;
|
|
||||||
|
|
||||||
_settings = new_fluid_settings();
|
_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_setnum(_settings, "synth.sample-rate", 44100);
|
||||||
fluid_settings_setint(_settings, "synth.midi-channels", 48);
|
fluid_settings_setint(_settings, "synth.midi-channels", 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
SFPlayer::~SFPlayer()
|
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);
|
if (_settings) delete_fluid_settings(_settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +37,8 @@ void SFPlayer::setInterpolationMethod(unsigned method)
|
||||||
{
|
{
|
||||||
shutdown();
|
shutdown();
|
||||||
uInterpolationMethod = method;
|
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)
|
void SFPlayer::send_event(uint32_t b)
|
||||||
|
@ -67,9 +50,10 @@ void SFPlayer::send_event(uint32_t b)
|
||||||
int cmd = b & 0xF0;
|
int cmd = b & 0xF0;
|
||||||
int chan = b & 0x0F;
|
int chan = b & 0x0F;
|
||||||
int port = (b >> 24) & 0x7F;
|
int port = (b >> 24) & 0x7F;
|
||||||
|
fluid_synth_t* _synth = this->_synth[0];
|
||||||
|
|
||||||
if ( port && port < 3 )
|
if ( port && port < 3 )
|
||||||
chan += port * 16;
|
_synth = this->_synth[port];
|
||||||
|
|
||||||
switch (cmd)
|
switch (cmd)
|
||||||
{
|
{
|
||||||
|
@ -83,28 +67,8 @@ void SFPlayer::send_event(uint32_t b)
|
||||||
break;
|
break;
|
||||||
case 0xB0:
|
case 0xB0:
|
||||||
fluid_synth_cc(_synth, chan, param1, param2);
|
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;
|
break;
|
||||||
case 0xC0:
|
case 0xC0:
|
||||||
if ( drum_channels [chan] ) fluid_synth_bank_select(_synth, chan, 16256 /*DRUM_INST_BANK*/);
|
|
||||||
fluid_synth_program_change(_synth, chan, param1);
|
fluid_synth_program_change(_synth, chan, param1);
|
||||||
break;
|
break;
|
||||||
case 0xD0:
|
case 0xD0:
|
||||||
|
@ -123,49 +87,33 @@ void SFPlayer::send_event(uint32_t b)
|
||||||
mSysexMap.get_entry( n, data, size, port );
|
mSysexMap.get_entry( n, data, size, port );
|
||||||
if (port >= 3)
|
if (port >= 3)
|
||||||
port = 0;
|
port = 0;
|
||||||
if ( ( size == _countof( sysex_gm_reset ) && !memcmp( data, sysex_gm_reset, _countof( sysex_gm_reset ) ) ) ||
|
fluid_synth_sysex(_synth[port], (const char *)data, size, NULL, NULL, NULL, 0);
|
||||||
( 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];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SFPlayer::render(float * out, unsigned long count)
|
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 )
|
void SFPlayer::setSoundFont( const char * in )
|
||||||
|
@ -182,25 +130,29 @@ void SFPlayer::setFileSoundFont( const char * in )
|
||||||
|
|
||||||
void SFPlayer::shutdown()
|
void SFPlayer::shutdown()
|
||||||
{
|
{
|
||||||
if (_synth) delete_fluid_synth(_synth);
|
for (unsigned int i = 0; i < 3; ++i)
|
||||||
_synth = 0;
|
{
|
||||||
|
if (_synth[i]) delete_fluid_synth(_synth[i]);
|
||||||
|
_synth[i] = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SFPlayer::startup()
|
bool SFPlayer::startup()
|
||||||
{
|
{
|
||||||
if ( _synth ) return true;
|
if ( _synth[0] && _synth[1] && _synth[2] ) return true;
|
||||||
|
|
||||||
fluid_settings_setnum(_settings, "synth.sample-rate", uSampleRate);
|
fluid_settings_setnum(_settings, "synth.sample-rate", uSampleRate);
|
||||||
|
|
||||||
_synth = new_fluid_synth(_settings);
|
for (unsigned int i = 0; i < 3; ++i)
|
||||||
if (!_synth)
|
|
||||||
{
|
{
|
||||||
_last_error = "Out of memory";
|
_synth[i] = new_fluid_synth(_settings);
|
||||||
return false;
|
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())
|
if (sSoundFontName.length())
|
||||||
{
|
{
|
||||||
std::string ext;
|
std::string ext;
|
||||||
|
@ -209,12 +161,15 @@ bool SFPlayer::startup()
|
||||||
ext.assign( sSoundFontName.begin() + dot + 1, sSoundFontName.end() );
|
ext.assign( sSoundFontName.begin() + dot + 1, sSoundFontName.end() );
|
||||||
if ( !strcasecmp( ext.c_str(), "sf2" ) || !strcasecmp( ext.c_str(), "sf3" ) )
|
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();
|
if ( FLUID_FAILED == fluid_synth_sfload( _synth[i], sSoundFontName.c_str(), 1) )
|
||||||
_last_error = "Failed to load SoundFont bank: ";
|
{
|
||||||
_last_error += sSoundFontName;
|
shutdown();
|
||||||
return false;
|
_last_error = "Failed to load SoundFont bank: ";
|
||||||
|
_last_error += sSoundFontName;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( !strcasecmp( ext.c_str(), "sflist" ) )
|
else if ( !strcasecmp( ext.c_str(), "sflist" ) )
|
||||||
|
@ -244,13 +199,16 @@ bool SFPlayer::startup()
|
||||||
temp = path;
|
temp = path;
|
||||||
temp += name;
|
temp += name;
|
||||||
}
|
}
|
||||||
if ( FLUID_FAILED == fluid_synth_sfload( _synth, temp.c_str(), 1 ) )
|
for (unsigned i = 0; i < 3; ++i)
|
||||||
{
|
{
|
||||||
fclose( fl );
|
if ( FLUID_FAILED == fluid_synth_sfload( _synth[i], temp.c_str(), 1 ) )
|
||||||
shutdown();
|
{
|
||||||
_last_error = "Failed to load SoundFont bank: ";
|
fclose( fl );
|
||||||
_last_error += temp;
|
shutdown();
|
||||||
return false;
|
_last_error = "Failed to load SoundFont bank: ";
|
||||||
|
_last_error += temp;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fclose( fl );
|
fclose( fl );
|
||||||
|
@ -266,12 +224,15 @@ bool SFPlayer::startup()
|
||||||
|
|
||||||
if ( sFileSoundFontName.length() )
|
if ( sFileSoundFontName.length() )
|
||||||
{
|
{
|
||||||
if ( FLUID_FAILED == fluid_synth_sfload(_synth, sFileSoundFontName.c_str(), 1) )
|
for (unsigned i = 0; i < 3; ++i)
|
||||||
{
|
{
|
||||||
shutdown();
|
if ( FLUID_FAILED == fluid_synth_sfload(_synth[i], sFileSoundFontName.c_str(), 1) )
|
||||||
_last_error = "Failed to load SoundFont bank: ";
|
{
|
||||||
_last_error += sFileSoundFontName;
|
shutdown();
|
||||||
return false;
|
_last_error = "Failed to load SoundFont bank: ";
|
||||||
|
_last_error += sFileSoundFontName;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,33 +241,6 @@ bool SFPlayer::startup()
|
||||||
return true;
|
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
|
const char * SFPlayer::GetLastError() const
|
||||||
{
|
{
|
||||||
if ( _last_error.length() ) return _last_error.c_str();
|
if ( _last_error.length() ) return _last_error.c_str();
|
||||||
|
|
|
@ -39,25 +39,11 @@ private:
|
||||||
std::string _last_error;
|
std::string _last_error;
|
||||||
|
|
||||||
fluid_settings_t * _settings;
|
fluid_settings_t * _settings;
|
||||||
fluid_synth_t * _synth;
|
fluid_synth_t * _synth[3];
|
||||||
std::string sSoundFontName;
|
std::string sSoundFontName;
|
||||||
std::string sFileSoundFontName;
|
std::string sFileSoundFontName;
|
||||||
|
|
||||||
unsigned uInterpolationMethod;
|
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 */
|
#endif /* SFPlayer_h */
|
||||||
|
|
Loading…
Reference in New Issue