Print SF2 text INFO chunks

This commit is contained in:
Chris Robinson 2014-07-01 00:36:44 -07:00
parent c06bb88756
commit 3c6752e765
2 changed files with 95 additions and 52 deletions

View File

@ -17,8 +17,13 @@ typedef struct Reader {
void *ptr;
int error;
} Reader;
#define READ(x_, buf_, len_) ((x_)->cb((buf_), (len_), (x_)->ptr))
#define READERR(x_) ((x_)->error)
inline size_t Reader_read(Reader *self, void *buf, size_t len)
{
size_t got = (!self->error) ? self->cb(buf, len, self->ptr) : 0;
if(got < len) self->error = 1;
return got;
}
#define READERR(x_) ((x_)->error)
ALboolean loadSf2(Reader *stream, struct ALsoundfont *sfont, ALCcontext *context);

View File

@ -12,34 +12,27 @@
#include "midi/base.h"
extern inline size_t Reader_read(Reader *self, void *buf, size_t len);
static ALuint read_le32(Reader *stream)
{
ALubyte buf[4];
if(READ(stream, buf, 4) != 4)
{
READERR(stream) = 1;
if(Reader_read(stream, buf, 4) != 4)
return 0;
}
return (buf[3]<<24) | (buf[2]<<16) | (buf[1]<<8) | buf[0];
}
static ALushort read_le16(Reader *stream)
{
ALubyte buf[2];
if(READ(stream, buf, 2) != 2)
{
READERR(stream) = 1;
if(Reader_read(stream, buf, 2) != 2)
return 0;
}
return (buf[1]<<8) | buf[0];
}
static ALubyte read_8(Reader *stream)
{
ALubyte buf[1];
if(READ(stream, buf, 1) != 1)
{
READERR(stream) = 1;
if(Reader_read(stream, buf, 1) != 1)
return 0;
}
return buf[0];
}
static void skip(Reader *stream, ALuint amt)
@ -47,13 +40,7 @@ static void skip(Reader *stream, ALuint amt)
while(amt > 0 && !READERR(stream))
{
char buf[4096];
size_t got;
got = READ(stream, buf, minu(sizeof(buf), amt));
if(got == 0 || got > amt)
READERR(stream) = 1;
amt -= (ALuint)got;
amt -= Reader_read(stream, buf, minu(sizeof(buf), amt));
}
}
@ -167,8 +154,7 @@ typedef struct PresetHeader {
} PresetHeader;
static void PresetHeader_read(PresetHeader *self, Reader *stream)
{
if(READ(stream, self->mName, sizeof(self->mName)) != sizeof(self->mName))
READERR(stream) = 1;
Reader_read(stream, self->mName, sizeof(self->mName));
self->mPreset = read_le16(stream);
self->mBank = read_le16(stream);
self->mZoneIdx = read_le16(stream);
@ -183,13 +169,12 @@ typedef struct InstrumentHeader {
} InstrumentHeader;
static void InstrumentHeader_read(InstrumentHeader *self, Reader *stream)
{
if(READ(stream, self->mName, sizeof(self->mName)) != sizeof(self->mName))
READERR(stream) = 1;
Reader_read(stream, self->mName, sizeof(self->mName));
self->mZoneIdx = read_le16(stream);
}
typedef struct SampleHeader {
ALchar mName[20]; // 20 bytes
ALchar mName[20];
ALuint mStart;
ALuint mEnd;
ALuint mStartloop;
@ -202,8 +187,7 @@ typedef struct SampleHeader {
} SampleHeader;
static void SampleHeader_read(SampleHeader *self, Reader *stream)
{
if(READ(stream, self->mName, sizeof(self->mName)) != sizeof(self->mName))
READERR(stream) = 1;
Reader_read(stream, self->mName, sizeof(self->mName));
self->mStart = read_le32(stream);
self->mEnd = read_le32(stream);
self->mStartloop = read_le32(stream);
@ -976,6 +960,22 @@ static void processInstrument(ALfontsound ***sounds, ALsizei *sounds_size, ALCco
GenModList_Destruct(&gzone);
}
static size_t printStringChunk(Reader *stream, const RiffHdr *chnk, const char *title)
{
size_t len = 0;
if(chnk->mSize == 0 || (chnk->mSize&1))
ERR("Invalid %c%c%c%c size: %d\n", FOURCCARGS(chnk->mCode), chnk->mSize);
else
{
char *str = calloc(1, chnk->mSize+1);
len = Reader_read(stream, str, chnk->mSize);
TRACE("%s: %s\n", title, str);
free(str);
}
return len;
}
ALboolean loadSf2(Reader *stream, ALsoundfont *soundfont, ALCcontext *context)
{
ALsfpreset **presets = NULL;
@ -1006,21 +1006,37 @@ ALboolean loadSf2(Reader *stream, ALsoundfont *soundfont, ALCcontext *context)
list.mSize -= 4;
while(list.mSize > 0 && !READERR(stream))
{
RiffHdr info;
RiffHdr chnk;
RiffHdr_read(&info, stream);
list.mSize -= 8;
if(info.mCode == FOURCC('i','f','i','l'))
if(list.mSize < 8)
{
if(info.mSize != 4)
ERR("Invalid ifil chunk size: %d\n", info.mSize);
WARN("Unexpected end of INFO list (%u extra bytes)\n", list.mSize);
skip(stream, list.mSize);
list.mSize = 0;
break;
}
RiffHdr_read(&chnk, stream);
list.mSize -= 8;
if(list.mSize < chnk.mSize)
{
WARN("INFO sub-chunk '%c%c%c%c' has %u bytes, but only %u bytes remain\n",
FOURCCARGS(chnk.mCode), chnk.mSize, list.mSize);
skip(stream, list.mSize);
list.mSize = 0;
break;
}
list.mSize -= chnk.mSize;
if(chnk.mCode == FOURCC('i','f','i','l'))
{
if(chnk.mSize != 4)
ERR("Invalid ifil chunk size: %d\n", chnk.mSize);
else
{
ALushort major = read_le16(stream);
ALushort minor = read_le16(stream);
list.mSize -= 4;
info.mSize -= 4;
chnk.mSize -= 4;
if(major != 2)
ERROR_GOTO(error, "Unsupported SF2 format version: %d.%02d\n", major, minor);
@ -1029,26 +1045,48 @@ ALboolean loadSf2(Reader *stream, ALsoundfont *soundfont, ALCcontext *context)
sfont.ifil = (major<<16) | minor;
}
}
else if(info.mCode == FOURCC('i','r','o','m'))
else if(chnk.mCode == FOURCC('i','r','o','m'))
{
if(info.mSize == 0 || (info.mSize&1))
ERR("Invalid irom size: %d\n", info.mSize);
if(chnk.mSize == 0 || (chnk.mSize&1))
ERR("Invalid irom size: %d\n", chnk.mSize);
else
{
free(sfont.irom);
sfont.irom = calloc(1, info.mSize+1);
READ(stream, sfont.irom, info.mSize);
list.mSize -= info.mSize;
info.mSize -= info.mSize;
sfont.irom = calloc(1, chnk.mSize+1);
chnk.mSize -= Reader_read(stream, sfont.irom, chnk.mSize);
TRACE("SF2 ROM ID: %s\n", sfont.irom);
}
}
else
TRACE("Skipping INFO sub-chunk '%c%c%c%c' (%u bytes)\n", FOURCCARGS(info.mCode), info.mSize);
list.mSize -= info.mSize;
skip(stream, info.mSize);
{
static const struct {
ALuint code;
char title[16];
} listinfos[] = {
{ FOURCC('i','s','n','g'), "Engine ID" },
{ FOURCC('I','N','A','M'), "Name" },
{ FOURCC('I','C','R','D'), "Creation Date" },
{ FOURCC('I','E','N','G'), "Creator" },
{ FOURCC('I','P','R','D'), "Product ID" },
{ FOURCC('I','C','O','P'), "Copyright" },
{ FOURCC('I','C','M','T'), "Comment" },
{ FOURCC('I','S','F','T'), "Created With" },
{ 0, "" },
};
for(i = 0;listinfos[i].code;i++)
{
if(listinfos[i].code == chnk.mCode)
{
chnk.mSize -= printStringChunk(stream, &chnk, listinfos[i].title);
break;
}
}
if(!listinfos[i].code)
TRACE("Skipping INFO sub-chunk '%c%c%c%c' (%u bytes)\n", FOURCCARGS(chnk.mCode), chnk.mSize);
}
skip(stream, chnk.mSize);
}
if(READERR(stream) != 0)
@ -1074,17 +1112,18 @@ ALboolean loadSf2(Reader *stream, ALsoundfont *soundfont, ALCcontext *context)
if(smpl.mSize > list.mSize)
ERROR_GOTO(error, "Invalid Format, sample chunk size mismatch\n");
list.mSize -= smpl.mSize;
buffer = NewBuffer(context);
if(!buffer)
SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, error);
/* Sample rate it unimportant, the individual fontsounds will specify it. */
/* Sample rate is unimportant, the individual fontsounds will specify it. */
if((err=LoadData(buffer, 22050, AL_MONO16_SOFT, smpl.mSize/2, UserFmtMono, UserFmtShort, NULL, 1, AL_FALSE)) != AL_NO_ERROR)
SET_ERROR_AND_GOTO(context, err, error);
ptr = buffer->data;
if(IS_LITTLE_ENDIAN)
READ(stream, ptr, smpl.mSize);
smpl.mSize -= Reader_read(stream, ptr, smpl.mSize);
else
{
ALuint total = 0;
@ -1094,14 +1133,13 @@ ALboolean loadSf2(Reader *stream, ALsoundfont *soundfont, ALCcontext *context)
ALuint todo = minu(smpl.mSize-total, sizeof(buf));
ALuint i;
READ(stream, buf, todo);
smpl.mSize -= Reader_read(stream, buf, todo);
for(i = 0;i < todo;i++)
ptr[total+i] = buf[i^1];
total += todo;
}
}
list.mSize -= smpl.mSize;
skip(stream, list.mSize);
}