Added sflist channel and preset redirection control, just like foo_midi
parent
16396ad20a
commit
2e07cf29a0
|
@ -1,5 +1,7 @@
|
||||||
#include "BMPlayer.h"
|
#include "BMPlayer.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
@ -244,6 +246,8 @@ void BMPlayer::send_event(uint32_t b)
|
||||||
unsigned command = b & 0xF0;
|
unsigned command = b & 0xF0;
|
||||||
unsigned event_length = ( command == 0xC0 || command == 0xD0 ) ? 2 : 3;
|
unsigned event_length = ( command == 0xC0 || command == 0xD0 ) ? 2 : 3;
|
||||||
channel += 16 * port;
|
channel += 16 * port;
|
||||||
|
channel %= 48;
|
||||||
|
if ( command == 0xB0 && event[ 1 ] == 0x20 ) return;
|
||||||
BASS_MIDI_StreamEvents( _stream, BASS_MIDI_EVENTS_RAW + 1 + channel, event, event_length );
|
BASS_MIDI_StreamEvents( _stream, BASS_MIDI_EVENTS_RAW + 1 + channel, event, event_length );
|
||||||
if ( command == 0xB0 && event[ 1 ] == 0 )
|
if ( command == 0xB0 && event[ 1 ] == 0 )
|
||||||
{
|
{
|
||||||
|
@ -280,7 +284,7 @@ void BMPlayer::send_event(uint32_t b)
|
||||||
is_gs_reset( data, size ) ||
|
is_gs_reset( data, size ) ||
|
||||||
( size == _countof( sysex_xg_reset ) && !memcmp( data, sysex_xg_reset, _countof( sysex_xg_reset ) ) ) )
|
( size == _countof( sysex_xg_reset ) && !memcmp( data, sysex_xg_reset, _countof( sysex_xg_reset ) ) ) )
|
||||||
{
|
{
|
||||||
reset_drum_channels();
|
reset_parameters();
|
||||||
synth_mode = ( size == _countof( sysex_xg_reset ) ) ? mode_xg :
|
synth_mode = ( size == _countof( sysex_xg_reset ) ) ? mode_xg :
|
||||||
( size == _countof( sysex_gs_reset ) ) ? mode_gs :
|
( size == _countof( sysex_gs_reset ) ) ? mode_gs :
|
||||||
( data [4] == 0x01 ) ? mode_gm :
|
( data [4] == 0x01 ) ? mode_gm :
|
||||||
|
@ -347,6 +351,8 @@ bool BMPlayer::startup()
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
memset( bank_lsb_override, 0, sizeof( bank_lsb_override ) );
|
||||||
|
std::vector<BASS_MIDI_FONTEX> presetList;
|
||||||
if (sSoundFontName.length())
|
if (sSoundFontName.length())
|
||||||
{
|
{
|
||||||
std::string ext;
|
std::string ext;
|
||||||
|
@ -364,7 +370,8 @@ bool BMPlayer::startup()
|
||||||
shutdown();
|
shutdown();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
_soundFonts.push_back( font );
|
_soundFonts.push_back( font );
|
||||||
|
presetList.push_back( {font, -1, -1, -1, 0, 0} );
|
||||||
}
|
}
|
||||||
else if ( !strcasecmp( ext.c_str(), "sflist" ) )
|
else if ( !strcasecmp( ext.c_str(), "sflist" ) )
|
||||||
{
|
{
|
||||||
|
@ -373,24 +380,197 @@ bool BMPlayer::startup()
|
||||||
{
|
{
|
||||||
std::string path, temp;
|
std::string path, temp;
|
||||||
char name[32768];
|
char name[32768];
|
||||||
|
char *nameptr;
|
||||||
size_t slash = sSoundFontName.find_last_of('/');
|
size_t slash = sSoundFontName.find_last_of('/');
|
||||||
if ( slash != std::string::npos ) path.assign( sSoundFontName.begin(), sSoundFontName.begin() + slash + 1 );
|
if ( slash != std::string::npos ) path.assign( sSoundFontName.begin(), sSoundFontName.begin() + slash + 1 );
|
||||||
while ( !feof( fl ) )
|
while ( !feof( fl ) )
|
||||||
{
|
{
|
||||||
|
std::vector<BASS_MIDI_FONTEX> presets;
|
||||||
|
|
||||||
if ( !fgets( name, 32767, fl ) ) break;
|
if ( !fgets( name, 32767, fl ) ) break;
|
||||||
name[32767] = 0;
|
name[32767] = 0;
|
||||||
char * cr = strchr( name, '\n' );
|
char * cr = strchr( name, '\n' );
|
||||||
if ( cr ) *cr = 0;
|
if ( cr ) *cr = 0;
|
||||||
cr = strchr( name, '\r' );
|
cr = strchr( name, '\r' );
|
||||||
if ( cr ) *cr = 0;
|
if ( cr ) *cr = 0;
|
||||||
if ( name[0] == '/' )
|
cr = strchr( name, '|' );
|
||||||
|
if ( cr )
|
||||||
|
{
|
||||||
|
long dbank = 0, dpreset = -1, sbank = -1, spreset = -1;
|
||||||
|
std::vector<long> channels;
|
||||||
|
bool valid = true;
|
||||||
|
bool pushed_back = true;
|
||||||
|
char *endchr;
|
||||||
|
nameptr = cr + 1;
|
||||||
|
*cr = 0;
|
||||||
|
cr = name;
|
||||||
|
while ( *cr && valid )
|
||||||
|
{
|
||||||
|
switch ( *cr++ )
|
||||||
|
{
|
||||||
|
case 'p':
|
||||||
|
{
|
||||||
|
// patch override - "p[db#,]dp#=[sb#,]sp#" ex. "p0,5=0,1"
|
||||||
|
// may be used once per preset group
|
||||||
|
pushed_back = false;
|
||||||
|
dbank = 0;
|
||||||
|
dpreset = strtol( cr, &endchr, 10 );
|
||||||
|
if ( endchr == cr )
|
||||||
|
{
|
||||||
|
valid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ( *endchr == ',' )
|
||||||
|
{
|
||||||
|
dbank = dpreset;
|
||||||
|
cr = endchr + 1;
|
||||||
|
dpreset = strtol( cr, &endchr, 10 );
|
||||||
|
if ( endchr == cr )
|
||||||
|
{
|
||||||
|
valid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( *endchr != '=' )
|
||||||
|
{
|
||||||
|
valid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cr = endchr + 1;
|
||||||
|
sbank = -1;
|
||||||
|
spreset = strtol( cr, &endchr, 10 );
|
||||||
|
if ( endchr == cr )
|
||||||
|
{
|
||||||
|
valid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ( *endchr == ',' )
|
||||||
|
{
|
||||||
|
sbank = spreset;
|
||||||
|
cr = endchr + 1;
|
||||||
|
spreset = strtol( cr, &endchr, 10 );
|
||||||
|
if ( endchr == cr )
|
||||||
|
{
|
||||||
|
cr = nameptr - 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( *endchr && *endchr != ';' && *endchr != '&' )
|
||||||
|
{
|
||||||
|
cr = nameptr - 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cr = endchr;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'c':
|
||||||
|
{
|
||||||
|
// channel override - implemented using bank LSB, which is disabled from
|
||||||
|
// actual use. - format "c#" ex. "c16" (range is 1-48)
|
||||||
|
// may be used multiple times per preset group
|
||||||
|
pushed_back = false;
|
||||||
|
long channel = strtol(cr, &endchr, 10);
|
||||||
|
if ( endchr == cr )
|
||||||
|
{
|
||||||
|
valid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ( channel < 1 || channel > 48 )
|
||||||
|
{
|
||||||
|
valid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for ( auto it = channels.begin(); it != channels.end(); ++it )
|
||||||
|
{
|
||||||
|
if ( *it == channel )
|
||||||
|
{
|
||||||
|
valid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( *endchr && *endchr != ';' )
|
||||||
|
{
|
||||||
|
valid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cr = endchr;
|
||||||
|
channels.push_back( channel );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '&':
|
||||||
|
{
|
||||||
|
// separates preset groups per SoundFont bank
|
||||||
|
if ( !pushed_back )
|
||||||
|
{
|
||||||
|
if ( channels.size() )
|
||||||
|
{
|
||||||
|
for ( auto it = channels.begin(); it != channels.end(); ++it )
|
||||||
|
{
|
||||||
|
bank_lsb_override[ *it - 1 ] = *it;
|
||||||
|
|
||||||
|
int dbanklsb = (int) *it;
|
||||||
|
presets.push_back( { 0, (int) spreset, (int) sbank, (int) dpreset, (int) dbank, dbanklsb } );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
presets.push_back( { 0, (int) spreset, (int) sbank, (int) dpreset, (int) dbank, 0 } );
|
||||||
|
}
|
||||||
|
sbank = -1; spreset = -1; dpreset = -1; dbank = 0; channels.clear();
|
||||||
|
pushed_back = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ';':
|
||||||
|
// separates preset items
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// invalid command character
|
||||||
|
valid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( !pushed_back && valid )
|
||||||
|
{
|
||||||
|
if ( channels.size() )
|
||||||
|
{
|
||||||
|
for ( auto it = channels.begin(); it != channels.end(); ++it )
|
||||||
|
{
|
||||||
|
bank_lsb_override[ *it - 1 ] = *it;
|
||||||
|
|
||||||
|
int dbanklsb = (int) *it;
|
||||||
|
presets.push_back( { 0, (int) spreset, (int) sbank, (int) dpreset, (int) dbank, dbanklsb } );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
presets.push_back( { 0, (int) spreset, (int) sbank, (int) dpreset, (int) dbank, 0 } );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( !valid )
|
||||||
|
{
|
||||||
|
presets.clear();
|
||||||
|
presets.push_back( { 0, -1, -1, -1, 0, 0 } );
|
||||||
|
memset( bank_lsb_override, 0, sizeof(bank_lsb_override) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
presets.push_back( { 0, -1, -1, -1, 0, 0 } );
|
||||||
|
nameptr = name;
|
||||||
|
}
|
||||||
|
if ( nameptr[0] == '/' )
|
||||||
{
|
{
|
||||||
temp = name;
|
temp = nameptr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
temp = path;
|
temp = path;
|
||||||
temp += name;
|
temp += nameptr;
|
||||||
}
|
}
|
||||||
HSOUNDFONT font = cache_open( temp.c_str() );
|
HSOUNDFONT font = cache_open( temp.c_str() );
|
||||||
if ( !font )
|
if ( !font )
|
||||||
|
@ -399,7 +579,12 @@ bool BMPlayer::startup()
|
||||||
shutdown();
|
shutdown();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
_soundFonts.push_back( font );
|
for ( auto it = presets.begin(); it != presets.end(); ++it )
|
||||||
|
{
|
||||||
|
it->font = font;
|
||||||
|
presetList.push_back( *it );
|
||||||
|
}
|
||||||
|
_soundFonts.push_back( font );
|
||||||
}
|
}
|
||||||
fclose( fl );
|
fclose( fl );
|
||||||
}
|
}
|
||||||
|
@ -418,28 +603,25 @@ bool BMPlayer::startup()
|
||||||
shutdown();
|
shutdown();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
_soundFonts.push_back( font );
|
_soundFonts.push_back( font );
|
||||||
|
presetList.push_back( { font, -1, -1, -1, 0, 0 } );
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector< BASS_MIDI_FONT > fonts;
|
std::vector< BASS_MIDI_FONTEX > fonts;
|
||||||
for ( unsigned long i = 0, j = _soundFonts.size(); i < j; ++i )
|
for ( unsigned long i = 0, j = presetList.size(); i < j; ++i )
|
||||||
{
|
{
|
||||||
BASS_MIDI_FONT sf;
|
fonts.push_back( presetList[j - i - 1] );
|
||||||
sf.font = _soundFonts[ j - i - 1 ];
|
|
||||||
sf.preset = -1;
|
|
||||||
sf.bank = 0;
|
|
||||||
fonts.push_back( sf );
|
|
||||||
}
|
}
|
||||||
BASS_MIDI_StreamSetFonts( _stream, &fonts[0], (unsigned int) fonts.size() );
|
BASS_MIDI_StreamSetFonts( _stream, &fonts[0], (unsigned int) fonts.size() | BASS_MIDI_FONT_EX );
|
||||||
|
|
||||||
reset_drum_channels();
|
reset_parameters();
|
||||||
|
|
||||||
synth_mode = mode_gm;
|
synth_mode = mode_gm;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BMPlayer::reset_drum_channels()
|
void BMPlayer::reset_parameters()
|
||||||
{
|
{
|
||||||
static const uint8_t part_to_ch[16] = { 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15 };
|
static const uint8_t part_to_ch[16] = { 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15 };
|
||||||
|
|
||||||
|
@ -458,4 +640,7 @@ void BMPlayer::reset_drum_channels()
|
||||||
BASS_MIDI_StreamEvent( _stream, i, MIDI_EVENT_DRUMS, drum_channels[ i ] );
|
BASS_MIDI_StreamEvent( _stream, i, MIDI_EVENT_DRUMS, drum_channels[ i ] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for ( unsigned int i = 0; i < 48; ++i )
|
||||||
|
BASS_MIDI_StreamEvent( _stream, i, MIDI_EVENT_BANK_LSB, bank_lsb_override[i] );
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ private:
|
||||||
virtual void shutdown();
|
virtual void shutdown();
|
||||||
virtual bool startup();
|
virtual bool startup();
|
||||||
|
|
||||||
void reset_drum_channels();
|
void reset_parameters();
|
||||||
|
|
||||||
std::vector<HSOUNDFONT> _soundFonts;
|
std::vector<HSOUNDFONT> _soundFonts;
|
||||||
std::string sSoundFontName;
|
std::string sSoundFontName;
|
||||||
|
@ -47,6 +47,7 @@ private:
|
||||||
|
|
||||||
uint8_t gs_part_to_ch[3][16];
|
uint8_t gs_part_to_ch[3][16];
|
||||||
uint8_t drum_channels[48];
|
uint8_t drum_channels[48];
|
||||||
|
uint8_t bank_lsb_override[48];
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue