Source Code Cross Referenced for JSDirectionalSample.java in  » 6.0-JDK-Modules » java-3d » com » sun » j3d » audioengines » javasound » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » java 3d » com.sun.j3d.audioengines.javasound 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * $RCSfile: JSDirectionalSample.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:        /*
046:         * DirectionalSample object
047:         *
048:         * IMPLEMENTATION NOTE: The JavaSoundMixer is incomplete and really needs
049:         * to be rewritten.
050:         */
051:
052:        package com.sun.j3d.audioengines.javasound;
053:
054:        import javax.media.j3d.*;
055:        import com.sun.j3d.audioengines.*;
056:        import javax.vecmath.*;
057:
058:        /**
059:         * The PostionalSample Class defines the data and methods associated with a 
060:         * PointSound sample played through the AudioDevice.
061:         */
062:
063:        class JSDirectionalSample extends JSPositionalSample {
064:            // The transformed direction of this sound
065:            Vector3f xformDirection = new Vector3f(0.0f, 0.0f, 1.0f);
066:
067:            public JSDirectionalSample() {
068:                super ();
069:                if (debugFlag)
070:                    debugPrintln("JSDirectionalSample constructor");
071:            }
072:
073:            void setXformedDirection() {
074:                if (debugFlag)
075:                    debugPrint("*** setXformedDirection");
076:                if (!getVWrldXfrmFlag()) {
077:                    if (debugFlag)
078:                        debugPrint("    Transform NOT set yet, so dir => xformDir");
079:                    xformDirection.set(direction);
080:                } else {
081:                    if (debugFlag)
082:                        debugPrint("    Transform dir => xformDir");
083:                    vworldXfrm.transform(direction, xformDirection);
084:                }
085:                if (debugFlag)
086:                    debugPrint("           xform(sound)Direction <= "
087:                            + xformDirection.x + ", " + xformDirection.y + ", "
088:                            + xformDirection.z);
089:            }
090:
091:            /* ***********************************
092:             *   
093:             *  Intersect ray to head with Ellipse
094:             *   
095:             * ***********************************/
096:            /*
097:             * An ellipse is defined using:
098:             *    (1) the ConeSound's direction vector as the major axis of the ellipse;
099:             *    (2) the max parameter (a front distance attenuation value) along the
100:             *        cone's position axis; and 
101:             *    (3) the min parameter (a back distance attenuation value) along the
102:             *        cone's negative axis
103:             * This method calculates the distance from the sound source to the 
104:             * Intersection of the Ellipse with the ray from the sound source to the
105:             * listener's head.
106:             * This method returns the resulting distance. 
107:             * If an error occurs, -1.0 is returned.
108:             *
109:             * A calculation are done in 'Cone' space:
110:             *    The origin is defined as being the sound source position.
111:             *    The ConeSound source axis is the X-axis of this Cone's space.
112:             *    Since this ConeSound source defines a prolate spheroid (obtained
113:             * by revolving an ellipsoid about the major axis) we can define the
114:             * Y-axis of this Cone space as being in the same plane as the X-axis
115:             * and the vector from the origin to the head.
116:             *    All calculations in Cone space can be generalized in this two-
117:             * dimensional space without loss of precision.
118:             *    Location of the head, H, in Cone space can then be defined as:
119:             *         H'(x,y) = (cos @, sin @) * | H |
120:             * where @ is the angle between the X-axis and the ray to H.
121:             * Using the equation of the line thru the origin and H', and the
122:             * equation of ellipse defined with min and max, find the 
123:             * intersection by solving for x and then y.
124:             *
125:             *    (I) The equation of the line thru the origin and H', and the
126:             *                    | H'(y) - S(y) |
127:             *         y - S(y) = | -----------  | * [x - S(x)]
128:             *                    | H'(x) - S(x) |
129:             * and since S(x,y) is the origin of ConeSpace:
130:             *                    | H'(y) |
131:             *               y  = | ----- | x
132:             *                    | H'(x) |
133:             *
134:             *    (II) The equation of ellipse:
135:             *         x**2   y**2
136:             *         ---- + ---- = 1
137:             *         a**2   b**2
138:             * given a is length from origin to ellipse along major, X-axis, and
139:             * b is length from origin to ellipse along minor, Y-axis;
140:             * where a**2 = [(max+min)/2]**2 , since 2a = min+max;
141:             * where b**2 = min*max , since the triangle abc is made is defined by the
142:             * the points: S(x,y), origin, and (0,b),
143:             * thus b**2 = a**2 - S(x,y) = a**2 - ((a-min)**2) = 2a*min - min**2
144:             *      b**2 = ((min+max)*min) - min**2 = min*max.
145:             * so the equation of the ellipse becomes:
146:             *            x**2          y**2
147:             *      ---------------- + ------- = 1
148:             *      [(max+min)/2]**2   min*max
149:             *
150:             * Substuting for y from Eq.(I) into Eq.(II) gives
151:             *            x**2         [(H'(y)/H'(x))*x]**2
152:             *      ---------------- + -------------------- = 1
153:             *      [(max+min)/2]**2          min*max
154:             *
155:             * issolating x**2 gives
156:             *           |         1          [H'(y)/H'(x)]**2 |
157:             *      x**2 | ---------------- + ---------------- | = 1
158:             *           | [(max+min)/2]**2       min*max      |
159:             *
160:             *
161:             *           |       4          [(sin @ * |H|)/(cos @ * |H|)]**2 |
162:             *      x**2 | -------------- + -------------------------------- | = 1
163:             *           | [(max+min)]**2               min*max              |
164:             *
165:             *              |                                         | 
166:             *              |                   1                     |
167:             *              |                                         | 
168:             *      x**2 =  | --------------------------------------- |
169:             *              |  |       4          [sin @/cos @]**2 |  |
170:             *              |  | -------------- + ---------------- |  |
171:             *              |  | [(max+min)]**2       min*max      |  |
172:             *
173:             * substitute tan @ for [sin @/cos @], and take the square root and you have
174:             * the equation for x as calculated below.
175:             *
176:             * Then solve for y by plugging x into Eq.(I).
177:             *
178:             * Return the distance from the origin in Cone space to this intersection 
179:             * point: square_root(x**2 + y**2).
180:             *
181:             */
182:            double intersectEllipse(double max, double min) {
183:
184:                if (debugFlag)
185:                    debugPrint("        intersectEllipse entered with min/max = "
186:                            + min + "/" + max);
187:                /*
188:                 * First find angle '@' between the X-axis ('A') and the ray to Head ('H').
189:                 * In local coordinates, use Dot Product of those two vectors to get cos @:
190:                 *               A(u)*H(u) + A(v)*H(v) + A(w)*H(v)
191:                 *       cos @ = --------------------------------
192:                 *                      |A|*|H|
193:                 * then since domain of @ is { 0 <= @ <= PI }, arccos can be used to get @.
194:                 */
195:                Vector3f xAxis = this .direction; // axis is sound direction vector
196:                // Get the already calculated vector from sound source position to head
197:                Vector3f sourceToHead = this .sourceToCenterEar;
198:                // error check vectors not empty
199:                if (xAxis == null || sourceToHead == null) {
200:                    if (debugFlag)
201:                        debugPrint("           one or both of the vectors are null");
202:                    return (-1.0f); // denotes an error occurred
203:                }
204:
205:                // Dot Product
206:                double dotProduct = (double) ((sourceToHead.dot(xAxis)) / (sourceToHead
207:                        .length() * xAxis.length()));
208:                if (debugFlag)
209:                    debugPrint("           dot product = " + dotProduct);
210:                // since theta angle is in the range between 0 and PI, arccos can be used
211:                double theta = (float) (Math.acos(dotProduct));
212:                if (debugFlag)
213:                    debugPrint("           theta = " + theta);
214:
215:                /*
216:                 * Solve for X using Eq.s (I) and (II) from above.
217:                 */
218:                double minPlusMax = (double) (min + max);
219:                double tangent = Math.tan(theta);
220:                double xSquared = 1.0 / ((4.0 / (minPlusMax * minPlusMax)) + ((tangent * tangent) / (min * max)));
221:                double x = Math.sqrt(xSquared);
222:                if (debugFlag)
223:                    debugPrint("           X = " + x);
224:                /*
225:                 * Solve for y, given the result for x:
226:                 *          | H'(y) |       | sin @ | 
227:                 *     y  = | ----- | x  =  | ----- | x
228:                 *          | H'(x) |       | cos @ | 
229:                 */
230:                double y = tangent * x;
231:                if (debugFlag)
232:                    debugPrint("           Y = " + y);
233:                double ySquared = y * y;
234:
235:                /*
236:                 * Now return distance from origin to intersection point (x,y)
237:                 */
238:                float distance = (float) (Math.sqrt(xSquared + ySquared));
239:                if (debugFlag)
240:                    debugPrint("           distance to intersection = "
241:                            + distance);
242:                return (distance);
243:            }
244:
245:            /* *****************
246:             *   
247:             *  Find Factor
248:             *   
249:             * *****************/
250:            /*
251:             *  Interpolates the correct attenuation scale factor given a 'distance'
252:             *  value.  This version used both front and back attenuation distance 
253:             *  and scale factor arrays (if non-null) in its calculation of the
254:             *  the distance attenuation.
255:             *  If the back attenuation arrays are null then this executes the
256:             *  PointSoundRetained version of this method.
257:             *  This method finds the intesection of the ray from the sound source
258:             *  to the center-ear, with the ellipses defined by the two sets (front
259:             *  and back) of distance attenuation arrays.
260:             *  This method looks at pairs of intersection distance values to find 
261:             *  which pair the input distance argument is between:
262:             *     [intersectionDistance[index] and intersectionDistance[index+1]
263:             *  The index is used to get factorArray[index] and factorArray[index+1].
264:             *  Then the ratio of the 'distance' between this pair of intersection
265:             *  values is used to scale the two found factorArray values proportionally.
266:             */
267:            float findFactor(double distanceToHead, double[] maxDistanceArray,
268:                    float[] maxFactorArray, double[] minDistanceArray,
269:                    float[] minFactorArray) {
270:                int index, lowIndex, highIndex, indexMid;
271:                double returnValue;
272:
273:                if (debugFlag) {
274:                    debugPrint("JSDirectionalSample.findFactor entered:");
275:                    debugPrint("      distance to head = " + distanceToHead);
276:                }
277:
278:                if (minDistanceArray == null || minFactorArray == null) {
279:                    /*
280:                     * Execute the PointSoundRetained version of this method.
281:                     * Assume it will check for other error conditions.
282:                     */
283:                    return (this .findFactor(distanceToHead, maxDistanceArray,
284:                            maxFactorArray));
285:                }
286:
287:                /*
288:                 * Error checking
289:                 */
290:                if (maxDistanceArray == null || maxFactorArray == null) {
291:                    if (debugFlag)
292:                        debugPrint("    findFactor: arrays null");
293:                    return -1.0f;
294:                }
295:                // Assuming length > 1 already tested in set attenuation arrays methods
296:                int arrayLength = maxDistanceArray.length;
297:                if (arrayLength < 2) {
298:                    if (debugFlag)
299:                        debugPrint("    findFactor: arrays length < 2");
300:                    return -1.0f;
301:                }
302:                int largestIndex = arrayLength - 1;
303:                /*
304:                 * Calculate distanceGain scale factor
305:                 */
306:                /*
307:                 * distanceToHead is larger than greatest distance in maxDistanceArray
308:                 * so head is beyond the outer-most ellipse.
309:                 */
310:                if (distanceToHead >= maxDistanceArray[largestIndex]) {
311:                    if (debugFlag)
312:                        debugPrint("    findFactor: distance > "
313:                                + maxDistanceArray[largestIndex]);
314:                    if (debugFlag)
315:                        debugPrint("    maxDistanceArray length = "
316:                                + maxDistanceArray.length);
317:                    if (debugFlag)
318:                        debugPrint("    findFactor returns ****** "
319:                                + maxFactorArray[largestIndex] + " ******");
320:                    return maxFactorArray[largestIndex];
321:                }
322:
323:                /*
324:                 * distanceToHead is smaller than least distance in minDistanceArray
325:                 * so head is inside the inner-most ellipse.
326:                 */
327:                if (distanceToHead <= minDistanceArray[0]) {
328:                    if (debugFlag)
329:                        debugPrint("    findFactor: distance < "
330:                                + maxDistanceArray[0]);
331:                    if (debugFlag)
332:                        debugPrint("    findFactor returns ****** "
333:                                + minFactorArray[0] + " ******");
334:                    return minFactorArray[0];
335:                }
336:
337:                /*
338:                 * distanceToHead is between points within attenuation arrays.
339:                 * Use binary halfing of distance attenuation arrays.
340:                 */
341:                {
342:                    double[] distanceArray = new double[arrayLength];
343:                    float[] factorArray = new float[arrayLength];
344:                    boolean[] intersectionCalculated = new boolean[arrayLength];
345:                    // initialize intersection calculated array flags to false
346:                    for (int i = 0; i < arrayLength; i++)
347:                        intersectionCalculated[i] = false;
348:                    boolean intersectionOnEllipse = false;
349:                    int factorIndex = -1;
350:
351:                    /* 
352:                     * Using binary halving to find the two index values in the
353:                     * front and back distance arrays that the distanceToHead 
354:                     * parameter (from sound source position to head) fails between.
355:                     * Changing the the current low and high index values 
356:                     * calculate the intesection of ellipses (defined by this
357:                     * min/max distance values) with the ray (sound source to
358:                     * head).  Put the resulting value into the distanceArray.
359:                     */
360:                    /*
361:                     * initialize the lowIndex to first index of distance arrays.
362:                     * initialize the highIndex to last index of distance arrays.
363:                     */
364:                    lowIndex = 0;
365:                    highIndex = largestIndex;
366:
367:                    if (debugFlag)
368:                        debugPrint("    while loop to find index that's closest: ");
369:                    while (lowIndex < (highIndex - 1)) {
370:                        if (debugFlag)
371:                            debugPrint("        lowIndex " + lowIndex
372:                                    + ", highIndex " + highIndex);
373:                        /*
374:                         * Calculate the Intersection of Ellipses (defined by this
375:                         * min/max values) with the ray from the sound source to the
376:                         * head.  Put the resulting value into the distanceArray.
377:                         */
378:                        if (!intersectionCalculated[lowIndex]) {
379:                            distanceArray[lowIndex] = this .intersectEllipse(
380:                                    maxDistanceArray[lowIndex],
381:                                    minDistanceArray[lowIndex]);
382:                            // If return intersection distance is < 0 an error occurred.
383:                            if (distanceArray[lowIndex] >= 0.0)
384:                                intersectionCalculated[lowIndex] = true;
385:                            else {
386:                                /*
387:                                 * Error in ellipse intersection calculation.  Use
388:                                 * average of max/min difference for intersection value.
389:                                 */
390:                                distanceArray[lowIndex] = (minDistanceArray[lowIndex] + maxDistanceArray[lowIndex]) * 0.5;
391:                                if (internalErrors)
392:                                    debugPrint("Internal Error in intersectEllipse; use "
393:                                            + distanceArray[lowIndex]
394:                                            + " for intersection value ");
395:                                // Rather than aborting, just use average and go on...
396:                                intersectionCalculated[lowIndex] = true;
397:                            }
398:                        } // end of if intersection w/ lowIndex not already calculated
399:
400:                        if (!intersectionCalculated[highIndex]) {
401:                            distanceArray[highIndex] = this .intersectEllipse(
402:                                    maxDistanceArray[highIndex],
403:                                    minDistanceArray[highIndex]);
404:                            // If return intersection distance is < 0 an error occurred.
405:                            if (distanceArray[highIndex] >= 0.0f)
406:                                intersectionCalculated[highIndex] = true;
407:                            else {
408:                                /*
409:                                 * Error in ellipse intersection calculation.  Use
410:                                 * average of max/min difference for intersection value.
411:                                 */
412:                                distanceArray[highIndex] = (minDistanceArray[highIndex] + maxDistanceArray[highIndex]) * 0.5f;
413:                                if (internalErrors)
414:                                    debugPrint("Internal Error in intersectEllipse; use "
415:                                            + distanceArray[highIndex]
416:                                            + " for intersection value ");
417:                                // Rather than aborting, just use average and go on...
418:                                intersectionCalculated[highIndex] = true;
419:                            }
420:                        } // end of if intersection w/ highIndex not already calculated
421:
422:                        /*
423:                         * Test for intersection points being the same as head position
424:                         * distanceArray[lowIndex] and distanceArray[highIndex], if so
425:                         * return factor value directly from array
426:                         */
427:                        if (distanceArray[lowIndex] >= distanceToHead) {
428:                            if ((lowIndex != 0)
429:                                    && (distanceToHead < distanceArray[lowIndex])) {
430:                                if (internalErrors)
431:                                    debugPrint("Internal Error: binary halving in "
432:                                            + "findFactor failed; distance < low "
433:                                            + "index value");
434:                            }
435:                            if (debugFlag) {
436:                                debugPrint("        distanceArray[lowIndex] >= "
437:                                        + "distanceToHead");
438:                                debugPrint("        factorIndex = " + lowIndex);
439:                            }
440:                            intersectionOnEllipse = true;
441:                            factorIndex = lowIndex;
442:                            break;
443:                        } else if (distanceArray[highIndex] <= distanceToHead) {
444:                            if ((highIndex != largestIndex)
445:                                    && (distanceToHead > distanceArray[highIndex])) {
446:                                if (internalErrors)
447:                                    debugPrint("Internal Error: binary halving in "
448:                                            + "findFactor failed; distance > high "
449:                                            + "index value");
450:                            }
451:                            if (debugFlag) {
452:                                debugPrint("        distanceArray[highIndex] >= "
453:                                        + "distanceToHead");
454:                                debugPrint("        factorIndex = " + highIndex);
455:                            }
456:                            intersectionOnEllipse = true;
457:                            factorIndex = highIndex;
458:                            break;
459:                        }
460:
461:                        if (distanceToHead > distanceArray[lowIndex]
462:                                && distanceToHead < distanceArray[highIndex]) {
463:                            indexMid = lowIndex + ((highIndex - lowIndex) / 2);
464:                            if (distanceToHead <= distanceArray[indexMid])
465:                                // value of distance in lower "half" of list
466:                                highIndex = indexMid;
467:                            else
468:                                // value if distance in upper "half" of list
469:                                lowIndex = indexMid;
470:                        }
471:                    } /* of while */
472:
473:                    /*
474:                     * First check to see if distanceToHead is beyond min or max
475:                     * ellipses, or on an ellipse.
476:                     * If so, factor is calculated using the distance Ratio 
477:                     *    (distanceToHead - min) / (max-min)
478:                     * where max = maxDistanceArray[factorIndex], and 
479:                     *       min = minDistanceArray[factorIndex]
480:                     */
481:                    if (intersectionOnEllipse && factorIndex >= 0) {
482:                        if (debugFlag) {
483:                            debugPrint("    ratio calculated using factorIndex "
484:                                    + factorIndex);
485:                            debugPrint("    d.A. max pair for factorIndex "
486:                                    + maxDistanceArray[factorIndex] + ", "
487:                                    + maxFactorArray[factorIndex]);
488:                            debugPrint("    d.A. min pair for lowIndex "
489:                                    + minDistanceArray[factorIndex] + ", "
490:                                    + minFactorArray[factorIndex]);
491:                        }
492:                        returnValue = (((distanceArray[factorIndex] - minDistanceArray[factorIndex]) / (maxDistanceArray[factorIndex] - minDistanceArray[factorIndex])) * (maxFactorArray[factorIndex] - minFactorArray[factorIndex]))
493:                                + minFactorArray[factorIndex];
494:                        if (debugFlag)
495:                            debugPrint("    findFactor returns ****** "
496:                                    + returnValue + " ******");
497:                        return (float) returnValue;
498:                    }
499:
500:                    /* Otherwise, for distanceToHead between distance intersection
501:                     * values, we need to calculate two factors - one for the
502:                     * ellipse defined by lowIndex min/max factor arrays, and
503:                     * the other by highIndex min/max factor arrays.  Then the
504:                     * distance Ratio (defined above) is applied, using these
505:                     * two factor values, to get the final return value.
506:                     */
507:                    double highFactorValue = 1.0;
508:                    double lowFactorValue = 0.0;
509:                    highFactorValue = (((distanceArray[highIndex] - minDistanceArray[highIndex]) / (maxDistanceArray[highIndex] - minDistanceArray[highIndex])) * (maxFactorArray[highIndex] - minFactorArray[highIndex]))
510:                            + minFactorArray[highIndex];
511:                    if (debugFlag) {
512:                        debugPrint("    highFactorValue calculated w/ highIndex "
513:                                + highIndex);
514:                        debugPrint("    d.A. max pair for highIndex "
515:                                + maxDistanceArray[highIndex] + ", "
516:                                + maxFactorArray[highIndex]);
517:                        debugPrint("    d.A. min pair for lowIndex "
518:                                + minDistanceArray[highIndex] + ", "
519:                                + minFactorArray[highIndex]);
520:                        debugPrint("    highFactorValue " + highFactorValue);
521:                    }
522:                    lowFactorValue = (((distanceArray[lowIndex] - minDistanceArray[lowIndex]) / (maxDistanceArray[lowIndex] - minDistanceArray[lowIndex])) * (maxFactorArray[lowIndex] - minFactorArray[lowIndex]))
523:                            + minFactorArray[lowIndex];
524:                    if (debugFlag) {
525:                        debugPrint("    lowFactorValue calculated w/ lowIndex "
526:                                + lowIndex);
527:                        debugPrint("    d.A. max pair for lowIndex "
528:                                + maxDistanceArray[lowIndex] + ", "
529:                                + maxFactorArray[lowIndex]);
530:                        debugPrint("    d.A. min pair for lowIndex "
531:                                + minDistanceArray[lowIndex] + ", "
532:                                + minFactorArray[lowIndex]);
533:                        debugPrint("    lowFactorValue " + lowFactorValue);
534:                    }
535:                    /*
536:                     * calculate gain scale factor based on the ratio distance
537:                     * between ellipses the distanceToHead lies between.
538:                     */
539:                    /*
540:                     * ratio: distance from listener to sound source
541:                     *        between lowIndex and highIndex times
542:                     *        attenuation value between lowIndex and highIndex
543:                     * gives linearly interpolationed attenuation value
544:                     */
545:                    if (debugFlag) {
546:                        debugPrint("    ratio calculated using distanceArray"
547:                                + lowIndex + ", highIndex " + highIndex);
548:                        debugPrint("    calculated pair for lowIndex "
549:                                + distanceArray[lowIndex] + ", "
550:                                + lowFactorValue);
551:                        debugPrint("    calculated pair for highIndex "
552:                                + distanceArray[highIndex] + ", "
553:                                + highFactorValue);
554:                    }
555:
556:                    returnValue = (((distanceToHead - distanceArray[lowIndex]) / (distanceArray[highIndex] - distanceArray[lowIndex])) * (highFactorValue - lowFactorValue))
557:                            + factorArray[lowIndex];
558:                    if (debugFlag)
559:                        debugPrint("    findFactor returns ******"
560:                                + returnValue + " ******");
561:                    return (float) returnValue;
562:                }
563:
564:            }
565:
566:            /**
567:             * CalculateDistanceAttenuation  
568:             * 
569:             * Simply calls ConeSound specific 'findFactor()' with 
570:             * both front and back attenuation linear distance and gain scale factor
571:             * arrays. 
572:             */
573:            float calculateDistanceAttenuation(float distance) {
574:                float factor = findFactor(distance, this .attenuationDistance,
575:                        this .attenuationGain, this .backAttenuationDistance,
576:                        this .backAttenuationGain);
577:                if (factor < 0.0f)
578:                    return 1.0f;
579:                else
580:                    return factor;
581:            }
582:
583:            /**
584:             * CalculateAngularGain  
585:             *   
586:             * Simply calls generic (for PointSound) 'findFactor()' with 
587:             * a single set of angular attenuation distance and gain scalefactor arrays.
588:             */
589:            float calculateAngularGain() {
590:                float angle = findAngularOffset();
591:                float factor = findFactor(angle, this .angularDistance,
592:                        this .angularGain);
593:                if (factor < 0.0f)
594:                    return 1.0f;
595:                else
596:                    return factor;
597:            }
598:
599:            /* *****************
600:             *   
601:             *  Find Angular Offset
602:             *   
603:             * *****************/
604:            /*   
605:             *  Calculates the angle from the sound's direction axis and the ray from
606:             *  the sound origin to the listener'center ear.
607:             *  For Cone Sounds this value is the arc cosine of dot-product between
608:             *  the sound direction vector and the vector (sound position,centerEar)
609:             *  all in Virtual World coordinates space.
610:             *  Center ear position is in Virtual World coordinates.
611:             *  Assumes that calculation done in VWorld Space...
612:             *  Assumes that xformPosition is already calculated...
613:             */
614:            float findAngularOffset() {
615:                Vector3f unitToEar = new Vector3f();
616:                Vector3f unitDirection = new Vector3f();
617:                Point3f xformPosition = positions[currentIndex];
618:                Point3f xformCenterEar = centerEars[currentIndex];
619:                float dotProduct;
620:                float angle;
621:                /* 
622:                 * TODO: (Question) is assumption that xformed values available O.K.
623:                 * TODO: (Performance) save this angular offset and only recalculate
624:                 *          if centerEar or sound position have changed. 
625:                 */
626:                unitToEar.x = xformCenterEar.x - xformPosition.x;
627:                unitToEar.y = xformCenterEar.y - xformPosition.y;
628:                unitToEar.z = xformCenterEar.z - xformPosition.z;
629:                unitToEar.normalize();
630:                unitDirection.normalize(this .direction);
631:                dotProduct = unitToEar.dot(unitDirection);
632:                angle = (float) (Math.acos((double) dotProduct));
633:                if (debugFlag)
634:                    debugPrint("           angle from cone direction = "
635:                            + angle);
636:                return (angle);
637:            }
638:
639:            /************
640:             *   
641:             *  Calculate Filter
642:             *   
643:             * *****************/
644:            /*   
645:             *  Calculates the low-pass cutoff frequency filter value applied to the
646:             *  a sound based on both:
647:             *      Distance Filter (from Aural Attributes) based on distance
648:             *         between the sound and the listeners position
649:             *      Angular Filter (for Directional Sounds) based on the angle
650:             *         between a sound's projected direction and the
651:             *         vector between the sounds position and center ear.
652:             *  The lowest of these two filter is used.
653:             *  This filter value is stored into the sample's filterFreq field.
654:             */
655:            void calculateFilter(float distance, AuralParameters attribs) {
656:                // setting filter cutoff freq to 44.1kHz which, in this
657:                // implementation, is the same as not performing filtering
658:                float distanceFilter = 44100.0f;
659:                float angularFilter = 44100.0f;
660:                int arrayLength = attribs.getDistanceFilterLength();
661:                int filterType = attribs.getDistanceFilterType();
662:
663:                boolean distanceFilterFound = false;
664:                boolean angularFilterFound = false;
665:                if ((filterType == AuralParameters.NO_FILTERING)
666:                        && arrayLength > 0) {
667:                    double[] distanceArray = new double[arrayLength];
668:                    float[] cutoffArray = new float[arrayLength];
669:                    attribs.getDistanceFilter(distanceArray, cutoffArray);
670:
671:                    if (debugFlag) {
672:                        debugPrint("distanceArray    cutoffArray");
673:                        for (int i = 0; i < arrayLength; i++)
674:                            debugPrint((float) distanceArray[i] + ", "
675:                                    + cutoffArray[i]);
676:                    }
677:
678:                    // Calculate angle from direction axis towards listener
679:                    float angle = findAngularOffset();
680:                    distanceFilter = findFactor((double) angle,
681:                            angularDistance, angularFilterCutoff);
682:                    if (distanceFilter < 0.0f)
683:                        distanceFilterFound = false;
684:                    else
685:                        distanceFilterFound = true;
686:                } else {
687:                    distanceFilterFound = false;
688:                    distanceFilter = -1.0f;
689:                }
690:
691:                if (debugFlag)
692:                    debugPrint("    calculateFilter arrayLength = "
693:                            + arrayLength);
694:
695:                // Angular filter of directional sound sources.
696:                arrayLength = angularDistance.length;
697:                filterType = angularFilterType;
698:                if ((filterType != AuralParameters.NO_FILTERING)
699:                        && arrayLength > 0) {
700:                    angularFilter = findFactor((double) distance,
701:                            angularDistance, angularFilterCutoff);
702:                    if (angularFilter < 0.0f)
703:                        angularFilterFound = false;
704:                    else
705:                        angularFilterFound = true;
706:                } else {
707:                    angularFilterFound = false;
708:                    angularFilter = -1.0f;
709:                }
710:
711:                filterFlag = distanceFilterFound || angularFilterFound;
712:                if (distanceFilter < 0.0f)
713:                    filterFreq = angularFilter;
714:                else if (angularFilter < 0.0f)
715:                    filterFreq = distanceFilter;
716:                else
717:                    // both filter frequencies are > 0
718:                    filterFreq = Math.min(distanceFilter, angularFilter);
719:
720:                if (debugFlag)
721:                    debugPrint("    calculateFilter flag,freq = " + filterFlag
722:                            + "," + filterFreq);
723:            }
724:
725:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.