Update libVGM and BASSMIDI, SF3 support

BASSMIDI now includes SF3 support, as well as several other changes.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
lastfm
Christopher Snowhill 2022-06-29 23:25:59 -07:00
parent ee5b6be4bb
commit 608483ae60
10 changed files with 124 additions and 104 deletions

View File

@ -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();
}

View File

@ -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<uint8_t>(b >> 8);
event[2] = static_cast<uint8_t>(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<unsigned int>(size));
if(port == 0) {
BASS_MIDI_StreamEvents(_stream[1], BASS_MIDI_EVENTS_RAW, data, static_cast<unsigned int>(size));
BASS_MIDI_StreamEvents(_stream[2], BASS_MIDI_EVENTS_RAW, data, static_cast<unsigned int>(size));
}
BASS_MIDI_StreamEvents(_stream, BASS_MIDI_EVENTS_RAW, data, static_cast<unsigned int>(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<BASS_MIDI_FONTEX> &out, std::vector<BASS_MIDI_FONTEX> &in, std::vector<long> &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<BASS_MIDI_FONTEX> 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<BASS_MIDI_FONTEX2> 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]);
}
}

View File

@ -28,8 +28,6 @@ class BMPlayer : public MIDIPlayer {
virtual void shutdown();
virtual bool startup();
void compound_presets(std::vector<BASS_MIDI_FONTEX>& out, std::vector<BASS_MIDI_FONTEX>& in, std::vector<long>& channels);
void reset_parameters();
std::vector<HSOUNDFONT> _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

View File

@ -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];

View File

@ -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];

View File

@ -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

View File

@ -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;
}
}

View File

@ -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

Binary file not shown.

View File

@ -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
```