001: /*
002: * $RCSfile: JSThread.java,v $
003: *
004: * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * - Redistribution of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * - Redistribution in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * Neither the name of Sun Microsystems, Inc. or the names of
019: * contributors may be used to endorse or promote products derived
020: * from this software without specific prior written permission.
021: *
022: * This software is provided "AS IS," without a warranty of any
023: * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
024: * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
025: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
026: * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
027: * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
028: * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
029: * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
030: * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
031: * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
032: * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
033: * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
034: * POSSIBILITY OF SUCH DAMAGES.
035: *
036: * You acknowledge that this software is not designed, licensed or
037: * intended for use in the design, construction, operation or
038: * maintenance of any nuclear facility.
039: *
040: * $Revision: 1.4 $
041: * $Date: 2007/02/09 17:20:03 $
042: * $State: Exp $
043: */
044:
045: package com.sun.j3d.audioengines.javasound;
046:
047: /*
048: * JavaSound engine Thread
049: *
050: * IMPLEMENTATION NOTE: The JavaSoundMixer is incomplete and really needs
051: * to be rewritten. When this is done, we may or may not need this class.
052: */
053:
054: import javax.media.j3d.*;
055: import com.sun.j3d.audioengines.*;
056:
057: /**
058: * The Thread Class extended for JavaSound Mixer specific audio device
059: * calls that dynamically, in 'real-time" change engine parameters
060: * such as volume/gain and sample-rate/frequency(pitch).
061: */
062:
063: class JSThread extends com.sun.j3d.audioengines.AudioEngineThread {
064:
065: /**
066: * The thread data for this thread
067: */
068: int totalChannels = 0;
069: /**
070: * flags denoting if dynamic gain or rate interpolation is to be performed
071: */
072: boolean rampGain = false;
073:
074: // global thread flat rampRate set true only when setTargetRate called
075: // for any sample. but it is cleared only by doWork when no sample
076: // has a need for the rate to be ramped any further.
077: boolean rampRate = false;
078:
079: /*** TODO:
080: *
081: * scalefactors applied to current sample rate to determine delta changes
082: * in rate (in Hz)
083: *
084: float currentGain = 1.0f;
085: float targetGain = 1.0f;
086: ***********/
087:
088: // reference to engine that created this thread
089: AudioEngine3D audioEngine = null;
090:
091: /**
092: * This constructor simply assigns the given id.
093: */
094: JSThread(ThreadGroup t, AudioEngine3DL2 engine) {
095: super (t, "J3D-JavaSoundThread");
096: audioEngine = engine;
097: // TODO: really get total JavaSound channels
098: totalChannels = 32;
099: if (debugFlag)
100: debugPrint("JSThread.constructor(" + t + ")");
101: }
102:
103: /**
104: * This method performs one iteration of pending work to do
105: *
106: * Wildly "garbled" sounds was caused by unequal changes in delta
107: * time verses delta distances (resulting in jumps in rate factors
108: * calculated for Doppler. This work thread is meant to smoothly
109: * increment/decrement changes in rate (and other future parameters)
110: * until the target value is reached.
111: */
112: synchronized public void doWork() {
113: if (debugFlag)
114: debugPrint("JSThread.doWork()");
115: /*******
116: while (rampRate || rampGain) {
117: *********/
118: /****** DESIGN
119: // Loop while sound is playing, reget attributes and gains/reverb,... params
120: // update lowlevel params then read modify then copy to line(s)
121:
122: can keep my own loop count for streams??? not really
123:
124: *******/
125: // QUESTION: will size ever get smaller after get performed???
126: int numSamples = audioEngine.getSampleListSize();
127: JSSample sample = null;
128: int numRateRamps = 0;
129: for (int index = 0; index < numSamples; index++) {
130: // loop thru samples looking for ones needing rate incremented
131: sample = (JSSample) audioEngine.getSample(index);
132: if (sample == null)
133: continue;
134: if (sample.getRampRateFlag()) {
135: if (debugFlag)
136: debugPrint(" rampRate true");
137: boolean endOfRampReached = adjustRate(sample);
138: sample.setRampRateFlag(!endOfRampReached);
139: if (!endOfRampReached)
140: numRateRamps++;
141: }
142: // TODO: support changes in gain this way as well
143: }
144: if (numRateRamps > 0) {
145: rampRate = true;
146: runMonitor(RUN, 0, null);
147: } else
148: rampRate = false;
149: /*********
150: try {
151: Thread.sleep(4);
152: } catch (InterruptedException e){}
153: *********/
154: /********
155: } // while
156: *********/
157: // otherwise do nothing
158: }
159:
160: int getTotalChannels() {
161: return (totalChannels);
162: }
163:
164: /**
165: * Gradually change rate scale factor
166: *
167: * If the rate change is too great suddenly, it sounds like a
168: * jump, so we need to change gradually over time.
169: * Since an octive delta change up is 2.0 but down is 0.5, forced
170: * "max" rate of change is different for both.
171: * @return true if target rate value was reached
172: */
173: boolean adjustRate(JSSample sample) {
174: // QUESTION: what should max delta rate changes be
175: // Using 1/32 of a half-step (1/12 of an octive)???
176: double maxRateChangeDown = 0.00130213;
177: double maxRateChangeUp = 0.00260417;
178:
179: double lastActualRateRatio = sample.getCurrentRateRatio();
180: double requestedRateRatio = sample.getTargetRateRatio();
181: boolean endOfRamp = false; // flag denotes if target rate reached
182: if (lastActualRateRatio > 0) {
183: double sampleRateRatio = requestedRateRatio; // in case diff = 0
184: double diff = 0.0;
185: if (debugFlag) {
186: debugPrint("JSThread.adjustRate: between "
187: + lastActualRateRatio + " & "
188: + requestedRateRatio);
189: }
190: diff = requestedRateRatio - lastActualRateRatio;
191: if (diff > 0.0) { // direction of movement is towards listener
192: // inch up towards the requested target rateRatio
193: if (diff >= maxRateChangeUp) {
194: sampleRateRatio = lastActualRateRatio
195: + maxRateChangeUp;
196: if (debugFlag) {
197: debugPrint(" adjustRate: "
198: + "diff >= maxRateChangeUp so ");
199: debugPrint(" adjustRate: "
200: + " sampleRateRatio incremented up by max");
201: }
202: endOfRamp = false; // target value not reached
203: }
204: /*
205: * otherwise delta change is within tolerance
206: * so use requested RateRatio as calculated w/out change
207: */
208: else {
209: sampleRateRatio = requestedRateRatio;
210: if (debugFlag) {
211: debugPrint(" adjustRate: "
212: + " requestedRateRatio reached");
213: }
214: endOfRamp = true; // reached
215: }
216: } else if (diff < 0.0) { // movement is away from listener
217: // inch down towards the requested target rateRatio
218: if ((-diff) >= maxRateChangeDown) {
219: sampleRateRatio = lastActualRateRatio
220: - maxRateChangeDown;
221: if (debugFlag) {
222: debugPrint(" adjustRate: "
223: + "-(diff) >= maxRateChangeUp so ");
224: debugPrint(" adjustRate: "
225: + " sampleRateRatio incremented down by max ");
226: }
227: endOfRamp = false; // target value not reached
228: }
229: /*
230: * otherwise negitive delta change is within tolerance so
231: * use sampleRateRatio as calculated w/out change
232: */
233: else {
234: sampleRateRatio = requestedRateRatio;
235: if (debugFlag) {
236: debugPrint(" adjustRate: "
237: + " requestedRateRatio reached");
238: }
239: endOfRamp = true; // reached
240: }
241: } else
242: // there is no difference between last set and requested rates
243: return true;
244:
245: this .setSampleRate(sample, (float) sampleRateRatio);
246: } else {
247: // this is the first time thru with a rate change
248: if (debugFlag) {
249: debugPrint(" adjustRate: "
250: + "last requested rateRatio not set yet "
251: + "so sampleRateRatio left unchanged");
252: }
253: this .setSampleRate(sample, (float) requestedRateRatio);
254: endOfRamp = false; // target value not reached
255: }
256: return endOfRamp;
257: } // adjustRate
258:
259: void setSampleRate(JSSample sample, JSAuralParameters attribs) {
260: // TODO:
261: }
262:
263: // gain set at start sample time as well
264: void setSampleGain(JSSample sample, JSAuralParameters attribs) {
265: /*******
266: // take fields as already set in sample and updates gain
267: // called after sample.render performed
268: if (debugFlag)
269: debugPrint("JSThread.setSampleGain()");
270: leftGain, rightGain
271: if (debugFlag) {
272: debugPrint(" " +
273: "StereoGain during update " + leftGain +
274: ", " + rightGain);
275: debugPrint(" " +
276: "StereoDelay during update " + leftDelay +
277: ", " + rightDelay);
278: }
279: int dataType = sample.getDataType();
280: int soundType = sample.getSoundType();
281: boolean muted = sample.getMuteFlag();
282:
283: if (debugFlag)
284: debugPrint("setStereoGain for sample "+sample+" " + leftGain +
285: ", " + rightGain);
286: if (dataType == JSAuralParameters.STREAMING_AUDIO_DATA ||
287: dataType == JSAuralParameters.BUFFERED_AUDIO_DATA ) {
288: thread.setSampleGain(sample, leftGain);
289: if ( (soundType == AudioDevice3D.CONE_SOUND) ||
290: (soundType == AudioDevice3D.POINT_SOUND) ) {
291: thread.setSampleGain(
292: ((JSPositionalSample)sample).getSecondIndex(), rightGain); thread.setSampleGain(
293: ((JSPositionalSample)sample).getReverbIndex(), reverbGain);
294: }
295: }
296: // TODO: JavaSound does not support MIDI song panning yet
297: else if (dataType == JSAuralParameters.STREAMING_MIDI_DATA ||
298:
299: dataType == JSAuralParameters.BUFFERED_MIDI_DATA) {
300: // Stereo samples not used for Midi Song playback
301: thread.setSampleGain(sample, (leftGain+rightGain) );
302: ******
303: // -1.0 far left, 0.0 center, 1.0 far right
304: position = (leftGain - rightGain) / (leftGain + rightGain);
305: JSMidi.setSamplePan(sample, position);
306:
307: if ( (soundType == AudioDevice3D.CONE_SOUND) ||
308: (soundType == AudioDevice3D.POINT_SOUND) ) {
309: JSMidi.setSampleGain(
310: ((JSPositionalSample)sample).getSecondIndex(), rightGain); JSMidi.setSampleGain(
311: ((JSPositionalSample)sample).getReverbIndex(), reverbGain);
312: }
313: ******
314: }
315: else {
316: if (debugFlag)
317: debugPrint( "JSThread: Internal Error setSampleGain dataType " +
318: dataType + " invalid");
319: return;
320: }
321: *****
322: // force specific gain
323: // go ahead and set gain immediately
324: this.setSampleGain(sample, scaleFactor);
325: rampGain = false; // disable ramping of gain
326: ******/
327: }
328:
329: void setSampleDelay(JSSample sample, JSAuralParameters attribs) {
330: /******
331: // take fields as already set in sample and updates delay
332: // called after sample.render performed
333: // adjust by attrib rolloff
334: float delayTime = attribs.reverbDelay * attribs.rolloff;
335:
336: leftDelay = (int)(sample.leftDelay * attribs.rolloff);
337: rightDelay = (int)(sample.rightDelay * attribs.rolloff);
338: leftDelay, rightDelay
339: int dataType = sample.getDataType();
340: int soundType = sample.getSoundType();
341: if (debugFlag)
342: debugPrint("setStereoDelay for sample "+sample+" " + leftDelay +
343: ", " + rightDelay);
344: if (dataType == JSAuralParameters.STREAMING_AUDIO_DATA) {
345: if ( (soundType == AudioDevice3D.CONE_SOUND) ||
346: (soundType == AudioDevice3D.POINT_SOUND) ) {
347: JSStream.setSampleDelay(
348: sample, leftDelay);
349: JSStream.setSampleDelay(
350: ((JSPositionalSample)sample).getSecondIndex(), rightDelay);
351: }
352: else
353: JSStream.setSampleDelay(sample, 0);
354: }
355: else if (dataType == JSAuralParameters.BUFFERED_AUDIO_DATA) {
356: if ( (soundType == AudioDevice3D.CONE_SOUND) ||
357: (soundType == AudioDevice3D.POINT_SOUND) ) {
358: JSClip.setSampleDelay(
359: sample, leftDelay);
360: JSClip.setSampleDelay(
361: ((JSPositionalSample)sample).getSecondIndex(), rightDelay);
362: }
363: else
364: JSClip.setSampleDelay(sample, 0);
365: }
366: else if (dataType == JSAuralParameters.STREAMING_MIDI_DATA ||
367:
368: dataType == JSAuralParameters.BUFFERED_MIDI_DATA) {
369: ********
370: if ( (soundType == AudioDevice3D.CONE_SOUND) ||
371: (soundType == AudioDevice3D.POINT_SOUND) ) {
372: JSMidi.setSampleDelay(
373: sample, leftDelay);
374: JSMidi.setSampleDelay(
375: ((JSPositionalSample)sample).getSecondIndex(), rightDelay);
376: }
377: else
378: ********
379: JSMidi.setSampleDelay(sample, 0);
380: }
381: else {
382: if (debugFlag)
383: debugPrint( "JSThread: Internal Error setSampleDelay dataType " +
384: dataType + " invalid");
385: return;
386: }
387: ******/
388: }
389:
390: void setTargetGain(JSSample sample, float scaleFactor) {
391: /**********
392: // TODO: implement this
393: // current gain is used as starting scalefactor for ramp
394: // TEMPORARY: for now just set gain
395: this.setSampleGain(sample, scaleFactor);
396: rampGain = false;
397: rampGain = true;
398: targetGain = scaleFactor;
399: runMonitor(RUN, 0, null);
400: **********/
401: }
402:
403: void setRate(JSSample sample, float rateScaleFactor) {
404: // force specific rate
405: // go ahead and set rate immediately
406: // take fields as already set in sample and updates rate
407: // called after sample.render performed
408: this .setSampleRate(sample, rateScaleFactor);
409: // disables rate from being gradually increased or decreased
410: // don't set global thread flat rampRate false just because
411: // one sample's rate is set to a specific value.
412: sample.setRampRateFlag(false);
413: }
414:
415: void setTargetRate(JSSample sample, float rateScaleFactor) {
416: // make gradual change in rate factors up or down to target rate
417: sample.setRampRateFlag(true);
418: sample.setTargetRateRatio(rateScaleFactor);
419: rampRate = true;
420: runMonitor(RUN, 0, null);
421: }
422:
423: // TODO: should have methods for delay and pan as well
424:
425: void setSampleGain(JSSample sample, float gain) {
426: /***********
427: // QUESTION: What needs to be synchronized???
428: if (debugFlag)
429: debugPrint("JSThread.setSampleGain for sample "+sample+" " + gain );
430: int dataType = sample.getDataType();
431: int soundType = sample.getSoundType();
432: boolean muted = sample.getMuteFlag();
433: // TODO:
434: if (dataType == JSAuralParameters.STREAMING_AUDIO_DATA)
435: {
436: com.sun.j3d.audio.J3DHaeStream.setSampleGain(index, gain);
437: }
438: else if (dataType == JSAuralParameters.BUFFERED_AUDIO_DATA) {
439: com.sun.j3d.audio.J3DHaeClip.setSampleGain(index, gain);
440: }
441: else {
442: // dataType==JSAuralParameters.STREAMING_MIDI_DATA
443: // dataType==JSAuralParameters.BUFFERED_MIDI_DATA
444: com.sun.j3d.audio.J3DHaeMidi.setSampleGain(index, gain);
445: }
446: ***************/
447: }
448:
449: void setSampleRate(JSSample sample, float scaleFactor) {
450: /*********
451: // QUESTION: What needs to be synchronized???
452: // TODO: use sample.rateRatio??
453: if (debugFlag)
454: debugPrint("JSThread.setSampleRate sample " +
455: sample + ", scale factor = " + scaleFactor);
456: int dataType = sample.getDataType();
457: int soundType = sample.getSoundType();
458:
459: // TODO:
460: if (dataType == JSAuralParameters.STREAMING_AUDIO_DATA) {
461: com.sun.j3d.audio.J3DHaeStream.scaleSampleRate(index, scaleFactor);
462: if ( (soundType == AudioDevice3D.CONE_SOUND) ||
463: (soundType == AudioDevice3D.POINT_SOUND) ) {
464: com.sun.j3d.audio.J3DHaeStream.scaleSampleRate(
465: ((JSPositionalSample)sample).getSecondIndex(),
466: scaleFactor);
467: com.sun.j3d.audio.J3DHaeStream.scaleSampleRate(
468: ((JSPositionalSample)sample).getReverbIndex(),
469: scaleFactor);
470: }
471: }
472: else if (dataType == JSAuralParameters.BUFFERED_AUDIO_DATA) {
473: com.sun.j3d.audio.J3DHaeClip.scaleSampleRate(index, scaleFactor);
474: if ( (soundType == AudioDevice3D.CONE_SOUND) ||
475: (soundType == AudioDevice3D.POINT_SOUND) ) {
476: com.sun.j3d.audio.J3DHaeClip.scaleSampleRate(
477: ((JSPositionalSample)sample).getSecondIndex(),
478: scaleFactor);
479: com.sun.j3d.audio.J3DHaeClip.scaleSampleRate(
480: ((JSPositionalSample)sample).getReverbIndex(),
481: scaleFactor);
482: }
483: }
484: else if (dataType == JSAuralParameters.STREAMING_MIDI_DATA ||
485: dataType == JSAuralParameters.BUFFERED_MIDI_DATA) {
486: com.sun.j3d.audio.J3DHaeMidi.scaleSampleRate(index, scaleFactor);
487: // TODO: MIDI only supported for Background sounds
488: }
489: ***********/
490: sample.setCurrentRateRatio(scaleFactor);
491: }
492:
493: boolean startSample(JSSample sample) {
494: /**********
495: // QUESTION: should this have a return values - error - or not??
496:
497: int returnValue = 0;
498: AuralParameters attribs = audioEngine.getAuralParameters();
499: int soundType = sample.getSoundType();
500: boolean muted = sample.getMuteFlag();
501: int dataType = sample.getDataType();
502: int loopCount = sample.getLoopCount();
503: float leftGain = sample.leftGain;
504: float rightGain = sample.rightGain;
505: int leftDelay = (int)(sample.leftDelay * attribs.rolloff);
506: int rightDelay = (int)(sample.rightDelay * attribs.rolloff);
507: if (dataType == JSAuralParameters.STREAMING_AUDIO_DATA) {
508: if (soundType == AudioDevice3D.BACKGROUND_SOUND) {
509: returnValue = JSStream.startSample(sample,
510: loopCount, leftGain);
511: if (debugFlag)
512: debugPrint("JSThread " +
513: "start stream backgroundSound with gain " + leftGain);
514: }
515: else { // soundType is POINT_SOUND or CONE_SOUND
516: // start up main left and right channels for spatial rendered sound
517: returnValue = JSStream.startSamples(sample,
518: ((JSPositionalSample)sample).getSecondIndex(),
519: loopCount, leftGain, rightGain, leftDelay, rightDelay);
520: //
521: // start up reverb channel w/out delay even if reverb not on now //
522: float reverbGain = 0.0f;
523: if (!muted && auralParams.reverbFlag) {
524: reverbGain = sample.getGain() *
525: attribs.reflectionCoefficient;
526: }
527: int reverbRtrnVal = JSStream.startSample(
528: ((JSPositionalSample)sample).getReverbIndex(), loopCount, reverbGain);
529: if (debugFlag)
530: debugPrint("JSThread " +
531: "start stream positionalSound with gain "+ leftGain +
532: ", " + rightGain);
533: }
534: }
535:
536: else if (dataType == JSAuralParameters.BUFFERED_AUDIO_DATA) {
537: if (soundType == AudioDevice3D.BACKGROUND_SOUND) {
538: returnValue = JSClip.startSample(sample,
539: loopCount, leftGain );
540: if (debugFlag)
541: debugPrint("JSThread " +
542: "start buffer backgroundSound with gain " + leftGain);
543: }
544: else { // soundType is POINT_SOUND or CONE_SOUND
545: // start up main left and right channels for spatial rendered sound
546: returnValue = JSClip.startSamples(sample,
547: ((JSPositionalSample)sample).getSecondIndex(),
548: loopCount, leftGain, rightGain, leftDelay, rightDelay);
549: //
550: // start up reverb channel w/out delay even if reverb not on now //
551: float reverbGain = 0.0f;
552: if (!muted && auralParams.reverbFlag) {
553: reverbGain = sample.getGain() *
554: attribs.reflectionCoefficient;
555: }
556: int reverbRtrnVal = JSClip.startSample(
557: ((JSPositionalSample)sample).getReverbIndex(),
558: loopCount, reverbGain);
559:
560: if (debugFlag)
561: debugPrint("JSThread " +
562: "start stream positionalSound with gain " + leftGain
563: + ", " + rightGain);
564: }
565: }
566: else if (dataType == JSAuralParameters.STREAMING_MIDI_DATA ||
567: dataType == JSAuralParameters.BUFFERED_MIDI_DATA) {
568: if (soundType == AudioDevice3D.BACKGROUND_SOUND) {
569: returnValue = JSMidi.startSample(sample,
570: loopCount, leftGain);
571: if (debugFlag)
572: debugPrint("JSThread " +
573: "start Midi backgroundSound with gain " + leftGain);
574: }
575: else { // soundType is POINT_SOUND or CONE_SOUND
576: // start up main left and right channels for spatial rendered sound
577: returnValue = JSMidi.startSamples(sample,
578: ((JSPositionalSample)sample).getSecondIndex(),
579: loopCount, leftGain, rightGain, leftDelay, rightDelay);
580: *******
581: // TODO: positional MIDI sounds not supported.
582: // The above startSamples really just start on sample
583: // Don't bother with reverb channel for now.
584:
585: //
586: // start up reverb channel w/out delay even if reverb not on now //
587: float reverbGain = 0.0f;
588: if (!muted && auralParams.reverbFlag) {
589: reverbGain = sample.getGain() *
590: attribs.reflectionCoefficient;
591: }
592: int reverbRtrnVal = JSMidi.startSample(
593: ((JSPositionalSample)sample).getReverbIndex(), loopCount, reverbGain);
594: *******
595: if (debugFlag)
596: debugPrint("JSThread " +
597: "start Midi positionalSound with gain "+ leftGain +
598: ", " + rightGain);
599: }
600: }
601:
602: else {
603: if (debugFlag)
604: debugPrint(
605: "JSThread: Internal Error startSample dataType " +
606: dataType + " invalid");
607: return false;
608: }
609: // TODO: have to look at return values and conditionally return 'success'
610: **********/
611: return true;
612: }
613:
614: boolean stopSample(JSSample sample) {
615: /***********
616: // QUESTION: should this have a return values - error - or not??
617: int dataType = sample.getDataType();
618: int soundType = sample.getSoundType();
619:
620: int returnValue = 0;
621: if (dataType == JSAuralParameters.STREAMING_AUDIO_DATA) {
622: if ( (soundType == AudioDevice3D.CONE_SOUND) ||
623: (soundType == AudioDevice3D.POINT_SOUND) ) {
624: returnValue = JSStream.stopSamples(sample,
625: ((JSPositionalSample)sample).getSecondIndex());
626: returnValue = JSStream.stopSample(
627: ((JSPositionalSample)sample).getReverbIndex());
628: }
629: else
630: returnValue = JSStream.stopSample(sample);
631: }
632: else if (dataType == JSAuralParameters.BUFFERED_AUDIO_DATA) {
633: if ( (soundType == AudioDevice3D.CONE_SOUND) ||
634: (soundType == AudioDevice3D.POINT_SOUND) ) {
635: returnValue = JSClip.stopSamples(sample,
636: ((JSPositionalSample)sample).getSecondIndex());
637: returnValue = JSClip.stopSample(
638: ((JSPositionalSample)sample).getReverbIndex());
639: }
640: else
641: returnValue = JSClip.stopSample(sample);
642: }
643: else if (dataType == JSAuralParameters.STREAMING_MIDI_DATA ||
644: dataType == JSAuralParameters.BUFFERED_MIDI_DATA) {
645:
646: *****
647: // TODO: positional sounds NOT supported yet
648: if ( (soundType == AudioDevice3D.CONE_SOUND) ||
649: (soundType == AudioDevice3D.POINT_SOUND) ) {
650: returnValue = JSMidi.stopSamples(sample,
651: ((JSPositionalSample)sample).getSecondIndex());
652: returnValue = JSMidi.stopSample(
653: ((JSPositionalSample)sample).getReverbIndex());
654: }
655: else
656: *****
657: returnValue = JSMidi.stopSample(sample);
658: }
659: else {
660: if (debugFlag)
661: debugPrint( "JSThread: Internal Error stopSample dataType " +
662: dataType + " invalid");
663: return -1;
664: }
665:
666: ************/
667: return true;
668: }
669:
670: void pauseSample(JSSample sample) {
671: /**********
672: int dataType = sample.getDataType();
673: int soundType = sample.getSoundType();
674: int returnValue = 0;
675: if (dataType == JSAuralParameters.STREAMING_AUDIO_DATA) {
676: if ( (soundType == AudioDevice3D.CONE_SOUND) ||
677: (soundType == AudioDevice3D.POINT_SOUND) ) {
678: returnValue = JSStream.pauseSamples(sample,
679: ((JSPositionalSample)sample).getSecondIndex());
680: returnValue = JSStream.pauseSample(
681: ((JSPositionalSample)sample).getReverbIndex());
682: }
683: else
684: returnValue = JSStream.pauseSample(sample);
685: }
686: else if (dataType == JSAuralParameters.BUFFERED_AUDIO_DATA) {
687: if ( (soundType == AudioDevice3D.CONE_SOUND) ||
688: (soundType == AudioDevice3D.POINT_SOUND) ) {
689: returnValue = JSClip.pauseSamples(sample,
690: ((JSPositionalSample)sample).getSecondIndex());
691: returnValue = JSClip.pauseSample(
692: ((JSPositionalSample)sample).getReverbIndex());
693: }
694: else
695: returnValue = JSClip.pauseSample(sample);
696: }
697: else if (dataType == JSAuralParameters.STREAMING_MIDI_DATA ||
698:
699: dataType == JSAuralParameters.BUFFERED_MIDI_DATA) {
700: *******
701: if ( (soundType == AudioDevice3D.CONE_SOUND) ||
702: (soundType == AudioDevice3D.POINT_SOUND) ) {
703: returnValue = JSMidi.pauseSamples(sample,
704: ((JSPositionalSample)sample).getSecondIndex());
705: returnValue = JSMidi.pauseSample(
706: ((JSPositionalSample)sample).getReverbIndex());
707: }
708: else
709: *****
710: returnValue = JSMidi.pauseSample(sample);
711: }
712: else {
713: if (debugFlag)
714: debugPrint(
715: "JSThread: Internal Error pauseSample dataType " +
716: dataType + " invalid");
717: }
718: if (returnValue < 0) {
719: if (debugFlag)
720: debugPrint( "JSThread: Internal Error pauseSample " +
721: "for sample " + sample + " failed");
722: }
723: // QUESTION: return value or not???
724: return;
725: *************/
726: }
727:
728: void unpauseSample(JSSample sample) {
729: /**************
730: int dataType = sample.getDataType();
731: int soundType = sample.getSoundType();
732: int returnValue = 0;
733: if (dataType == JSAuralParameters.STREAMING_AUDIO_DATA) {
734: if ( (soundType == AudioDevice3D.CONE_SOUND) ||
735: (soundType == AudioDevice3D.POINT_SOUND) ) {
736: returnValue = JSStream.unpauseSamples(sample,
737: ((JSPositionalSample)sample).getSecondIndex());
738: returnValue = JSStream.unpauseSample(
739: ((JSPositionalSample)sample).getReverbIndex());
740: }
741: else
742: returnValue = JSStream.unpauseSample(sample);
743: }
744: else if (dataType == JSAuralParameters.BUFFERED_AUDIO_DATA) {
745: if ( (soundType == AudioDevice3D.CONE_SOUND) ||
746: (soundType == AudioDevice3D.POINT_SOUND) ) {
747: returnValue = JSClip.unpauseSamples(sample,
748: ((JSPositionalSample)sample).getSecondIndex());
749: returnValue = JSClip.unpauseSample(
750: ((JSPositionalSample)sample).getReverbIndex());
751: }
752: else
753: returnValue = JSClip.unpauseSample(sample);
754: }
755: else if (dataType == JSAuralParameters.STREAMING_MIDI_DATA ||
756:
757: dataType == JSAuralParameters.BUFFERED_MIDI_DATA) {
758: *********
759: // TODO: positional Midi sounds
760: if ( (soundType == AudioDevice3D.CONE_SOUND) ||
761: (soundType == AudioDevice3D.POINT_SOUND) ) {
762: returnValue = JSMidi.unpauseSamples(sample,
763: ((JSPositionalSample)sample).getSecondIndex());
764: returnValue = JSMidi.unpauseSample(
765: ((JSPositionalSample)sample).getReverbIndex());
766: }
767: else
768: *********
769: returnValue = JSMidi.unpauseSample(sample);
770: }
771: else {
772: if (debugFlag)
773: debugPrint(
774: "JSThread: Internal Error unpauseSample dataType " + dataType + " invalid");
775: }
776: if (returnValue < 0) {
777: if (debugFlag)
778: debugPrint( "JSThread: Internal Error unpauseSample " +
779: "for sample " + sample + " failed");
780:
781: }
782: // QUESTION: return value or not???
783: return;
784: *************/
785: }
786:
787: // TODO:
788: void muteSample(JSSample sample) {
789: // is this already muted? if so don't do anytning
790:
791: // This determines if mute is done as a zero gain or
792: // as a stop, advance restart...
793: }
794:
795: // TODO:
796: void unmuteSample(JSSample sample) {
797: if (debugFlag)
798: debugPrint("JSThread.unmuteSample not implemented");
799: }
800:
801: int startStreams() {
802: // QUESTION: return value or not???
803: return 0;
804: }
805:
806: int startStream() {
807: // QUESTION: return value or not???
808: return 0;
809: }
810:
811: int startClips() {
812: // QUESTION: return value or not???
813: return 0;
814: }
815:
816: int startClip() {
817: // QUESTION: return value or not???
818: return 0;
819: }
820:
821: /**
822: * This initializes this thread. Once this method returns, the thread is
823: * ready to do work.
824: */
825: public void initialize() {
826: super .initialize();
827: // this.setPriority(Thread.MAX_PRIORITY);
828: // TODO: init values of fields???
829: if (debugFlag)
830: debugPrint("JSThread.initialize()");
831: // TODO: doesn't do anything yet
832: }
833:
834: /**
835: * Code to close the device
836: * @return flag: true is closed sucessfully, false if error
837: */
838: boolean close() {
839: // TODO: for now do nothing
840: return false;
841: }
842:
843: public void shutdown() {
844: }
845:
846: // default resource clean up method
847: public void cleanup() {
848: super .cleanup();
849: if (debugFlag)
850: debugPrint("JSThread.cleanup()");
851: }
852: }
|