Audio-TinySoundFont
view release on metacpan or search on metacpan
Revision history for Audio-TinySoundFont
0.12 2024-04-05 00:25:30 EDT
* Update TinySoundFont to newest commit
0.11 2021-01-11 23:39:33 EST
* Fix building on threaded perls
0.10 2021-01-11 00:10:30 EST
* Initial release
TinySoundFont/tsf.h view on Meta::CPAN
// Function pointer will be called to skip ahead over 'count' bytes (returns 1 on success, 0 on error)
int (*skip)(void* data, unsigned int count);
};
// Generic SoundFont loading method using the stream structure above
TSFDEF tsf* tsf_load(struct tsf_stream* stream);
// Copy a tsf instance from an existing one, use tsf_close to close it as well.
// All copied tsf instances and their original instance are linked, and share the underlying soundfont.
// This allows loading a soundfont only once, but using it for multiple independent playbacks.
// (This function isn't thread-safe without locking.)
TSFDEF tsf* tsf_copy(tsf* f);
// Free the memory related to this tsf instance
TSFDEF void tsf_close(tsf* f);
// Stop all playing notes immediately and reset all channel parameters
TSFDEF void tsf_reset(tsf* f);
// Returns the preset index from a bank and preset number, or -1 if it does not exist in the loaded SoundFont
TSFDEF int tsf_get_presetindex(const tsf* f, int bank, int preset_number);
TinySoundFont/tsf.h view on Meta::CPAN
TSF_STEREO_UNWEAVED,
// A single channel (stereo instruments are mixed into center)
TSF_MONO
};
// Thread safety:
//
// 1. Rendering / voices:
//
// Your audio output which calls the tsf_render* functions will most likely
// run on a different thread than where the playback tsf_note* functions
// are called. In which case some sort of concurrency control like a
// mutex needs to be used so they are not called at the same time.
// Alternatively, you can pre-allocate a maximum number of voices that can
// play simultaneously by calling tsf_set_max_voices after loading.
// That way memory re-allocation will not happen during tsf_note_on and
// TSF should become mostly thread safe.
// There is a theoretical chance that ending notes would negatively influence
// a voice that is rendering at the time but it is hard to say.
// Also be aware, this has not been tested much.
//
// 2. Channels:
//
// Calls to tsf_channel_set_... functions may allocate new channels
// if no channel with that number was previously used. Make sure to
// create all channels at the beginning as required if you call tsf_render*
// from a different thread.
// Setup the parameters for the voice render methods
// outputmode: if mono or stereo and how stereo channel data is ordered
// samplerate: the number of samples per second (output frequency)
// global_gain_db: volume gain in decibels (>0 means higher, <0 means lower)
TSFDEF void tsf_set_output(tsf* f, enum TSFOutputMode outputmode, int samplerate, float global_gain_db CPP_DEFAULT0);
// Set the global gain as a volume factor
// global_gain: the desired volume where 1.0 is 100%
TSFDEF void tsf_set_volume(tsf* f, float global_gain);
TinySoundFont/tsf.h view on Meta::CPAN
else if (e->level < -1.0f) { e->delta = -e->delta; e->level = -2.0f - e->level; }
}
static void tsf_voice_kill(struct tsf_voice* v)
{
v->playingPreset = -1;
}
static void tsf_voice_end(tsf* f, struct tsf_voice* v)
{
// if maxVoiceNum is set, assume that voice rendering and note queuing are on separate threads
// so to minimize the chance that voice rendering would advance the segment at the same time
// we just do it twice here and hope that it sticks
int repeats = (f->maxVoiceNum ? 2 : 1);
while (repeats--)
{
tsf_voice_envelope_nextsegment(&v->ampenv, TSF_SEGMENT_SUSTAIN, f->outSampleRate);
tsf_voice_envelope_nextsegment(&v->modenv, TSF_SEGMENT_SUSTAIN, f->outSampleRate);
if (v->region->loop_mode == TSF_LOOPMODE_SUSTAIN)
{
// Continue playing, but stop looping.
v->loopEnd = v->loopStart;
}
}
}
static void tsf_voice_endquick(tsf* f, struct tsf_voice* v)
{
// if maxVoiceNum is set, assume that voice rendering and note queuing are on separate threads
// so to minimize the chance that voice rendering would advance the segment at the same time
// we just do it twice here and hope that it sticks
int repeats = (f->maxVoiceNum ? 2 : 1);
while (repeats--)
{
v->ampenv.parameters.release = 0.0f; tsf_voice_envelope_nextsegment(&v->ampenv, TSF_SEGMENT_SUSTAIN, f->outSampleRate);
v->modenv.parameters.release = 0.0f; tsf_voice_envelope_nextsegment(&v->modenv, TSF_SEGMENT_SUSTAIN, f->outSampleRate);
}
}
( run in 1.077 second using v1.01-cache-2.11-cpan-3cd7ad12f66 )