// sequencer for uncompressed data public void sequencer(ref _VOICE_SET vs) { short j; byte b; SeqEntry se; do { se = seq.seqs[vs.seq_current].seq[vs.seq_index]; vs.seq_index += 1; switch (se.note) { case -1: { return; } case 0xFF: { // --- Track-Interpeter --- if (PlayMode == Mode.PlaySeq) { vs.track_note = 0; vs.track_shape = 0; vs.seq_current = 0; vs.seq_index = 0; //Form1.WaveGen.reset(); //Form1.WaveGen.PlayFlag = false; } if (vs.nr == 0) { vs.track_count -= 1; if (vs.track_count < 0) { if (PlayMode == Mode.PlayTrackOnce) { vs.track_note = 0; vs.track_shape = 0; vs.seq_current = 0; vs.seq_index = 0; //Form1.WaveGen.reset(); //Form1.WaveGen.PlayFlag = false; } vs.track_count = track_length; VoiceSet[0].track_index = 0; VoiceSet[1].track_index = 0; VoiceSet[2].track_index = 0; } } j = (short)(vs.track_current + vs.track_index); trackPos = j; vs.track_note = track.GetNote(vs.nr, j); vs.track_shape = track.GetInstr(vs.nr, j); b = track.GetCmd(vs.nr, j); if ((b & 0xF0) == 0xF0) { vs.track_reduce = (short)(b & 0xF); } else if ((b & 0xE0) == 0xE0) { play_speed = (short)(b & 0xF); } vs.seq_current = track.GetSeq(vs.nr, j); vs.seq_index = 0; vs.track_index += 1; break; } default: { vs.seq_note = (byte)se.note; b = se.shape; vs.seq_shape = b; if ((b & 0xE0) > 0) { vs.seq_instr = se.xtra; } vs.bend_var = 0; if ((vs.seq_note & 0x80) == 0) { b = (byte)((vs.seq_shape & 0x1F) + vs.track_shape); vs.shape_time = shape.shape_set[b].para1; vs.shape_time_init = shape.shape_set[b].para1; vs.delta_f = shape.shape_set[b].para3; vs.flags = 0x40; vs.mod_f_work = shape.shape_set[b].para4; vs.mod_f_max = shape.shape_set[b].para4; vs.tfmx_count = shape.shape_set[b].para5; vs.shape_current = b; vs.shape_index = 0; if ((vs.seq_shape & 0x40) > 0) { b = vs.seq_instr; } else { b = shape.shape_set[b].para2; } vs.instr_current = b; vs.instr_count = 0; vs.instr_index = 0; vs.shape_count = 0; } return; } } }while (true)// nix tun// end of sequence// seq 0 must be always "pause"// seq 0 must be always "pause"// play it again// Tonh�he// hkurve// Instrument ; }
//public void tick(ref WaveGen._YM ym) //{ // short i; // short ym_div; // byte amplitude; // byte b; // // ym.eshape = &HFF // for (i = 0; i <= 2; i++) // { // VoiceSet[i].triangle_fine = 0xFF; // VoiceSet[i].triangle_restart = false; // work_voice(ref VoiceSet[i], ref ym_div, ref amplitude); // ym.chn(i).coars = ym_div >> 8; // ym.chn(i).fine = ym_div & 0xFF; // ym.chn(i).volume = amplitude; // if (VoiceSet[i].triangle_fine != 0xFF) // ym.efine = VoiceSet[i].triangle_fine; // if (VoiceSet[i].triangle_restart) // { // ym.ecoars = 0; // ym.eshape = 10; // Triangle // ym.shape.counter = 0; // Restart // } // // ---SID on Channel A // if (i == 0) // { // b = VoiceSet[0].sid_mode; // switch (b) // { // case 0: // { // ym.sidvol = 0xFF; // SID OFF // break; // } // case 4: // { // ym.sidvol = amplitude; // break; // } // case 1: // case 2: // { // ym_div = VoiceSet[b - 1].div; // if (ym_div <= 16) // ym.sidvol = 0xFF; // SID OFF // else // ym.sidfreq = ym_div; // break; // } // } // } // // --- Digi-Drum on Channel C // if (i == 2) // { // if (VoiceSet[i].digi_drum >= 0) // { // ym.digidrum = VoiceSet[i].digi_drum; // VoiceSet[i].digi_drum = -1; // ym.digipos = 0; // } // } // } // ym.enable = ym_enable; // ym.noisep = ym_noise_f; // if (PlayMode != Mode.PlayShape) // { // play_speed_count -= 1; // if (play_speed_count == 0) // { // play_speed_count = play_speed; // for (i = 0; i <= 2; i++) // sequencer(ref VoiceSet[i]); // } // } //} public void work_voice(ref _VOICE_SET vs, ref short ym_div, ref byte amplitude) { byte b; short note; int bender; short f_max, f_work; byte flag; short i; int l1, l2; icount: ; if (vs.instr_count > 0) { vs.instr_count -= 1; } else { next_i: ; i = vs.instr_index; b = instr.instruments[vs.instr_current].script[i]; i += 1; if (b < 0xE0) { vs.instr_note = b; vs.instr_index += 1; } else { switch (b) { case 0xE0: // absolute JMP { vs.instr_index = instr.instruments[vs.instr_current].script[i]; goto next_i; } case 0xE1: // End { vs.instr_note = instr.instruments[vs.instr_current].script[i - 2]; // stay on last note break; } case 0xE2: // reset shape index { vs.shape_index = 0; vs.shape_time = 1; vs.instr_index += 1; goto next_i; } case 0xE3: // parameters for f modulation { vs.delta_f = instr.instruments[vs.instr_current].script[i]; i += 1; vs.mod_f_max = instr.instruments[vs.instr_current].script[i]; i += 1; vs.instr_index += 3; goto next_i; } case 0xE4: // noise & tune on { vs.tune_noise = 0; vs.noise_freq = instr.instruments[vs.instr_current].script[i]; i++; vs.instr_index += 2; goto next_i; } case 0xE5: // noise on, tune off { vs.tune_noise = 1; vs.instr_index += 1; goto next_i; } case 0xE6: // noise off, tune on { vs.tune_noise = 2; vs.instr_index += 1; goto next_i; } case 0xE7: // select instr group { vs.instr_index += 2; // MsgBox("InstrGroup") goto next_i; } case 0xE8: // set instr counter { vs.instr_count = instr.instruments[vs.instr_current].script[i]; vs.instr_index += 2; goto icount; } case 0xE9: // triangle evelope { vs.triangle_fine = instr.instruments[vs.instr_current].script[i]; vs.triangle_restart = true; vs.instr_index += 2; goto next_i; } case 0xEA: // ??? { vs.seq_shape = 0x20; vs.seq_instr = instr.instruments[vs.instr_current].script[i]; vs.instr_index += 2; goto next_i; } case 0xEB: // shape vibrato { vs.shape_sync = instr.instruments[vs.instr_current].script[i]; i++; vs.instr_index += 2; goto next_i; } case 0xEC: // digi drum { vs.digi_drum = instr.instruments[vs.instr_current].script[i]; vs.tune_noise = 3; // noise off, tune off vs.instr_index += 4; // 4 goto next_i; } case 0xEE: // sid mode { vs.sid_mode = instr.instruments[vs.instr_current].script[i]; i++; vs.instr_index += 2; goto next_i; } } } } // --- Shape handling --- scount: ; if (vs.shape_count > 0) { vs.shape_count -= 1; } else { vs.shape_time -= 1; if (vs.shape_time == 0) { vs.shape_time = vs.shape_time_init; next_s: ; i = vs.shape_index; b = shape.shape_set[vs.shape_current].data[i]; i += 1; if (b < 0xE0) { vs.shape_amplitude = b; vs.shape_index += 1; } else { switch (b) { case 0xE0: // absolute JMP { i = shape.shape_set[vs.shape_current].data[i]; // dest vs.shape_index = i; goto next_s; } case 0xE1: // end { vs.shape_amplitude = shape.shape_set[vs.shape_current].data[i - 2]; // stay on last amplitude break; } case object _ when 0xE2 <= b && b <= 0xE7: // not supported { return; } case 0xE8: // set shape_counter { vs.shape_count = shape.shape_set[vs.shape_current].data[i]; vs.shape_index += 2; goto scount; } } } } } // --- divider for ym freq --- note = vs.instr_note; if ((note & 0x80) == 0) { note += (short)(vs.seq_note + vs.track_note); } note = (short)(note & 0x7F); ym_div = div[note]; // --- Tune/Noise on/off --- switch (vs.tune_noise) { case 0: // tune & noise on { ym_enable = (byte)(ym_enable & mask[2 * vs.nr]); // tune on ym_enable = (byte)(ym_enable & mask[2 * vs.nr + 1]); // noise on break; } case 1: // tune off, noise on { ym_enable = (byte)(ym_enable | ~mask[2 * vs.nr]); // tune off ym_enable = (byte)(ym_enable & mask[2 * vs.nr + 1]); // noise on vs.noise_freq = vs.seq_note; note = vs.instr_note; if ((note & 0x80) > 0) { note = (short)(note | 0xFF00); } if (note < 0) { vs.noise_freq = (byte)(note & 0x7F); } else { vs.noise_freq += (byte)note; } break; } case 2: // tune on, noise off { ym_enable = (byte)(ym_enable & mask[2 * vs.nr]); // tune on ym_enable = (byte)(ym_enable | ~mask[2 * vs.nr + 1]); // noise off break; } } if (vs.noise_freq != 0) { ym_noise_f = (byte)((~vs.noise_freq) & 0x1F); } // --- TFMX --- if (ftype == _fType.TFMX) { if (vs.tfmx_count == 0) { flag = vs.flags; f_max = vs.mod_f_max; // Wertebereich mod_f_max: 0...127 entspricht 0...254 in 2er Schritten // 128...255 entspricht 0... 127 if ((f_max & 0x80) == 0x80) { f_max = (short)(f_max & 0x7F); } else { f_max *= 2; } f_work = vs.mod_f_work; if (((flag & 0x80) == 0x0) | ((flag & 0x81) == 0x80)) { if ((flag & 0x20) == 0) { // b5=0, subtract f_work -= vs.delta_f; if (f_work < 0) { f_work = 0; flag = (byte)(flag | 0x20); // b5=1 -> add } } else { // b5=1, add f_work += vs.delta_f; if (f_work > f_max) { f_work = f_max; flag = (byte)(flag & ~0x20); // b5=0 -> sub } } vs.mod_f_work = f_work; } f_work -= (short)(f_max / 2); while (note < 4 * 12) { f_work += f_work; note += 12; } ym_div += f_work; vs.flags = (byte)(flag ^ 1); } else { vs.tfmx_count -= 1; } // freq-bender if ((vs.seq_shape & 0x20) == 0x20) { bender = vs.seq_instr; bender *= 4096; if ((bender & 0x80000) > 0) { bender = (int)(bender | 0xFFF00000); } bender += vs.bend_var; vs.bend_var = bender; ym_div -= (short)(bender / 65536); } // --- amplitude --- i = vs.shape_amplitude; i -= vs.track_reduce; i -= vs.reduce; if (i < 0) { i = 0; } amplitude = (byte)i; } else { // --- MMME --------------------------------------------------------- if (vs.tfmx_count == 0) { flag = vs.flags; f_max = vs.mod_f_max; f_work = vs.mod_f_work; if ((flag & 0x20) == 0x0) { f_work += vs.delta_f; if (f_work > 2 * f_max) { f_work = (short)(2 * f_max); flag = (byte)(flag | 0x20); // auf Sub umschalten } } else { f_work -= vs.delta_f; if (f_work < 0) { f_work = 0; flag = (byte)(flag & 0xDF); // auf Add umschalten } } vs.mod_f_work = f_work; vs.flags = flag; l1 = f_work - f_max; // convert Short to Integer l1 = (l1 * ym_div) >> 10; ym_div += (short)l1; } else { vs.tfmx_count -= 1; } // --- Bender if ((vs.seq_shape & 0x20) == 0x20) { b = vs.seq_instr; // convert unsigned Byte to Integer l2 = b; if ((b & 0x80) > 0) { l2 -= 256; } vs.bend_var += l2; l1 = ym_div; ym_div = (short)(l1 - ((l1 * vs.bend_var) >> 10)); } // --- amplitude --- i = vs.shape_amplitude; i -= vs.track_reduce; i -= vs.reduce; if (i < 0) { i = 0; } amplitude = (byte)i; // --- shapeform sync b = vs.shape_sync; if (b != 0) { if ((b & 0x80) > 0) { vs.triangle_restart = true; } if ((b & 0x2) > 0) { ym_div = 0;// Ton aus } if ((b & 0x8) > 0) { vs.triangle_fine = (byte)(ym_div / 8); } else { vs.triangle_fine = (byte)(ym_div / 16); } } } vs.div = ym_div; }