1 /* 2 * Copyright (c) 2002-2008 LWJGL Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * * Neither the name of 'LWJGL' nor the names of 17 * its contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 package org.lwjgl.test.openal; 33 34 import java.nio.FloatBuffer; 35 import java.nio.IntBuffer; 36 37 import org.lwjgl.BufferUtils; 38 import org.lwjgl.LWJGLUtil; 39 import org.lwjgl.input.Keyboard; 40 import org.lwjgl.input.Mouse; 41 import org.lwjgl.openal.AL; 42 import org.lwjgl.opengl.Display; 43 import org.lwjgl.util.WaveData; 44 45 import static org.lwjgl.openal.AL10.*; 46 import static org.lwjgl.opengl.GL11.*; 47 import static org.lwjgl.util.glu.GLU.*; 48 49 /** 50 * <br> 51 * This test demonstrates OpenAL positioning Based on the example by Chad Armstrong 52 * (http://www.edenwaith.com/products/pige/tutorials/openal.php) 53 * 54 * @author Brian Matzon <brian@matzon.dk> 55 * @version $Revision$ 56 * $Id$ 57 */ 58 public class PositionTest extends BasicTest { 59 60 /** *Small* glut implementation :) */ 61 private GLUT glut; 62 63 /** Width of window */ 64 public static final int WINDOW_WIDTH = 640; 65 66 /** Height of window */ 67 public static final int WINDOW_HEIGHT = 480; 68 69 /** LEFT enumeration */ 70 public static final int LEFT = 0; 71 72 /** CENTER enumeration */ 73 public static final int CENTER = 1; 74 75 /** RIGHT enumeration */ 76 public static final int RIGHT = 2; 77 78 /** Whether the demo is done */ 79 private boolean finished; 80 81 /** Whether in pause mode */ 82 private boolean pauseMode; 83 84 // OpenAL stuff 85 // =================================================== 86 87 /** OpenAL buffers */ 88 private IntBuffer soundBuffers = BufferUtils.createIntBuffer(3); 89 90 /** OpenAL sources */ 91 private IntBuffer soundSources = BufferUtils.createIntBuffer(3); 92 93 /** Position of listener */ 94 private FloatBuffer listenerPosition = createFloatBuffer(new float[] { 0.0f, 0.0f, 0.0f }); 95 96 /** Velocity of listener */ 97 private FloatBuffer listenerVelocity = createFloatBuffer(new float[] { 0.0f, 0.0f, 0.0f }); 98 99 /** Orientation of listener */ 100 private FloatBuffer listenerOrientation = 101 createFloatBuffer(new float[] { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }); 102 103 /** Position of left sound */ 104 private FloatBuffer leftPosition = createFloatBuffer(new float[] { -2.0f, 0.0f, 0.0f }); 105 106 /** Velocity of left sound */ 107 private FloatBuffer leftVelocity = createFloatBuffer(new float[] { 0.0f, 0.0f, 0.0f }); 108 109 /** Position of center sound */ 110 private FloatBuffer centerPosition = createFloatBuffer(new float[] { 0.0f, 0.0f, -4.0f }); 111 112 /** Velocity of center sound */ 113 private FloatBuffer centerVelocity = createFloatBuffer(new float[] { 0.0f, 0.0f, 0.0f }); 114 115 /** Position of right sound */ 116 private FloatBuffer rightPosition = createFloatBuffer(new float[] { 2.0f, 0.0f, 0.0f }); 117 118 /** Velocity of right sound */ 119 private FloatBuffer rightVelocity = createFloatBuffer(new float[] { 0.0f, 0.0f, 0.0f }); 120 // --------------------------------------------------- 121 122 /** 123 * Runs the actual test, using supplied arguments 124 */ execute(String[] args)125 protected void execute(String[] args) { 126 // Setup needed stuff 127 try { 128 setup(); 129 } catch (Exception e) { 130 System.out.println("Error setting up demonstration: "); 131 e.printStackTrace(); 132 System.exit(-1); 133 } 134 135 // run the actual demonstration 136 run(); 137 138 // shutdown 139 shutdown(); 140 } 141 142 /** 143 * Performs setup of demonstration 144 */ setup()145 private void setup() throws Exception { 146 147 // Setup Window 148 // ===================================================== 149 LWJGLUtil.log("Setting up window"); 150 151 // calc center 152 int centerX = (Display.getDisplayMode().getWidth() - WINDOW_WIDTH) / 2; 153 int centerY = (Display.getDisplayMode().getHeight() - WINDOW_HEIGHT) / 2; 154 155 // setup window 156 setDisplayMode(); 157 Display.create(); 158 // ----------------------------------------------------- 159 160 // Setup OpenGL 161 // ===================================================== 162 LWJGLUtil.log("Setting up OpenGL"); 163 164 glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); 165 glMatrixMode(GL_PROJECTION); 166 glLoadIdentity(); 167 gluPerspective(50.0f, (float) WINDOW_WIDTH / WINDOW_HEIGHT, 0.0f, 50.0f); 168 glMatrixMode(GL_MODELVIEW); 169 glLoadIdentity(); 170 glTranslatef(0.0f, 0.0f, -6.6f); 171 glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 172 glut = this.new GLUT(); 173 174 Display.setVSyncEnabled(true); 175 // ----------------------------------------------------- 176 177 // Setup OpenAL 178 // ===================================================== 179 LWJGLUtil.log("Setting up OpenAL"); 180 181 alListener(AL_POSITION, listenerPosition); 182 alListener(AL_VELOCITY, listenerVelocity); 183 alListener(AL_ORIENTATION, listenerOrientation); 184 185 // creating buffers 186 LWJGLUtil.log("Creating buffers"); 187 alGenBuffers(soundBuffers); 188 soundBuffers.rewind(); 189 190 // creating sources 191 alGenSources(soundSources); 192 soundSources.rewind(); 193 194 // load sound files (left, center, right).wav 195 LWJGLUtil.log("Loading soundfiles..."); 196 197 LWJGLUtil.log("Loading left.wav"); 198 WaveData left = WaveData.create("left.wav"); 199 alBufferData(soundBuffers.get(LEFT), left.format, left.data, left.samplerate); 200 alSourcef(soundSources.get(LEFT), AL_PITCH, 1.0f); 201 alSourcef(soundSources.get(LEFT), AL_GAIN, 1.0f); 202 alSource(soundSources.get(LEFT), AL_POSITION, leftPosition); 203 alSource(soundSources.get(LEFT), AL_VELOCITY, leftVelocity); 204 alSourcei(soundSources.get(LEFT), AL_BUFFER, soundBuffers.get(LEFT)); 205 alSourcei(soundSources.get(LEFT), AL_LOOPING, AL_TRUE); 206 207 LWJGLUtil.log("Loading center.wav"); 208 WaveData center = WaveData.create("center.wav"); 209 alBufferData(soundBuffers.get(CENTER), center.format, center.data, center.samplerate); 210 alSourcef(soundSources.get(CENTER), AL_PITCH, 1.0f); 211 alSourcef(soundSources.get(CENTER), AL_GAIN, 1.0f); 212 alSource(soundSources.get(CENTER), AL_POSITION, centerPosition); 213 alSource(soundSources.get(CENTER), AL_VELOCITY, centerVelocity); 214 alSourcei(soundSources.get(CENTER), AL_BUFFER, soundBuffers.get(CENTER)); 215 alSourcei(soundSources.get(CENTER), AL_LOOPING, AL_TRUE); 216 217 LWJGLUtil.log("Loading right.wav"); 218 WaveData right = WaveData.create("right.wav"); 219 alBufferData(soundBuffers.get(RIGHT), right.format, right.data, right.samplerate); 220 alSourcef(soundSources.get(RIGHT), AL_PITCH, 1.0f); 221 alSourcef(soundSources.get(RIGHT), AL_GAIN, 1.0f); 222 alSource(soundSources.get(RIGHT), AL_POSITION, rightPosition); 223 alSource(soundSources.get(RIGHT), AL_VELOCITY, rightVelocity); 224 alSourcei(soundSources.get(RIGHT), AL_BUFFER, soundBuffers.get(RIGHT)); 225 alSourcei(soundSources.get(RIGHT), AL_LOOPING, AL_TRUE); 226 227 LWJGLUtil.log("Soundfiles loaded successfully"); 228 // ----------------------------------------------------- 229 230 Mouse.setGrabbed(true); 231 } 232 233 /** 234 * Runs the actual demonstration 235 */ run()236 private void run() { 237 boolean firstRun = true; 238 239 System.out.println("Press 1/4 (left), 2/5 (center) or 3/6 (right) to toggle sound"); 240 System.out.println("Press LEFT/RIGHT to move along x axis"); 241 System.out.println("Press SHIFT and either UP/DOWN to move along y axis"); 242 System.out.println("Press UP/DOWN to move along z axis"); 243 System.out.println("Move along the x and y axis with the mouse"); 244 System.out.println("Press LEFT or RIGHT mouse button to move along z axis"); 245 System.out.println("Press ESC to exit demo"); 246 247 LWJGLUtil.log( 248 "Listener position: " 249 + listenerPosition.get(0) 250 + ", " 251 + listenerPosition.get(1) 252 + ", " 253 + listenerPosition.get(2)); 254 LWJGLUtil.log("Left position: " + leftPosition.get(0) + ", " + leftPosition.get(1) + ", " + leftPosition.get(2)); 255 LWJGLUtil.log("Center position: " + centerPosition.get(0) + ", " + centerPosition.get(1) + ", " + centerPosition.get(2)); 256 LWJGLUtil.log("Right position: " + rightPosition.get(0) + ", " + rightPosition.get(1) + ", " + rightPosition.get(2)); 257 258 while (!finished) { 259 // handle any input 260 handleInput(); 261 262 // allow window to process internal messages 263 Display.update(); 264 265 // render and paint if !minimized and not dirty 266 if(Display.isVisible()) { 267 render(); 268 } else { 269 // sleeeeeep 270 pause(100); 271 } 272 273 // act on pause mode 274 paused(!(Display.isVisible() || Display.isActive())); 275 276 // start sound after first paint, since we don't want 277 // the delay before something is painted on the screen 278 if (firstRun && !pauseMode) { 279 firstRun = false; 280 281 // start sounds with delays 282 startSounds(); 283 } 284 } 285 } 286 287 /** 288 * Starts playing the sounds at different times 289 */ startSounds()290 private void startSounds() { 291 alSourcePlay(soundSources.get(LEFT)); 292 pause(300); 293 alSourcePlay(soundSources.get(CENTER)); 294 pause(500); 295 alSourcePlay(soundSources.get(RIGHT)); 296 } 297 298 /** 299 * Handles any changes in pause mode 300 * 301 * @param paused Which pause mode to enter 302 */ paused(boolean paused)303 private void paused(boolean paused) { 304 // if requesting pause, and not paused - pause and stop sound 305 if(paused && !pauseMode) { 306 pauseMode = true; 307 alSourcePause(soundSources); 308 System.out.println("pauseMode = true"); 309 } 310 311 // else go out of pause mode and start sounds 312 else if(!paused && pauseMode) { 313 pauseMode = false; 314 startSounds(); 315 System.out.println("pauseMode = false"); 316 } 317 } 318 319 /** 320 * Handles any input 321 */ handleInput()322 private void handleInput() { 323 // User wants to exit? 324 finished = Display.isCloseRequested() || Keyboard.isKeyDown(Keyboard.KEY_ESCAPE); 325 if (finished) { 326 return; 327 } 328 329 boolean shift = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT); 330 331 // Test for play 332 // ============================================ 333 if (Keyboard.isKeyDown(Keyboard.KEY_1)) { 334 alSourcePlay(soundSources.get(LEFT)); 335 LWJGLUtil.log("Playing left.wav"); 336 } 337 338 if (Keyboard.isKeyDown(Keyboard.KEY_2)) { 339 alSourcePlay(soundSources.get(CENTER)); 340 LWJGLUtil.log("Playing center.wav"); 341 } 342 343 if (Keyboard.isKeyDown(Keyboard.KEY_3)) { 344 alSourcePlay(soundSources.get(RIGHT)); 345 LWJGLUtil.log("Playing right.wav"); 346 } 347 // -------------------------------------------- 348 349 // Test for stop 350 // ============================================ 351 if (Keyboard.isKeyDown(Keyboard.KEY_4)) { 352 alSourceStop(soundSources.get(LEFT)); 353 LWJGLUtil.log("Stopped left.wav"); 354 } 355 356 if (Keyboard.isKeyDown(Keyboard.KEY_5)) { 357 alSourceStop(soundSources.get(CENTER)); 358 LWJGLUtil.log("Stopped center.wav"); 359 } 360 361 if (Keyboard.isKeyDown(Keyboard.KEY_6)) { 362 alSourceStop(soundSources.get(RIGHT)); 363 LWJGLUtil.log("Stopped right.wav"); 364 } 365 // -------------------------------------------- 366 367 // Test for movement with keyboard 368 // ============================================ 369 if (Keyboard.isKeyDown(Keyboard.KEY_LEFT)) { 370 listenerPosition.put(0, listenerPosition.get(0) - 0.1f); 371 alListener(AL_POSITION, listenerPosition); 372 } 373 374 if (Keyboard.isKeyDown(Keyboard.KEY_RIGHT)) { 375 listenerPosition.put(0, listenerPosition.get(0) + 0.1f); 376 alListener(AL_POSITION, listenerPosition); 377 } 378 379 if (Keyboard.isKeyDown(Keyboard.KEY_UP)) { 380 if (shift) { 381 listenerPosition.put(1, listenerPosition.get(1) + 0.1f); 382 } else { 383 listenerPosition.put(2, listenerPosition.get(2) - 0.1f); 384 } 385 alListener(AL_POSITION, listenerPosition); 386 } 387 388 if (Keyboard.isKeyDown(Keyboard.KEY_DOWN)) { 389 if (shift) { 390 listenerPosition.put(1, listenerPosition.get(1) - 0.1f); 391 } else { 392 listenerPosition.put(2, listenerPosition.get(2) + 0.1f); 393 } 394 alListener(AL_POSITION, listenerPosition); 395 } 396 // -------------------------------------------- 397 398 // Test for movement with Mouse 399 // ============================================ 400 listenerPosition.put(0, listenerPosition.get(0) + (0.01f * Mouse.getDX())); 401 listenerPosition.put(1, listenerPosition.get(1) + (0.01f * Mouse.getDY())); 402 if (Mouse.isButtonDown(0)) { 403 listenerPosition.put(2, listenerPosition.get(2) - 0.1f); 404 } 405 if (Mouse.isButtonDown(1)) { 406 listenerPosition.put(2, listenerPosition.get(2) + 0.1f); 407 } 408 409 alListener(AL_POSITION, listenerPosition); 410 411 // empty mouse buffer 412 while(Mouse.next()); 413 } 414 415 /** 416 * Render the scene 417 */ render()418 private void render() { 419 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 420 glPushMatrix(); 421 { 422 glRotatef(20.0f, 1.0f, 1.0f, 0.0f); 423 424 // left 425 glPushMatrix(); 426 { 427 glTranslatef(leftPosition.get(0), leftPosition.get(1), leftPosition.get(2)); 428 glColor3f(1.0f, 0.0f, 0.0f); 429 glut.glutWireCube(0.5f); 430 } 431 glPopMatrix(); 432 433 // center 434 glPushMatrix(); 435 { 436 glTranslatef(centerPosition.get(0), centerPosition.get(1), centerPosition.get(2)); 437 glColor3f(0.0f, 0.0f, 1.0f); 438 glut.glutWireCube(0.5f); 439 } 440 glPopMatrix(); 441 442 // right 443 glPushMatrix(); 444 { 445 glTranslatef(rightPosition.get(0), rightPosition.get(1), rightPosition.get(2)); 446 glColor3f(0.0f, 1.0f, 0.0f); 447 glut.glutWireCube(0.5f); 448 } 449 glPopMatrix(); 450 451 // listener 452 glPushMatrix(); 453 { 454 glTranslatef(listenerPosition.get(0), listenerPosition.get(1), listenerPosition.get(2)); 455 glColor3f(1.0f, 1.0f, 1.0f); 456 glut.glutSolidCube(0.5f); 457 } 458 glPopMatrix(); 459 } 460 glPopMatrix(); 461 } 462 463 /** 464 * Shutdown of demonstration 465 */ shutdown()466 private void shutdown() { 467 LWJGLUtil.log("Shutting down OpenAL"); 468 alSourceStop(soundSources); 469 alDeleteSources(soundSources); 470 alDeleteBuffers(soundBuffers); 471 AL.destroy(); 472 473 LWJGLUtil.log("Shutting down Window"); 474 Display.destroy(); 475 } 476 477 /** 478 * main entry point 479 * 480 * @param args 481 * String array containing arguments 482 */ main(String[] args)483 public static void main(String[] args) { 484 PositionTest positionTest = new PositionTest(); 485 positionTest.execute(args); 486 System.exit(0); 487 } 488 489 /** 490 * Minute implementation of GLUT: <br>COPYRIGHT: 491 * 492 * The OpenGL Utility Toolkit distribution for Win32 (Windows NT & Windows 493 * 95) contains source code modified from the original source code for GLUT 494 * version 3.3 which was developed by Mark J. Kilgard. The original source 495 * code for GLUT is Copyright 1997 by Mark J. Kilgard. GLUT for Win32 is 496 * Copyright 1997 by Nate Robins and is not in the public domain, but it is 497 * freely distributable without licensing fees. It is provided without 498 * guarantee or warrantee expressed or implied. It was ported with the 499 * permission of Mark J. Kilgard by Nate Robins. 500 * 501 * THIS SOURCE CODE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER 502 * EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 503 * OR MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. 504 */ 505 class GLUT { 506 507 float n[][] = new float[][] { { -1.0f, 0.0f, 0.0f }, { 508 0.0f, 1.0f, 0.0f }, { 509 1.0f, 0.0f, 0.0f }, { 510 0.0f, -1.0f, 0.0f }, { 511 0.0f, 0.0f, 1.0f }, { 512 0.0f, 0.0f, -1.0f } 513 }; 514 515 int faces[][] = new int[][] { { 0, 1, 2, 3 }, { 516 3, 2, 6, 7 }, { 517 7, 6, 5, 4 }, { 518 4, 5, 1, 0 }, { 519 5, 6, 2, 1 }, { 520 7, 4, 0, 3 } 521 }; 522 float v[][] = new float[8][3]; 523 glutWireCube(float size)524 public void glutWireCube(float size) { 525 drawBox(size, GL_LINE_LOOP); 526 } 527 glutSolidCube(float size)528 public void glutSolidCube(float size) { 529 drawBox(size, GL_QUADS); 530 } 531 drawBox(float size, int type)532 private void drawBox(float size, int type) { 533 534 v[0][0] = v[1][0] = v[2][0] = v[3][0] = -size / 2; 535 v[4][0] = v[5][0] = v[6][0] = v[7][0] = size / 2; 536 v[0][1] = v[1][1] = v[4][1] = v[5][1] = -size / 2; 537 v[2][1] = v[3][1] = v[6][1] = v[7][1] = size / 2; 538 v[0][2] = v[3][2] = v[4][2] = v[7][2] = -size / 2; 539 v[1][2] = v[2][2] = v[5][2] = v[6][2] = size / 2; 540 541 for (int i = 5; i >= 0; i--) { 542 glBegin(type); 543 glNormal3f(n[i][0], n[i][1], n[i][2]); 544 glVertex3f(v[faces[i][0]][0], v[faces[i][0]][1], v[faces[i][0]][2]); 545 glVertex3f(v[faces[i][1]][0], v[faces[i][1]][1], v[faces[i][1]][2]); 546 glVertex3f(v[faces[i][2]][0], v[faces[i][2]][1], v[faces[i][2]][2]); 547 glVertex3f(v[faces[i][3]][0], v[faces[i][3]][1], v[faces[i][3]][2]); 548 glEnd(); 549 } 550 551 } 552 } 553 } 554