Parallelize SF3 loading (#746)

This commit is contained in:
Tom M 2021-02-06 20:32:17 +01:00 committed by GitHub
parent 4836ff15c4
commit 0d76403f9f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 57 additions and 25 deletions

View file

@ -374,6 +374,7 @@ int fluid_defsfont_load_all_sampledata(fluid_defsfont_t *defsfont, SFData *sfdat
fluid_list_t *list;
fluid_sample_t *sample;
int sf3_file = (sfdata->version.major == 3);
int sample_parsing_result = FLUID_OK;
/* For SF2 files, we load the sample data in one large block */
if(!sf3_file)
@ -392,6 +393,8 @@ int fluid_defsfont_load_all_sampledata(fluid_defsfont_t *defsfont, SFData *sfdat
}
}
#pragma omp parallel
#pragma omp single
for(list = defsfont->sample; list; list = fluid_list_next(list))
{
sample = fluid_list_get(list);
@ -400,13 +403,22 @@ int fluid_defsfont_load_all_sampledata(fluid_defsfont_t *defsfont, SFData *sfdat
{
/* SF3 samples get loaded individually, as most (or all) of them are in Ogg Vorbis format
* anyway */
if(fluid_defsfont_load_sampledata(defsfont, sfdata, sample) == FLUID_FAILED)
#pragma omp task firstprivate(sample,sfdata,defsfont) shared(sample_parsing_result) default(none)
{
FLUID_LOG(FLUID_ERR, "Failed to load sample '%s'", sample->name);
return FLUID_FAILED;
if(fluid_defsfont_load_sampledata(defsfont, sfdata, sample) == FLUID_FAILED)
{
#pragma omp critical
{
FLUID_LOG(FLUID_ERR, "Failed to load sample '%s'", sample->name);
sample_parsing_result = FLUID_FAILED;
}
}
else
{
fluid_sample_sanitize_loop(sample, (sample->end + 1) * sizeof(short));
fluid_voice_optimize_sample(sample);
}
}
fluid_sample_sanitize_loop(sample, (sample->end + 1) * sizeof(short));
}
else
{
@ -414,12 +426,11 @@ int fluid_defsfont_load_all_sampledata(fluid_defsfont_t *defsfont, SFData *sfdat
sample->data = defsfont->sampledata;
sample->data24 = defsfont->sample24data;
fluid_sample_sanitize_loop(sample, defsfont->samplesize);
fluid_voice_optimize_sample(sample);
}
fluid_voice_optimize_sample(sample);
}
return FLUID_OK;
return sample_parsing_result;
}
/*

View file

@ -89,6 +89,7 @@ int fluid_samplecache_load(SFData *sf,
if(entry == NULL)
{
fluid_mutex_unlock(samplecache_mutex);
entry = new_samplecache_entry(sf, sample_start, sample_end, sample_type, mtime);
if(entry == NULL)
@ -97,8 +98,10 @@ int fluid_samplecache_load(SFData *sf,
goto unlock_exit;
}
fluid_mutex_lock(samplecache_mutex);
samplecache_list = fluid_list_prepend(samplecache_list, entry);
}
fluid_mutex_unlock(samplecache_mutex);
if(try_mlock && !entry->mlocked)
{
@ -129,7 +132,6 @@ int fluid_samplecache_load(SFData *sf,
ret = entry->sample_count;
unlock_exit:
fluid_mutex_unlock(samplecache_mutex);
return ret;
}

View file

@ -422,6 +422,7 @@ SFData *fluid_sffile_open(const char *fname, const fluid_file_callbacks_t *fcbs)
FLUID_MEMSET(sf, 0, sizeof(SFData));
fluid_rec_mutex_init(sf->mtx);
sf->fcbs = fcbs;
if((sf->sffd = fcbs->fopen(fname)) == NULL)
@ -530,6 +531,7 @@ void fluid_sffile_close(SFData *sf)
SFPreset *preset;
SFInst *inst;
fluid_rec_mutex_destroy(sf->mtx);
if(sf->sffd)
{
sf->fcbs->fclose(sf->sffd);
@ -2529,10 +2531,14 @@ static sf_count_t sfvio_seek(sf_count_t offset, int whence, void *user_data)
goto fail; /* proper error handling not possible?? */
}
if(sf->fcbs->fseek(sf->sffd, sf->samplepos + data->start + new_offset, SEEK_SET) != FLUID_FAILED)
new_offset += data->start;
fluid_rec_mutex_lock(sf->mtx);
if (data->start <= new_offset && new_offset <= data->end &&
sf->fcbs->fseek(sf->sffd, new_offset, SEEK_SET) != FLUID_FAILED)
{
data->offset = new_offset;
data->offset = new_offset - data->start;
}
fluid_rec_mutex_unlock(sf->mtx);
fail:
return data->offset;
@ -2556,11 +2562,21 @@ static sf_count_t sfvio_read(void *ptr, sf_count_t count, void *user_data)
return count;
}
if(sf->fcbs->fread(ptr, count, sf->sffd) == FLUID_FAILED)
fluid_rec_mutex_lock(sf->mtx);
if (sf->fcbs->fseek(sf->sffd, data->start + data->offset, SEEK_SET) == FLUID_FAILED)
{
FLUID_LOG(FLUID_ERR, "Failed to read compressed sample data");
return 0;
FLUID_LOG(FLUID_ERR, "This should never happen: fseek failed in sfvoid_read()");
count = 0;
}
else
{
if (sf->fcbs->fread(ptr, count, sf->sffd) == FLUID_FAILED)
{
FLUID_LOG(FLUID_ERR, "Failed to read compressed sample data");
count = 0;
}
}
fluid_rec_mutex_unlock(sf->mtx);
data->offset += count;
@ -2607,25 +2623,26 @@ static int fluid_sffile_read_vorbis(SFData *sf, unsigned int start_byte, unsigne
// Initialize file position indicator and SF_INFO structure
sfdata.sffile = sf;
sfdata.start = start_byte;
sfdata.end = end_byte;
sfdata.offset = 0;
sfdata.start = sf->samplepos + start_byte;
sfdata.end = sf->samplepos + end_byte;
sfdata.offset = -1;
FLUID_MEMSET(&sfinfo, 0, sizeof(sfinfo));
/* Seek to beginning of Ogg Vorbis data in Soundfont */
if(sf->fcbs->fseek(sf->sffd, sf->samplepos + start_byte, SEEK_SET) == FLUID_FAILED)
/* Seek to sfdata.start, the beginning of Ogg Vorbis data in Soundfont */
sfvio_seek(0, SEEK_SET, &sfdata);
if (sfdata.offset != 0)
{
FLUID_LOG(FLUID_ERR, "Failed to seek to compressd sample position");
FLUID_LOG(FLUID_ERR, "Failed to seek to compressed sample position");
return -1;
}
FLUID_MEMSET(&sfinfo, 0, sizeof(sfinfo));
// Open sample as a virtual file
sndfile = sf_open_virtual(&sfvio, SFM_READ, &sfinfo, &sfdata);
if(!sndfile)
{
FLUID_LOG(FLUID_ERR, "%s", sf_strerror(sndfile));
FLUID_LOG(FLUID_ERR, "sf_open_virtual(): %s", sf_strerror(sndfile));
return -1;
}
@ -2662,7 +2679,7 @@ static int fluid_sffile_read_vorbis(SFData *sf, unsigned int start_byte, unsigne
if(sf_readf_short(sndfile, wav_data, sfinfo.frames) < sfinfo.frames)
{
FLUID_LOG(FLUID_DBG, "Decompression failed!");
FLUID_LOG(FLUID_ERR, "%s", sf_strerror(sndfile));
FLUID_LOG(FLUID_ERR, "sf_readf_short(): %s", sf_strerror(sndfile));
goto error_exit;
}

View file

@ -29,7 +29,7 @@
#include "fluid_list.h"
#include "fluid_mod.h"
#include "fluidsynth.h"
#include "fluidsynth_priv.h"
#include "fluid_sys.h"
/* Sound Font structure defines */
@ -159,6 +159,8 @@ struct _SFData
FILE *sffd; /* loaded sfont file descriptor */
const fluid_file_callbacks_t *fcbs; /* file callbacks used to read this file */
fluid_rec_mutex_t mtx; /* this mutex can be used to synchronize calls to fcbs when using multiple threads (e.g. SF3 loading) */
fluid_list_t *info; /* linked list of info strings (1st byte is ID) */
fluid_list_t *preset; /* linked list of preset info */
fluid_list_t *inst; /* linked list of instrument info */