@ -84,6 +84,7 @@ CSysExFileLoader::~CSysExFileLoader (void)
void CSysExFileLoader : : Load ( bool bHeaderlessSysExVoices )
void CSysExFileLoader : : Load ( bool bHeaderlessSysExVoices )
{
{
m_nNumHighestBank = 0 ;
m_nNumHighestBank = 0 ;
m_nBanksLoaded = 0 ;
DIR * pDirectory = opendir ( m_DirName . c_str ( ) ) ;
DIR * pDirectory = opendir ( m_DirName . c_str ( ) ) ;
if ( ! pDirectory )
if ( ! pDirectory )
@ -96,107 +97,155 @@ void CSysExFileLoader::Load (bool bHeaderlessSysExVoices)
dirent * pEntry ;
dirent * pEntry ;
while ( ( pEntry = readdir ( pDirectory ) ) ! = nullptr )
while ( ( pEntry = readdir ( pDirectory ) ) ! = nullptr )
{
{
unsigned nBank ;
LoadBank ( m_DirName . c_str ( ) , pEntry - > d_name , bHeaderlessSysExVoices , 0 ) ;
size_t nLen = strlen ( pEntry - > d_name ) ;
}
LOGDBG ( " %u Banks loaded. Highest Bank loaded: #%u " , m_nBanksLoaded , m_nNumHighestBank ) ;
if ( nLen < 5 // "[NNNN]N[_name].syx"
closedir ( pDirectory ) ;
| | strcasecmp ( & pEntry - > d_name [ nLen - 4 ] , " .syx " ) ! = 0
}
| | sscanf ( pEntry - > d_name , " %u " , & nBank ) ! = 1 )
{
LOGWARN ( " %s: Invalid filename format " , pEntry - > d_name ) ;
continue ;
void CSysExFileLoader : : LoadBank ( const char * sDirName , const char * sBankName , bool bHeaderlessSysExVoices , unsigned nSubDirCount )
}
{
unsigned nBank ;
size_t nLen = strlen ( sBankName ) ;
if ( nLen < 5 // "[NNNN]N[_name].syx"
| | strcasecmp ( & sBankName [ nLen - 4 ] , " .syx " ) ! = 0
| | sscanf ( sBankName , " %u " , & nBank ) ! = 1 )
{
// See if this is a subdirectory...
std : : string Dirname ( sDirName ) ;
Dirname + = " / " ;
Dirname + = sBankName ;
if ( nBank > MaxVoiceBankID )
DIR * pDirectory = opendir ( Dirname . c_str ( ) ) ;
if ( pDirectory )
{
{
LOGWARN ( " Bank #%u is not supported " , nBank ) ;
if ( nSubDirCount > = MaxSubDirs )
{
LOGWARN ( " Too many nested subdirectories: %s " , sBankName ) ;
return ;
}
LOGDBG ( " Processing subdirectory %s " , sBankName ) ;
continue ;
dirent * pEntry ;
while ( ( pEntry = readdir ( pDirectory ) ) ! = nullptr )
{
LoadBank ( Dirname . c_str ( ) , pEntry - > d_name , bHeaderlessSysExVoices , nSubDirCount + 1 ) ;
}
closedir ( pDirectory ) ;
}
}
else
if ( m_pVoiceBank [ nBank ] )
{
{
LOGWARN ( " Bank #%u already loaded " , nBank ) ;
LOGWARN ( " %s: Invalid filename format " , sBankName ) ;
continue ;
}
}
m_pVoiceBank [ nBank ] = new TVoiceBank ;
return ;
assert ( m_pVoiceBank [ nBank ] ) ;
}
assert ( sizeof ( TVoiceBank ) = = VoiceSysExHdrSize + VoiceSysExSize ) ;
// File and UI handling requires banks to be 1..indexed.
// Internally (and via MIDI) we need 0..indexed.
// Any mention of a BankID internally is assumed to be 0..indexed.
unsigned nBankIdx = nBank - 1 ;
// BankIdx goes from 0 to MaxVoiceBankID inclusive
if ( nBankIdx > MaxVoiceBankID )
{
LOGWARN ( " Bank #%u is not supported " , nBank ) ;
return ;
}
std : : string Filename ( m_DirName ) ;
if ( m_pVoiceBank [ nBankIdx ] )
Filename + = " / " ;
{
Filename + = pEntry - > d_name ;
LOGWARN ( " Bank #%u already loaded " , nBank ) ;
return ;
}
FILE * pFile = fopen ( Filename . c_str ( ) , " rb " ) ;
m_pVoiceBank [ nBankIdx ] = new TVoiceBank ;
if ( pFile )
assert ( m_pVoiceBank [ nBankIdx ] ) ;
assert ( sizeof ( TVoiceBank ) = = VoiceSysExHdrSize + VoiceSysExSize ) ;
std : : string Filename ( sDirName ) ;
Filename + = " / " ;
Filename + = sBankName ;
FILE * pFile = fopen ( Filename . c_str ( ) , " rb " ) ;
if ( pFile )
{
bool bBankLoaded = false ;
if ( fread ( m_pVoiceBank [ nBankIdx ] , VoiceSysExHdrSize + VoiceSysExSize , 1 , pFile ) = = 1
& & m_pVoiceBank [ nBankIdx ] - > StatusStart = = 0xF0
& & m_pVoiceBank [ nBankIdx ] - > CompanyID = = 0x43
& & m_pVoiceBank [ nBankIdx ] - > Format = = 0x09
& & m_pVoiceBank [ nBankIdx ] - > StatusEnd = = 0xF7 )
{
{
bool bBankLoaded = false ;
if ( m_nBanksLoaded % 100 = = 0 )
if ( fread ( m_pVoiceBank [ nBank ] , VoiceSysExHdrSize + VoiceSysExSize , 1 , pFile ) = = 1
& & m_pVoiceBank [ nBank ] - > StatusStart = = 0xF0
& & m_pVoiceBank [ nBank ] - > CompanyID = = 0x43
& & m_pVoiceBank [ nBank ] - > Format = = 0x09
& & m_pVoiceBank [ nBank ] - > StatusEnd = = 0xF7 )
{
{
LOGDBG ( " Bank #%u successfully loaded " , nBank ) ;
LOGDBG ( " Banks successfully loaded #%u " , m_nBanksLoaded ) ;
}
//LOGDBG ("Bank #%u successfully loaded", nBank);
m_BankFileName [ nBank ] = pEntry - > d_name ;
m_BankFileName [ nBankIdx ] = sBankName ;
if ( nBank > m_nNumHighestBank )
{
// This is the bank ID of the highest loaded bank
m_nNumHighestBank = nBank ;
}
m_nBanksLoaded + + ;
bBankLoaded = true ;
}
else if ( bHeaderlessSysExVoices )
{
// Config says to accept headerless SysEx Voice Banks
// so reset file pointer and try again.
fseek ( pFile , 0 , SEEK_SET ) ;
if ( fread ( m_pVoiceBank [ nBankIdx ] - > Voice , VoiceSysExSize , 1 , pFile ) = = 1 )
{
if ( m_nBanksLoaded % 100 = = 0 )
{
LOGDBG ( " Banks successfully loaded #%u " , m_nBanksLoaded ) ;
}
//LOGDBG ("Bank #%u successfully loaded (headerless)", nBank);
// Add in the missing header items.
// Naturally it isn't possible to validate these!
m_pVoiceBank [ nBankIdx ] - > StatusStart = 0xF0 ;
m_pVoiceBank [ nBankIdx ] - > CompanyID = 0x43 ;
m_pVoiceBank [ nBankIdx ] - > Format = 0x09 ;
m_pVoiceBank [ nBankIdx ] - > ByteCountMS = 0x20 ;
m_pVoiceBank [ nBankIdx ] - > ByteCountLS = 0x00 ;
m_pVoiceBank [ nBankIdx ] - > Checksum = 0x00 ;
m_pVoiceBank [ nBankIdx ] - > StatusEnd = 0xF7 ;
m_BankFileName [ nBankIdx ] = sBankName ;
if ( nBank > m_nNumHighestBank )
if ( nBank > m_nNumHighestBank )
{
{
// This is the bank ID of the highest loaded bank
// This is the bank ID of the highest loaded bank
m_nNumHighestBank = nBank ;
m_nNumHighestBank = nBank ;
}
}
bBankLoaded = true ;
bBankLoaded = true ;
m_nBanksLoaded + + ;
}
}
else if ( bHeaderlessSysExVoices )
{
// Config says to accept headerless SysEx Voice Banks
// so reset file pointer and try again.
fseek ( pFile , 0 , SEEK_SET ) ;
if ( fread ( m_pVoiceBank [ nBank ] - > Voice , VoiceSysExSize , 1 , pFile ) = = 1 )
{
LOGDBG ( " Bank #%u successfully loaded (headerless) " , nBank ) ;
// Add in the missing header items.
// Naturally it isn't possible to validate these!
m_pVoiceBank [ nBank ] - > StatusStart = 0xF0 ;
m_pVoiceBank [ nBank ] - > CompanyID = 0x43 ;
m_pVoiceBank [ nBank ] - > Format = 0x09 ;
m_pVoiceBank [ nBank ] - > ByteCountMS = 0x20 ;
m_pVoiceBank [ nBank ] - > ByteCountLS = 0x00 ;
m_pVoiceBank [ nBank ] - > Checksum = 0x00 ;
m_pVoiceBank [ nBank ] - > StatusEnd = 0xF7 ;
m_BankFileName [ nBank ] = pEntry - > d_name ;
if ( nBank > m_nNumHighestBank )
{
// This is the bank ID of the highest loaded bank
m_nNumHighestBank = nBank ;
}
bBankLoaded = true ;
}
}
if ( ! bBankLoaded )
{
LOGWARN ( " %s: Invalid size or format " , Filename . c_str ( ) ) ;
delete m_pVoiceBank [ nBank ] ;
m_pVoiceBank [ nBank ] = nullptr ;
}
fclose ( pFile ) ;
}
}
else
if ( ! bBankLoaded )
{
{
delete m_pVoiceBank [ nBank ] ;
LOGWARN ( " %s: Invalid size or format " , Filename . c_str ( ) ) ;
m_pVoiceBank [ nBank ] = nullptr ;
delete m_pVoiceBank [ nBankIdx ] ;
m_pVoiceBank [ nBankIdx ] = nullptr ;
}
}
}
closedir ( pDirectory ) ;
fclose ( pFile ) ;
}
else
{
delete m_pVoiceBank [ nBankIdx ] ;
m_pVoiceBank [ nBankIdx ] = nullptr ;
}
}
}
std : : string CSysExFileLoader : : GetBankName ( unsigned nBankID )
std : : string CSysExFileLoader : : GetBankName ( unsigned nBankID )