OpenAL音频库例程
Windows下C++可用的OpenAL demo。
基于alut工具库的OpenAL例程,涵盖了基本的OpenAL指令,对部分作出了注释,并且可以播放(当然得把对应的音频文件放到正确的路径下)。
1 #include <iostream> 2 #include <al/alut.h>//alut includes al.h 3 #include <math.h> 4 #include <windows.h> 5 using namespace std; 6 7 #define PI 3.14159265359 8 9 #define TEST_ERROR(_msg) \ 10 error = alGetError(); \ 11 if (error != AL_NO_ERROR) { \ 12 fprintf(stderr, _msg "\n"); \ 13 return -1; \ 14 } 15 16 //ALboolean EnableSource2 = AL_TRUE; //是否播放第二组声音 17 ALboolean EnableSource2 = AL_FALSE; //是否播放第二组声音 18 ALboolean EnableSource3 = AL_FALSE; //是否播放第三组声音 19 20 ALuint buffer2,buffer3; 21 22 void Init(){ 23 alutInit(NULL, NULL); 24 } 25 26 //OS音量40,windows7 27 void main() 28 { 29 ALuint source1[10]; //buffer source 30 31 //Init();//分离到一个单独的函数或类成员中 32 alutInit(NULL, NULL); 33 34 //ALuint source1; 35 alGenSources(1, &source1[0]); 36 //短哔声:10217,Music:RevolvingDoorMONO,中国军魂 37 ALuint buffer1 = alutCreateBufferFromFile("RevolvingDoorMONO.WAV");//要实现空间化效果,必须为单声道文件(monaural)RevolvingDoorMONO 38 39 if ((alGetError()) != AL_NO_ERROR)std::cout << "Buffer Create error!" << std::endl; 40 41 alSourcei(source1[0], AL_BUFFER, buffer1); 42 43 if (EnableSource2){ 44 alGenSources(2, &source1[1]); 45 buffer2 = alutCreateBufferFromFile("E:\\VS2013\\Projects2013\\OpenALtest\\OpenALtest\\10217.WAV"); 46 alSourcei(source1[1], AL_BUFFER, buffer2); 47 alSourcePlay(source1[1]); 48 alSourcei(source1[1], AL_LOOPING, AL_TRUE);//第二个音频是否循环 49 } 50 51 if (EnableSource3){ 52 alGenSources(3, &source1[2]); 53 ALuint temp = buffer1; 54 alSourcei(source1[2], AL_BUFFER, temp); 55 alSourcePlay(source1[2]); 56 alSourcei(source1[2], AL_LOOPING, AL_TRUE);//第二个音频是否循环 57 } 58 59 alSourcei(source1[0], AL_SOURCE_RELATIVE, 0); // set to relative positioning so we can set everything to 0 60 if ((alGetError()) != AL_NO_ERROR)std::cout << "AL_SOURCE_RELATIVE error" << std::endl; 61 /*AL_SOURCE_RELATIVE设为1时,没有衰减,也没有空间化。 62 */ 63 64 alSourcef(source1[0], AL_ROLLOFF_FACTOR, 1.0); // 0 to disable attenuation 滚降衰减模型 65 /*AL_ROLLOFF_FACTOR设为1时,开启衰减,设为0时,没有衰减 66 */ 67 68 if ((alGetError()) != AL_NO_ERROR)std::cout << "AL_ROLLOFF_FACTOR error" << std::endl; 69 alSourcef(source1[0], AL_REFERENCE_DISTANCE, 1); // doesn't matter 70 71 alSourcef(source1[0], AL_MAX_DISTANCE, 5.f);//超过AL_MAX_DISTANCE个单位后,将声音gain值限制在AL_MIN_GAIN(如果在cone之外,好像是再乘以AL_MIN_GAIN) 72 alSourcef(source1[0], AL_MIN_GAIN, 0.0f);//设置AL_MIN_GAIN 73 alSourcef(source1[0], AL_MAX_GAIN, 5.f);//设置AL_MAX_GAIN,即使设得比1大,也会自动回成1,并报输出ERROR 74 75 alDistanceModel(AL_INVERSE_DISTANCE);//距离模型 76 //alDistanceModel(AL_NONE);//距离模型 77 //gain = AL_REFERENCE_DISTANCE / (AL_REFERENCE_DISTANCE + AL_ROLLOFF_FACTOR * (distance – AL_REFERENCE_DISTANCE)); 78 79 alSourcef(source1[0], AL_PITCH, 1.f);//调节音高乘数 80 if ((alGetError()) != AL_NO_ERROR)std::cout << "AL_PITCH error" << std::endl; 81 alSourcef(source1[0], AL_GAIN, 1.f);//调节音量,但是受AL_MIN_GAIN影响,即使设得比min低,实际gain也会保持min设的值 82 if ((alGetError()) != AL_NO_ERROR)std::cout << "AL_GAIN error" << std::endl; 83 84 //set source direction 85 alSource3f(source1[0], AL_DIRECTION, 0.f, 0.f, 1.f);//朝z轴正方向 86 //set source position 87 alSource3f(source1[0], AL_POSITION, 0.f, 0.f, 0.f);//初始位置为原点 88 //set source velocity 89 alSource3f(source1[0], AL_VELOCITY, 0.f, 0.f, 0.f);//多普勒效应影响频率 90 91 alSourcef(source1[0], AL_CONE_OUTER_GAIN, 0.0f);//the gain when outside the oriented cone 92 if ((alGetError()) != AL_NO_ERROR)std::cout << "AL_CONE_OUTER_GAIN error" << std::endl; 93 alSourcef(source1[0], AL_CONE_INNER_ANGLE, 90.f);//内角 *PI / 180.f 94 if ((alGetError()) != AL_NO_ERROR)std::cout << "AL_CONE_INNER_ANGLE error" << std::endl; 95 alSourcef(source1[0], AL_CONE_OUTER_ANGLE, 150.f); 96 if ((alGetError()) != AL_NO_ERROR)std::cout << "AL_CONE_OUTER_ANGLE error" << std::endl; 97 98 //set current listener position 99 alListener3f(AL_POSITION, -1.f,0.f,0.f); 100 //-1.f,0.f,1.f 监听者在左,右耳音量较大 101 //1.f,0.f,1.f 监听者在右,左耳音量较大 102 //0.f,0.f,-1.f 监听者在后,在外角之外,声音为原来的AL_CONE_OUTER_GAIN倍,好像还要乘以AL_MIN_GAIN系数 103 104 //set current listener orientation 105 ALfloat orivec[] = { 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f }; 106 alListenerfv(AL_ORIENTATION, orivec); 107 //设置好listener位置 108 ////////////////////////////////////////////////////////////////////////// 109 110 //tell the sound to loop continuously 111 alSourcei(source1[0], AL_LOOPING, AL_TRUE); 112 113 //play the sound 114 alSourcePlay(source1[0]);//have its state changed to AL_PLAYING,重新播放 115 116 ALfloat gain,outer_gain,min_gain,max_gain,max_distance; 117 alGetSourcef(source1[0], AL_GAIN, &gain); std::cout << "AL_GAIN: " << gain << std::endl; 118 alGetSourcef(source1[0], AL_CONE_OUTER_GAIN, &outer_gain); std::cout << "AL_CONE_OUTER_GAIN: " << outer_gain << std::endl; 119 alGetSourcef(source1[0], AL_MIN_GAIN, &min_gain); std::cout << "AL_MIN_GAIN: " << min_gain << std::endl; 120 alGetSourcef(source1[0], AL_MAX_GAIN, &max_gain); std::cout << "AL_MAX_GAIN: " << max_gain << std::endl; 121 alGetSourcef(source1[0], AL_MAX_DISTANCE, &max_distance); std::cout << "AL_MAX_DISTANCE: " << max_distance << std::endl; 122 std::cout << std::endl << "在音锥外角和最远衰减距离之外 gain * outer_gain * min_gain: " << gain*outer_gain*min_gain << std::endl; 123 std::cout << std::endl; 124 125 ALint sourceID; 126 alGetSourcei(source1[0], AL_SOURCE_TYPE, &sourceID); 127 std::cout << "AL_SOURCE_TYPE的ID: "<<sourceID << endl<<endl; 128 129 ALint state; 130 ALfloat tick = 0; 131 ALfloat moveStart_posx = -2.f, moveStart_posy = 0.f, moveStart_posz = 0.f; 132 do{ 133 std::cout << "playing......" << "\b\b\b\b\b\b\b\b\b\b\b\b\b"; 134 135 ////旋转音锥 136 //float updatex = -sinf(play_it*PI / 180.f); 137 //float upadtez = cosf(play_it*PI / 180.f); 138 //alSource3f(source1, AL_DIRECTION, updatex, 0.f, upadtez); 139 //if ((alGetError()) != AL_NO_ERROR)std::cout << "AL_POSITION error" << std::endl; 140 //play_it=play_it+0.1f; 141 142 ////平移声源 143 //alSource3f(source1, AL_POSITION, moveStart_posx, moveStart_posy, moveStart_posz); 144 //moveStart_posx = moveStart_posx + 0.00000011f; moveStart_posz = moveStart_posz + 0.00000015f; 145 146 alGetSourcei(source1[0], AL_SOURCE_STATE, &state); 147 148 //是否播第二个音频资源 149 if (EnableSource2) 150 alGetSourcei(source1[1], AL_SOURCE_STATE, &state); 151 152 if (EnableSource3) 153 alGetSourcei(source1[2], AL_SOURCE_STATE, &state); 154 155 } while (state == AL_PLAYING || state==AL_PAUSED);//结束时state自动变成AL_STOPPED,source1、2共享一个state 156 157 // To stop the sound 158 alSourceStop(source1[0]); 159 //delete our source 160 alDeleteSources(1, &source1[0]); 161 ////delete our buffer 162 alDeleteBuffers(1, &buffer1); 163 if ((alGetError()) != AL_NO_ERROR)std::cout << "delete buffer1 error " << std::endl; 164 165 if (EnableSource2){ 166 alSourceStop(source1[1]); 167 alDeleteBuffers(1, &buffer2); 168 if ((alGetError()) != AL_NO_ERROR)std::cout << "delete buffer2 error" << std::endl; 169 alDeleteSources(1, &source1[1]); 170 if ((alGetError()) != AL_NO_ERROR)std::cout << "delete source error" << std::endl; 171 } 172 }