// sample code for 10/7/04 lecture, simplified version of the demo from OpenAL distribution // OpenALDemo.cpp : Defines the entry point for the console application. // #include #include #include #include "al.h" #include "alc.h" #include "alut.h" #include #include #include #define PI 3.141592654 #define NUM_BUFFERS 7 // Number of buffers to be Generated // Global variables ALuint g_Buffers[NUM_BUFFERS]; // Array of Buffer IDs // Function prototypes ALvoid DisplayALError(ALubyte *szText, ALint errorCode); // Test Function prototypes ALvoid PositionTest(ALvoid); ALvoid LoopingTest(ALvoid); ALvoid FreqTest(ALvoid); ALvoid StereoTest(ALvoid); ALvoid GainTest(ALvoid); ALvoid RelativeTest(ALvoid); ALvoid MultipleSourcesTest(ALvoid); ALvoid SourceRollOffTest(ALvoid); /* Display AL Error message */ /* In this sample code most error checking from the original openal demo was removed to make it easier to read; however in real code it is best to insert error-checking code for debugging; see example below for loading files */ ALvoid DisplayALError(ALbyte *szText, ALint errorcode) { printf("%s%s", szText, alGetString(errorcode)); } /* Main application - Initializes Open AL, Sets up Listener, Generates Buffers, and loads in audio data. Displays Test Menu and calls appropriate Test functions. On exit, buffers are destroyed and Open AL is shutdown. Each Test function is responsible for creating and destroying whatever Sources they require. All test applications use the same set of Buffers (created in this function). */ int main(int argc, char* argv[]) { ALint error; ALCcontext *Context; ALCdevice *Device; ALfloat listenerPos[]={0.0,0.0,0.0}; ALfloat listenerVel[]={0.0,0.0,0.0}; ALfloat listenerOri[]={0.0,0.0,-1.0, 0.0,1.0,0.0}; // Listener facing into the screen printf("OpenAL Test application\n\n"); // Initialize Open AL manually //Open device Device = alcOpenDevice(NULL); // this is supposed to select the "preferred device" //Create context(s) Context=alcCreateContext(Device,NULL); //Set active context alcMakeContextCurrent(Context); // Set Listener attributes alListenerfv(AL_POSITION,listenerPos); // Position ... alListenerfv(AL_VELOCITY,listenerVel); // Velocity ... alListenerfv(AL_ORIENTATION,listenerOri); // Orientation ... alGenBuffers(NUM_BUFFERS, g_Buffers); // Generate Buffers // Load in samples to be used by Test functions ALbyte* WaveNames[] = { "footsteps.wav", "ding.wav", "wave1.wav", "wave2.wav", "wave3.wav", "wave4.wav", "stereo.wav" }; for( int which_wave = 0; which_wave < sizeof(WaveNames)/sizeof(ALbyte*); ++which_wave ) { ALsizei size,freq; ALenum format; ALvoid *data; ALboolean loop; // Load WaveNames[which_wave] alutLoadWAVFile(WaveNames[which_wave],&format,&data,&size,&freq,&loop); // an example of error checking if ((error = alGetError()) != AL_NO_ERROR) { DisplayALError("alutLoadWAVFile : ", error); // Delete Buffers alDeleteBuffers(NUM_BUFFERS, g_Buffers); exit(-1); } // Copy WaveNames[which_wave] data into AL Buffer which_wave alBufferData(g_Buffers[which_wave],format,data,size,freq); // Unload WaveNames[which_wave] alutUnloadWAV(format,data,size,freq); } ALbyte ch ; do { printf("\nSelect a test from the following options\n\n"); printf("1 Position Test\n"); printf("2 Looping Test\n"); printf("3 Frequency Test\n"); printf("4 Stereo Test\n"); printf("5 Gain Test\n"); printf("6 Source Relative Test\n"); printf("7 Multiple Sources Test\n"); printf("8 Source Roll-off Test\n"); printf("Q to quit\n\n\n"); ch = _getch(); ch = toupper( ch ); switch (ch) { case '1': PositionTest(); break; case '2': LoopingTest(); break; case '3': FreqTest(); break; case '4': StereoTest(); break; case '5': GainTest(); break; case '6': RelativeTest(); break; case '7': MultipleSourcesTest(); break; case '8': SourceRollOffTest(); break; default: break; } } while (ch != 'Q'); // Quitting, let's cleanup alDeleteBuffers(NUM_BUFFERS, g_Buffers); //Get active context Context=alcGetCurrentContext(); //Get device for active context Device=alcGetContextsDevice(Context); //Disable context alcMakeContextCurrent(NULL); //Release context(s) alcDestroyContext(Context); //Close device alcCloseDevice(Device); return 0; } /* Position Test Creates 2 Sources - one to the front right of the listener, and one to the rear left of the listener */ ALvoid PositionTest(ALvoid) { ALint error; ALuint source[2]; ALbyte ch; ALfloat source0Pos[]={ -2.0, 0.0, 2.0}; // Behind and to the left of the listener ALfloat source0Vel[]={ 0.0, 0.0, 0.0}; ALfloat source1Pos[]={ 2.0, 0.0, -2.0}; // Front and to the right of the listener ALfloat source1Vel[]={ 0.0, 0.0, 0.0}; alGenSources(2,source); alSourcef(source[0],AL_PITCH,1.0f); alSourcef(source[0],AL_GAIN,1.0f); alSourcefv(source[0],AL_POSITION,source0Pos); alSourcefv(source[0],AL_VELOCITY,source0Vel); alSourcei(source[0],AL_BUFFER, g_Buffers[1]); alSourcei(source[0],AL_LOOPING,AL_TRUE); alSourcef(source[1],AL_PITCH,1.0f); alSourcef(source[1],AL_GAIN,1.0f); alSourcefv(source[1],AL_POSITION,source1Pos); alSourcefv(source[1],AL_VELOCITY,source1Vel); alSourcei(source[1],AL_BUFFER, g_Buffers[1]); alSourcei(source[1],AL_LOOPING,AL_FALSE); printf("Position Test\n"); printf("Press '1' to play source 0 rear left of listener\n"); printf("Press '2' to play source 1 once (single shot) front right of listener\n"); printf("Press '3' to stop source 0\n"); printf("Press '4' to stop source 1\n"); printf("Press '5' to set Source 0 Reference Distance to 2\n"); printf("Press '6' to set Source 0 Reference Distance to 1\n"); printf("Press 'q' to quit\n"); do { ch = _getch(); ch = toupper( ch ); switch (ch) { case '1': alSourcePlay(source[0]); break; case '2': alSourcePlay(source[1]); break; case '3': alSourceStop(source[0]); break; case '4': alSourceStop(source[1]); break; case '5': alSourcef(source[0], AL_REFERENCE_DISTANCE, 2.0f); break; case '6': alSourcef(source[0], AL_REFERENCE_DISTANCE, 1.0f); break; } } while (ch != 'Q'); // Release resources alSourceStopv(2, source); alDeleteSources(2, source); return; } /* Looping Test Tests the ability to switch Looping ON and OFF for a particular source, either before or during Playback. (If looping is switched off during playback, the buffer should finish playing until the end of the sample.) */ ALvoid LoopingTest(ALvoid) { ALint error; ALuint source[2]; ALbyte ch; ALboolean bLooping0 = AL_FALSE; ALboolean bLooping1 = AL_FALSE; ALfloat source0Pos[]={ 2.0, 0.0, 2.0}; // Front left of the listener ALfloat source0Vel[]={ 0.0, 0.0, 0.0}; ALfloat source1Pos[]={ 2.0, 0,0, -2.0}; // Front right of the listener ALfloat source1Vel[]={ 0.0, 0.0, 0,0}; alGenSources(2,source); alSourcef(source[0],AL_PITCH,1.0f); alSourcef(source[0],AL_GAIN,1.0f); alSourcefv(source[0],AL_POSITION,source0Pos); alSourcefv(source[0],AL_VELOCITY,source0Vel); alSourcei(source[0],AL_BUFFER, g_Buffers[0]); alSourcei(source[0],AL_LOOPING,AL_FALSE); alSourcef(source[1],AL_PITCH,1.0f); alSourcef(source[1],AL_GAIN,1.0f); alSourcefv(source[1],AL_POSITION,source1Pos); alSourcefv(source[1],AL_VELOCITY,source1Vel); alSourcei(source[1],AL_BUFFER, g_Buffers[1]); alSourcei(source[1],AL_LOOPING,AL_FALSE); printf("Looping Test\n"); printf("Press '1' to play source 0 once (single shot)\n"); printf("Press '2' to toggle looping on source 0\n"); printf("Press '3' to play source 1 once (single shot)\n"); printf("Press '4' to toggle looping on source 1\n"); printf("Press 'q' to quit\n"); printf("\nSource 0 : Not looping Source 1 : Not looping\r"); do { ch = _getch(); ch = toupper( ch ); switch (ch) { case '1': alSourcePlay(source[0]); break; case '2': if (bLooping0 == AL_FALSE) { bLooping0 = AL_TRUE; if (bLooping1) printf("Source 0 : Looping Source 1 : Looping \r"); else printf("Source 0 : Looping Source 1 : Not looping\r"); } else { bLooping0 = AL_FALSE; if (bLooping1) printf("Source 0 : Not looping Source 1 : Looping \r"); else printf("Source 0 : Not looping Source 1 : Not looping\r"); } alSourcei(source[0], AL_LOOPING, bLooping0); break; case '3': alSourcePlay(source[1]); break; case '4': if (bLooping1 == AL_FALSE) { bLooping1 = AL_TRUE; if (bLooping0) printf("Source 0 : Looping Source 1 : Looping \r"); else printf("Source 0 : Not looping Source 1 : Looping \r"); } else { bLooping1 = AL_FALSE; if (bLooping0) printf("Source 0 : Looping Source 1 : Not looping\r"); else printf("Source 0 : Not looping Source 1 : Not looping\r"); } alSourcei(source[1], AL_LOOPING, bLooping1); break; } } while (ch != 'Q'); printf("\n"); // Release resources alSourceStop(source[0]); alDeleteSources(2, source); return; } /* FreqTest Test AL_PITCH functionality */ ALvoid FreqTest(ALvoid) { ALint error; ALuint source[1]; ALbyte ch; ALfloat source0Pos[]={ 2.0, 0.0,-2.0}; // Front and right of the listener ALfloat source0Vel[]={ 0.0, 0.0, 0.0}; alGenSources(1,source); alSourcef(source[0],AL_PITCH,1.0f); alSourcef(source[0],AL_GAIN,1.0f); alSourcefv(source[0],AL_POSITION,source0Pos); alSourcefv(source[0],AL_VELOCITY,source0Vel); alSourcei(source[0],AL_BUFFER, g_Buffers[1]); alSourcei(source[0],AL_LOOPING,AL_TRUE); printf("Frequency Test\n"); printf("Press '1' to play source 0 (looping)\n"); printf("Press '2' to Double Frequency\n"); printf("Press '3' to Halve Frequency\n"); printf("Press 'q' to quit\n"); do { ch = _getch(); ch = toupper( ch ); switch (ch) { case '1': alSourcePlay(source[0]); break; case '2': alSourcef(source[0], AL_PITCH, 2.0f); break; case '3': alSourcef(source[0], AL_PITCH, 0.5f); break; } } while (ch != 'Q'); // Release resources alSourceStopv(1, source); alDeleteSources(1, source); return; } /* Stereo Test Plays a stereo buffer */ ALvoid StereoTest(ALvoid) { ALint error; ALuint source[1]; ALuint buffers[2]; ALuint Buffer; ALint BuffersInQueue, BuffersProcessed; ALbyte ch; ALboolean bLoop = true; ALfloat source0Pos[]={ 2.0, 0.0,-2.0}; // Front and right of the listener ALfloat source0Vel[]={ 0.0, 0.0, 0.0}; alGenSources(1,source); buffers[0] = g_Buffers[6]; buffers[1] = g_Buffers[6]; printf("Stereo Test\n"); printf("Press '1' to play a stereo buffer on source 0 (looping)\n"); printf("Press '2' to play a mono buffer on source 0 (looping)\n"); printf("Press '3' to stop source 0\n"); printf("Press '4' to queue 2 stereo buffers on source 0 and start playing\n"); printf("Press '5' to unqueue the 2 stereo buffers on source 0\n"); printf("Press '6' to toggle looping on / off\n"); printf("Press '0' to display stats\n"); printf("Press 'q' to quit\n"); printf("Looping is on\r"); do { ch = _getch(); ch = toupper( ch ); switch (ch) { case '1': // Stop source alSourceStop(source[0]); // Attach new buffer alSourcei(source[0],AL_BUFFER, g_Buffers[6]); // Set volume alSourcef(source[0],AL_GAIN,0.5f); // Set looping alSourcei(source[0],AL_LOOPING,bLoop); // Play source alSourcePlay(source[0]); break; case '2': // Stop source alSourceStop(source[0]); // Attach new buffer alSourcei(source[0],AL_BUFFER, g_Buffers[0]); // Set 3D position alSourcefv(source[0],AL_POSITION,source0Pos); // Set 3D velocity alSourcefv(source[0],AL_VELOCITY,source0Vel); // Set volume to full alSourcef(source[0],AL_GAIN,1.0f); // Set Looping alSourcei(source[0],AL_LOOPING,bLoop); // Play source alSourcePlay(source[0]); break; case '3': // Stop source alSourceStop(source[0]); break; case '4': // Stop source alSourceStop(source[0]); // Attach NULL buffer to source to clear everything alSourcei(source[0], AL_BUFFER, 0); // Queue two buffers alSourceQueueBuffers(source[0], 2, buffers); // Set Looping alSourcei(source[0],AL_LOOPING,bLoop); // Play source alSourcePlay(source[0]); break; case '5': alSourceUnqueueBuffers(source[0], 2, buffers); break; case '6': if (bLoop) { printf("Looping is off\r"); bLoop = AL_FALSE; } else { printf("Looping is on \r"); bLoop = AL_TRUE; } alSourcei(source[0], AL_LOOPING, bLoop); break; case '0': // Retrieve number of buffers in queue alGetSourcei(source[0], AL_BUFFERS_QUEUED, &BuffersInQueue); // Retrieve number of processed buffers alGetSourcei(source[0], AL_BUFFERS_PROCESSED, &BuffersProcessed); // Retrieve current buffer alGetSourcei(source[0], AL_BUFFER, (ALint*)&Buffer); if (Buffer == buffers[0]) Buffer = 6; else if (Buffer == buffers[1]) Buffer = 6; else Buffer = 0; printf("Current Buffer is %d, %d Buffers in queue, %d Processed\r", Buffer, BuffersInQueue, BuffersProcessed); break; } } while (ch != 'Q'); // Release resources alSourceStop(source[0]); alDeleteSources(1, source); return; } /* GainTest Play 2 Sources - control gain of each, and control Listener Gain */ ALvoid GainTest(ALvoid) { ALint error; ALuint source[2]; ALbyte ch; ALfloat source0Pos[]={ 2.0, 0.0,-2.0}; // Front and right of the listener ALfloat source0Vel[]={ 0.0, 0.0, 0.0}; ALfloat source1Pos[]={-2.0, 0.0,-2.0}; ALfloat source1Vel[]={ 0.0, 0.0, 0.0}; alGenSources(2,source); alSourcef(source[0],AL_PITCH,1.0f); alSourcef(source[0],AL_GAIN,1.0f); alSourcefv(source[0],AL_POSITION,source0Pos); alSourcefv(source[0],AL_VELOCITY,source0Vel); alSourcei(source[0],AL_BUFFER, g_Buffers[0]); alSourcei(source[0],AL_LOOPING,AL_TRUE); alSourcef(source[1],AL_PITCH,1.0f); alSourcef(source[1],AL_GAIN,1.0f); alSourcefv(source[1],AL_POSITION,source1Pos); alSourcefv(source[1],AL_VELOCITY,source1Vel); alSourcei(source[1],AL_BUFFER, g_Buffers[1]); alSourcei(source[1],AL_LOOPING,AL_TRUE); printf("Gain Test\n"); printf("Press '1' to play source 0 (looping)\n"); printf("Press '2' to play source 1 (looping)\n"); printf("Press '3' to stop source 0\n"); printf("Press '4' to stop source 1\n"); printf("Press '5' to set source 0 gain to 1.0\n"); printf("Press '6' to set source 0 gain to 0.5\n"); printf("Press '7' to set source 0 gain to 0.25\n"); printf("Press '8' to set source 0 gain to 0\n"); printf("Press 'a' to set Listener Gain to 1.0\n"); printf("Press 'b' to set Listener Gain to 0.5\n"); printf("Press 'c' to set Listener Gain to 0.25\n"); printf("Press 'd' to set Listener Gain to 0.0\n"); printf("Press 'q' to quit\n"); do { ch = _getch(); ch = toupper( ch ); switch (ch) { case '1': alSourcePlay(source[0]); break; case '2': alSourcePlay(source[1]); break; case '3': alSourceStop(source[0]); break; case '4': alSourceStop(source[1]); break; case '5': alSourcef(source[0],AL_GAIN,1.0f); break; case '6': alSourcef(source[0],AL_GAIN,0.5f); break; case '7': alSourcef(source[0],AL_GAIN,0.25f); break; case '8': alSourcef(source[0],AL_GAIN,0.0f); break; case 'A': alListenerf(AL_GAIN,1.0f); break; case 'B': alListenerf(AL_GAIN,0.5f); break; case 'C': alListenerf(AL_GAIN,0.25f); break; case 'D': alListenerf(AL_GAIN,0.0f); break; } } while (ch != 'Q'); // Release resources alSourceStopv(2,source); alDeleteSources(2, source); return; } ALvoid RelativeTest(ALvoid) { ALint error; ALuint source[1]; ALbyte ch; ALboolean bRelative = AL_FALSE; ALfloat Pos[3]; ALfloat LPos[3]; ALfloat Vel[]={ 0.0, 0.0, 0.0}; alGenSources(1, source); alSourcef(source[0],AL_PITCH,1.0f); alSourcef(source[0],AL_GAIN,1.0f); alSourcefv(source[0],AL_VELOCITY, Vel); alSourcei(source[0],AL_BUFFER, g_Buffers[1]); alSourcei(source[0],AL_LOOPING,AL_TRUE); alSourcei(source[0], AL_SOURCE_RELATIVE, AL_FALSE); printf("Source Relative Test\n"); printf("Press '1' to play source 0 at 1, 0, 0\n"); printf("Press '2' to move listener to 2, 0, 0\n"); printf("Press '3' to toggle SOURCE RELATIVE Mode\n"); printf("Press 'q' to quit\n"); do { ch = _getch(); ch = toupper( ch ); switch (ch) { case '1': Pos[0] = 1.f; Pos[1] = 0.f; Pos[2] = 0.f; alSourcefv(source[0],AL_POSITION,Pos); alSourcePlay(source[0]); break; case '2': LPos[0] = 2.f; LPos[1] = 0.0f; LPos[2] = 0.0f; alListenerfv(AL_POSITION, LPos); break; case '3': if (bRelative) { printf("Source Relative == FALSE\r"); alSourcei(source[0], AL_SOURCE_RELATIVE, AL_FALSE); bRelative = AL_FALSE; } else { alSourcei(source[0], AL_SOURCE_RELATIVE, AL_TRUE); printf("Source Relative == TRUE \r"); bRelative = AL_TRUE; } } } while (ch != 'Q'); // Release resources alSourceStopv(1, source); alDeleteSources(1, source); return; } ALvoid MultipleSourcesTest() { ALuint numSources = 0; ALuint Sources[64] = { 0 }; ALuint SourceStopped[64] = { 0 }; ALint error; ALuint i; char ch; ALfloat radius; double anglestep; ALfloat pos[3]; // Generate as many sources as possible (up to 64) for (i = 0; i < 64; i++) { alGenSources(1, &Sources[i]); if ((error = alGetError()) != AL_NO_ERROR) break; else numSources++; } printf("Multiple Sources Test\n\n"); printf("Generated %d Sources\n", numSources); // Set sources to located in a circle around the listener anglestep = (2 * PI) / (ALfloat)numSources; radius = 2.0f; for (i = 0; i < numSources; i++) { // Attach buffer alSourcei(Sources[i], AL_BUFFER, g_Buffers[0]); // Set position pos[0] = (float)(cos(anglestep*i) * radius); pos[1] = 0.0f; pos[2] = (float)(sin(anglestep*i) * radius); alSourcefv(Sources[i], AL_POSITION, pos); // Enable looping alSourcei(Sources[i], AL_LOOPING, AL_TRUE); } printf("Press '1' to start playing Sources seperately\n"); printf("Press '2' to stop playing Sources seperately\n"); printf("Press 'q' to quit\n"); do { ch = _getch(); ch = toupper( ch ); switch (ch) { case '1': for (i = 0; i < numSources; i++) { alSourcePlay(Sources[i]); // Delay a little Sleep(100); } break; case '2': alSourceStopv(numSources, Sources); break; } } while (ch != 'Q'); // Delete the Sources alDeleteSources(numSources, Sources); } ALvoid SourceRollOffTest() { ALint error; ALuint source[2]; ALbyte ch; ALfloat source0Pos[]={ -10.0, 0.0, 10.0}; // Behind and to the left of the listener ALfloat source1Pos[]={ 10.0, 0.0, -10.0}; // Front and to the right of the listener alGenSources(2,source); if ((error = alGetError()) != AL_NO_ERROR) { DisplayALError("alGenSources 2 : ", error); return; } alSourcefv(source[0],AL_POSITION,source0Pos); alSourcei(source[0],AL_BUFFER, g_Buffers[1]); alSourcei(source[0],AL_LOOPING,AL_TRUE); alSourcefv(source[1],AL_POSITION,source1Pos); alSourcei(source[1],AL_BUFFER, g_Buffers[1]); alSourcei(source[1],AL_LOOPING,AL_TRUE); printf("Source Roll-off Test\n"); printf("Press '1' to play source 0 rear left of listener\n"); printf("Press '2' to stop source 0\n"); printf("Press '3' to play source 1 front right of listener\n"); printf("Press '4' to stop source 1\n"); printf("Press '5' to set Source 0 Roff-off Factor to 0.5\n"); printf("Press '6' to set Source 0 Roll-off Factor to 1.0\n"); printf("Press '7' to set Source 0 Roll-off Factor to 2.0\n"); printf("Press '8' to set Source 1 Roff-off Factor to 0.5\n"); printf("Press '9' to set Source 1 Roll-off Factor to 1.0\n"); printf("Press 'A' to set Source 1 Roll-off Factor to 2.0\n"); printf("Press 'q' to quit\n"); do { ch = _getch(); ch = toupper( ch ); switch (ch) { case '1': alSourcePlay(source[0]); break; case '2': alSourceStop(source[0]); break; case '3': alSourcePlay(source[1]); break; case '4': alSourceStop(source[1]); break; case '5': alSourcef(source[0], AL_ROLLOFF_FACTOR, 0.5f); break; case '6': alSourcef(source[0], AL_ROLLOFF_FACTOR, 1.0f); break; case '7': alSourcef(source[0], AL_ROLLOFF_FACTOR, 2.0f); break; case '8': alSourcef(source[1], AL_ROLLOFF_FACTOR, 0.5f); break; case '9': alSourcef(source[1], AL_ROLLOFF_FACTOR, 1.0f); break; case 'A': alSourcef(source[1], AL_ROLLOFF_FACTOR, 2.0f); break; } } while (ch != 'Q'); // Release resources alSourceStopv(2, source); alDeleteSources(2, source); return; }