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: public class Delay extends AbstractAudio {
039:
040: // Private class data
041: private boolean initializationComplete = false;
042: private int delayInMs;
043: private int dryLevel;
044: private int wetLevel;
045: private int feedbackLevel;
046:
047: private int sampleRate = 0;
048: private int numberOfChannels = 0;
049: private int delayBufferSize = 0;
050: private short[] localBuffer = null;
051: private short[] delayBuffer = null;
052: private int readIndex;
053: private int writeIndex;
054:
055: public Delay() {
056:
057: super ("Delay", AbstractAudio.PROCESSOR);
058:
059: initializationComplete = false;
060:
061: // Allocate local sample buffer
062: localBuffer = new short[AbstractAudio.SAMPLEBUFFERSIZE];
063:
064: }
065:
066: // Process the samples that pass thru this effect
067: public int getSamples(short[] buffer, int length) {
068:
069: if (getByPass() || !initializationComplete)
070: return previous.getSamples(buffer, length);
071:
072: // Read number of samples requested from previous stage
073: int len = previous.getSamples(localBuffer, length);
074:
075: // Do the processing
076: for (int i = 0; i < len; i++) {
077: int inputSample = (int) localBuffer[i];
078: int delaySample = (int) delayBuffer[readIndex++];
079: int outputSample = ((inputSample * dryLevel) / 100)
080: + ((delaySample * wetLevel) / 100);
081:
082: // Clamp output to legal range
083: if (outputSample > 32767)
084: outputSample = 32767;
085: else if (outputSample < -32768)
086: outputSample = -32768;
087:
088: // Store in output sample
089: buffer[i] = (short) outputSample;
090:
091: // Calculate feedback
092: inputSample += (delaySample * feedbackLevel) / 100;
093:
094: // Clamp output to legal range
095: if (inputSample > 32767)
096: inputSample = 32767;
097: else if (inputSample < -32768)
098: inputSample = -32768;
099:
100: delayBuffer[writeIndex++] = (short) inputSample;
101:
102: // Update indices
103: readIndex %= delayBufferSize;
104: writeIndex %= delayBufferSize;
105: }
106:
107: return len;
108:
109: }
110:
111: public void setDelayInMs(int delayInMs) {
112:
113: initializationComplete = false;
114: this .delayInMs = delayInMs;
115:
116: doInitialization();
117:
118: }
119:
120: public void setDryLevel(int dryLevel) {
121:
122: this .dryLevel = dryLevel;
123:
124: }
125:
126: public void setWetLevel(int wetLevel) {
127:
128: this .wetLevel = wetLevel;
129:
130: }
131:
132: public void setFeedbackLevel(int feedbackLevel) {
133:
134: this .feedbackLevel = feedbackLevel;
135:
136: }
137:
138: public void doInitialization() {
139:
140: // See if we have the necessary data to initialize delay
141: if ((sampleRate != 0) && (numberOfChannels != 0)
142: && (!initializationComplete)) {
143:
144: // Allocate delay buffer
145: int delayOffset = (delayInMs * sampleRate * numberOfChannels) / 1000;
146:
147: delayBufferSize = AbstractAudio.SAMPLEBUFFERSIZE
148: + delayOffset;
149:
150: // Allocate new delay buffer
151: delayBuffer = new short[delayBufferSize];
152:
153: // Initialize indices
154: // Index where dry sample is written
155: writeIndex = 0;
156:
157: // Index where wet sample is read
158: readIndex = AbstractAudio.SAMPLEBUFFERSIZE;
159:
160: // Indicate initialization is complete
161: initializationComplete = true;
162: }
163:
164: }
165:
166: public void minMaxSamplingRate(int min, int max, int preferred) {
167:
168: super .minMaxSamplingRate(min, max, preferred);
169: sampleRate = preferred;
170: doInitialization();
171:
172: }
173:
174: // Negotiate the number of channels
175: public void minMaxChannels(int min, int max, int preferred) {
176:
177: super.minMaxChannels(min, max, preferred);
178: numberOfChannels = preferred;
179:
180: }
181:
182: }
|