mirror of
https://github.com/ZDoom/fluidsynth.git
synced 2024-11-10 06:51:54 +00:00
Fourcc support (#482)
Have a direct comparison to the fourcc code rather than searching through chunk ids all the time with chunkid()
This commit is contained in:
parent
b7af84fbd5
commit
c9b8d40fc2
4 changed files with 199 additions and 174 deletions
|
@ -81,6 +81,41 @@ static int fluid_midi_file_get_division(fluid_midi_file *midifile);
|
|||
* MIDIFILE
|
||||
*/
|
||||
|
||||
/**
|
||||
* Check if a file is a MIDI file.
|
||||
* @param filename Path to the file to check
|
||||
* @return TRUE if it could be a MIDI file, FALSE otherwise
|
||||
*
|
||||
* The current implementation only checks for the "MThd" header in the file.
|
||||
* It is useful only to distinguish between SoundFont and MIDI files.
|
||||
*/
|
||||
int fluid_is_midifile(const char *filename)
|
||||
{
|
||||
FILE *fp = FLUID_FOPEN(filename, "rb");
|
||||
uint32_t id;
|
||||
int retcode = 0;
|
||||
|
||||
do
|
||||
{
|
||||
if(fp == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if(FLUID_FREAD(&id, sizeof(id), 1, fp) != 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
retcode = (id == FLUID_FOURCC('M', 'T', 'h', 'd'));
|
||||
}
|
||||
while(0);
|
||||
|
||||
FLUID_FCLOSE(fp);
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new MIDI file handle for parsing an already-loaded MIDI file.
|
||||
* @internal
|
||||
|
|
|
@ -34,77 +34,80 @@
|
|||
Borrowed from Smurf SoundFont Editor by Josh Green
|
||||
=================================================================*/
|
||||
|
||||
/*
|
||||
functions for loading data from sfont files, with appropriate byte swapping
|
||||
on big endian machines. Sfont IDs are not swapped because the ID read is
|
||||
equivalent to the matching ID list in memory regardless of LE/BE machine
|
||||
*/
|
||||
/* FOURCC definitions */
|
||||
#define RIFF_FCC FLUID_FOURCC('R','I','F','F')
|
||||
#define LIST_FCC FLUID_FOURCC('L','I','S','T')
|
||||
#define SFBK_FCC FLUID_FOURCC('s','f','b','k')
|
||||
#define INFO_FCC FLUID_FOURCC('I','N','F','O')
|
||||
#define SDTA_FCC FLUID_FOURCC('s','d','t','a')
|
||||
#define PDTA_FCC FLUID_FOURCC('p','d','t','a') /* info/sample/preset */
|
||||
|
||||
/* sf file chunk IDs */
|
||||
enum
|
||||
#define IFIL_FCC FLUID_FOURCC('i','f','i','l')
|
||||
#define ISNG_FCC FLUID_FOURCC('i','s','n','g')
|
||||
#define INAM_FCC FLUID_FOURCC('I','N','A','M')
|
||||
#define IROM_FCC FLUID_FOURCC('i','r','o','m') /* info ids (1st byte of info strings) */
|
||||
#define IVER_FCC FLUID_FOURCC('i','v','e','r')
|
||||
#define ICRD_FCC FLUID_FOURCC('I','C','R','D')
|
||||
#define IENG_FCC FLUID_FOURCC('I','E','N','G')
|
||||
#define IPRD_FCC FLUID_FOURCC('I','P','R','D') /* more info ids */
|
||||
#define ICOP_FCC FLUID_FOURCC('I','C','O','P')
|
||||
#define ICMT_FCC FLUID_FOURCC('I','C','M','T')
|
||||
#define ISFT_FCC FLUID_FOURCC('I','S','F','T') /* and yet more info ids */
|
||||
|
||||
#define SNAM_FCC FLUID_FOURCC('s','n','a','m')
|
||||
#define SMPL_FCC FLUID_FOURCC('s','m','p','l') /* sample ids */
|
||||
#define PHDR_FCC FLUID_FOURCC('p','h','d','r')
|
||||
#define PBAG_FCC FLUID_FOURCC('p','b','a','g')
|
||||
#define PMOD_FCC FLUID_FOURCC('p','m','o','d')
|
||||
#define PGEN_FCC FLUID_FOURCC('p','g','e','n') /* preset ids */
|
||||
#define IHDR_FCC FLUID_FOURCC('i','n','s','t')
|
||||
#define IBAG_FCC FLUID_FOURCC('i','b','a','g')
|
||||
#define IMOD_FCC FLUID_FOURCC('i','m','o','d')
|
||||
#define IGEN_FCC FLUID_FOURCC('i','g','e','n') /* instrument ids */
|
||||
#define SHDR_FCC FLUID_FOURCC('s','h','d','r') /* sample info */
|
||||
#define SM24_FCC FLUID_FOURCC('s','m','2','4')
|
||||
|
||||
/* Set when the FCC code is unknown */
|
||||
#define UNKN_ID FLUID_N_ELEMENTS(idlist)
|
||||
|
||||
/*
|
||||
* This declares a uint32_t array containing the SF2 chunk identifiers.
|
||||
*/
|
||||
static const uint32_t idlist[] =
|
||||
{
|
||||
RIFF_ID,
|
||||
LIST_ID,
|
||||
SFBK_ID,
|
||||
INFO_ID,
|
||||
SDTA_ID,
|
||||
PDTA_ID, /* info/sample/preset */
|
||||
RIFF_FCC,
|
||||
LIST_FCC,
|
||||
SFBK_FCC,
|
||||
INFO_FCC,
|
||||
SDTA_FCC,
|
||||
PDTA_FCC,
|
||||
|
||||
IFIL_ID,
|
||||
ISNG_ID,
|
||||
INAM_ID,
|
||||
IROM_ID, /* info ids (1st byte of info strings) */
|
||||
IVER_ID,
|
||||
ICRD_ID,
|
||||
IENG_ID,
|
||||
IPRD_ID, /* more info ids */
|
||||
ICOP_ID,
|
||||
ICMT_ID,
|
||||
ISFT_ID, /* and yet more info ids */
|
||||
IFIL_FCC,
|
||||
ISNG_FCC,
|
||||
INAM_FCC,
|
||||
IROM_FCC,
|
||||
IVER_FCC,
|
||||
ICRD_FCC,
|
||||
IENG_FCC,
|
||||
IPRD_FCC,
|
||||
ICOP_FCC,
|
||||
ICMT_FCC,
|
||||
ISFT_FCC,
|
||||
|
||||
SNAM_ID,
|
||||
SMPL_ID, /* sample ids */
|
||||
PHDR_ID,
|
||||
PBAG_ID,
|
||||
PMOD_ID,
|
||||
PGEN_ID, /* preset ids */
|
||||
IHDR_ID,
|
||||
IBAG_ID,
|
||||
IMOD_ID,
|
||||
IGEN_ID, /* instrument ids */
|
||||
SHDR_ID, /* sample info */
|
||||
SM24_ID,
|
||||
|
||||
UNKN_ID
|
||||
SNAM_FCC,
|
||||
SMPL_FCC,
|
||||
PHDR_FCC,
|
||||
PBAG_FCC,
|
||||
PMOD_FCC,
|
||||
PGEN_FCC,
|
||||
IHDR_FCC,
|
||||
IBAG_FCC,
|
||||
IMOD_FCC,
|
||||
IGEN_FCC,
|
||||
SHDR_FCC,
|
||||
SM24_FCC
|
||||
};
|
||||
|
||||
/*
|
||||
* This declares a char array containing the SF2 chunk identifiers. This
|
||||
* array is being accessed like an uint32 below to simplify id comparison.
|
||||
* To make sure it is suitably aligned for uint32 access, we must wrap it
|
||||
* inside a union along with a uint32 telling the compiler to align it
|
||||
* for integer access and avoiding undefined behaviour.
|
||||
* This basically is the C89 equivalent to what is written in C11 as:
|
||||
* alignas(uint32_t) static const char idlist[] = {};
|
||||
*
|
||||
* See: EXP36-C. Do not cast pointers into more strictly aligned pointer
|
||||
* types - SEI CERT C Coding Standard
|
||||
*/
|
||||
static const union fluid_idlist
|
||||
{
|
||||
/*
|
||||
* Cannot be char c[ ], because in C89, arrays wraped in unions
|
||||
* must have a fixed size. Otherwise the size of the union would depend
|
||||
* on the initialization of its first member, which results in
|
||||
* different sizes for different instances of the same union type.
|
||||
*/
|
||||
char c[116];
|
||||
uint32_t i;
|
||||
} idlist = {"RIFFLISTsfbkINFOsdtapdtaifilisngINAMiromiverICRDIENGIPRD"
|
||||
"ICOPICMTISFTsnamsmplphdrpbagpmodpgeninstibagimodigenshdrsm24"
|
||||
};
|
||||
|
||||
|
||||
/* generator types */
|
||||
typedef enum
|
||||
{
|
||||
|
@ -206,8 +209,6 @@ static const unsigned short invalid_preset_gen[] =
|
|||
};
|
||||
|
||||
|
||||
#define CHNKIDSTR(id) &idlist.c[(id - 1) * 4]
|
||||
|
||||
/* sfont file chunk sizes */
|
||||
#define SF_PHDR_SIZE (38)
|
||||
#define SF_BAG_SIZE (4)
|
||||
|
@ -323,6 +324,56 @@ static void delete_zone(SFZone *zone);
|
|||
static int fluid_sffile_read_vorbis(SFData *sf, unsigned int start_byte, unsigned int end_byte, short **data);
|
||||
static int fluid_sffile_read_wav(SFData *sf, unsigned int start, unsigned int end, short **data, char **data24);
|
||||
|
||||
/**
|
||||
* Check if a file is a SoundFont file.
|
||||
* @param filename Path to the file to check
|
||||
* @return TRUE if it could be a SoundFont, FALSE otherwise
|
||||
*
|
||||
* @note The current implementation only checks for the "RIFF" and "sfbk" headers in
|
||||
* the file. It is useful to distinguish between SoundFont and other (e.g. MIDI) files.
|
||||
*/
|
||||
int fluid_is_soundfont(const char *filename)
|
||||
{
|
||||
FILE *fp = FLUID_FOPEN(filename, "rb");
|
||||
uint32_t fcc;
|
||||
int retcode = 0;
|
||||
|
||||
do
|
||||
{
|
||||
if(fp == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if(FLUID_FREAD(&fcc, sizeof(fcc), 1, fp) != 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if(fcc != RIFF_FCC)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if(FLUID_FSEEK(fp, 4, SEEK_CUR))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if(FLUID_FREAD(&fcc, sizeof(fcc), 1, fp) != 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
retcode = (fcc == SFBK_FCC);
|
||||
}
|
||||
while(0);
|
||||
|
||||
FLUID_FCLOSE(fp);
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
/*
|
||||
* Open a SoundFont file and parse it's contents into a SFData structure.
|
||||
*
|
||||
|
@ -512,11 +563,10 @@ void fluid_sffile_close(SFData *sf)
|
|||
static int chunkid(uint32_t id)
|
||||
{
|
||||
unsigned int i;
|
||||
const uint32_t *p = &idlist.i;
|
||||
|
||||
for(i = 0; i < sizeof(idlist) / sizeof(idlist.i); i++, p += 1)
|
||||
for(i = 0; i < FLUID_N_ELEMENTS(idlist); i++)
|
||||
{
|
||||
if(*p == id)
|
||||
if(idlist[i] == id)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@ -532,7 +582,7 @@ static int load_header(SFData *sf)
|
|||
|
||||
READCHUNK(sf, &chunk); /* load RIFF chunk */
|
||||
|
||||
if(chunkid(chunk.id) != RIFF_ID)
|
||||
if(chunk.id != RIFF_FCC)
|
||||
{
|
||||
/* error if not RIFF */
|
||||
FLUID_LOG(FLUID_ERR, "Not a RIFF file");
|
||||
|
@ -541,7 +591,7 @@ static int load_header(SFData *sf)
|
|||
|
||||
READID(sf, &chunk.id); /* load file ID */
|
||||
|
||||
if(chunkid(chunk.id) != SFBK_ID)
|
||||
if(chunk.id != SFBK_FCC)
|
||||
{
|
||||
/* error if not SFBK_ID */
|
||||
FLUID_LOG(FLUID_ERR, "Not a SoundFont file");
|
||||
|
@ -560,7 +610,7 @@ static int load_header(SFData *sf)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if(chunkid(chunk.id) != INFO_ID)
|
||||
if(chunk.id != INFO_FCC)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Invalid ID found when expecting INFO chunk");
|
||||
return FALSE;
|
||||
|
@ -577,7 +627,7 @@ static int load_header(SFData *sf)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if(chunkid(chunk.id) != SDTA_ID)
|
||||
if(chunk.id != SDTA_FCC)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Invalid ID found when expecting SAMPLE chunk");
|
||||
return FALSE;
|
||||
|
@ -594,7 +644,7 @@ static int load_header(SFData *sf)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if(chunkid(chunk.id) != PDTA_ID)
|
||||
if(chunk.id != PDTA_FCC)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Invalid ID found when expecting HYDRA chunk");
|
||||
return FALSE;
|
||||
|
@ -639,7 +689,7 @@ static int read_listchunk(SFData *sf, SFChunk *chunk)
|
|||
{
|
||||
READCHUNK(sf, chunk); /* read list chunk */
|
||||
|
||||
if(chunkid(chunk->id) != LIST_ID) /* error if ! list chunk */
|
||||
if(chunk->id != LIST_FCC) /* error if ! list chunk */
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Invalid chunk id in level 0 parse");
|
||||
return FALSE;
|
||||
|
@ -653,8 +703,11 @@ static int read_listchunk(SFData *sf, SFChunk *chunk)
|
|||
static int process_info(SFData *sf, int size)
|
||||
{
|
||||
SFChunk chunk;
|
||||
unsigned char id;
|
||||
char *item;
|
||||
union
|
||||
{
|
||||
char *chr;
|
||||
uint32_t *fcc;
|
||||
} item;
|
||||
unsigned short ver;
|
||||
|
||||
while(size > 0)
|
||||
|
@ -662,9 +715,7 @@ static int process_info(SFData *sf, int size)
|
|||
READCHUNK(sf, &chunk);
|
||||
size -= 8;
|
||||
|
||||
id = chunkid(chunk.id);
|
||||
|
||||
if(id == IFIL_ID)
|
||||
if(chunk.id == IFIL_FCC)
|
||||
{
|
||||
/* sound font version chunk? */
|
||||
if(chunk.size != 4)
|
||||
|
@ -705,7 +756,7 @@ static int process_info(SFData *sf, int size)
|
|||
return FALSE;
|
||||
}
|
||||
}
|
||||
else if(id == IVER_ID)
|
||||
else if(chunk.id == IVER_FCC)
|
||||
{
|
||||
/* ROM version chunk? */
|
||||
if(chunk.size != 4)
|
||||
|
@ -719,34 +770,35 @@ static int process_info(SFData *sf, int size)
|
|||
READW(sf, ver);
|
||||
sf->romver.minor = ver;
|
||||
}
|
||||
else if(id != UNKN_ID)
|
||||
else if(chunkid(chunk.id) != UNKN_ID)
|
||||
{
|
||||
if((id != ICMT_ID && chunk.size > 256) || (chunk.size > 65536) || (chunk.size % 2))
|
||||
if((chunk.id != ICMT_FCC && chunk.size > 256) || (chunk.size > 65536) || (chunk.size % 2))
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "INFO sub chunk %.4s has invalid chunk size of %d bytes",
|
||||
&chunk.id, chunk.size);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* alloc for chunk id and da chunk */
|
||||
if(!(item = FLUID_MALLOC(chunk.size + 1)))
|
||||
/* alloc for chunk fcc and da chunk */
|
||||
if(!(item.fcc = FLUID_MALLOC(chunk.size + sizeof(uint32_t) + 1)))
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* attach to INFO list, fluid_sffile_close will cleanup if FAIL occurs */
|
||||
sf->info = fluid_list_append(sf->info, item);
|
||||
sf->info = fluid_list_append(sf->info, item.fcc);
|
||||
|
||||
*(unsigned char *)item = id;
|
||||
/* save chunk fcc and update pointer to data value */
|
||||
*item.fcc++ = chunk.id;
|
||||
|
||||
if(sf->fcbs->fread(&item[1], chunk.size, sf->sffd) == FLUID_FAILED)
|
||||
if(sf->fcbs->fread(item.chr, chunk.size, sf->sffd) == FLUID_FAILED)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* force terminate info item (don't forget uint8 info ID) */
|
||||
*(item + chunk.size) = '\0';
|
||||
/* force terminate info item */
|
||||
item.chr[chunk.size] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -779,7 +831,7 @@ static int process_sdta(SFData *sf, unsigned int size)
|
|||
READCHUNK(sf, &chunk);
|
||||
size -= 8;
|
||||
|
||||
if(chunkid(chunk.id) != SMPL_ID)
|
||||
if(chunk.id != SMPL_FCC)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Expected SMPL chunk found invalid id instead");
|
||||
return FALSE;
|
||||
|
@ -812,7 +864,7 @@ static int process_sdta(SFData *sf, unsigned int size)
|
|||
READCHUNK(sf, &chunk);
|
||||
size -= 8;
|
||||
|
||||
if(chunkid(chunk.id) == SM24_ID)
|
||||
if(chunk.id == SM24_FCC)
|
||||
{
|
||||
int sm24size, sdtahalfsize;
|
||||
|
||||
|
@ -852,29 +904,24 @@ ret:
|
|||
|
||||
static int pdtahelper(SFData *sf, unsigned int expid, unsigned int reclen, SFChunk *chunk, int *size)
|
||||
{
|
||||
unsigned int id;
|
||||
const char *expstr;
|
||||
|
||||
expstr = CHNKIDSTR(expid); /* in case we need it */
|
||||
|
||||
READCHUNK(sf, chunk);
|
||||
*size -= 8;
|
||||
|
||||
if((id = chunkid(chunk->id)) != expid)
|
||||
if(chunk->id != expid)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Expected PDTA sub-chunk '%.4s' found invalid id instead", expstr);
|
||||
FLUID_LOG(FLUID_ERR, "Expected PDTA sub-chunk '%.4s' found invalid id instead", &expid);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if(chunk->size % reclen) /* valid chunk size? */
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "'%.4s' chunk size is not a multiple of %d bytes", expstr, reclen);
|
||||
FLUID_LOG(FLUID_ERR, "'%.4s' chunk size is not a multiple of %d bytes", &expid, reclen);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if((*size -= chunk->size) < 0)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "'%.4s' chunk size exceeds remaining PDTA chunk size", expstr);
|
||||
FLUID_LOG(FLUID_ERR, "'%.4s' chunk size exceeds remaining PDTA chunk size", &expid);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -885,7 +932,7 @@ static int process_pdta(SFData *sf, int size)
|
|||
{
|
||||
SFChunk chunk;
|
||||
|
||||
if(!pdtahelper(sf, PHDR_ID, SF_PHDR_SIZE, &chunk, &size))
|
||||
if(!pdtahelper(sf, PHDR_FCC, SF_PHDR_SIZE, &chunk, &size))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -895,7 +942,7 @@ static int process_pdta(SFData *sf, int size)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if(!pdtahelper(sf, PBAG_ID, SF_BAG_SIZE, &chunk, &size))
|
||||
if(!pdtahelper(sf, PBAG_FCC, SF_BAG_SIZE, &chunk, &size))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -905,7 +952,7 @@ static int process_pdta(SFData *sf, int size)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if(!pdtahelper(sf, PMOD_ID, SF_MOD_SIZE, &chunk, &size))
|
||||
if(!pdtahelper(sf, PMOD_FCC, SF_MOD_SIZE, &chunk, &size))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -915,7 +962,7 @@ static int process_pdta(SFData *sf, int size)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if(!pdtahelper(sf, PGEN_ID, SF_GEN_SIZE, &chunk, &size))
|
||||
if(!pdtahelper(sf, PGEN_FCC, SF_GEN_SIZE, &chunk, &size))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -925,7 +972,7 @@ static int process_pdta(SFData *sf, int size)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if(!pdtahelper(sf, IHDR_ID, SF_IHDR_SIZE, &chunk, &size))
|
||||
if(!pdtahelper(sf, IHDR_FCC, SF_IHDR_SIZE, &chunk, &size))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -935,7 +982,7 @@ static int process_pdta(SFData *sf, int size)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if(!pdtahelper(sf, IBAG_ID, SF_BAG_SIZE, &chunk, &size))
|
||||
if(!pdtahelper(sf, IBAG_FCC, SF_BAG_SIZE, &chunk, &size))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -945,7 +992,7 @@ static int process_pdta(SFData *sf, int size)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if(!pdtahelper(sf, IMOD_ID, SF_MOD_SIZE, &chunk, &size))
|
||||
if(!pdtahelper(sf, IMOD_FCC, SF_MOD_SIZE, &chunk, &size))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -955,7 +1002,7 @@ static int process_pdta(SFData *sf, int size)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if(!pdtahelper(sf, IGEN_ID, SF_GEN_SIZE, &chunk, &size))
|
||||
if(!pdtahelper(sf, IGEN_FCC, SF_GEN_SIZE, &chunk, &size))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -965,7 +1012,7 @@ static int process_pdta(SFData *sf, int size)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if(!pdtahelper(sf, SHDR_ID, SF_SHDR_SIZE, &chunk, &size))
|
||||
if(!pdtahelper(sf, SHDR_FCC, SF_SHDR_SIZE, &chunk, &size))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
@ -274,71 +274,6 @@ fluid_error()
|
|||
return fluid_errbuf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a file is a MIDI file.
|
||||
* @param filename Path to the file to check
|
||||
* @return TRUE if it could be a MIDI file, FALSE otherwise
|
||||
*
|
||||
* The current implementation only checks for the "MThd" header in the file.
|
||||
* It is useful only to distinguish between SoundFont and MIDI files.
|
||||
*/
|
||||
int
|
||||
fluid_is_midifile(const char *filename)
|
||||
{
|
||||
FILE *fp = fopen(filename, "rb");
|
||||
char id[4];
|
||||
|
||||
if(fp == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(fread((void *) id, 1, 4, fp) != 4)
|
||||
{
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return FLUID_STRNCMP(id, "MThd", 4) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a file is a SoundFont file.
|
||||
* @param filename Path to the file to check
|
||||
* @return TRUE if it could be a SoundFont, FALSE otherwise
|
||||
*
|
||||
* @note The current implementation only checks for the "RIFF" and "sfbk" headers in
|
||||
* the file. It is useful to distinguish between SoundFont and other (e.g. MIDI) files.
|
||||
*/
|
||||
int
|
||||
fluid_is_soundfont(const char *filename)
|
||||
{
|
||||
FILE *fp = fopen(filename, "rb");
|
||||
char riff_id[4], sfbk_id[4];
|
||||
|
||||
if(fp == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if((fread((void *) riff_id, 1, sizeof(riff_id), fp) != sizeof(riff_id)) ||
|
||||
(fseek(fp, 4, SEEK_CUR) != 0) ||
|
||||
(fread((void *) sfbk_id, 1, sizeof(sfbk_id), fp) != sizeof(sfbk_id)))
|
||||
{
|
||||
goto error_rec;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return (FLUID_STRNCMP(riff_id, "RIFF", sizeof(riff_id)) == 0) &&
|
||||
(FLUID_STRNCMP(sfbk_id, "sfbk", sizeof(sfbk_id)) == 0);
|
||||
|
||||
error_rec:
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Suspend the execution of the current thread for the specified amount of time.
|
||||
* @param milliseconds to wait.
|
||||
|
|
|
@ -77,6 +77,14 @@
|
|||
#define FLUID_LE32TOH(x) GINT32_FROM_LE(x)
|
||||
#define FLUID_LE16TOH(x) GINT16_FROM_LE(x)
|
||||
|
||||
#if FLUID_IS_BIG_ENDIAN
|
||||
#define FLUID_FOURCC(_a, _b, _c, _d) \
|
||||
(uint32_t)(((uint32_t)(_a) << 24) | ((uint32_t)(_b) << 16) | ((uint32_t)(_c) << 8) | (uint32_t)(_d))
|
||||
#else
|
||||
#define FLUID_FOURCC(_a, _b, _c, _d) \
|
||||
(uint32_t)(((uint32_t)(_d) << 24) | ((uint32_t)(_c) << 16) | ((uint32_t)(_b) << 8) | (uint32_t)(_a))
|
||||
#endif
|
||||
|
||||
|
||||
#define fluid_return_if_fail(cond) \
|
||||
if(cond) \
|
||||
|
|
Loading…
Reference in a new issue