예제 #1
0
    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());
    }
예제 #2
0
파일: asc_supp.cpp 프로젝트: fgroen/zxtune
 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);
   }
 }
예제 #3
0
파일: asc_supp.cpp 프로젝트: fgroen/zxtune
    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();
      }
    }
예제 #4
0
파일: asc_supp.cpp 프로젝트: fgroen/zxtune
 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;
   }
 }
예제 #5
0
파일: pt2_supp.cpp 프로젝트: fgroen/zxtune
    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();
      }
    }
예제 #6
0
파일: pt2_supp.cpp 프로젝트: fgroen/zxtune
 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");
     }
   }
 }
예제 #7
0
 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;
     }
   }
 }