[BGM] Envelopes

This commit is contained in:
Luke Hubmayer-Werner 2024-07-17 18:50:42 +09:30
parent 5babc200f2
commit 38a822362a
2 changed files with 31 additions and 16 deletions

View File

@ -253,17 +253,17 @@ static func render_channels(tracks: Array, inst_map: Array, debug_name := 'none'
current_instrument = inst_map[event_idx] - 1 current_instrument = inst_map[event_idx] - 1
if current_instrument < len(instrument_adsrs) and current_instrument > 0: if current_instrument < len(instrument_adsrs) and current_instrument > 0:
var adsr = instrument_adsrs[current_instrument] var adsr = instrument_adsrs[current_instrument]
current_adsr_attack_rate = adsr[2] current_adsr_attack_rate = adsr[0]
current_adsr_decay_rate = adsr[3] current_adsr_decay_rate = adsr[1]
current_adsr_sustain_level = adsr[0] current_adsr_sustain_level = adsr[2]
current_adsr_sustain_rate = adsr[1] current_adsr_sustain_rate = adsr[3]
EventType.ADSR_DEFAULT: # TODO - Investigate actual scaling and order EventType.ADSR_DEFAULT: # TODO - Investigate actual scaling and order
if current_instrument < len(instrument_adsrs) and current_instrument > 0: if current_instrument < len(instrument_adsrs) and current_instrument > 0:
var adsr = instrument_adsrs[current_instrument] var adsr = instrument_adsrs[current_instrument]
current_adsr_attack_rate = adsr[2] current_adsr_attack_rate = adsr[0]
current_adsr_decay_rate = adsr[3] current_adsr_decay_rate = adsr[1]
current_adsr_sustain_level = adsr[0] current_adsr_sustain_level = adsr[2]
current_adsr_sustain_rate = adsr[1] current_adsr_sustain_rate = adsr[3]
EventType.ADSR_ATTACK_RATE: EventType.ADSR_ATTACK_RATE:
current_adsr_attack_rate = event[1] current_adsr_attack_rate = event[1]
EventType.ADSR_DECAY_RATE: EventType.ADSR_DECAY_RATE:

View File

@ -171,6 +171,14 @@ highp float get_instrument_sample(highp float instrument_index, highp float note
// return rescale_int16(get_inst_texel_int16(target_texel)); // return rescale_int16(get_inst_texel_int16(target_texel));
} }
// const int ATTACK_TIME_MS[16] = {4100, 2600, 1500, 1000, 640, 380, 260, 160, 96, 64, 40, 24, 16, 10, 6, 0};
const int ATTACK_TIME_SMPS[16] = {131200, 83200, 48000, 32000, 20480, 12160, 8320, 5120, 3072, 2048, 1280, 768, 512, 320, 192, 1};
// const int DECAY_TIME_MS[8] = {1200, 740, 440, 290, 180, 110, 74, 37};
const int DECAY_TIME_SMPS[8] = {38400, 23680, 14080, 9280, 5760, 3520, 2368, 1184};
// const int SUSTAIN_DECAY_TIME_MS[32] = {Infinite, 38000, 28000, 24000, 19000, 14000, 12000, 9400, 7100, 5900, 4700, 3500, 2900, 2400, 1800, 1500, 1200, 880, 740, 590, 440, 370, 290, 220, 180, 150, 110, 92, 74, 55, 37, 18};
const int SUSTAIN_DECAY_TIME_SMPS[32] = {0, 1216000, 896000, 768000, 608000, 448000, 384000, 300800, 227200, 188800, 150400, 112000, 92800, 76800, 57600, 48000, 38400, 28160, 23680, 18880, 14080, 11840, 9280, 7040, 5760, 4800, 3520, 2944, 2368, 1760, 1184, 576};
// const int SPC_PERIOD_SMPS[32] = {0, 2048, 1536, 1280, 1024, 768, 640, 512, 384, 320, 256, 192, 160, 128, 96, 80, 64, 48, 40, 32, 24, 20, 16, 12, 10, 8, 6, 5, 4, 3, 2, 1};
const int NUM_CHANNELS = 8; const int NUM_CHANNELS = 8;
const highp int MAX_CHANNEL_NOTE_EVENTS = 2048; const highp int MAX_CHANNEL_NOTE_EVENTS = 2048;
const int NUM_CHANNEL_NOTE_PROBES = 11; // log2(MAX_CHANNEL_NOTE_EVENTS) const int NUM_CHANNEL_NOTE_PROBES = 11; // log2(MAX_CHANNEL_NOTE_EVENTS)
@ -210,26 +218,33 @@ highp vec4 render_song(highp sampler2D tex, highp int smp) {
highp float pitch_idx = note_event_supplement.y * 255.0; highp float pitch_idx = note_event_supplement.y * 255.0;
highp float velocity = note_event_supplement.z; highp float velocity = note_event_supplement.z;
highp float pan = note_event_supplement.w; highp float pan = note_event_supplement.w;
highp vec4 adsr = get_midi_texel(tex, event_idx, row+3.0); // left as [0.0, 1.0] highp ivec4 adsr = ivec4(get_midi_texel(tex, event_idx, row+3.0) * 255.0);
// ====================At some point I'll look back into packing floats==================== // ====================At some point I'll look back into packing floats====================
// TBD = note_event_supplement.zw; - tremolo/vibrato/noise/pan_lfo/pitchbend/echo remain // TBD = note_event_supplement.zw; - tremolo/vibrato/noise/pan_lfo/pitchbend/echo remain
// ====================At some point I'll look back into packing floats==================== // ====================At some point I'll look back into packing floats====================
highp float attack_rate = 1.0 + adsr.x*255.0; //65535.0 + 1.0; // TODO: work out effective resolution for this - it's actually only 4 of 8 bits highp float sustain_level = float(adsr.z + 1)/8.0;
highp float decay_rate = adsr.y; // TODO: work out effective resolution for this - it's actually only 3 of 8 bits highp int smp_sustain_decay = SUSTAIN_DECAY_TIME_SMPS[adsr.w];
highp float sustain_level = adsr.z; // TODO: work out effective resolution for this - it's actually only 3 of 8 bits highp int smp_attack = ATTACK_TIME_SMPS[adsr.x];
highp float sustain_rate = adsr.w; // TODO: work out effective resolution for this - it's actually only 4 of 8 bits highp int smp_decay = DECAY_TIME_SMPS[adsr.y];
highp int smp_attack = int(attack_rate) * 2; // Max value is 131072 samples = 4.096 seconds
// For now, just branch this // For now, just branch this
if (smp_start < smp) { // First sample may not start at zero! if (smp_start < smp) { // First sample may not start at zero!
highp int smp_overrun = smp - smp_end; // 256 samples of linear decay to 0 after note_off highp int smp_overrun = smp - smp_end; // 256 samples of linear decay to 0 after note_off
smp_overrun = (smp_overrun < 0) ? 0 : smp_overrun; smp_overrun = (smp_overrun < 0) ? 0 : smp_overrun;
if (smp_overrun < 256) { if (smp_overrun < 256) {
highp int smp_progress = smp - smp_start;
highp float t_start = float(smp_start)/output_mixrate; highp float t_start = float(smp_start)/output_mixrate;
highp float attack_factor = min(float(smp - smp_start)/float(smp_attack), 1.0); highp float attack_factor = clamp(float(smp_progress)/float(smp_attack), 0.0, 1.0);
highp float decay_factor = mix(1.0, sustain_level, clamp(float(smp_progress - smp_attack)/float(smp_decay), 0.0, 1.0));
highp float sustain_decay_factor = 1.0;
if (smp_sustain_decay > 0) {
// TODO: make this appropriately exponential
sustain_decay_factor = mix(1.0, 0.0, clamp(float(smp_progress - smp_attack - smp_decay)/float(smp_sustain_decay), 0.0, 1.0));
sustain_decay_factor *= sustain_decay_factor; // Quadratic decay isn't exponential but it sounds closer to exponential than linear does.
}
highp float release_factor = float(255-smp_overrun)/255.0; // 256 samples of linear decay to 0 after note_off highp float release_factor = float(255-smp_overrun)/255.0; // 256 samples of linear decay to 0 after note_off
highp float samp = get_instrument_sample(instrument_idx, pitch_idx, t-t_start); highp float samp = get_instrument_sample(instrument_idx, pitch_idx, t-t_start);
samp *= velocity * attack_factor * release_factor; samp *= velocity * attack_factor * decay_factor * sustain_decay_factor * release_factor;
// TODO: proper decay and sustain, revisit release // TODO: proper decay and sustain, revisit release
downmixed_stereo += samp * vec2(pan, 1.0-pan) * 0.5; // TODO: double it to maintain the mono level on each channel at center=0.5? downmixed_stereo += samp * vec2(pan, 1.0-pan) * 0.5; // TODO: double it to maintain the mono level on each channel at center=0.5?
} }