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])))
|
||||
|
||||
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)
|
||||
{
|
||||
_synth[i] = new_fluid_synth(_settings);
|
||||
if (!_synth[i])
|
||||
{
|
||||
_last_error = "Out of memory";
|
||||
return false;
|
||||
}
|
||||
fluid_synth_set_interp_method( _synth, -1, uInterpolationMethod );
|
||||
reset_drums();
|
||||
synth_mode = mode_gm;
|
||||
fluid_synth_set_interp_method( _synth[i], -1, uInterpolationMethod );
|
||||
}
|
||||
if (sSoundFontName.length())
|
||||
{
|
||||
std::string ext;
|
||||
|
@ -209,7 +161,9 @@ 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)
|
||||
{
|
||||
if ( FLUID_FAILED == fluid_synth_sfload( _synth[i], sSoundFontName.c_str(), 1) )
|
||||
{
|
||||
shutdown();
|
||||
_last_error = "Failed to load SoundFont bank: ";
|
||||
|
@ -217,6 +171,7 @@ bool SFPlayer::startup()
|
|||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( !strcasecmp( ext.c_str(), "sflist" ) )
|
||||
{
|
||||
FILE * fl = fopen( sSoundFontName.c_str(), "r" );
|
||||
|
@ -244,7 +199,9 @@ 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)
|
||||
{
|
||||
if ( FLUID_FAILED == fluid_synth_sfload( _synth[i], temp.c_str(), 1 ) )
|
||||
{
|
||||
fclose( fl );
|
||||
shutdown();
|
||||
|
@ -253,6 +210,7 @@ bool SFPlayer::startup()
|
|||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose( fl );
|
||||
}
|
||||
else
|
||||
|
@ -266,7 +224,9 @@ bool SFPlayer::startup()
|
|||
|
||||
if ( sFileSoundFontName.length() )
|
||||
{
|
||||
if ( FLUID_FAILED == fluid_synth_sfload(_synth, sFileSoundFontName.c_str(), 1) )
|
||||
for (unsigned i = 0; i < 3; ++i)
|
||||
{
|
||||
if ( FLUID_FAILED == fluid_synth_sfload(_synth[i], sFileSoundFontName.c_str(), 1) )
|
||||
{
|
||||
shutdown();
|
||||
_last_error = "Failed to load SoundFont bank: ";
|
||||
|
@ -274,39 +234,13 @@ bool SFPlayer::startup()
|
|||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_last_error = "";
|
||||
|
||||
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();
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue