//http://www.youtube.com/user/thecplusplusguy
//Playing 3D sound with OpenAL, and loading a wav file manually
#include <iostream>
#include <fstream>
#include <cstring>
#include <AL/al.h>
#include <AL/alc.h>
#include <SDL/SDL.h>
bool isBigEndian()
{
int a=1;
return !((char*)&a)[0];
}
int convertToInt(char* buffer,int len)
{
int a=0;
if(!isBigEndian())
for(int i=0;i<len;i++)
((char*)&a)[i]=buffer[i];
else
for(int i=0;i<len;i++)
((char*)&a)[3-i]=buffer[i];
return a;
}
char* loadWAV(const char* fn,int& chan,int& samplerate,int& bps,int& size)
{
char buffer[4];
std::ifstream in(fn,std::ios::binary);
in.read(buffer,4);
if(strncmp(buffer,"RIFF",4)!=0)
{
std::cout << "this is not a valid WAVE file" << std::endl;
return NULL;
}
in.read(buffer,4);
in.read(buffer,4); //WAVE
in.read(buffer,4); //fmt
in.read(buffer,4); //16
in.read(buffer,2); //1
in.read(buffer,2);
chan=convertToInt(buffer,2);
in.read(buffer,4);
samplerate=convertToInt(buffer,4);
in.read(buffer,4);
in.read(buffer,2);
in.read(buffer,2);
bps=convertToInt(buffer,2);
in.read(buffer,4); //data
in.read(buffer,4);
size=convertToInt(buffer,4);
char* data=new char[size];
in.read(data,size);
return data;
}
int main(int argc,char** argv)
{
int channel,sampleRate,bps,size;
char* data=loadWAV("test.wav",channel,sampleRate,bps,size);
ALCdevice* device=alcOpenDevice(NULL);
if(device==NULL)
{
std::cout << "cannot open sound card" << std::endl;
return 0;
}
ALCcontext* context=alcCreateContext(device,NULL);
if(context==NULL)
{
std::cout << "cannot open context" << std::endl;
return 0;
}
alcMakeContextCurrent(context);
unsigned int bufferid,format;
alGenBuffers(1,&bufferid);
if(channel==1)
{
if(bps==8)
{
format=AL_FORMAT_MONO8;
}else{
format=AL_FORMAT_MONO16;
}
}else{
if(bps==8)
{
format=AL_FORMAT_STEREO8;
}else{
format=AL_FORMAT_STEREO16;
}
}
alBufferData(bufferid,format,data,size,sampleRate);
unsigned int sourceid;
alGenSources(1,&sourceid);
alSourcei(sourceid,AL_BUFFER,bufferid);
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Surface* screen=SDL_SetVideoMode(640,480,32,SDL_SWSURFACE);
SDL_Event event;
Uint32 start;
bool running;
bool b[4]={0,0,0,0};
float x=0,z=0;
while(running)
{
start=SDL_GetTicks();
while(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_QUIT:
running=false;
break;
case SDL_KEYDOWN:
switch(event.key.keysym.sym)
{
case SDLK_UP:
b[0]=true;
break;
case SDLK_RIGHT:
b[1]=true;
break;
case SDLK_DOWN:
b[2]=true;
break;
case SDLK_LEFT:
b[3]=true;
break;
case SDLK_SPACE:
alSourcePlay(sourceid);
break;
}
break;
case SDL_KEYUP:
switch(event.key.keysym.sym)
{
case SDLK_UP:
b[0]=false;
break;
case SDLK_RIGHT:
b[1]=false;
break;
case SDLK_DOWN:
b[2]=false;
break;
case SDLK_LEFT:
b[3]=false;
break;
}
break;
}
}
if(b[0])
z+=0.3;
if(b[1])
x+=0.3;
if(b[2])
z-=0.3;
if(b[3])
x-=0.3;
alSource3f(sourceid,AL_POSITION,x,0,z);
alSourcei(sourceid,AL_LOOPING,AL_TRUE);
float f[]={1,0,0,0,1,0};
alListenerfv(AL_ORIENTATION,f);
if(1000/30.0>SDL_GetTicks()-start)
SDL_Delay(1000/30.0-(SDL_GetTicks()-start));
}
alDeleteSources(1,&sourceid);
alDeleteBuffers(1,&bufferid);
alcDestroyContext(context);
alcCloseDevice(device);
delete[] data;
return 0;
}