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 | } |