diff options
-rw-r--r-- | Alc/midi/base.h | 4 | ||||
-rw-r--r-- | Alc/midi/sf2load.c | 72 | ||||
-rw-r--r-- | OpenAL32/alMidi.c | 29 |
3 files changed, 82 insertions, 23 deletions
diff --git a/Alc/midi/base.h b/Alc/midi/base.h index dd7788e6..7dc80395 100644 --- a/Alc/midi/base.h +++ b/Alc/midi/base.h @@ -9,6 +9,8 @@ extern "C" { #endif +struct ALsoundfont; + typedef size_t (*ReaderCb)(void *ptr, size_t size, void *stream); typedef struct Reader { ReaderCb cb; @@ -18,7 +20,7 @@ typedef struct Reader { #define READ(x_, buf_, len_) ((x_)->cb((buf_), (len_), (x_)->ptr)) #define READERR(x_) ((x_)->error) -ALboolean loadSf2(Reader *stream, ALuint sfid); +ALboolean loadSf2(Reader *stream, struct ALsoundfont *sfont, ALCcontext *context); struct MidiSynthVtable; diff --git a/Alc/midi/sf2load.c b/Alc/midi/sf2load.c index 5fb71893..1733bab2 100644 --- a/Alc/midi/sf2load.c +++ b/Alc/midi/sf2load.c @@ -4,7 +4,9 @@ #include <stdio.h> #include <stdlib.h> -#include "AL/al.h" +#include "alMain.h" +#include "alMidi.h" +#include "alError.h" #include "alu.h" #include "midi/base.h" @@ -1029,7 +1031,7 @@ static void processInstrument(InstrumentHeader *inst, IDList *sounds, const Soun GenModList_Destruct(&gzone); } -ALboolean loadSf2(Reader *stream, ALuint sfid) +ALboolean loadSf2(Reader *stream, ALsoundfont *soundfont, ALCcontext *context) { ALuint version = 0; Soundfont sfont; @@ -1092,7 +1094,7 @@ ALboolean loadSf2(Reader *stream, ALuint sfid) if(list.mList != FOURCC('s','d','t','a')) ERROR_GOTO(error, "Invalid Format, expected sdta got '%c%c%c%c'\n", FOURCCARGS(list.mList)); { - ALubyte *ptr; + ALbyte *ptr; RiffHdr smpl; RiffHdr_read(&smpl, stream); @@ -1103,29 +1105,27 @@ ALboolean loadSf2(Reader *stream, ALuint sfid) if(smpl.mSize > list.mSize) ERROR_GOTO(error, "Invalid Format, sample chunk size mismatch\n"); - alSoundfontSamplesSOFT(sfid, AL_SHORT_SOFT, smpl.mSize/2, NULL); + if(!(ptr=realloc(soundfont->Samples, smpl.mSize))) + SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, error); + soundfont->Samples = (ALshort*)ptr; + soundfont->NumSamples = smpl.mSize/2; - ptr = alSoundfontMapSamplesSOFT(sfid, 0, smpl.mSize); - if(ptr) + if(IS_LITTLE_ENDIAN) + READ(stream, ptr, smpl.mSize); + else { - if(IS_LITTLE_ENDIAN) - READ(stream, ptr, smpl.mSize); - else + while(smpl.mSize > 0) { - while(smpl.mSize > 0) - { - ALubyte buf[4096]; - ALuint todo = minu(smpl.mSize, sizeof(buf)); - ALuint i; + ALbyte buf[4096]; + ALuint todo = minu(smpl.mSize, sizeof(buf)); + ALuint i; - READ(stream, buf, todo); - for(i = 0;i < todo;i++) - ptr[i] = buf[i^1]; - } + READ(stream, buf, todo); + for(i = 0;i < todo;i++) + ptr[i] = buf[i^1]; } - alSoundfontUnmapSamplesSOFT(sfid); - list.mSize -= smpl.mSize; } + list.mSize -= smpl.mSize; skip(stream, list.mSize); } @@ -1322,7 +1322,37 @@ ALboolean loadSf2(Reader *stream, ALuint sfid) GenModList_Destruct(&gzone); IDList_Destruct(&fsids); } - alSoundfontPresetsSOFT(sfid, pids.ids_size, pids.ids); + { + ALsizei count = pids.ids_size; + ALsfpreset **presets; + + if(count == 0) + presets = NULL; + else + { + ALCdevice *device = context->Device; + + presets = calloc(count, sizeof(presets[0])); + if(!presets) + SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, error); + + for(i = 0;i < count;i++) + { + if(!(presets[i]=LookupPreset(device, pids.ids[i]))) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, error); + } + } + + for(i = 0;i < count;i++) + IncrementRef(&presets[i]->ref); + + presets = ExchangePtr((XchgPtr*)&soundfont->Presets, presets); + count = ExchangeInt(&soundfont->NumPresets, count); + + for(i = 0;i < count;i++) + DecrementRef(&presets[i]->ref); + free(presets); + } IDList_Destruct(&pids); Soundfont_Destruct(&sfont); diff --git a/OpenAL32/alMidi.c b/OpenAL32/alMidi.c index c040bf36..17384bcf 100644 --- a/OpenAL32/alMidi.c +++ b/OpenAL32/alMidi.c @@ -63,11 +63,38 @@ done: AL_API void AL_APIENTRY alLoadSoundfontSOFT(ALuint id, size_t(*cb)(ALvoid*,size_t,ALvoid*), ALvoid *user) { + ALCdevice *device; + ALCcontext *context; + ALsoundfont *sfont; Reader reader; + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + if(!(sfont=LookupSfont(device, id))) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + + WriteLock(&sfont->Lock); + if(sfont->ref != 0) + { + WriteUnlock(&sfont->Lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done); + } + if(sfont->Mapped) + { + WriteUnlock(&sfont->Lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done); + } + reader.cb = cb; reader.ptr = user; reader.error = 0; - loadSf2(&reader, id); + loadSf2(&reader, sfont, context); + WriteUnlock(&sfont->Lock); + +done: + ALCcontext_DecRef(context); } |