5#define TSF_IMPLEMENTATION
9#pragma GCC diagnostic push
10#pragma GCC diagnostic ignored "-Wconversion"
11#pragma GCC diagnostic ignored "-Wunused-function"
13#pragma GCC diagnostic pop
24static bool compValue(
const tsf_hydra_phdr& a,
const tsf_hydra_phdr& b){
26 std::memcmp(a.presetName,b.presetName,20)==0 &&
27 a.preset ==b.preset &&
29 a.presetBagNdx==b.presetBagNdx &&
30 a.library ==b.library &&
32 a.morphology ==b.morphology;
35static bool compValue(
const tsf_hydra_shdr& a,
const tsf_hydra_shdr& b){
37 std::memcmp(a.sampleName,b.sampleName,20)==0 &&
42 a.sampleRate ==b.sampleRate &&
43 a.originalPitch ==b.originalPitch &&
44 a.pitchCorrection==b.pitchCorrection &&
45 a.sampleLink ==b.sampleLink &&
46 a.sampleType ==b.sampleType;
49static bool compValue(
const tsf_hydra_pbag& a,
const tsf_hydra_pbag& b){
55static bool compValue(
const tsf_hydra_pmod& a,
const tsf_hydra_pmod& b){
57 a.modSrcOper ==b.modSrcOper &&
58 a.modDestOper ==b.modDestOper &&
59 a.modAmount ==b.modAmount &&
60 a.modAmtSrcOper==b.modAmtSrcOper &&
61 a.modTransOper ==b.modTransOper;
64static bool compValue(
const tsf_hydra_pgen& a,
const tsf_hydra_pgen& b){
65 return std::memcmp(&a,&b,
sizeof(a))==0;
68static bool compValue(
const tsf_hydra_inst& a,
const tsf_hydra_inst& b){
69 return std::memcmp(&a,&b,
sizeof(a))==0;
72static bool compValue(
const tsf_hydra_ibag& a,
const tsf_hydra_ibag& b){
73 return std::memcmp(&a,&b,
sizeof(a))==0;
76static bool compValue(
const tsf_hydra_imod& a,
const tsf_hydra_imod& b){
77 return std::memcmp(&a,&b,
sizeof(a))==0;
80static bool compValue(
const tsf_hydra_igen& a,
const tsf_hydra_igen& b){
81 return std::memcmp(&a,&b,
sizeof(a))==0;
85static bool comp(
const T* a,
const T* b,
int n,
size_t vn){
97 std::strncpy(r.presetName,instr.
info.
inam.c_str(),19);
100 r.presetBagNdx = index;
107static tsf_hydra_phdr
mkPhdr(
const char* presetName,uint16_t index){
108 tsf_hydra_phdr r = {};
109 std::strncpy(r.presetName,presetName,19);
110 r.presetBagNdx = index;
114static tsf_hydra_pbag
mkPbag(uint16_t genNdx,uint16_t modNdx){
121static tsf_hydra_pgen
mkPgen(uint16_t genOper,uint16_t wordAmount){
124 r.genAmount.wordAmount = wordAmount;
128static tsf_hydra_inst
mkInst(
const char* instName,uint16_t instBagNdx){
130 std::strncpy(r.instName,instName,19);
131 r.instBagNdx=instBagNdx;
135static tsf_hydra_ibag
mkIbag(uint16_t instGenNdx,uint16_t instModNdx){
137 r.instGenNdx = instGenNdx;
138 r.instModNdx = instModNdx;
142struct tsf_hydra_igen
mkIgen(uint16_t op,uint16_t lo,uint16_t hi) {
144 throw std::runtime_error(
"hydra.igen range error");
147 r.genAmount.range.lo = uint8_t(lo);
148 r.genAmount.range.hi = uint8_t(hi);
152struct tsf_hydra_igen
mkIgen(uint16_t op,uint16_t u16) {
155 r.genAmount.wordAmount = u16;
159uint16_t Hydra::mkGeneratorOp(uint16_t usDestination) {
160 switch(usDestination) {
184 std::vector<tsf_hydra_shdr> samples;
187 const uint16_t modIndex = 0;
188 const uint16_t instModNdx = 0;
189 uint16_t instBagIndex = 0;
191 for(
size_t idInstr=0; idInstr<dls.
instrument.size(); ++idInstr) {
198 inst.push_back(
mkInst(instr.info.inam.c_str(),instBagIndex));
200 instBagIndex = uint16_t(instBagIndex+instr.regions.size());
202 for(
const auto& reg : instr.regions) {
203 const auto& hdr = reg.head;
204 const auto& wavelink = reg.wlink;
205 const auto& wavesample = reg.waveSample;
209 uint16_t keyrangeLow = hdr.RangeKey.usLow;
210 uint16_t keyrangeHigh = hdr.RangeKey.usHigh;
211 uint16_t velrangeLow = 0;
212 uint16_t velrangeHigh = 0;
213 if(hdr.RangeVelocity.usHigh<=hdr.RangeVelocity.usLow) {
217 velrangeLow = hdr.RangeVelocity.usLow;
218 velrangeHigh = hdr.RangeVelocity.usHigh;
223 const uint16_t time = 61550;
226 for(
const auto& art : instr.articulators) {
227 for(
const auto& c : art.connectionBlocks) {
228 if(c.usControl == 0 && c.usSource == 0 && c.usTransform == 0) {
229 uint16_t gen = mkGeneratorOp(c.usDestination);
230 igen.push_back(
mkIgen(gen,uint16_t(c.lScale/65536)));
235 if(hdr.RangeKey.usHigh < hdr.RangeKey.usLow)
236 throw std::runtime_error(
"Invalid key range in instrument");
238 tsf_hydra_shdr sample={};
239 if(reg.loop.size()==0) {
240 sample = samples[wavelink.ulTableIndex];
241 sample.startLoop = 0;
245 auto loop = reg.loop[0];
246 sample = samples[wavelink.ulTableIndex];
247 sample.startLoop = loop.ulLoopStart;
248 sample.endLoop = loop.ulLoopStart + loop.ulLoopLength;
250 sample.startLoop += sample.start;
251 sample.endLoop += sample.start;
257 sample.originalPitch = uint8_t(wavesample.usUnityNote);
258 sample.pitchCorrection = int8_t (wavesample.sFineTune);
259 shdr.push_back(sample);
266 tsf_hydra_pmod mod={};
273 tsf_hydra_imod imd={};
276 tsf_hydra_igen gen={};
279 tsf_hydra_shdr sampleEnd={};
280 std::strncpy(sampleEnd.sampleName,
"EOS",19);
281 shdr.push_back(sampleEnd);
288 tsf->fontSamples=
nullptr;
293 tsf_voice *v = tsf->voices, *vEnd = v + tsf->voiceNum;
295 if(v->playingPreset != -1)
301 tsf_note_on(f, presetId, key, vel);
305 tsf_note_off(f, presetId, key);
309 return tsf_get_presetindex(f, bank, presetNum);
313 tsf_render_float(f, buffer, samples, flag);
317 return tsf_channel_set_pan(f, channel, pan);
321 tsf_set_output(f, TSF_STEREO_INTERLEAVED, samplerate, gain);
328 tsf* res =
reinterpret_cast<tsf*
>(TSF_MALLOC(
sizeof(tsf)));
329 TSF_MEMSET(res, 0,
sizeof(tsf));
330 res->outSampleRate = 44100.0f;
331 res->presetNum = hydra.phdrNum - 1;
332 res->presets =
reinterpret_cast<tsf_preset*
>(TSF_MALLOC(
size_t(res->presetNum)*
sizeof(tsf_preset)));
334 res->fontSamples =
wdata.get();
335 tsf_load_presets(res, &hydra,
unsigned(
wdataSize));
340 out.phdrNum = int(
phdr.size());
341 out.phdrs =
phdr.data();
343 out.pbagNum = int(
pbag.size());
344 out.pbags =
pbag.data();
346 out.pmodNum = int(
pmod.size());
347 out.pmods =
pmod.data();
349 out.pgenNum = int(
pgen.size());
350 out.pgens =
pgen.data();
352 out.instNum = int(
inst.size());
353 out.insts =
inst.data();
355 out.ibagNum = int(
ibag.size());
356 out.ibags =
ibag.data();
358 out.imodNum = int(
imod.size());
359 out.imods =
imod.data();
361 out.igenNum = int(
igen.size());
362 out.igens =
igen.data();
364 out.shdrNum = int(
shdr.size());
365 out.shdrs =
shdr.data();
368std::unique_ptr<float[]> Hydra::allocSamples(
const std::vector<Wave>& wave,std::vector<tsf_hydra_shdr>& smp,
size_t& count) {
370 for(
const auto& wav : wave) {
371 if(wav.wfmt.wBitsPerSample!=16)
372 throw std::runtime_error(
"Unexpected DLS sample format");
373 const size_t wavSize = wav.wavedata.size()/(
sizeof(int16_t));
375 tsf_hydra_shdr sx={};
376 std::strncpy(sx.sampleName,wav.info.inam.c_str(),19);
377 sx.start = tsf_u32(wavStart);
378 sx.end = tsf_u32(wavStart+wavSize);
381 sx.sampleRate = wav.wfmt.dwSamplesPerSec;
382 sx.originalPitch = uint8_t(wav.waveSample.usUnityNote);
383 sx.pitchCorrection = int8_t (wav.waveSample.sFineTune);
392 std::unique_ptr<float[]> samples(
new float[wavStart]);
393 float* wr = samples.get();
396 for(
const auto& wav : wave) {
397 wav.toFloatSamples(wr);
398 wr+=wav.wavedata.size()/
sizeof(int16_t);
411 if(!
comp(tsf.phdrs,
phdr.data(),tsf.phdrNum,
phdr.size()))
413 if(!
comp(tsf.pbags,
pbag.data(),tsf.pbagNum,
pbag.size()))
415 if(!
comp(tsf.pmods,
pmod.data(),tsf.pmodNum,
pmod.size()))
417 if(!
comp(tsf.pgens,
pgen.data(),tsf.pgenNum,
pgen.size()))
419 if(!
comp(tsf.insts,
inst.data(),tsf.instNum,
inst.size()))
421 if(!
comp(tsf.ibags,
ibag.data(),tsf.ibagNum,
ibag.size()))
423 if(!
comp(tsf.imods,
imod.data(),tsf.imodNum,
imod.size()))
425 if(!
comp(tsf.igens,
igen.data(),tsf.igenNum,
igen.size()))
427 if(!
comp(tsf.shdrs,
shdr.data(),tsf.shdrNum,
shdr.size()))
std::vector< Instrument > instrument
std::vector< tsf_hydra_igen > igen
Hydra(const DlsCollection &dls, const std::vector< Wave > &wave)
static void renderFloat(tsf *f, float *buffer, int samples, int flag)
bool validate(const tsf_hydra &tsf) const
static void setOutput(tsf *f, int samplerate, float gain)
std::vector< tsf_hydra_pbag > pbag
std::vector< tsf_hydra_ibag > ibag
std::vector< tsf_hydra_pgen > pgen
std::vector< tsf_hydra_phdr > phdr
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)
std::vector< tsf_hydra_pmod > pmod
static void finalize(tsf *tsf)
std::vector< tsf_hydra_inst > inst
std::unique_ptr< float[]> wdata
static void noteOff(tsf *f, int presetId, int key)
std::vector< tsf_hydra_shdr > shdr
std::vector< tsf_hydra_imod > imod
static tsf_hydra_phdr mkPhdr(const DlsCollection::Instrument &instr, uint16_t index)
static tsf_hydra_ibag mkIbag(uint16_t instGenNdx, uint16_t instModNdx)
static bool compValue(const tsf_hydra_phdr &a, const tsf_hydra_phdr &b)
struct tsf_hydra_igen mkIgen(uint16_t op, uint16_t lo, uint16_t hi)
static bool comp(const T *a, const T *b, int n, size_t vn)
@ kTerminatorSampleLength
static tsf_hydra_inst mkInst(const char *instName, uint16_t instBagNdx)
static tsf_hydra_pgen mkPgen(uint16_t genOper, uint16_t wordAmount)
static tsf_hydra_pbag mkPbag(uint16_t genNdx, uint16_t modNdx)