| Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||||||
| ToneGenerator | 
  | 
  | 1.8181818181818181;1.818 | 
| 1 |  /* | 
|
| 2 |   * ToneGenerator.java | 
|
| 3 |   * | 
|
| 4 |   * This file is part of JavaGear. | 
|
| 5 |   * | 
|
| 6 |   * JavaGear is free software; you can redistribute it and/or modify | 
|
| 7 |   * it under the terms of the GNU General Public License as published by | 
|
| 8 |   * the Free Software Foundation; either version 2 of the License, or | 
|
| 9 |   * (at your option) any later version. | 
|
| 10 |   * | 
|
| 11 |   * JavaGear is distributed in the hope that it will be useful, | 
|
| 12 |   * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|
| 13 |   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|
| 14 |   * GNU General Public License for more details. | 
|
| 15 |   * | 
|
| 16 |   * You should have received a copy of the GNU General Public License | 
|
| 17 |   * along with JavaGear; if not, write to the Free Software | 
|
| 18 |   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | 
|
| 19 |   */ | 
|
| 20 | ||
| 21 |  package uk.co.javagear; | 
|
| 22 | ||
| 23 |  /** | 
|
| 24 |   * Texas SN76496 Tone Generator Emulation. | 
|
| 25 |   * | 
|
| 26 |   * @author Copyright (C) 2002-2003 Chris White | 
|
| 27 |   * @version 18th January 2003 | 
|
| 28 |   * @see "JavaGear Final Project Report" | 
|
| 29 |   */ | 
|
| 30 | public final class ToneGenerator {  | 
|
| 31 | ||
| 32 |      /** | 
|
| 33 |       * Volume of channel. | 
|
| 34 |       */ | 
|
| 35 | private int volume;  | 
|
| 36 | ||
| 37 |      /** | 
|
| 38 |       * Frequency of channel. | 
|
| 39 |       */ | 
|
| 40 | private int frequency;  | 
|
| 41 | ||
| 42 |      /** | 
|
| 43 |       * First byte of frequency. | 
|
| 44 |       */ | 
|
| 45 | private int firstByte;  | 
|
| 46 | ||
| 47 |      /** | 
|
| 48 |       * Counter for square waves. | 
|
| 49 |       */ | 
|
| 50 | private double counter;  | 
|
| 51 | ||
| 52 |      /** | 
|
| 53 |       * Positive/Negative output. | 
|
| 54 |       */ | 
|
| 55 | private boolean amplitudeFlipFlop;  | 
|
| 56 | ||
| 57 |      /** | 
|
| 58 |       * PSG cycles per sample. | 
|
| 59 |       */ | 
|
| 60 | private double psgCycles;  | 
|
| 61 | ||
| 62 |      /** | 
|
| 63 |       * Channel enabled. | 
|
| 64 |       */ | 
|
| 65 | private boolean enabled;  | 
|
| 66 | ||
| 67 | ||
| 68 |      /** | 
|
| 69 |       * ToneGenerator Constructor. | 
|
| 70 |       * | 
|
| 71 |       * @param clockSpeed clock speed (Hz) | 
|
| 72 |       * @param sampleRate sample rate (Hz) | 
|
| 73 |       */ | 
|
| 74 | 0 |      public ToneGenerator(double clockSpeed, int sampleRate) { | 
| 75 | 0 |          psgCycles = ((clockSpeed / sampleRate) * 2); // *2 as we cycle for half wave | 
| 76 | 0 |          enabled = true; | 
| 77 | 0 |          reset(); | 
| 78 | 0 |      } | 
| 79 | ||
| 80 | ||
| 81 |      /** | 
|
| 82 |       * Reset Tone Generator to Default Values. | 
|
| 83 |       */ | 
|
| 84 | public void reset() {  | 
|
| 85 | 0 |          amplitudeFlipFlop = true; | 
| 86 | 0 |          volume = 0x0F; | 
| 87 | 0 |          frequency = 1; | 
| 88 | 0 |          firstByte = 0; | 
| 89 | 0 |          counter = 0; | 
| 90 | 0 |      } | 
| 91 | ||
| 92 | ||
| 93 |      /** | 
|
| 94 |       * Toggle Channel On/Off. | 
|
| 95 |       */ | 
|
| 96 | public void setEnabled() {  | 
|
| 97 | 0 |          enabled = !enabled; | 
| 98 | 0 |      } | 
| 99 | ||
| 100 |      /** | 
|
| 101 |       * Set significant bits of frequency. | 
|
| 102 |       * | 
|
| 103 |       * @param value high byte. | 
|
| 104 |       */ | 
|
| 105 | public void setFreqSigf(int value) {  | 
|
| 106 | 0 |          frequency = firstByte | ((value & 0x3F) << 4); | 
| 107 | 0 |      } | 
| 108 | ||
| 109 |      /** | 
|
| 110 |       * Return a single sample from Tone Generator. | 
|
| 111 |       * | 
|
| 112 |       * @return Sample (-15 to +15) | 
|
| 113 |       */ | 
|
| 114 | public int getSample() {  | 
|
| 115 | 0 |          if (!enabled) { | 
| 116 | 0 |              return 0; | 
| 117 | }  | 
|
| 118 | ||
| 119 |          // Decrement Counter | 
|
| 120 | 0 |          counter -= psgCycles; | 
| 121 | ||
| 122 |          // Counter Expired | 
|
| 123 | 0 |          if (counter < 0) { | 
| 124 |              // Toggle Amplitude Flip Flop | 
|
| 125 | 0 |              amplitudeFlipFlop = !amplitudeFlipFlop; | 
| 126 | ||
| 127 |              // Reload counter | 
|
| 128 | 0 |              while (counter < 0) { | 
| 129 | 0 |                  if (frequency > 0) { | 
| 130 | 0 |                      counter += frequency; | 
| 131 |                  } else { | 
|
| 132 | 0 |                      counter = 1; // so we don't get stuck in an endless loop | 
| 133 | }  | 
|
| 134 | }  | 
|
| 135 | }  | 
|
| 136 | ||
| 137 | 0 |          int outputVolume = 15 - (volume & 0x0F); // ie 0 is 15, 1 is 14 etc | 
| 138 | ||
| 139 |          // Real SMS Only Outputs Values Over 4? | 
|
| 140 | 0 |          if (frequency > 4) { | 
| 141 | 0 |              if (amplitudeFlipFlop) { | 
| 142 | 0 |                  return +outputVolume; | 
| 143 |              } else { | 
|
| 144 | 0 |                  return -outputVolume; | 
| 145 | }  | 
|
| 146 |          } else { | 
|
| 147 | 0 |              return 0; | 
| 148 | }  | 
|
| 149 | }  | 
|
| 150 | ||
| 151 |      /** | 
|
| 152 |       * Getter for property <code>volume</code>. The channel's volume. | 
|
| 153 |       * | 
|
| 154 |       * @return Value of property <code>volume</code>. The channel's volume. | 
|
| 155 |       */ | 
|
| 156 | public int getVolume() {  | 
|
| 157 | 0 |          return this.volume; | 
| 158 | }  | 
|
| 159 | ||
| 160 |      /** | 
|
| 161 |       * Setter for property <code>volume</code>. The channel's volume. | 
|
| 162 |       * | 
|
| 163 |       * @param volume New value of property <code>volume</code>. The channel's volume. | 
|
| 164 |       */ | 
|
| 165 | public void setVolume(int volume) {  | 
|
| 166 | 0 |          this.volume = volume; | 
| 167 | 0 |      } | 
| 168 | ||
| 169 |      /** | 
|
| 170 |       * Getter for property <code>frequency</code>. The channel's frequency. | 
|
| 171 |       * | 
|
| 172 |       * @return Value of property <code>frequency</code>. The channel's frequency. | 
|
| 173 |       */ | 
|
| 174 | public int getFrequency() {  | 
|
| 175 | 0 |          return this.frequency; | 
| 176 | }  | 
|
| 177 | ||
| 178 |      /** | 
|
| 179 |       * Setter for property <code>frequency</code>. The channel's frequency. | 
|
| 180 |       * | 
|
| 181 |       * @param frequency New value of property <code>frequency</code>. The channel's frequency. | 
|
| 182 |       */ | 
|
| 183 | public void setFrequency(int frequency) {  | 
|
| 184 | 0 |          this.frequency = frequency; | 
| 185 | 0 |      } | 
| 186 | ||
| 187 |      /** | 
|
| 188 |       * Getter for property <code>firstByte</code>. First byte of frequency. | 
|
| 189 |       * | 
|
| 190 |       * @return Value of property <code>firstByte</code>. First byte of frequency. | 
|
| 191 |       */ | 
|
| 192 | public int getFirstByte() {  | 
|
| 193 | 0 |          return this.firstByte; | 
| 194 | }  | 
|
| 195 | ||
| 196 |      /** | 
|
| 197 |       * Setter for property <code>firstByte</code>. First byte of frequency. | 
|
| 198 |       * | 
|
| 199 |       * @param firstByte New value of property <code>firstByte</code>. First byte of frequency. | 
|
| 200 |       */ | 
|
| 201 | public void setFirstByte(int firstByte) {  | 
|
| 202 | 0 |          this.firstByte = firstByte; | 
| 203 | 0 |      } | 
| 204 | ||
| 205 | }  |