void SynthesizeChannel(ChannelState& dst, AYM::ChannelBuilder& channel, AYM::TrackBuilder& track) { if (!dst.Enabled) { channel.SetLevel(0); return; } const Sample& curSample = Data->Samples.Get(dst.SampleNum); const Sample::Line& curSampleLine = curSample.GetLine(dst.PosInSample); const Ornament& curOrnament = Data->Ornaments.Get(dst.OrnamentNum); //apply tone const int_t halftones = int_t(dst.Note) + curOrnament.GetLine(dst.PosInOrnament); channel.SetTone(halftones, dst.Sliding + curSampleLine.Vibrato); if (curSampleLine.ToneMask) { channel.DisableTone(); } //apply level channel.SetLevel(GetVolume(dst.Volume, curSampleLine.Level)); //apply envelope if (dst.Envelope) { channel.EnableEnvelope(); } //apply noise if (!curSampleLine.NoiseMask) { track.SetNoise(curSampleLine.Noise + dst.NoiseAdd); } else { channel.DisableNoise(); } //recalculate gliss if (dst.SlidingTargetNote != LIMITER) { const int_t absoluteSlidingRange = track.GetSlidingDifference(dst.Note, dst.SlidingTargetNote); const int_t realSlidingRange = absoluteSlidingRange - (dst.Sliding + dst.Glissade); if ((dst.Glissade > 0 && realSlidingRange <= 0) || (dst.Glissade < 0 && realSlidingRange >= 0)) { dst.Note = dst.SlidingTargetNote; dst.SlidingTargetNote = LIMITER; dst.Sliding = dst.Glissade = 0; } } dst.Sliding += dst.Glissade; if (++dst.PosInSample >= curSample.GetSize()) { dst.PosInSample = curSample.GetLoop(); } if (++dst.PosInOrnament >= curOrnament.GetSize()) { dst.PosInOrnament = curOrnament.GetLoop(); } }
void GetNewChannelState(const Cell& src, ChannelState& dst, AYM::TrackBuilder& track) { if (const bool* enabled = src.GetEnabled()) { dst.Enabled = *enabled; } dst.VolSlideCounter = 0; dst.SlidingSteps = 0; bool contSample = false, contOrnament = false; bool reloadNote = false; for (CommandsIterator it = src.GetCommands(); it; ++it) { switch (it->Type) { case ENVELOPE: if (-1 != it->Param1) { track.SetEnvelopeType(it->Param1); } if (-1 != it->Param2) { EnvelopeTone = it->Param2; track.SetEnvelopeTone(EnvelopeTone); } break; case ENVELOPE_ON: dst.Envelope = true; break; case ENVELOPE_OFF: dst.Envelope = false; break; case NOISE: dst.BaseNoise = it->Param1; break; case CONT_SAMPLE: contSample = true; break; case CONT_ORNAMENT: contOrnament = true; break; case GLISS: dst.Glissade = it->Param1; dst.SlidingSteps = -1;//infinite sliding break; case SLIDE: { dst.SlidingSteps = it->Param1; const int_t newSliding = (dst.Sliding | 0xf) ^ 0xf; dst.Glissade = -newSliding / (dst.SlidingSteps ? dst.SlidingSteps : 1); dst.Sliding = dst.Glissade * dst.SlidingSteps; break; } case SLIDE_NOTE: { dst.SlidingSteps = it->Param1; dst.SlidingTargetNote = it->Param2; const int_t absoluteSliding = track.GetSlidingDifference(dst.Note, dst.SlidingTargetNote); const int_t newSliding = absoluteSliding - (contSample ? dst.Sliding / 16 : 0); dst.Glissade = 16 * newSliding / (dst.SlidingSteps ? dst.SlidingSteps : 1); reloadNote = true; break; } case AMPLITUDE_SLIDE: dst.VolSlideCounter = dst.VolSlideDelay = it->Param1; dst.VolSlideAddon = it->Param2; break; case BREAK_SAMPLE: dst.BreakSample = true; break; default: assert(!"Invalid cmd"); break; } } if (const uint_t* ornament = src.GetOrnament()) { dst.OrnamentNum = *ornament; } if (const uint_t* sample = src.GetSample()) { dst.SampleNum = *sample; } if (const uint_t* note = src.GetNote()) { dst.Note = *note; reloadNote = true; } if (reloadNote) { dst.CurrentNoise = dst.BaseNoise; if (dst.SlidingSteps <= 0) { dst.Sliding = 0; } if (!contSample) { dst.CurrentSampleNum = dst.SampleNum; dst.PosInSample = 0; dst.VolumeAddon = 0; dst.ToneDeviation = 0; dst.BreakSample = false; } if (!contOrnament) { dst.CurrentOrnamentNum = dst.OrnamentNum; dst.PosInOrnament = 0; dst.NoteAddon = 0; } } if (const uint_t* volume = src.GetVolume()) { dst.Volume = *volume; } }
void GetNewChannelState(const Cell& src, ChannelState& dst, AYM::TrackBuilder& track) { if (const bool* enabled = src.GetEnabled()) { if (*enabled) { dst.SampleIterator.Reset(); } else { dst.SampleIterator.Disable(); } dst.SampleNoiseAccumulator.Reset(); dst.VolumeSlide = 0; dst.NoiseAccumulator.Reset(); dst.NoteAccumulator.Reset(); dst.OrnamentIterator.Reset(); dst.ToneAccumulator.Reset(); dst.EnvelopeAccumulator.Reset(); dst.ToneSlide.Reset(); } if (const uint_t* note = src.GetNote()) { dst.Note = *note + Transposition; } if (const uint_t* sample = src.GetSample()) { dst.SampleIterator.Set(Data->Samples.Get(*sample)); } if (const uint_t* ornament = src.GetOrnament()) { dst.OrnamentIterator.Set(Data->Ornaments.Get(*ornament)); dst.OrnamentIterator.Reset(); dst.NoiseAccumulator.Reset(); dst.NoteAccumulator.Reset(); } if (const uint_t* volume = src.GetVolume()) { dst.Volume = *volume; } for (CommandsIterator it = src.GetCommands(); it; ++it) { switch (it->Type) { case ENVELOPE: track.SetEnvelopeType(it->Param1); dst.Envelope = it->Param2; dst.EnvelopeEnabled = true; break; case ENVELOPE_OFF: dst.EnvelopeEnabled = false; break; case NOISE: dst.Noise = it->Param1; break; case SLIDE: dst.ToneSlide.SetGlissade(it->Param1); break; case SLIDE_NOTE: { const int_t slide = track.GetSlidingDifference(it->Param2, dst.Note); const int_t gliss = slide >= 0 ? -it->Param1 : it->Param1; const int_t direction = slide >= 0 ? -1 : +1; dst.ToneSlide.SetSlide(slide); dst.ToneSlide.SetGlissade(gliss); dst.ToneSlide.SetSlideDirection(direction); dst.Note = it->Param2 + Transposition; } break; } } }