10using namespace Tempest;
12#ifdef TSF_IMPLEMENTATION
14TSFDEF
void __note_on(tsf* f,
int preset_index,
int key,
float vel) {
15 short midiVelocity = short(vel * 127);
16 struct tsf_region *region, *regionEnd;
18 if(preset_index < 0 || preset_index >= f->presetNum)
22 tsf_note_off(f, preset_index, key);
27 int voicePlayIndex = f->voicePlayIndex++;
28 for(region = f->presets[preset_index].regions, regionEnd = region + f->presets[preset_index].regionNum; region != regionEnd; region++) {
29 if(key < region->lokey || key > region->hikey || midiVelocity < region->lovel || midiVelocity > region->hivel)
32 tsf_voice *voice =
nullptr;
33 tsf_voice *v = f->voices, *vEnd = v + f->voiceNum;
36 if(v->playingPreset == preset_index && v->region->group == region->group)
37 tsf_voice_endquick(v, f->outSampleRate);
38 else if (v->playingPreset == -1 && !voice)
42 if(v->playingPreset==-1) {
50 f->voices = (
struct tsf_voice*)TSF_REALLOC(f->voices, f->voiceNum *
sizeof(
struct tsf_voice));
51 voice = &f->voices[f->voiceNum - 4];
52 voice[1].playingPreset = voice[2].playingPreset = voice[3].playingPreset = -1;
55 voice->region = region;
56 voice->playingPreset = preset_index;
57 voice->playingKey = key;
58 voice->playIndex = voicePlayIndex;
59 voice->noteGainDB = f->globalGainDB - region->attenuation - tsf_gainToDecibels(1.0f / vel);
62 f->channels->setupVoice(f, voice);
64 tsf_voice_calcpitchratio(voice, 0, f->outSampleRate);
66 voice->panFactorLeft = TSF_SQRTF(0.5f - region->pan);
67 voice->panFactorRight = TSF_SQRTF(0.5f + region->pan);
71 voice->sourceSamplePosition = region->offset;
74 bool doLoop = (region->loop_mode != TSF_LOOPMODE_NONE && region->loop_start < region->loop_end);
75 voice->loopStart = (doLoop ? region->loop_start : 0);
76 voice->loopEnd = (doLoop ? region->loop_end : 0);
79 tsf_voice_envelope_setup(&voice->ampenv, ®ion->ampenv, key, midiVelocity, TSF_TRUE, f->outSampleRate);
80 tsf_voice_envelope_setup(&voice->modenv, ®ion->modenv, key, midiVelocity, TSF_FALSE, f->outSampleRate);
83 float filterQDB = region->initialFilterQ / 10.0f;
84 voice->lowpass.QInv = 1.0 / TSF_POW(10.0, (filterQDB / 20.0));
85 voice->lowpass.z1 = voice->lowpass.z2 = 0;
86 voice->lowpass.active = (region->initialFilterFc <= 13500);
87 if (voice->lowpass.active) tsf_voice_lowpass_setup(&voice->lowpass, tsf_cents2Hertz((
float)region->initialFilterFc) / f->outSampleRate);
90 tsf_voice_lfo_setup(&voice->modlfo, region->delayModLFO, region->freqModLFO, f->outSampleRate);
91 tsf_voice_lfo_setup(&voice->viblfo, region->delayVibLFO, region->freqVibLFO, f->outSampleRate);
95TSFDEF
void __note_off(tsf* f,
int preset_index,
int key) {
96 tsf_voice *v = f->voices, *vEnd = v + f->voiceNum, *vMatchFirst =
nullptr, *vMatchLast =
nullptr;
99 if(v->playingPreset != preset_index || v->playingKey != key || v->ampenv.segment >= TSF_SEGMENT_RELEASE)
101 if(!vMatchFirst || v->playIndex < vMatchFirst->playIndex)
102 vMatchFirst = vMatchLast = v;
103 else if(v->playIndex == vMatchFirst->playIndex)
108 int sz = vMatchLast-vMatchFirst;
111 for(v = vMatchFirst; v <= vMatchLast; v++) {
113 if(v != vMatchFirst && v != vMatchLast &&
114 (v->playIndex != vMatchFirst->playIndex || v->playingPreset != preset_index || v->playingKey != key || v->ampenv.segment >= TSF_SEGMENT_RELEASE))
116 tsf_voice_end(v, f->outSampleRate);
120TSFDEF
void __render_float(tsf* f,
float* buffer,
int samples,
int flag_mixing)
122 struct tsf_voice *v = f->voices, *vEnd = v + f->voiceNum;
123 if (!flag_mixing) TSF_MEMSET(buffer, 0, (f->outputmode == TSF_MONO ? 1 : 2) * sizeof(float) * samples);
124 for (; v != vEnd; v++)
125 if (v->playingPreset != -1)
126 tsf_voice_render(f, v, buffer, samples);
139 Instance(std::shared_ptr<Data> &shData,uint32_t dwPatch){
140 uint8_t bankHi = uint8_t((dwPatch & 0x00FF0000) >> 0x10);
141 uint8_t bankLo = uint8_t((dwPatch & 0x0000FF00) >> 0x8);
142 uint8_t patch = uint8_t(dwPatch & 0x000000FF);
143 int32_t bank = (bankHi << 16) + bankLo;
145 fnt = shData->hydra.toTsf();
163 bool noteOn(uint8_t note, uint8_t velosity){
199 std::shared_ptr<Instance>
noteOn(uint8_t note, uint8_t velosity){
201 if(i->noteOn(note,velosity))
206 fnt->noteOn(note,velosity);
207 inst.emplace_back(fnt);
226 void mix(
float *samples,
size_t count) {
234 std::vector<std::shared_ptr<Instance>>
inst;
241 impl = std::shared_ptr<Impl>(
new Impl(sh,dwPatch));
248 return std::shared_ptr<Data>(
new Data(dls,wave));
254 return impl->hasNotes();
270 impl->mix(samples,count);
277 t.impl = impl->noteOn(note,velosity);
static void renderFloat(tsf *f, float *buffer, int samples, int flag)
static void setOutput(tsf *f, int samplerate, float gain)
static int presetIndex(const tsf *f, int bank, int presetNum)
static bool hasNotes(tsf *tsf)
static void noteOn(tsf *f, int presetId, int key, float vel)
static int channelSetPan(tsf *f, int channel, float pan)
static void finalize(tsf *tsf)
static void noteOff(tsf *f, int presetId, int key)
static void noteOff(Ticket &t)
Ticket noteOn(uint8_t note, uint8_t velosity)
void mix(float *samples, size_t count)
static std::shared_ptr< Data > shared(const DlsCollection &dls, const std::vector< Wave > &wave)
Data(const DlsCollection &dls, const std::vector< Wave > &wave)
Impl(std::shared_ptr< Data > &shData, uint32_t dwPatch)
std::vector< std::shared_ptr< Instance > > inst
std::shared_ptr< Instance > noteOn(uint8_t note, uint8_t velosity)
void mix(float *samples, size_t count)
std::shared_ptr< Data > shData
bool noteOff(uint8_t note)
bool noteOn(uint8_t note, uint8_t velosity)
Instance(std::shared_ptr< Data > &shData, uint32_t dwPatch)