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 SynthesizeChannelsData(AYM::TrackBuilder& track) { for (uint_t chan = 0; chan != PlayerState.size(); ++chan) { AYM::ChannelBuilder channel = track.GetChannel(chan); SynthesizeChannel(PlayerState[chan], channel, track); } }
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 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 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; if (!dst.Enabled) { dst.Sliding = dst.Glissade = 0; dst.SlidingTargetNote = LIMITER; } dst.PosInSample = dst.PosInOrnament = 0; } if (const uint_t* note = src.GetNote()) { assert(src.GetEnabled()); dst.Note = *note; dst.Sliding = dst.Glissade = 0; dst.SlidingTargetNote = LIMITER; } if (const uint_t* sample = src.GetSample()) { dst.SampleNum = *sample; dst.PosInSample = 0; } if (const uint_t* ornament = src.GetOrnament()) { dst.OrnamentNum = *ornament; dst.PosInOrnament = 0; } 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); track.SetEnvelopeTone(it->Param2); dst.Envelope = true; break; case NOENVELOPE: dst.Envelope = false; break; case NOISE_ADD: dst.NoiseAdd = it->Param1; break; case GLISS_NOTE: dst.Sliding = 0; dst.Glissade = it->Param1; dst.SlidingTargetNote = it->Param2; break; case GLISS: dst.Glissade = it->Param1; dst.SlidingTargetNote = LIMITER; break; case NOGLISS: dst.Glissade = 0; break; default: assert(!"Invalid command"); } } }
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; } } }