aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Alc/midi/base.h4
-rw-r--r--Alc/midi/sf2load.c72
-rw-r--r--OpenAL32/alMidi.c29
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);
}