001: /*
002: * Copyright (c) 2000 Silvere Martin-Michiellot All Rights Reserved.
003: *
004: * Silvere Martin-Michiellot grants you ("Licensee") a non-exclusive,
005: * royalty free, license to use, modify and redistribute this
006: * software in source and binary code form,
007: * provided that i) this copyright notice and license appear on all copies of
008: * the software; and ii) Licensee does not utilize the software in a manner
009: * which is disparaging to Silvere Martin-Michiellot.
010: *
011: * This software is provided "AS IS," without a warranty of any kind. ALL
012: * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
013: * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
014: * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. Silvere Martin-Michiellot
015: * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES
016: * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
017: * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
018: * Silvere Martin-Michiellot OR ITS LICENSORS BE LIABLE
019: * FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
020: * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
021: * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
022: * OR INABILITY TO USE SOFTWARE, EVEN IF Silvere Martin-Michiellot HAS BEEN
023: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
024: *
025: * This software is not designed or intended for use in on-line control of
026: * aircraft, air traffic, aircraft navigation or aircraft communications; or in
027: * the design, construction, operation or maintenance of any nuclear
028: * facility. Licensee represents and warrants that it will not use or
029: * redistribute the Software for such purposes.
030: *
031: */
032:
033: // This code is repackaged after the code from Craig A. Lindley, from Digital Audio with Java
034: // Site ftp://ftp.prenhall.com/pub/ptr/professional_computer_science.w-022/digital_audio/
035: // Email
036: package com.db.media.audio.dsp.processors;
037:
038: /*
039: This graphic equalizer processor uses the optimized bandpass
040: filters implemented in the IIRBandpassFilter and IIRBandpassFilterDesign
041: classes in the filters package. A quality factor (Q) of 1.4 was
042: chosen for the filters to minimize the ripple in the passband with
043: full boost or cut. Range of boost and cut is +12db .. -12db.
044:
045: The frequency of the bandpass filters were choosen to be:
046: 50Hz, 100Hz, 200Hz, 400Hz, 800Hz, 1.6KHz, 3.2KHz, 6.4KHz, 12.8KHz
047:
048: At a 11025 sample rate or lower, the highest two filters are disabled due to
049: Nyquist criteria. At a sample rate of 22050, only the highest filter is
050: disabled. At a 44100 sample rate, all filters are enabled.
051: */
052:
053: public class GraphicEQ extends AbstractAudio {
054:
055: private static final double Q = 1.4;
056:
057: // Private class data
058: private double[] dBuffer = new double[1];
059: private int sampleRate;
060: private boolean initializationComplete;
061: private double gainFactor;
062:
063: // Individual filter object instances
064: private IIRBandpassFilterDesign fd50Hz;
065: private IIRBandpassFilter f50Hz = null;
066:
067: private IIRBandpassFilterDesign fd100Hz;
068: private IIRBandpassFilter f100Hz = null;
069:
070: private IIRBandpassFilterDesign fd200Hz;
071: private IIRBandpassFilter f200Hz = null;
072:
073: private IIRBandpassFilterDesign fd400Hz;
074: private IIRBandpassFilter f400Hz = null;
075:
076: private IIRBandpassFilterDesign fd800Hz;
077: private IIRBandpassFilter f800Hz = null;
078:
079: private IIRBandpassFilterDesign fd1600Hz;
080: private IIRBandpassFilter f1600Hz = null;
081:
082: private IIRBandpassFilterDesign fd3200Hz;
083: private IIRBandpassFilter f3200Hz = null;
084:
085: private IIRBandpassFilterDesign fd6400Hz;
086: private IIRBandpassFilter f6400Hz = null;
087:
088: private IIRBandpassFilterDesign fd12800Hz;
089: private IIRBandpassFilter f12800Hz = null;
090:
091: public GraphicEQ() {
092:
093: super ("Graphic Equalizer", AbstractAudio.PROCESSOR);
094:
095: // Initialization will take place after sample rate is known
096: initializationComplete = false;
097:
098: }
099:
100: public int getSamples(short[] buffer, int length) {
101:
102: // Ask for a buffer of samples
103: int len = previous.getSamples(buffer, length);
104: if (len == -1)
105: return len;
106:
107: // If bypass is enabled, short circuit filtering
108: if (getByPass() || !initializationComplete)
109: return len;
110:
111: // Realloc buffer as required
112: if (dBuffer.length != len)
113: dBuffer = new double[len];
114:
115: // Move short samples into summation buffer for processing
116: // Prescale the data according to number of filter elements
117: for (int i = 0; i < len; i++)
118: dBuffer[i] = (double) buffer[i] * gainFactor;
119:
120: // Apply the filters
121: f50Hz.doFilter(buffer, dBuffer, len);
122: f100Hz.doFilter(buffer, dBuffer, len);
123: f200Hz.doFilter(buffer, dBuffer, len);
124: f400Hz.doFilter(buffer, dBuffer, len);
125: f800Hz.doFilter(buffer, dBuffer, len);
126: f1600Hz.doFilter(buffer, dBuffer, len);
127: f3200Hz.doFilter(buffer, dBuffer, len);
128:
129: if (sampleRate > 12800)
130: f6400Hz.doFilter(buffer, dBuffer, len);
131:
132: if (sampleRate > 25600)
133: f12800Hz.doFilter(buffer, dBuffer, len);
134:
135: // Convert the double samples back into short samples after
136: // range constraining them.
137: for (int i = 0; i < len; i++) {
138: double dSample = dBuffer[i];
139: if (dSample > 32767.0)
140: dSample = 32767.0;
141: else if (dSample < -32768.0)
142: dSample = -32768.0;
143:
144: // Convert sample and store
145: buffer[i] = (short) dSample;
146: }
147:
148: return len;
149:
150: }
151:
152: // These methods called when UI controls are manipulated
153: public void f50HzGain(double gain) {
154:
155: if (f50Hz != null)
156: f50Hz.setAmplitudeAdj(gain);
157:
158: }
159:
160: public void f100HzGain(double gain) {
161:
162: if (f100Hz != null)
163: f100Hz.setAmplitudeAdj(gain);
164:
165: }
166:
167: public void f200HzGain(double gain) {
168:
169: if (f200Hz != null)
170: f200Hz.setAmplitudeAdj(gain);
171:
172: }
173:
174: public void f400HzGain(double gain) {
175:
176: if (f400Hz != null)
177: f400Hz.setAmplitudeAdj(gain);
178:
179: }
180:
181: public void f800HzGain(double gain) {
182:
183: if (f800Hz != null)
184: f800Hz.setAmplitudeAdj(gain);
185:
186: }
187:
188: public void f1600HzGain(double gain) {
189:
190: if (f1600Hz != null)
191: f1600Hz.setAmplitudeAdj(gain);
192:
193: }
194:
195: public void f3200HzGain(double gain) {
196:
197: if (f3200Hz != null)
198: f3200Hz.setAmplitudeAdj(gain);
199:
200: }
201:
202: public void f6400HzGain(double gain) {
203:
204: if (f6400Hz != null)
205: f6400Hz.setAmplitudeAdj(gain);
206:
207: }
208:
209: public void f12800HzGain(double gain) {
210:
211: if (f12800Hz != null)
212: f12800Hz.setAmplitudeAdj(gain);
213:
214: }
215:
216: private void doInitialization() {
217:
218: // Total the number of filter gain elements in chain
219: int gainElements = 1;
220:
221: // Design the filters now that the sampling rate is known.
222: // Design the filter
223: fd50Hz = new IIRBandpassFilterDesign(50, sampleRate, Q);
224: fd50Hz.doFilterDesign();
225:
226: // Implement the filter design
227: f50Hz = new IIRBandpassFilter(fd50Hz);
228: gainElements++;
229:
230: // Design the filter
231: fd100Hz = new IIRBandpassFilterDesign(100, sampleRate, Q);
232: fd100Hz.doFilterDesign();
233:
234: // Implement the filter design
235: f100Hz = new IIRBandpassFilter(fd100Hz);
236: gainElements++;
237:
238: // Design the filter
239: fd200Hz = new IIRBandpassFilterDesign(200, sampleRate, Q);
240: fd200Hz.doFilterDesign();
241:
242: // Implement the filter design
243: f200Hz = new IIRBandpassFilter(fd200Hz);
244: gainElements++;
245:
246: // Design the filter
247: fd400Hz = new IIRBandpassFilterDesign(400, sampleRate, Q);
248: fd400Hz.doFilterDesign();
249:
250: // Implement the filter design
251: f400Hz = new IIRBandpassFilter(fd400Hz);
252: gainElements++;
253:
254: // Design the filter
255: fd800Hz = new IIRBandpassFilterDesign(800, sampleRate, Q);
256: fd800Hz.doFilterDesign();
257:
258: // Implement the filter design
259: f800Hz = new IIRBandpassFilter(fd800Hz);
260: gainElements++;
261:
262: // Design the filter
263: fd1600Hz = new IIRBandpassFilterDesign(1600, sampleRate, Q);
264: fd1600Hz.doFilterDesign();
265:
266: // Implement the filter design
267: f1600Hz = new IIRBandpassFilter(fd1600Hz);
268: gainElements++;
269:
270: // Design the filter
271: fd3200Hz = new IIRBandpassFilterDesign(3200, sampleRate, Q);
272: fd3200Hz.doFilterDesign();
273:
274: // Implement the filter design
275: f3200Hz = new IIRBandpassFilter(fd3200Hz);
276: gainElements++;
277:
278: // Conditionally design and implement the higher freq filters
279: if (sampleRate > 12800) {
280: // Design the filter
281: fd6400Hz = new IIRBandpassFilterDesign(6400, sampleRate, Q);
282: fd6400Hz.doFilterDesign();
283:
284: // Implement the filter design
285: f6400Hz = new IIRBandpassFilter(fd6400Hz);
286: gainElements++;
287: }
288:
289: if (sampleRate > 25600) {
290: // Design the filter
291: fd12800Hz = new IIRBandpassFilterDesign(12800, sampleRate,
292: Q);
293: fd12800Hz.doFilterDesign();
294:
295: // Implement the filter design
296: f12800Hz = new IIRBandpassFilter(fd12800Hz);
297: gainElements++;
298: }
299:
300: gainFactor = 1.0 / gainElements;
301:
302: // All filters designed, indicate initialization is complete
303: initializationComplete = true;
304:
305: }
306:
307: public void minMaxSamplingRate(int min, int max, int preferred) {
308:
309: super .minMaxSamplingRate(min, max, preferred);
310:
311: sampleRate = preferred;
312:
313: // Cannot do initialization until sample rate is known
314: doInitialization();
315:
316: }
317:
318: }
|