mirror of
https://github.com/ZDoom/fluidsynth.git
synced 2025-05-31 01:00:53 +00:00
Enable decompressed Ogg Vorbis samples to be stored in sample cache
This change moves the Ogg Vorbis decompression to fluid_sffile, so that this is the only place where we have to deal with compressed audio. It also changes the way the samples are loaded for SF3 files: previously, the compressed data was copied into memory, then the individual samples were decompressed (resulting in both compressed and decompressed data to stay in memory). Also, decompressed data wasn't cached, so previous loads of the same file ran the decompressed again for each sample. After this change, the vorbis decompression is changed so that it reads the compressed data directly from the Soundfont file. And the resulting WAV data is stored in the sample cache.
This commit is contained in:
parent
f52bbf53a4
commit
a985c68a13
8 changed files with 432 additions and 299 deletions
|
@ -21,11 +21,6 @@
|
|||
#include "fluid_sfont.h"
|
||||
#include "fluid_sys.h"
|
||||
|
||||
#if LIBSNDFILE_SUPPORT
|
||||
#include <sndfile.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void * default_fopen(const char * path)
|
||||
{
|
||||
|
@ -605,16 +600,6 @@ int fluid_sample_sanitize_loop(fluid_sample_t *sample, unsigned int buffer_size)
|
|||
* to the data word after the last sample. FIXME: why? */
|
||||
unsigned int sample_end = sample->end + 1;
|
||||
|
||||
/* Checking loops on compressed samples makes no sense at all and is really
|
||||
* a programming error. Disable the loop to be on the safe side. */
|
||||
if (sample->sampletype & FLUID_SAMPLETYPE_OGG_VORBIS)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Sample '%s': checking loop on compressed sample, disabling loop",
|
||||
sample->name);
|
||||
sample->loopstart = sample->loopend = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (sample->loopstart == sample->loopend)
|
||||
{
|
||||
/* Some SoundFonts disable loops by setting loopstart = loopend. While
|
||||
|
@ -670,128 +655,3 @@ int fluid_sample_sanitize_loop(fluid_sample_t *sample, unsigned int buffer_size)
|
|||
|
||||
return modified;
|
||||
}
|
||||
|
||||
#if LIBSNDFILE_SUPPORT
|
||||
|
||||
// virtual file access rountines to allow for handling
|
||||
// samples as virtual files in memory
|
||||
static sf_count_t
|
||||
sfvio_get_filelen(void* user_data)
|
||||
{
|
||||
fluid_sample_t *sample = (fluid_sample_t *)user_data;
|
||||
|
||||
return (sf_count_t)(sample->end + 1 - sample->start);
|
||||
}
|
||||
|
||||
static sf_count_t
|
||||
sfvio_seek(sf_count_t offset, int whence, void* user_data)
|
||||
{
|
||||
fluid_sample_t *sample = (fluid_sample_t *)user_data;
|
||||
|
||||
switch (whence)
|
||||
{
|
||||
case SEEK_SET:
|
||||
sample->userdata = (void *)offset;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
sample->userdata = (void *)((sf_count_t)sample->userdata + offset);
|
||||
break;
|
||||
case SEEK_END:
|
||||
sample->userdata = (void *)(sfvio_get_filelen(user_data) + offset);
|
||||
break;
|
||||
}
|
||||
|
||||
return (sf_count_t)sample->userdata;
|
||||
}
|
||||
|
||||
static sf_count_t
|
||||
sfvio_read(void* ptr, sf_count_t count, void* user_data)
|
||||
{
|
||||
fluid_sample_t *sample = (fluid_sample_t *)user_data;
|
||||
sf_count_t remain = sfvio_get_filelen(user_data) - (sf_count_t)sample->userdata;
|
||||
|
||||
if (count > remain)
|
||||
count = remain;
|
||||
|
||||
memcpy(ptr, (char *)sample->data + sample->start + (sf_count_t)sample->userdata, count);
|
||||
sample->userdata = (void *)((sf_count_t)sample->userdata + count);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static sf_count_t
|
||||
sfvio_tell (void* user_data)
|
||||
{
|
||||
fluid_sample_t *sample = (fluid_sample_t *)user_data;
|
||||
|
||||
return (sf_count_t)sample->userdata;
|
||||
}
|
||||
|
||||
int fluid_sample_decompress_vorbis(fluid_sample_t *sample)
|
||||
{
|
||||
SNDFILE *sndfile;
|
||||
SF_INFO sfinfo;
|
||||
SF_VIRTUAL_IO sfvio = {
|
||||
sfvio_get_filelen,
|
||||
sfvio_seek,
|
||||
sfvio_read,
|
||||
NULL,
|
||||
sfvio_tell
|
||||
};
|
||||
short *sampledata_ogg;
|
||||
|
||||
// initialize file position indicator and SF_INFO structure
|
||||
g_assert(sample->userdata == NULL);
|
||||
memset(&sfinfo, 0, sizeof(sfinfo));
|
||||
|
||||
// open sample as a virtual file in memory
|
||||
sndfile = sf_open_virtual(&sfvio, SFM_READ, &sfinfo, sample);
|
||||
if (!sndfile)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, sf_strerror(sndfile));
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
|
||||
// empty sample
|
||||
if (!sfinfo.frames || !sfinfo.channels)
|
||||
{
|
||||
sample->start = sample->end = 0;
|
||||
sample->loopstart = sample->loopend = 0;
|
||||
sample->data = NULL;
|
||||
sf_close(sndfile);
|
||||
return FLUID_OK;
|
||||
}
|
||||
|
||||
// allocate memory for uncompressed sample data stream
|
||||
sampledata_ogg = (short *)FLUID_MALLOC(sfinfo.frames * sfinfo.channels * sizeof(short));
|
||||
if (!sampledata_ogg)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
sf_close(sndfile);
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
|
||||
// uncompress sample data stream
|
||||
if (sf_readf_short(sndfile, sampledata_ogg, sfinfo.frames) < sfinfo.frames)
|
||||
{
|
||||
FLUID_FREE(sampledata_ogg);
|
||||
FLUID_LOG(FLUID_ERR, sf_strerror(sndfile));
|
||||
sf_close(sndfile);
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
sf_close(sndfile);
|
||||
|
||||
// point sample data to uncompressed data stream
|
||||
sample->data = sampledata_ogg;
|
||||
sample->auto_free = TRUE;
|
||||
sample->start = 0;
|
||||
sample->end = sfinfo.frames - 1;
|
||||
|
||||
return FLUID_OK;
|
||||
}
|
||||
#else
|
||||
int fluid_sample_decompress_vorbis(fluid_sample_t *sample)
|
||||
{
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue