home *** CD-ROM | disk | FTP | other *** search
/ Large Pack of OldSkool DOS MOD Trackers / goattracker_2.73.zip / src / resid-fp / wavefp.h < prev   
Encoding:
C/C++ Source or Header  |  2014-07-23  |  5.7 KB  |  170 lines

  1. //  ---------------------------------------------------------------------------
  2. //  This file is part of reSID, a MOS6581 SID emulator engine.
  3. //  Copyright (C) 2004  Dag Lem <resid@nimrod.no>
  4. //
  5. //  This program is free software; you can redistribute it and/or modify
  6. //  it under the terms of the GNU General Public License as published by
  7. //  the Free Software Foundation; either version 2 of the License, or
  8. //  (at your option) any later version.
  9. //
  10. //  This program is distributed in the hope that it will be useful,
  11. //  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. //  GNU General Public License for more details.
  14. //
  15. //  You should have received a copy of the GNU General Public License
  16. //  along with this program; if not, write to the Free Software
  17. //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18. //  ---------------------------------------------------------------------------
  19.  
  20. #ifndef __WAVEFP_H__
  21. #define __WAVEFP_H__
  22.  
  23. #include "siddefsfp.h"
  24.  
  25. extern float dac[12];
  26. extern float wftable[11][4096];
  27.  
  28. // ----------------------------------------------------------------------------
  29. // A 24 bit accumulator is the basis for waveform generation. FREQ is added to
  30. // the lower 16 bits of the accumulator each cycle.
  31. // The accumulator is set to zero when TEST is set, and starts counting
  32. // when TEST is cleared.
  33. // The noise waveform is taken from intermediate bits of a 23 bit shift
  34. // register. This register is clocked by bit 19 of the accumulator.
  35. // ----------------------------------------------------------------------------
  36. class WaveformGeneratorFP
  37. {
  38. public:
  39.   WaveformGeneratorFP();
  40.  
  41.   void set_chip_model(chip_model model);
  42.  
  43.   inline void clock();
  44.   inline void synchronize(WaveformGeneratorFP& dest, WaveformGeneratorFP& source);
  45.   void reset();
  46.  
  47.   void writeFREQ_LO(reg8 value);
  48.   void writeFREQ_HI(reg8 value);
  49.   void writePW_LO(reg8 value);
  50.   void writePW_HI(reg8 value);
  51.   void writeCONTROL_REG(WaveformGeneratorFP& source, reg8 value);
  52.   reg8 readOSC(WaveformGeneratorFP& source);
  53.  
  54.   inline float output(WaveformGeneratorFP& source);
  55.  
  56. protected:
  57.   void clock_noise(const bool clock);
  58.   reg12 outputN___();
  59.   void set_nonlinearity(float nl);
  60.   void rebuild_wftable();
  61.   void calculate_waveform_sample(float o[12]);
  62.  
  63.   chip_model model;
  64.  
  65.   // Tell whether the accumulator MSB was set high on this cycle.
  66.   bool msb_rising;
  67.  
  68.   reg24 accumulator;
  69.   reg24 shift_register;
  70.   reg8 previous;
  71.   int noise_overwrite_delay;
  72.  
  73.   // Fout  = (Fn*Fclk/16777216)Hz
  74.   reg16 freq;
  75.   // PWout = (PWn/40.95)%
  76.   reg12 pw;
  77.  
  78.   // The control register right-shifted 4 bits; used for output function
  79.   // table lookup.
  80.   reg8 waveform;
  81.  
  82.   // The remaining control register bits.
  83.   bool test, ring_mod, sync;
  84.   // The gate bit is handled by the EnvelopeGenerator.
  85.  
  86.   // zero level offset of waveform (< 0)
  87.   float wave_zero;
  88.  
  89.   float previous_dac;
  90.  
  91. friend class VoiceFP;
  92. friend class SIDFP;
  93. };
  94.  
  95. // ----------------------------------------------------------------------------
  96. // SID clocking - 1 cycle.
  97. // ----------------------------------------------------------------------------
  98. inline
  99. void WaveformGeneratorFP::clock()
  100. {
  101.   /* no digital operation if test bit is set. Only emulate analog fade. */
  102.   if (test) {
  103.     if (noise_overwrite_delay != 0) {
  104.     if (-- noise_overwrite_delay == 0) {
  105.         shift_register |= 0x7ffffc;
  106.         clock_noise(false);
  107.     }
  108.     }
  109.     return;
  110.   }
  111.  
  112.   reg24 accumulator_prev = accumulator;
  113.  
  114.   // Calculate new accumulator value;
  115.   accumulator += freq;
  116.   accumulator &= 0xffffff;
  117.  
  118.   // Check whether the MSB became set high. This is used for synchronization.
  119.   msb_rising = !(accumulator_prev & 0x800000) && (accumulator & 0x800000);
  120.  
  121.   // Shift noise register once for each time accumulator bit 19 is set high.
  122.   if (!(accumulator_prev & 0x080000) && (accumulator & 0x080000)) {
  123.     clock_noise(true);
  124.   }
  125. }
  126.  
  127. // ----------------------------------------------------------------------------
  128. // Synchronize oscillators.
  129. // This must be done after all the oscillators have been clock()'ed since the
  130. // oscillators operate in parallel.
  131. // Note that the oscillators must be clocked exactly on the cycle when the
  132. // MSB is set high for hard sync to operate correctly. See SID::clock().
  133. // ----------------------------------------------------------------------------
  134. inline
  135. void WaveformGeneratorFP::synchronize(WaveformGeneratorFP& sync_dest, WaveformGeneratorFP &sync_source)
  136. {
  137.   // A special case occurs when a sync source is synced itself on the same
  138.   // cycle as when its MSB is set high. In this case the destination will
  139.   // not be synced. This has been verified by sampling OSC3.
  140.   if (msb_rising && sync_dest.sync && !(sync && sync_source.msb_rising)) {
  141.     sync_dest.accumulator = 0;
  142.   }
  143. }
  144.  
  145. // ----------------------------------------------------------------------------
  146. // Select one of 16 possible combinations of waveforms.
  147. // ----------------------------------------------------------------------------
  148. inline
  149. float WaveformGeneratorFP::output(WaveformGeneratorFP& sync_source)
  150. {
  151.   if (waveform == 0 || waveform > 7) {
  152.     return previous_dac;
  153.   }
  154.   /* waveforms 1 .. 7 left */
  155.  
  156.   /* Phase for all waveforms */
  157.   reg12 phase = accumulator >> 12;
  158.   /* pulse on/off generates 4 more variants after the main pulse types */
  159.   int variant = waveform >= 4 && (test || phase >= pw) ? 3 : -1;
  160.  
  161.   /* triangle waveform XOR circuit. Since the table already makes a triangle
  162.    * wave internally, we only need to account for the sync source here.
  163.    * Flipping the top bit suffices to reproduce the original SID ringmod */
  164.   phase ^= ((waveform & 3) == 1 && ring_mod && (sync_source.accumulator & 0x800000)) ? 0x800 : 0x00;
  165.  
  166.   return wftable[waveform + variant][phase];
  167. }
  168.  
  169. #endif // not __WAVEFP_H__
  170.