void SynthesizeChannel(ChannelState& dst, AYM::ChannelBuilder& channel, AYM::TrackBuilder& track) { const Ornament::Line& curOrnamentLine = *dst.OrnamentIterator.GetLine(); const int_t noteAddon = dst.NoteAccumulator.Update(curOrnamentLine.NoteAddon, curOrnamentLine.KeepNoteAddon); const int_t noiseAddon = dst.NoiseAccumulator.Update(curOrnamentLine.NoiseAddon, curOrnamentLine.KeepNoiseAddon); dst.OrnamentIterator.Next(); if (const Sample::Line* curSampleLine = dst.SampleIterator.GetLine()) { //apply noise const int_t sampleNoiseAddon = dst.SampleNoiseAccumulator.Update(curSampleLine->Noise, curSampleLine->AccumulateNoise); if (curSampleLine->NoiseMask) { channel.DisableNoise(); } else { track.SetNoise(dst.Noise + noiseAddon + sampleNoiseAddon); } //apply tone dst.ToneAddon = dst.ToneAccumulator.Update(curSampleLine->Tone, curSampleLine->AccumulateTone); if (curSampleLine->ToneMask) { channel.DisableTone(); } //apply level dst.VolumeSlide += curSampleLine->VolSlide; const int_t volume = Math::Clamp<int_t>(curSampleLine->Level + dst.VolumeSlide, 0, 15); const uint_t level = ((dst.Volume * 17 + (dst.Volume > 7)) * volume + 128) / 256; channel.SetLevel(level); const uint_t envelope = dst.EnvelopeAccumulator.Update(curSampleLine->EnvelopeAddon, curSampleLine->AccumulateEnvelope); if (curSampleLine->EnableEnvelope && dst.EnvelopeEnabled) { channel.EnableEnvelope(); track.SetEnvelopeTone(dst.Envelope - envelope); } dst.SampleIterator.Next(); } else { channel.SetLevel(0); channel.DisableTone(); channel.DisableNoise(); } channel.SetTone(dst.Note + noteAddon, dst.ToneAddon + dst.ToneSlide.Update()); }
void SynthesizeChannel(ChannelState& dst, AYM::ChannelBuilder& channel, AYM::TrackBuilder& track) { if (!dst.Enabled) { channel.SetLevel(0); return; } const Sample& curSample = Data->Samples.Get(dst.CurrentSampleNum); const Sample::Line& curSampleLine = curSample.GetLine(dst.PosInSample); const Ornament& curOrnament = Data->Ornaments.Get(dst.CurrentOrnamentNum); const Ornament::Line& curOrnamentLine = curOrnament.GetLine(dst.PosInOrnament); //calculate volume addon if (dst.VolSlideCounter >= 2) { dst.VolSlideCounter--; } else if (dst.VolSlideCounter) { dst.VolumeAddon += dst.VolSlideAddon; dst.VolSlideCounter = dst.VolSlideDelay; } dst.VolumeAddon += curSampleLine.VolSlide; dst.VolumeAddon = Math::Clamp<int_t>(dst.VolumeAddon, -15, 15); //calculate tone dst.ToneDeviation += curSampleLine.ToneDeviation; dst.NoteAddon += curOrnamentLine.NoteAddon; const int_t halfTone = int_t(dst.Note) + dst.NoteAddon; const int_t toneAddon = dst.ToneDeviation + dst.Sliding / 16; //apply tone channel.SetTone(halfTone, toneAddon); //apply level channel.SetLevel((dst.Volume + 1) * Math::Clamp<int_t>(dst.VolumeAddon + curSampleLine.Level, 0, 15) / 16); //apply envelope if (dst.Envelope && curSampleLine.EnableEnvelope) { channel.EnableEnvelope(); } //calculate noise dst.CurrentNoise += curOrnamentLine.NoiseAddon; //mixer if (curSampleLine.ToneMask) { channel.DisableTone(); } if (curSampleLine.NoiseMask && curSampleLine.EnableEnvelope) { EnvelopeTone += curSampleLine.Adding; track.SetEnvelopeTone(EnvelopeTone); } else { dst.CurrentNoise += curSampleLine.Adding; } if (!curSampleLine.NoiseMask) { track.SetNoise((dst.CurrentNoise + dst.Sliding / 256) & 0x1f); } else { channel.DisableNoise(); } //recalc positions if (dst.SlidingSteps != 0) { if (dst.SlidingSteps > 0) { if (!--dst.SlidingSteps && LIMITER != dst.SlidingTargetNote) //finish slide to note { dst.Note = dst.SlidingTargetNote; dst.SlidingTargetNote = LIMITER; dst.Sliding = dst.Glissade = 0; } } dst.Sliding += dst.Glissade; } if (dst.PosInSample++ >= curSample.GetLoopLimit()) { if (!dst.BreakSample) { dst.PosInSample = curSample.GetLoop(); } else if (dst.PosInSample >= curSample.GetSize()) { dst.Enabled = false; } } if (dst.PosInOrnament++ >= curOrnament.GetLoopLimit()) { dst.PosInOrnament = curOrnament.GetLoop(); } }
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(); } }