Skip to content

Commit

Permalink
refactor: more cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
lmichaelis committed May 3, 2024
1 parent 46b35fa commit 4c823e1
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 110 deletions.
21 changes: 5 additions & 16 deletions src/Common.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

enum {
DmInt_TICKS_PER_QUARTER_NOTE = 768,
DmInt_SECONDS_PER_MINUTE = 60,
};

size_t max_usize(size_t a, size_t b) {
Expand Down Expand Up @@ -37,18 +38,6 @@ int32_t clamp_s32(int32_t val, int32_t min, int32_t max) {
return val;
}

float clamp_f32(float val, float min, float max) {
if (val < min) {
return min;
}

if (val > max) {
return max;
}

return val;
}

int32_t Dm_randRange(int32_t range) {
uint32_t rnd = Dm_rand() % range;
return range - (int32_t) (rnd / 2);
Expand Down Expand Up @@ -97,10 +86,10 @@ uint32_t Dm_getMeasureLength(DmTimeSignature sig) {
}

double Dm_getTicksPerSample(DmTimeSignature time_signature, double beats_per_minute, uint32_t sample_rate) {
uint32_t pulses_per_beat = Dm_getBeatLength(time_signature); // unit: music-time per beat
double beats_per_second = beats_per_minute / 60; // unit: 1 per second
double pulses_per_second = pulses_per_beat * beats_per_second; // unit: music-time per second
double pulses_per_sample = pulses_per_second / sample_rate; // unit: music-time per sample
uint32_t pulses_per_beat = Dm_getBeatLength(time_signature); // unit: music-time per beat
double beats_per_second = beats_per_minute / DmInt_SECONDS_PER_MINUTE; // unit: 1 per second
double pulses_per_second = pulses_per_beat * beats_per_second; // unit: music-time per second
double pulses_per_sample = pulses_per_second / sample_rate; // unit: music-time per sample
return pulses_per_sample;
}

Expand Down
2 changes: 1 addition & 1 deletion src/Composer.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ DmResult Dm_composeTransition(DmStyle* sty,
}

if (embellishment == DmEmbellishment_END_AND_INTRO) {
// Complex "extro" plus "intro" transitoon
// Complex "extro" plus "intro" transition
msg.type = DmMessage_COMMAND;
msg.command.command = DmCommand_END;
msg.command.groove_level = 1;
Expand Down
17 changes: 7 additions & 10 deletions src/Synth.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ static DmSynthFont* DmSynth_getFont(DmSynth* slf, DmInstrument* ins) {
}

static DmResult DmSynth_updateFonts(DmSynth* slf, DmBand* band) {
DmResult rv = DmResult_SUCCESS;
for (size_t i = 0; i < band->instruments_len; ++i) {
DmInstrument* ins = &band->instruments[i];
if (ins->dls == NULL) {
Expand All @@ -78,12 +77,13 @@ static DmResult DmSynth_updateFonts(DmSynth* slf, DmBand* band) {
DmSynthFont new_fnt;
new_fnt.dls = ins->dls;

DmResult rv = DmResult_SUCCESS;
rv = DmSynth_createTsfForDls(ins->dls, &new_fnt.syn);
if (rv != DmResult_SUCCESS) {
continue;
}

tsf_set_output(new_fnt.syn, TSF_STEREO_INTERLEAVED, slf->rate, 0);
tsf_set_output(new_fnt.syn, TSF_STEREO_INTERLEAVED, (int) slf->rate, 0);
tsf_set_volume(new_fnt.syn, slf->volume);

rv = DmSynthFontArray_add(&slf->fonts, new_fnt);
Expand Down Expand Up @@ -145,7 +145,7 @@ static DmResult DmSynth_assignInstrumentChannels(DmSynth* slf, DmBand* band) {

DmSynthFont* fnt = DmSynth_getFont(slf, ins);
chan->font = fnt;
chan->channel = ins->channel;
chan->channel = (int) ins->channel;

if (fnt == NULL) {
continue;
Expand All @@ -155,18 +155,18 @@ static DmResult DmSynth_assignInstrumentChannels(DmSynth* slf, DmBand* band) {
uint32_t patch = ins->patch & 0xFFU;

tsf_set_volume(fnt->syn, slf->volume);
tsf_channel_set_bank_preset(fnt->syn, ins->channel, bank, patch);
tsf_channel_set_bank_preset(fnt->syn, (int) ins->channel, (int) bank, (int) patch);

// Update the instrument's properties
if (ins->options & DmInstrument_VALID_PAN) {
float pan = (float) ins->pan / (float) DmInt_MIDI_MAX;
tsf_channel_set_pan(fnt->syn, ins->channel, pan);
tsf_channel_set_pan(fnt->syn, (int) ins->channel, pan);
chan->reset_pan = pan;
}

if (ins->options & DmInstrument_VALID_VOLUME) {
float vol = (float) ins->volume / DmInt_MIDI_MAX;
tsf_channel_set_volume(fnt->syn, ins->channel, vol);
tsf_channel_set_volume(fnt->syn, (int) ins->channel, vol);
chan->reset_volume = vol;
}

Expand All @@ -178,10 +178,7 @@ static DmResult DmSynth_assignInstrumentChannels(DmSynth* slf, DmBand* band) {
return DmResult_SUCCESS;
}

// TODO(lmichaelis): Technically, we should change as little as possible to accommodate the new band.
// For example: if only the pan of an instrument changes, we should also only update that
// instead of reloading the entire instrument list and re-creating all TSFs.
// See also: https://documentation.help/DirectMusic/usingbands.htm
// See https://documentation.help/DirectMusic/usingbands.htm
void DmSynth_sendBandUpdate(DmSynth* slf, DmBand* band) {
if (slf == NULL || band == NULL) {
return;
Expand Down
1 change: 0 additions & 1 deletion src/_Internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,6 @@ DMINT int32_t max_s32(int32_t a, int32_t b);
DMINT uint8_t min_u8(uint8_t a, uint8_t b);
DMINT float lerp(float x, float start, float end);
DMINT int32_t clamp_s32(int32_t val, int32_t min, int32_t max);
DMINT float clamp_f32(float val, float min, float max);
DMINT int32_t Dm_randRange(int32_t range);
DMINT DmCommandType Dm_embellishmentToCommand(DmEmbellishmentType embellishment);
DMINT bool DmGuid_equals(DmGuid const* a, DmGuid const* b);
Expand Down
179 changes: 97 additions & 82 deletions src/util/Tsf.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ static DmResult Dm_createHydraSamplesForDls(DmDls* dls, float** pcm, int32_t* pc
return DmResult_SUCCESS;
}

static DmResult Dm_createHydra(DmDls* dls, struct tsf_hydra* res) {
static DmResult Dm_createHydraSkeleton(DmDls* dls, struct tsf_hydra* res) {
// 1. Count the number of presets required and allocate them
// -> We need one for each instrument
res->phdrNum = dls->instrument_count + 1; // One for the sentinel
Expand Down Expand Up @@ -262,25 +262,17 @@ static DmResult Dm_createHydra(DmDls* dls, struct tsf_hydra* res) {
return ok ? DmResult_SUCCESS : DmResult_MEMORY_EXHAUSTED;
}

DmResult DmSynth_createTsfForDls(DmDls* dls, tsf** out) {
if (dls == NULL) {
return DmResult_INVALID_ARGUMENT;
}

// Initialize the hydra by allocation all required memory
struct tsf_hydra hydra;

DmResult rv = Dm_createHydra(dls, &hydra);
// We export this function for the tools.
static DmResult Dm_createHydra(DmDls* dls, struct tsf_hydra* hydra, float** pcm, int32_t* pcm_len) {
DmResult rv = Dm_createHydraSkeleton(dls, hydra);
if (rv != DmResult_SUCCESS) {
return rv;
}

// Decode all PCM and create the sample headers.
float* pcm = NULL;
int32_t pcm_len = 0;
struct tsf_hydra_shdr* default_shdrs = NULL;
int32_t default_shdrs_len = 0;
rv = Dm_createHydraSamplesForDls(dls, &pcm, &pcm_len, &default_shdrs, &default_shdrs_len);
rv = Dm_createHydraSamplesForDls(dls, pcm, pcm_len, &default_shdrs, &default_shdrs_len);
if (rv != DmResult_SUCCESS) {
return rv;
}
Expand All @@ -301,37 +293,37 @@ DmResult DmSynth_createTsfForDls(DmDls* dls, tsf** out) {
bank = 999;
}

strncpy(hydra.phdrs[i].presetName, ins->info.inam, 19);
hydra.phdrs[i].bank = bank;
hydra.phdrs[i].preset = ins->patch;
hydra.phdrs[i].genre = 0;
hydra.phdrs[i].morphology = 0;
hydra.phdrs[i].library = 0;
hydra.phdrs[i].presetBagNdx = i;
strncpy(hydra->phdrs[i].presetName, ins->info.inam, 19);
hydra->phdrs[i].bank = bank;
hydra->phdrs[i].preset = ins->patch;
hydra->phdrs[i].genre = 0;
hydra->phdrs[i].morphology = 0;
hydra->phdrs[i].library = 0;
hydra->phdrs[i].presetBagNdx = i;

hydra.pbags[i].genNdx = pgen_ndx;
hydra.pbags[i].modNdx = pmod_ndx;
hydra->pbags[i].genNdx = pgen_ndx;
hydra->pbags[i].modNdx = pmod_ndx;

hydra.pgens[pgen_ndx].genOper = kInstrument;
hydra.pgens[pgen_ndx].genAmount.wordAmount = i;
hydra->pgens[pgen_ndx].genOper = kInstrument;
hydra->pgens[pgen_ndx].genAmount.wordAmount = i;
pgen_ndx++;

strncpy(hydra.insts[i].instName, ins->info.inam, 19);
hydra.insts[i].instBagNdx = ibag_ndx;
strncpy(hydra->insts[i].instName, ins->info.inam, 19);
hydra->insts[i].instBagNdx = ibag_ndx;

for (size_t r = 0; r < ins->region_count; ++r) {
DmDlsRegion* reg = &ins->regions[r];

hydra.ibags[ibag_ndx].instGenNdx = igen_ndx;
hydra.ibags[ibag_ndx].instModNdx = imod_ndx;
hydra->ibags[ibag_ndx].instGenNdx = igen_ndx;
hydra->ibags[ibag_ndx].instModNdx = imod_ndx;
ibag_ndx++;

hydra.igens[igen_ndx].genOper = kKeyRange;
hydra.igens[igen_ndx].genAmount.range.hi = (tsf_u8) reg->range_high;
hydra.igens[igen_ndx].genAmount.range.lo = (tsf_u8) reg->range_low;
hydra->igens[igen_ndx].genOper = kKeyRange;
hydra->igens[igen_ndx].genAmount.range.hi = (tsf_u8) reg->range_high;
hydra->igens[igen_ndx].genAmount.range.lo = (tsf_u8) reg->range_low;
igen_ndx++;

hydra.igens[igen_ndx].genOper = kVelRange;
hydra->igens[igen_ndx].genOper = kVelRange;
uint8_t vel_hi = reg->velocity_high;
uint8_t vel_lo = reg->velocity_low;

Expand All @@ -340,37 +332,37 @@ DmResult DmSynth_createTsfForDls(DmDls* dls, tsf** out) {
vel_lo = 0;
}

hydra.igens[igen_ndx].genAmount.range.hi = vel_hi;
hydra.igens[igen_ndx].genAmount.range.lo = vel_lo;
hydra->igens[igen_ndx].genAmount.range.hi = vel_hi;
hydra->igens[igen_ndx].genAmount.range.lo = vel_lo;
igen_ndx++;

hydra.igens[igen_ndx].genOper = kAttackVolEnv;
hydra.igens[igen_ndx].genAmount.shortAmount = sf2SecondsToTimeCents(0.1);
hydra->igens[igen_ndx].genOper = kAttackVolEnv;
hydra->igens[igen_ndx].genAmount.shortAmount = sf2SecondsToTimeCents(0.1);
igen_ndx++;

hydra.igens[igen_ndx].genOper = kInitialAttenuation;
hydra.igens[igen_ndx].genAmount.shortAmount = (tsf_s16) reg->sample.attenuation;
hydra->igens[igen_ndx].genOper = kInitialAttenuation;
hydra->igens[igen_ndx].genAmount.shortAmount = (tsf_s16) reg->sample.attenuation;
igen_ndx++;

// Articulators
for (size_t a = 0; a < ins->articulator_count; ++a) {
igen_ndx += DmSynth_insertGeneratorArticulators(hydra.igens + igen_ndx, &ins->articulators[a]);
igen_ndx += DmSynth_insertGeneratorArticulators(hydra->igens + igen_ndx, &ins->articulators[a]);
}

for (size_t a = 0; a < reg->articulator_count; ++a) {
igen_ndx += DmSynth_insertGeneratorArticulators(hydra.igens + igen_ndx, &reg->articulators[a]);
igen_ndx += DmSynth_insertGeneratorArticulators(hydra->igens + igen_ndx, &reg->articulators[a]);
}

hydra.igens[igen_ndx].genOper = kSampleModes;
hydra.igens[igen_ndx].genAmount.wordAmount = reg->sample.looping == true ? 1 : 0;
hydra->igens[igen_ndx].genOper = kSampleModes;
hydra->igens[igen_ndx].genAmount.wordAmount = reg->sample.looping == true ? 1 : 0;
igen_ndx++;

hydra.igens[igen_ndx].genOper = kSampleID;
hydra.igens[igen_ndx].genAmount.wordAmount = shdr_ndx;
hydra->igens[igen_ndx].genOper = kSampleID;
hydra->igens[igen_ndx].genAmount.wordAmount = shdr_ndx;
igen_ndx++;

// Additional sample configuration.
struct tsf_hydra_shdr* hdr = &hydra.shdrs[shdr_ndx];
struct tsf_hydra_shdr* hdr = &hydra->shdrs[shdr_ndx];
*hdr = default_shdrs[reg->link_table_index];
shdr_ndx++;

Expand All @@ -394,40 +386,72 @@ DmResult DmSynth_createTsfForDls(DmDls* dls, tsf** out) {
}

// Populate the sentinel values of the hydra
strncpy(hydra.phdrs[hydra.phdrNum - 1].presetName, "EOP", 19);
hydra.phdrs[hydra.phdrNum - 1].bank = 0;
hydra.phdrs[hydra.phdrNum - 1].preset = 0;
hydra.phdrs[hydra.phdrNum - 1].genre = 0;
hydra.phdrs[hydra.phdrNum - 1].morphology = 0;
hydra.phdrs[hydra.phdrNum - 1].library = 0;
hydra.phdrs[hydra.phdrNum - 1].presetBagNdx = hydra.pbagNum - 1;
strncpy(hydra->phdrs[hydra->phdrNum - 1].presetName, "EOP", 19);
hydra->phdrs[hydra->phdrNum - 1].bank = 0;
hydra->phdrs[hydra->phdrNum - 1].preset = 0;
hydra->phdrs[hydra->phdrNum - 1].genre = 0;
hydra->phdrs[hydra->phdrNum - 1].morphology = 0;
hydra->phdrs[hydra->phdrNum - 1].library = 0;
hydra->phdrs[hydra->phdrNum - 1].presetBagNdx = hydra->pbagNum - 1;

hydra->pbags[hydra->pbagNum - 1].genNdx = hydra->pgenNum - 1;
hydra->pbags[hydra->pbagNum - 1].modNdx = hydra->pmodNum - 1;

hydra->pgens[hydra->pgenNum - 1].genOper = 0;
hydra->pgens[hydra->pgenNum - 1].genAmount.shortAmount = 0;

hydra.pbags[hydra.pbagNum - 1].genNdx = hydra.pgenNum - 1;
hydra.pbags[hydra.pbagNum - 1].modNdx = hydra.pmodNum - 1;
hydra->pmods[hydra->pmodNum - 1].modSrcOper = 0;
hydra->pmods[hydra->pmodNum - 1].modDestOper = 0;
hydra->pmods[hydra->pmodNum - 1].modTransOper = 0;
hydra->pmods[hydra->pmodNum - 1].modAmount = 0;
hydra->pmods[hydra->pmodNum - 1].modAmtSrcOper = 0;

hydra.pgens[hydra.pgenNum - 1].genOper = 0;
hydra.pgens[hydra.pgenNum - 1].genAmount.shortAmount = 0;
strncpy(hydra->insts[hydra->instNum - 1].instName, "EOI", 19);
hydra->insts[hydra->instNum - 1].instBagNdx = hydra->ibagNum - 1;

hydra.pmods[hydra.pmodNum - 1].modSrcOper = 0;
hydra.pmods[hydra.pmodNum - 1].modDestOper = 0;
hydra.pmods[hydra.pmodNum - 1].modTransOper = 0;
hydra.pmods[hydra.pmodNum - 1].modAmount = 0;
hydra.pmods[hydra.pmodNum - 1].modAmtSrcOper = 0;
hydra->ibags[hydra->ibagNum - 1].instGenNdx = hydra->igenNum - 1;
hydra->ibags[hydra->ibagNum - 1].instModNdx = hydra->imodNum - 1;

strncpy(hydra.insts[hydra.instNum - 1].instName, "EOI", 19);
hydra.insts[hydra.instNum - 1].instBagNdx = hydra.ibagNum - 1;
hydra->igens[hydra->igenNum - 1].genOper = 0;
hydra->igens[hydra->igenNum - 1].genAmount.shortAmount = 0;

hydra.ibags[hydra.ibagNum - 1].instGenNdx = hydra.igenNum - 1;
hydra.ibags[hydra.ibagNum - 1].instModNdx = hydra.imodNum - 1;
hydra->imods[hydra->imodNum - 1].modSrcOper = 0;
hydra->imods[hydra->imodNum - 1].modDestOper = 0;
hydra->imods[hydra->imodNum - 1].modTransOper = 0;
hydra->imods[hydra->imodNum - 1].modAmount = 0;
hydra->imods[hydra->imodNum - 1].modAmtSrcOper = 0;

hydra.igens[hydra.igenNum - 1].genOper = 0;
hydra.igens[hydra.igenNum - 1].genAmount.shortAmount = 0;
Dm_free(default_shdrs);
return DmResult_SUCCESS;
}

hydra.imods[hydra.imodNum - 1].modSrcOper = 0;
hydra.imods[hydra.imodNum - 1].modDestOper = 0;
hydra.imods[hydra.imodNum - 1].modTransOper = 0;
hydra.imods[hydra.imodNum - 1].modAmount = 0;
hydra.imods[hydra.imodNum - 1].modAmtSrcOper = 0;
// We export this function for the tools.
static void Dm_freeHydra(struct tsf_hydra* hydra) {
Dm_free(hydra->phdrs);
Dm_free(hydra->pbags);
Dm_free(hydra->pgens);
Dm_free(hydra->pmods);
Dm_free(hydra->insts);
Dm_free(hydra->ibags);
Dm_free(hydra->igens);
Dm_free(hydra->imods);
Dm_free(hydra->shdrs);
}

DmResult DmSynth_createTsfForDls(DmDls* dls, tsf** out) {
if (dls == NULL) {
return DmResult_INVALID_ARGUMENT;
}

// Initialize the hydra by allocation all required memory
struct tsf_hydra hydra;
float* pcm = NULL;
int32_t pcm_len = 0;

DmResult rv = Dm_createHydra(dls, &hydra, &pcm, &pcm_len);
if (rv != DmResult_SUCCESS) {
return rv;
}

// Finally, create the tsf
tsf* res = *out = Dm_alloc(sizeof(tsf));
Expand All @@ -443,16 +467,7 @@ DmResult DmSynth_createTsfForDls(DmDls* dls, tsf** out) {
res->fontSamples = pcm;

// Lastly, free up all the hydra stuff
Dm_free(default_shdrs);
Dm_free(hydra.phdrs);
Dm_free(hydra.pbags);
Dm_free(hydra.pgens);
Dm_free(hydra.pmods);
Dm_free(hydra.insts);
Dm_free(hydra.ibags);
Dm_free(hydra.igens);
Dm_free(hydra.imods);
Dm_free(hydra.shdrs);
Dm_freeHydra(&hydra);

return DmResult_SUCCESS;
}

0 comments on commit 4c823e1

Please sign in to comment.