diff --git a/Plugins/MIDI/MIDI/AUPlayer.mm b/Plugins/MIDI/MIDI/AUPlayer.mm index 37a9ba41f..3a7b6e4ef 100644 --- a/Plugins/MIDI/MIDI/AUPlayer.mm +++ b/Plugins/MIDI/MIDI/AUPlayer.mm @@ -205,7 +205,7 @@ void AUPlayer::setComponent(OSType uSubType, OSType uManufacturer) { void AUPlayer::setSoundFont(const char *in) { const char *ext = strrchr(in, '.'); - if(*ext && ((strncasecmp(ext + 1, "sf2", 3) == 0) || (strncasecmp(ext + 1, "dls", 3) == 0))) { + if(ext && *ext && ((strncasecmp(ext + 1, "sf2", 3) == 0) || (strncasecmp(ext + 1, "dls", 3) == 0))) { sSoundFontName = in; shutdown(); } diff --git a/Plugins/MIDI/MIDI/BMPlayer.cpp b/Plugins/MIDI/MIDI/BMPlayer.cpp index a3bd26527..49f7ad2b0 100644 --- a/Plugins/MIDI/MIDI/BMPlayer.cpp +++ b/Plugins/MIDI/MIDI/BMPlayer.cpp @@ -256,7 +256,7 @@ static class Bass_Initializer { BMPlayer::BMPlayer() : MIDIPlayer() { - memset(_stream, 0, sizeof(_stream)); + _stream = NULL; bSincInterpolation = false; _presetList = 0; @@ -279,39 +279,19 @@ void BMPlayer::send_event(uint32_t b) { event[1] = static_cast(b >> 8); event[2] = static_cast(b >> 16); unsigned port = (b >> 24) & 0x7F; - const unsigned channel = b & 0x0F; + if(port > 2) port = 0; + const unsigned channel = (b & 0x0F) + port * 16; const unsigned command = b & 0xF0; const unsigned event_length = (command >= 0xF8 && command <= 0xFF) ? 1 : ((command == 0xC0 || command == 0xD0) ? 2 : 3); - if(port > 2) port = 0; - if(bank_lsb_overridden && command == 0xB0 && event[1] == 0x20) return; - BASS_MIDI_StreamEvents(_stream[port], BASS_MIDI_EVENTS_RAW + 1 + channel, event, event_length); + BASS_MIDI_StreamEvents(_stream, BASS_MIDI_EVENTS_RAW + 1 + channel, event, event_length); } void BMPlayer::send_sysex(const uint8_t *data, size_t size, size_t port) { - if(port > 2) port = 0; - BASS_MIDI_StreamEvents(_stream[port], BASS_MIDI_EVENTS_RAW, data, static_cast(size)); - if(port == 0) { - BASS_MIDI_StreamEvents(_stream[1], BASS_MIDI_EVENTS_RAW, data, static_cast(size)); - BASS_MIDI_StreamEvents(_stream[2], BASS_MIDI_EVENTS_RAW, data, static_cast(size)); - } + BASS_MIDI_StreamEvents(_stream, BASS_MIDI_EVENTS_RAW, data, static_cast(size)); } void BMPlayer::render(float *out, unsigned long count) { - float buffer[1024]; - while(count) { - unsigned long todo = count; - if(todo > 512) - todo = 512; - memset(out, 0, todo * sizeof(float) * 2); - for(unsigned long i = 0; i < 3; ++i) { - BASS_ChannelGetData(_stream[i], buffer, BASS_DATA_FLOAT | (unsigned int)(todo * sizeof(float) * 2)); - for(unsigned long j = 0; j < todo * 2; ++j) { - out[j] += buffer[j]; - } - } - out += todo * 2; - count -= todo; - } + BASS_ChannelGetData(_stream, out, BASS_DATA_FLOAT | (unsigned int)(count * sizeof(float) * 2)); } void BMPlayer::setSoundFont(const char *in) { @@ -325,10 +305,8 @@ void BMPlayer::setFileSoundFont(const char *in) { } void BMPlayer::shutdown() { - if(_stream[2]) BASS_StreamFree(_stream[2]); - if(_stream[1]) BASS_StreamFree(_stream[1]); - if(_stream[0]) BASS_StreamFree(_stream[0]); - memset(_stream, 0, sizeof(_stream)); + if(_stream) BASS_StreamFree(_stream); + _stream = NULL; for(unsigned long i = 0; i < _soundFonts.size(); ++i) { cache_close_font(_soundFonts[i]); } @@ -339,37 +317,17 @@ void BMPlayer::shutdown() { } } -void BMPlayer::compound_presets(std::vector &out, std::vector &in, std::vector &channels) { - if(!in.size()) - in.push_back({ 0, -1, -1, -1, 0, 0 }); - if(channels.size()) { - for(auto pit = in.begin(); pit != in.end(); ++pit) { - for(auto it = channels.begin(); it != channels.end(); ++it) { - bank_lsb_override[*it - 1] = *it; - - int dbanklsb = (int)*it; - pit->dbanklsb = dbanklsb; - out.push_back(*pit); - } - } - } else { - for(auto pit = in.begin(); pit != in.end(); ++pit) { - out.push_back(*pit); - } - } -} - bool BMPlayer::startup() { - if(_stream[0] && _stream[1] && _stream[2]) return true; + if(_stream) return true; - _stream[0] = BASS_MIDI_StreamCreate(16, BASS_SAMPLE_FLOAT | BASS_STREAM_DECODE | (bSincInterpolation ? BASS_MIDI_SINCINTER : 0), (unsigned int)uSampleRate); - _stream[1] = BASS_MIDI_StreamCreate(16, BASS_SAMPLE_FLOAT | BASS_STREAM_DECODE | (bSincInterpolation ? BASS_MIDI_SINCINTER : 0), (unsigned int)uSampleRate); - _stream[2] = BASS_MIDI_StreamCreate(16, BASS_SAMPLE_FLOAT | BASS_STREAM_DECODE | (bSincInterpolation ? BASS_MIDI_SINCINTER : 0), (unsigned int)uSampleRate); - if(!_stream[0] || !_stream[1] || !_stream[2]) { + _stream = BASS_MIDI_StreamCreate(48, BASS_SAMPLE_FLOAT | BASS_STREAM_DECODE | (bSincInterpolation ? BASS_MIDI_SINCINTER : 0), (unsigned int)uSampleRate); + if(!_stream) { return false; } - memset(bank_lsb_override, 0, sizeof(bank_lsb_override)); - std::vector presetList; + BASS_MIDI_StreamEvent(_stream, 9, MIDI_EVENT_DEFDRUMS, 1); + BASS_MIDI_StreamEvent(_stream, 9 + 16, MIDI_EVENT_DEFDRUMS, 1); + BASS_MIDI_StreamEvent(_stream, 9 + 32, MIDI_EVENT_DEFDRUMS, 1); + std::vector presetList; if(sFileSoundFontName.length()) { HSOUNDFONT font = cache_open_font(sFileSoundFontName.c_str()); if(!font) { @@ -377,14 +335,14 @@ bool BMPlayer::startup() { return false; } _soundFonts.push_back(font); - presetList.push_back({ font, -1, -1, -1, 0, 0 }); + presetList.push_back({ font, -1, -1, -1, 0, 0, 0, 48 }); } if(sSoundFontName.length()) { std::string ext; size_t dot = sSoundFontName.find_last_of('.'); if(dot != std::string::npos) ext.assign(sSoundFontName.begin() + dot + 1, sSoundFontName.end()); - if(!strcasecmp(ext.c_str(), "sf2") + if(!strcasecmp(ext.c_str(), "sf2") || !strcasecmp(ext.c_str(), "sf3") #ifdef SF2PACK || !strcasecmp(ext.c_str(), "sf2pack") #endif @@ -395,7 +353,7 @@ bool BMPlayer::startup() { return false; } _soundFonts.push_back(font); - presetList.push_back({ font, -1, -1, -1, 0, 0 }); + presetList.push_back({ font, -1, -1, -1, 0, 0, 0, 48 }); } else if(!strcasecmp(ext.c_str(), "sflist") || !strcasecmp(ext.c_str(), "json")) { _presetList = cache_open_list(sSoundFontName.c_str()); if(!_presetList) { @@ -408,20 +366,7 @@ bool BMPlayer::startup() { } } - BASS_MIDI_StreamSetFonts(_stream[0], &presetList[0], (unsigned int)presetList.size() | BASS_MIDI_FONT_EX); - BASS_MIDI_StreamSetFonts(_stream[1], &presetList[0], (unsigned int)presetList.size() | BASS_MIDI_FONT_EX); - BASS_MIDI_StreamSetFonts(_stream[2], &presetList[0], (unsigned int)presetList.size() | BASS_MIDI_FONT_EX); - - reset_parameters(); + BASS_MIDI_StreamSetFonts(_stream, &presetList[0], (unsigned int)presetList.size() | BASS_MIDI_FONT_EX2); return true; } - -void BMPlayer::reset_parameters() { - bank_lsb_overridden = false; - for(unsigned int i = 0; i < 48; ++i) { - if(bank_lsb_override[i]) - bank_lsb_overridden = true; - BASS_MIDI_StreamEvent(_stream[i / 16], i % 16, MIDI_EVENT_BANK_LSB, bank_lsb_override[i]); - } -} diff --git a/Plugins/MIDI/MIDI/BMPlayer.h b/Plugins/MIDI/MIDI/BMPlayer.h index 81be0608e..3c6e62ae3 100644 --- a/Plugins/MIDI/MIDI/BMPlayer.h +++ b/Plugins/MIDI/MIDI/BMPlayer.h @@ -28,8 +28,6 @@ class BMPlayer : public MIDIPlayer { virtual void shutdown(); virtual bool startup(); - void compound_presets(std::vector& out, std::vector& in, std::vector& channels); - void reset_parameters(); std::vector _soundFonts; @@ -37,12 +35,9 @@ class BMPlayer : public MIDIPlayer { std::string sSoundFontName; std::string sFileSoundFontName; - HSTREAM _stream[3]; + HSTREAM _stream; bool bSincInterpolation; - - bool bank_lsb_overridden; - uint8_t bank_lsb_override[48]; }; #endif diff --git a/Plugins/MIDI/MIDI/MIDIDecoder.mm b/Plugins/MIDI/MIDI/MIDIDecoder.mm index 660d5f9bb..28c270e63 100644 --- a/Plugins/MIDI/MIDI/MIDIDecoder.mm +++ b/Plugins/MIDI/MIDI/MIDIDecoder.mm @@ -120,7 +120,7 @@ static OSType getOSType(const char *in_) { if([[source url] isFileURL]) { // Let's check for a SoundFont - NSArray *extensions = @[@"sflist", @"sf2pack", @"sf2"]; + NSArray *extensions = @[@"sflist", @"sf2pack", @"sf2", @"sf3"]; NSString *filePath = [[source url] path]; NSString *fileNameBase = [filePath lastPathComponent]; filePath = [filePath stringByDeletingLastPathComponent]; diff --git a/Preferences/Preferences/MIDIPane.m b/Preferences/Preferences/MIDIPane.m index f6ef876dd..40bfaa55a 100644 --- a/Preferences/Preferences/MIDIPane.m +++ b/Preferences/Preferences/MIDIPane.m @@ -25,7 +25,7 @@ } - (IBAction)setSoundFont:(id)sender { - NSArray *fileTypes = @[@"sf2", @"sf2pack", @"sflist"]; + NSArray *fileTypes = @[@"sf2", @"sf2pack", @"sflist", @"sf3"]; NSOpenPanel *panel = [NSOpenPanel openPanel]; [panel setAllowsMultipleSelection:NO]; [panel setCanChooseDirectories:NO]; diff --git a/ThirdParty/BASS/bassmidi.h b/ThirdParty/BASS/bassmidi.h index dcfecd460..fce6e6d47 100644 --- a/ThirdParty/BASS/bassmidi.h +++ b/ThirdParty/BASS/bassmidi.h @@ -1,6 +1,6 @@ /* BASSMIDI 2.4 C/C++ header file - Copyright (c) 2006-2020 Un4seen Developments Ltd. + Copyright (c) 2006-2022 Un4seen Developments Ltd. See the BASSMIDI.CHM file for more detailed documentation */ @@ -14,6 +14,11 @@ #error conflicting BASS and BASSMIDI versions #endif +#ifdef __OBJC__ +typedef int BOOL32; +#define BOOL BOOL32 // override objc's BOOL +#endif + #ifdef __cplusplus extern "C" { #endif @@ -35,10 +40,11 @@ typedef DWORD HSOUNDFONT; // soundfont handle #define BASS_CONFIG_MIDI_SAMPLETHREADS 0x10406 #define BASS_CONFIG_MIDI_SAMPLEMEM 0x10407 #define BASS_CONFIG_MIDI_SAMPLEREAD 0x10408 +#define BASS_CONFIG_MIDI_SAMPLELOADING 0x1040a // Additional BASS_SetConfigPtr options #define BASS_CONFIG_MIDI_DEFFONT 0x10403 -#define BASS_CONFIG_MIDI_SFZHEAD 0x10408 +#define BASS_CONFIG_MIDI_SFZHEAD 0x10409 // Additional sync types #define BASS_SYNC_MIDI_MARK 0x10000 @@ -52,12 +58,14 @@ typedef DWORD HSOUNDFONT; // soundfont handle #define BASS_SYNC_MIDI_KEYSIG 0x10007 // Additional BASS_MIDI_StreamCreateFile/etc flags +#define BASS_MIDI_NODRUMPARAM 0x400 #define BASS_MIDI_NOSYSRESET 0x800 #define BASS_MIDI_DECAYEND 0x1000 #define BASS_MIDI_NOFX 0x2000 #define BASS_MIDI_DECAYSEEK 0x4000 #define BASS_MIDI_NOCROP 0x8000 #define BASS_MIDI_NOTEOFF1 0x10000 +#define BASS_MIDI_ASYNC 0x400000 #define BASS_MIDI_SINCINTER 0x800000 // BASS_MIDI_FontInit flags @@ -69,6 +77,7 @@ typedef DWORD HSOUNDFONT; // soundfont handle #define BASS_MIDI_FONT_LINDECVOL 0x200000 #define BASS_MIDI_FONT_NORAMPIN 0x400000 #define BASS_MIDI_FONT_NOLIMITS 0x800000 +#define BASS_MIDI_FONT_MINFX 0x1000000 typedef struct { HSOUNDFONT font; // soundfont @@ -85,8 +94,20 @@ typedef struct { int dbanklsb; // destination bank number LSB } BASS_MIDI_FONTEX; +typedef struct { + HSOUNDFONT font; // soundfont + int spreset; // source preset number + int sbank; // source bank number + int dpreset; // destination preset/program number + int dbank; // destination bank number + int dbanklsb; // destination bank number LSB + DWORD minchan; // minimum channel number + DWORD numchan; // number of channels from minchan +} BASS_MIDI_FONTEX2; + // BASS_MIDI_StreamSet/GetFonts flag #define BASS_MIDI_FONT_EX 0x1000000 // BASS_MIDI_FONTEX +#define BASS_MIDI_FONT_EX2 0x2000000 // BASS_MIDI_FONTEX2 typedef struct { const char *name; @@ -197,10 +218,13 @@ typedef struct { #define MIDI_EVENT_VIBRATO_RATE 80 #define MIDI_EVENT_VIBRATO_DEPTH 81 #define MIDI_EVENT_VIBRATO_DELAY 82 +#define MIDI_EVENT_MASTER_FINETUNE 83 +#define MIDI_EVENT_MASTER_COARSETUNE 84 #define MIDI_EVENT_MIXLEVEL 0x10000 #define MIDI_EVENT_TRANSPOSE 0x10001 #define MIDI_EVENT_SYSTEMEX 0x10002 #define MIDI_EVENT_SPEED 0x10004 +#define MIDI_EVENT_DEFDRUMS 0x10006 #define MIDI_EVENT_END 0 #define MIDI_EVENT_END_TRACK 0x10003 @@ -230,6 +254,9 @@ typedef struct { #define BASS_MIDI_EVENTS_CANCEL 0x4000000 // flag: cancel pending events #define BASS_MIDI_EVENTS_TIME 0x8000000 // flag: delta-time info is present #define BASS_MIDI_EVENTS_ABSTIME 0x10000000 // flag: absolute time info is present +#define BASS_MIDI_EVENTS_ASYNC 0x20000000 // flag: process asynchronously +#define BASS_MIDI_EVENTS_FILTER 0x40000000 // flag: apply filtering +#define BASS_MIDI_EVENTS_FLUSH 0x80000000 // flag: flush async events // BASS_MIDI_StreamGetChannel special channels #define BASS_MIDI_CHAN_CHORUS (DWORD)-1 @@ -259,7 +286,7 @@ typedef struct { // BASS_ChannelGetLength/GetPosition/SetPosition mode #define BASS_POS_MIDI_TICK 2 // tick position -typedef BOOL (CALLBACK MIDIFILTERPROC)(HSTREAM handle, DWORD track, BASS_MIDI_EVENT *event, BOOL seeking, void *user); +typedef BOOL (CALLBACK MIDIFILTERPROC)(HSTREAM handle, int track, BASS_MIDI_EVENT *event, BOOL seeking, void *user); /* Event filtering callback function. handle : MIDI stream handle track : Track containing the event @@ -294,6 +321,8 @@ buffer : Buffer containing MIDI data length : Number of bytes of data user : The 'user' parameter value given when calling BASS_MIDI_InInit */ +DWORD BASSMIDIDEF(BASS_MIDI_GetVersion)(void); + HSTREAM BASSMIDIDEF(BASS_MIDI_StreamCreate)(DWORD channels, DWORD flags, DWORD freq); HSTREAM BASSMIDIDEF(BASS_MIDI_StreamCreateFile)(BOOL mem, const void *file, QWORD offset, QWORD length, DWORD flags, DWORD freq); HSTREAM BASSMIDIDEF(BASS_MIDI_StreamCreateURL)(const char *url, DWORD offset, DWORD flags, DOWNLOADPROC *proc, void *user, DWORD freq); @@ -325,6 +354,7 @@ BOOL BASSMIDIDEF(BASS_MIDI_FontUnload)(HSOUNDFONT handle, int preset, int bank); BOOL BASSMIDIDEF(BASS_MIDI_FontCompact)(HSOUNDFONT handle); BOOL BASSMIDIDEF(BASS_MIDI_FontPack)(HSOUNDFONT handle, const void *outfile, const void *encoder, DWORD flags); BOOL BASSMIDIDEF(BASS_MIDI_FontUnpack)(HSOUNDFONT handle, const void *outfile, DWORD flags); +DWORD BASSMIDIDEF(BASS_MIDI_FontFlags)(HSOUNDFONT handle, DWORD flags, DWORD mask); BOOL BASSMIDIDEF(BASS_MIDI_FontSetVolume)(HSOUNDFONT handle, float volume); float BASSMIDIDEF(BASS_MIDI_FontGetVolume)(HSOUNDFONT handle); @@ -341,23 +371,33 @@ BOOL BASSMIDIDEF(BASS_MIDI_InStop)(DWORD device); static inline BOOL BASS_MIDI_StreamSetFonts(HSTREAM handle, const BASS_MIDI_FONTEX *fonts, DWORD count) { - return BASS_MIDI_StreamSetFonts(handle, (const void*)fonts, count|BASS_MIDI_FONT_EX); + return BASS_MIDI_StreamSetFonts(handle, (const void*)fonts, count | BASS_MIDI_FONT_EX); +} + +static inline BOOL BASS_MIDI_StreamSetFonts(HSTREAM handle, const BASS_MIDI_FONTEX2 *fonts, DWORD count) +{ + return BASS_MIDI_StreamSetFonts(handle, (const void*)fonts, count | BASS_MIDI_FONT_EX2); } static inline DWORD BASS_MIDI_StreamGetFonts(HSTREAM handle, BASS_MIDI_FONTEX *fonts, DWORD count) { - return BASS_MIDI_StreamGetFonts(handle, (void*)fonts, count|BASS_MIDI_FONT_EX); + return BASS_MIDI_StreamGetFonts(handle, (void*)fonts, count | BASS_MIDI_FONT_EX); +} + +static inline DWORD BASS_MIDI_StreamGetFonts(HSTREAM handle, BASS_MIDI_FONTEX2 *fonts, DWORD count) +{ + return BASS_MIDI_StreamGetFonts(handle, (void*)fonts, count | BASS_MIDI_FONT_EX2); } #ifdef _WIN32 static inline HSTREAM BASS_MIDI_StreamCreateFile(BOOL mem, const WCHAR *file, QWORD offset, QWORD length, DWORD flags, DWORD freq) { - return BASS_MIDI_StreamCreateFile(mem, (const void*)file, offset, length, flags|BASS_UNICODE, freq); + return BASS_MIDI_StreamCreateFile(mem, (const void*)file, offset, length, flags | BASS_UNICODE, freq); } static inline HSTREAM BASS_MIDI_StreamCreateURL(const WCHAR *url, DWORD offset, DWORD flags, DOWNLOADPROC *proc, void *user, DWORD freq) { - return BASS_MIDI_StreamCreateURL((const char*)url, offset, flags|BASS_UNICODE, proc, user, freq); + return BASS_MIDI_StreamCreateURL((const char*)url, offset, flags | BASS_UNICODE, proc, user, freq); } static inline HSOUNDFONT BASS_MIDI_FontInit(const WCHAR *file, DWORD flags) @@ -367,14 +407,18 @@ static inline HSOUNDFONT BASS_MIDI_FontInit(const WCHAR *file, DWORD flags) static inline BOOL BASS_MIDI_FontPack(HSOUNDFONT handle, const WCHAR *outfile, const WCHAR *encoder, DWORD flags) { - return BASS_MIDI_FontPack(handle, (const void*)outfile, (const void*)encoder, flags|BASS_UNICODE); + return BASS_MIDI_FontPack(handle, (const void*)outfile, (const void*)encoder, flags | BASS_UNICODE); } static inline BOOL BASS_MIDI_FontUnpack(HSOUNDFONT handle, const WCHAR *outfile, DWORD flags) { - return BASS_MIDI_FontUnpack(handle, (const void*)outfile, flags|BASS_UNICODE); + return BASS_MIDI_FontUnpack(handle, (const void*)outfile, flags | BASS_UNICODE); } #endif #endif +#ifdef __OBJC__ +#undef BOOL +#endif + #endif diff --git a/ThirdParty/BASS/sflist.c b/ThirdParty/BASS/sflist.c index 2ebdfdd3c..1ef81ddb5 100644 --- a/ThirdParty/BASS/sflist.c +++ b/ThirdParty/BASS/sflist.c @@ -457,7 +457,7 @@ static const json_value *json_object_item(const json_value *object, const char * return &json_value_none; } -static void sflist_process_patchmappings(BASS_MIDI_FONTEX *out, BASS_MIDI_FONTEX *fontex, const json_value *patchMappings, unsigned int channel) { +static void sflist_process_patchmappings(BASS_MIDI_FONTEX2 *out, BASS_MIDI_FONTEX2 *fontex, const json_value *patchMappings, unsigned int channel, unsigned int channelCount) { unsigned int i, j; for(i = 0, j = patchMappings->u.array.length; i < j; ++i) { json_value *preset = patchMappings->u.array.values[i]; @@ -471,7 +471,8 @@ static void sflist_process_patchmappings(BASS_MIDI_FONTEX *out, BASS_MIDI_FONTEX fontex->sbank = (source_bank->type == json_none) ? -1 : (int)source_bank->u.integer; fontex->dpreset = (destination_program->type == json_none) ? -1 : (int)destination_program->u.integer; fontex->dbank = (destination_bank->type == json_none) ? 0 : (int)destination_bank->u.integer; - fontex->dbanklsb = channel; + fontex->minchan = channel; + fontex->numchan = channelCount; *out++ = *fontex; } } @@ -487,7 +488,7 @@ static sflist_presets *sflist_process(const json_value *sflist, const char *base json_value *arr; unsigned int i, j, k, l, preset_number; HSOUNDFONT hfont = 0; - BASS_MIDI_FONTEX fontex; + BASS_MIDI_FONTEX2 fontex; if(!rval) { strcpy(error_buf, "Out of memory"); @@ -544,6 +545,8 @@ static sflist_presets *sflist_process(const json_value *sflist, const char *base sprintf(error_buf, "soundFont item #%u 'channels' is not an array", i + 1); goto error; } + int prevchannel = -1; + int contiguouschannelsets = 0; for(k = 0, l = channels->u.array.length; k < l; ++k) { json_value *channel = channels->u.array.values[k]; if(channel->type != json_integer) { @@ -554,8 +557,12 @@ static sflist_presets *sflist_process(const json_value *sflist, const char *base sprintf(error_buf, "soundFont item #%u 'channels' #%u is out of range (wanted 1-48, got %" PRId64 ")", i + 1, k + 1, channel->u.integer); goto error; } + if(prevchannel < 0 || channel->u.integer > (prevchannel + 1)) { + ++contiguouschannelsets; + } + prevchannel = (int)channel->u.integer; } - patches_needed = l; + patches_needed = contiguouschannelsets; } if(patchMappings->type != json_none) { if(patchMappings->type != json_array) { @@ -647,7 +654,7 @@ static sflist_presets *sflist_process(const json_value *sflist, const char *base } rval->count = presets_to_allocate; - rval->presets = calloc(sizeof(BASS_MIDI_FONTEX), rval->count); + rval->presets = calloc(sizeof(BASS_MIDI_FONTEX2), rval->count); if(!rval->presets) { strcpy(error_buf, "Out of memory"); @@ -725,22 +732,51 @@ static sflist_presets *sflist_process(const json_value *sflist, const char *base fontex.dpreset = -1; fontex.dbank = 0; fontex.dbanklsb = 0; + fontex.minchan = 0; + fontex.numchan = 48; /* Simplest case, whole bank loading */ if(channels->type == json_none && patchMappings->type == json_none) { rval->presets[preset_number++] = fontex; } else if(patchMappings->type == json_none) { + int prevchannel = -1; + int firstchannel = -1; for(k = 0, l = channels->u.array.length; k < l; ++k) { - fontex.dbanklsb = (int)channels->u.array.values[k]->u.integer; - rval->presets[preset_number++] = fontex; + int channel = (int)channels->u.array.values[k]->u.integer; + if(firstchannel < 0) { + firstchannel = channel; + prevchannel = channel; + } + if(channel > (prevchannel + 1)) { + fontex.minchan = firstchannel; + fontex.numchan = prevchannel - firstchannel + 1; + rval->presets[preset_number++] = fontex; + firstchannel = channel; + } + prevchannel = channel; } + fontex.minchan = firstchannel; + fontex.numchan = prevchannel - firstchannel + 1; + rval->presets[preset_number++] = fontex; } else if(channels->type == json_none) { - sflist_process_patchmappings(rval->presets + preset_number, &fontex, patchMappings, 0); + sflist_process_patchmappings(rval->presets + preset_number, &fontex, patchMappings, 0, 48); preset_number += patchMappings->u.array.length; } else { + int prevchannel = -1; + int firstchannel = -1; for(k = 0, l = channels->u.array.length; k < l; ++k) { - sflist_process_patchmappings(rval->presets + preset_number, &fontex, patchMappings, (int)channels->u.array.values[k]->u.integer); - preset_number += patchMappings->u.array.length; + int channel = (int)channels->u.array.values[k]->u.integer; + if(firstchannel < 0) { + firstchannel = channel; + prevchannel = channel; + } + if(channel > (prevchannel + 1)) { + sflist_process_patchmappings(rval->presets + preset_number, &fontex, patchMappings, firstchannel, prevchannel - firstchannel + 1); + preset_number += patchMappings->u.array.length; + } + prevchannel = channel; } + sflist_process_patchmappings(rval->presets + preset_number, &fontex, patchMappings, firstchannel, prevchannel - firstchannel + 1); + preset_number += patchMappings->u.array.length; } } diff --git a/ThirdParty/BASS/sflist.h b/ThirdParty/BASS/sflist.h index e758c1697..bc44d534d 100644 --- a/ThirdParty/BASS/sflist.h +++ b/ThirdParty/BASS/sflist.h @@ -42,7 +42,7 @@ extern "C" { typedef struct sflist_presets { unsigned int count; - BASS_MIDI_FONTEX *presets; + BASS_MIDI_FONTEX2 *presets; } sflist_presets; #define sflist_max_error 1024 diff --git a/ThirdParty/libraries.tar.xz b/ThirdParty/libraries.tar.xz index 09fb0bd0e..3bce75834 100644 Binary files a/ThirdParty/libraries.tar.xz and b/ThirdParty/libraries.tar.xz differ diff --git a/ThirdParty/libvgm/README.md b/ThirdParty/libvgm/README.md index 39cca4770..2c67f0541 100644 --- a/ThirdParty/libvgm/README.md +++ b/ThirdParty/libvgm/README.md @@ -6,6 +6,6 @@ Built on an M1 Mac mini, using CMake from Homebrew, with the following options: ``` -cmake .. -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -DCMAKE_OSX_DEPLOYMENT_TARGET="10.12" \ +cmake .. -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -DCMAKE_OSX_DEPLOYMENT_TARGET="10.13" \ -DBUILD_LIBAUDIO=NO -DBUILD_PLAYER=NO -DBUILD_VGM2WAV=NO ```