diff options
Diffstat (limited to 'tools/audio/soundfont_compiler.c')
| -rw-r--r-- | tools/audio/soundfont_compiler.c | 69 |
1 files changed, 58 insertions, 11 deletions
diff --git a/tools/audio/soundfont_compiler.c b/tools/audio/soundfont_compiler.c index 4f9a5779c..6a47d643b 100644 --- a/tools/audio/soundfont_compiler.c +++ b/tools/audio/soundfont_compiler.c @@ -64,7 +64,7 @@ midinote_to_z64note(int note) * (with appropriate shifting such that the index for C4 results in 1.0) */ static float -calc_tuning(float sample_rate, int basenote) +calc_tuning(float sample_rate, int basenote, int8_t finetune) { static const float playback_sample_rate = 32000.0f; // Target samplerate in-game is 32KHz static const float pitch_frequencies[] = { @@ -199,7 +199,24 @@ calc_tuning(float sample_rate, int basenote) /* 0x7F */ 0.099213f, // PITCH_AF0 }; - return (sample_rate / playback_sample_rate) * pitch_frequencies[basenote]; + float tuning = (sample_rate / playback_sample_rate) * pitch_frequencies[basenote]; + if (finetune == 0) + return tuning; + + // Compute 2^(x / (12 * 100)) for 8-bit signed integer x + static const double fine_coeffs[5] = { + // Coefficients generated by sollya: + // fpminimax(1.00057778950655486^x, 4, [|SG...|], [-128,128], absolute, 2^(-24)); + // <= 1ulp + 1.0, + 5.776226171292365e-4, + 1.668239519858616e-7, + 3.213055863038328e-11, + 4.639919853633443e-15, + }; + float x = finetune; + tuning *= fine_coeffs[0] + x * (fine_coeffs[1] + x * (fine_coeffs[2] + x * (fine_coeffs[3] + x * fine_coeffs[4]))); + return tuning; } void @@ -317,16 +334,19 @@ read_instrs_info(soundfont *sf, xmlNodePtr instrs) { "Sample", true, xml_parse_c_identifier, offsetof(instr_data, sample_name_mid) }, { "BaseNote", true, xml_parse_note_number, offsetof(instr_data, base_note_mid) }, + { "FineTune", true, xml_parse_fine_tune, offsetof(instr_data, fine_tune_mid) }, { "SampleRate", true, xml_parse_double, offsetof(instr_data, sample_rate_mid) }, { "RangeLo", true, xml_parse_note_number, offsetof(instr_data, sample_low_end) }, { "SampleLo", true, xml_parse_c_identifier, offsetof(instr_data, sample_name_low) }, { "BaseNoteLo", true, xml_parse_note_number, offsetof(instr_data, base_note_lo) }, + { "FineTuneLo", true, xml_parse_fine_tune, offsetof(instr_data, fine_tune_lo) }, { "SampleRateLo", true, xml_parse_double, offsetof(instr_data, sample_rate_lo) }, { "RangeHi", true, xml_parse_note_number, offsetof(instr_data, sample_high_start)}, { "SampleHi", true, xml_parse_c_identifier, offsetof(instr_data, sample_name_high) }, { "BaseNoteHi", true, xml_parse_note_number, offsetof(instr_data, base_note_hi) }, + { "FineTuneHi", true, xml_parse_fine_tune, offsetof(instr_data, fine_tune_hi) }, { "SampleRateHi", true, xml_parse_double, offsetof(instr_data, sample_rate_hi) }, }; @@ -356,6 +376,9 @@ read_instrs_info(soundfont *sf, xmlNodePtr instrs) instr->base_note_mid = NOTE_UNSET; instr->base_note_lo = NOTE_UNSET; instr->base_note_hi = NOTE_UNSET; + instr->fine_tune_mid = FINE_TUNE_UNSET; + instr->fine_tune_lo = FINE_TUNE_UNSET; + instr->fine_tune_hi = FINE_TUNE_UNSET; instr->sample_rate_mid = -1.0; instr->sample_rate_lo = -1.0; instr->sample_rate_hi = -1.0; @@ -478,10 +501,13 @@ read_instrs_info(soundfont *sf, xmlNodePtr instrs) if (instr->base_note_lo == NOTE_UNSET) instr->base_note_lo = instr->sample_low->base_note; + if (instr->fine_tune_lo == FINE_TUNE_UNSET) + instr->fine_tune_lo = instr->sample_low->fine_tune; + if (instr->sample_rate_lo < 0.0) instr->sample_rate_lo = instr->sample_low->sample_rate; - instr->sample_low_tuning = calc_tuning(instr->sample_rate_lo, instr->base_note_lo); + instr->sample_low_tuning = calc_tuning(instr->sample_rate_lo, instr->base_note_lo, instr->fine_tune_lo); } instr->sample_mid = sample_data_forname(sf, instr->sample_name_mid); @@ -492,15 +518,18 @@ read_instrs_info(soundfont *sf, xmlNodePtr instrs) if (instr->base_note_mid == NOTE_UNSET) instr->base_note_mid = instr->sample_mid->base_note; + if (instr->fine_tune_mid == FINE_TUNE_UNSET) + instr->fine_tune_mid = instr->sample_mid->fine_tune; + if (instr->sample_rate_mid < 0.0) instr->sample_rate_mid = instr->sample_mid->sample_rate; - instr->sample_mid_tuning = calc_tuning(instr->sample_rate_mid, instr->base_note_mid); + instr->sample_mid_tuning = calc_tuning(instr->sample_rate_mid, instr->base_note_mid, instr->fine_tune_mid); // Some tuning values don't decompose properly into a samplerate and basenote, they must be accounted for here // for matching. So far this has only been seen for an Instrument mid sample. // NOTE: Keep in sync with the BAD_FLOATS list in extraction/tuning.py - if (f2i(instr->sample_mid_tuning) == 0x3E7319DF /* 0.237403377 */) // diff = 2^-24 + if (sf->matching && f2i(instr->sample_mid_tuning) == 0x3E7319DF /* 0.237403377 */) // diff = 2^-24 instr->sample_mid_tuning = i2f(0x3E7319E3 /* 0.237403437 */); if (instr->sample_name_high != NULL) { @@ -512,10 +541,13 @@ read_instrs_info(soundfont *sf, xmlNodePtr instrs) if (instr->base_note_hi == NOTE_UNSET) instr->base_note_hi = instr->sample_high->base_note; + if (instr->fine_tune_hi == FINE_TUNE_UNSET) + instr->fine_tune_hi = instr->sample_high->fine_tune; + if (instr->sample_rate_hi < 0.0) instr->sample_rate_hi = instr->sample_high->sample_rate; - instr->sample_high_tuning = calc_tuning(instr->sample_rate_hi, instr->base_note_hi); + instr->sample_high_tuning = calc_tuning(instr->sample_rate_hi, instr->base_note_hi, instr->fine_tune_hi); } // link @@ -544,6 +576,7 @@ read_drums_info(soundfont *sf, xmlNodePtr drums) { "Sample", false, xml_parse_c_identifier, offsetof(drum_data, sample_name) }, { "SampleRate", true, xml_parse_double, offsetof(drum_data, sample_rate) }, { "BaseNote", true, xml_parse_note_number, offsetof(drum_data, base_note) }, + { "FineTune", true, xml_parse_fine_tune, offsetof(drum_data, fine_tune) }, }; LL_FOREACH(xmlNodePtr, drum_node, drums->children) { @@ -560,6 +593,7 @@ read_drums_info(soundfont *sf, xmlNodePtr drums) drum->note_end = NOTE_UNSET; drum->sample_rate = -1; drum->base_note = NOTE_UNSET; + drum->fine_tune = FINE_TUNE_UNSET; drum->release = RELEASE_UNSET; if (drum_node->properties == NULL) { @@ -605,13 +639,16 @@ read_drums_info(soundfont *sf, xmlNodePtr drums) // set basenote if not overridden if (drum->base_note == NOTE_UNSET) { - if (drum->sample->aifc.has_inst) { + if (drum->sample->aifc.has_inst) drum->base_note = drum->sample->base_note; - } else { + else error("No basenote for drum (line %d)", drum_node->line); - } } + // set finetune if not overridden + if (drum->fine_tune == FINE_TUNE_UNSET) + drum->fine_tune = drum->sample->fine_tune; + // link link_drum: if (sf->drums == NULL) { @@ -633,6 +670,7 @@ read_sfx_info(soundfont *sf, xmlNodePtr effects) { "Sample", false, xml_parse_c_identifier, offsetof(sfx_data, sample_name)}, { "SampleRate", true, xml_parse_double, offsetof(sfx_data, sample_rate)}, { "BaseNote", true, xml_parse_note_number, offsetof(sfx_data, base_note) }, + { "FineTune", true, xml_parse_fine_tune, offsetof(sfx_data, fine_tune) }, }; LL_FOREACH(xmlNodePtr, sfx_node, effects->children) { @@ -652,6 +690,7 @@ read_sfx_info(soundfont *sf, xmlNodePtr effects) } else { sfx->sample_rate = -1; sfx->base_note = NOTE_UNSET; + sfx->fine_tune = FINE_TUNE_UNSET; xml_parse_node_by_spec(sfx, sfx_node, sfx_spec, ARRAY_COUNT(sfx_spec)); sfx->sample = sample_data_forname(sf, sfx->sample_name); @@ -662,10 +701,13 @@ read_sfx_info(soundfont *sf, xmlNodePtr effects) if (sfx->base_note == NOTE_UNSET) sfx->base_note = sfx->sample->base_note; + if (sfx->fine_tune == FINE_TUNE_UNSET) + sfx->fine_tune = sfx->sample->fine_tune; + if (sfx->sample_rate == -1) sfx->sample_rate = sfx->sample->sample_rate; - sfx->tuning = calc_tuning(sfx->sample_rate, sfx->base_note); + sfx->tuning = calc_tuning(sfx->sample_rate, sfx->base_note, sfx->fine_tune); } // link @@ -696,6 +738,7 @@ read_samples_info(soundfont *sf, xmlNodePtr samples) {"Name", false, xml_parse_c_identifier, offsetof(sample_data, name) }, { "SampleRate", true, xml_parse_double, offsetof(sample_data, sample_rate)}, { "BaseNote", true, xml_parse_note_number, offsetof(sample_data, base_note) }, + { "FineTune", true, xml_parse_fine_tune, offsetof(sample_data, fine_tune) }, { "IsDD", true, xml_parse_bool, offsetof(sample_data, is_dd) }, { "Cached", true, xml_parse_bool, offsetof(sample_data, cached) }, }; @@ -717,6 +760,7 @@ read_samples_info(soundfont *sf, xmlNodePtr samples) sample->sample_rate = -1.0; sample->base_note = NOTE_UNSET; + sample->fine_tune = FINE_TUNE_UNSET; sample->is_dd = defaults.is_dd; sample->cached = defaults.cached; @@ -740,6 +784,9 @@ read_samples_info(soundfont *sf, xmlNodePtr samples) error("No basenote for sample %s (line %d)", sample->name, sample_node->line); } + if (sample->fine_tune == FINE_TUNE_UNSET) + sample->fine_tune = sample->aifc.detune; + if (!sample->aifc.has_book) error("No vadpcm codebook for sample %s (line %d)", sample->name, sample_node->line); @@ -1403,7 +1450,7 @@ emit_c_drums(FILE *out, soundfont *sf) if (note > 127) note -= 128; - float tuning = calc_tuning(drum->sample_rate, note); + float tuning = calc_tuning(drum->sample_rate, note, drum->fine_tune); fprintf(out, " SF%d_%s_ENTRY(" F32_FMT "f),\n", sf->info.index, drum->name, tuning); } |
