(20111213)

This commit is contained in:
2011-12-13 17:00:00 +01:00
commit a80dda1a85
45 changed files with 2001 additions and 0 deletions

259
Audio.c Normal file
View File

@@ -0,0 +1,259 @@
#ifdef WIN32
#define _WIN32_WINNT 0x0501
#include <windows.h>
#endif
#include <SDL/SDL.h>
#include "Audio.h"
static void Audio_MixerCallback(void *ud,Uint8 *stream,int l);
////////////////////////////////////////////////
// AudioWave //
///////////////
// Reference to a sound.
typedef struct Tag_AudioWave {
SDL_AudioSpec spec;
Uint32 len;
Uint8 *buffer;
struct Tag_AudioWave *next;
} AudioWave;
AudioWave *_waves=NULL;
////////////////////////////////////////////////
// AudioChan //
///////////////
// Reference to a sound.
typedef struct Tag_AudioChan {
AudioWave *wave;
Uint32 pos;
unsigned char rightvol;
unsigned char leftvol;
struct Tag_AudioChan *next;
} AudioChan;
AudioChan *_channels=NULL;
AudioChan *_free_channels=NULL;
/////////////////////////////
// Audio_Init
//
// Initializes the game audio.
int Audio_Init(){
SDL_AudioSpec as;
SDL_AudioSpec as2;
// Initialize audio subsistem
#ifdef WIN32
// Force DSound Driver on win32
putenv("SDL_AUDIODRIVER=dsound");
#endif
if(SDL_InitSubSystem(SDL_INIT_AUDIO) < 0){
printf("Audio_Init: Failure initializing SDL Audio.\n");
printf("Audio_Init: SDL Error: %s\n",SDL_GetError());
return(0);
}
// Open the audio device using the desired parameters
as.freq = 44100;
as.format = AUDIO_S16SYS;
as.channels = 2;
as.samples = 1024;
as.callback = Audio_MixerCallback;
if(SDL_OpenAudio(&as, &as2) < 0){
printf("Audio_Init: Failure opening audio.\n");
printf("Audio_Init: SDL Error: %s\n",SDL_GetError());
return(0);
}
// Asert results
if( as2.format != AUDIO_S16SYS ||
as2.freq != 44100 ||
as2.channels != 2 )
{
printf("Audio_Init: Failure opening audio. (44.1Khz/16b/2c).\n");
SDL_CloseAudio();
return(0);
}
// Unpause and ready to go
SDL_PauseAudio(0);
return(1);
}
/////////////////////////////
// Audio_MixerCallback
//
// Mixes the audio channels.
static void Audio_MixerCallback(void *ud,Uint8 *stream,int l){
signed short *ptr_out,*ptr_wave;
AudioChan *prevchan;
AudioChan *chan;
AudioWave *wave;
int len=l/4; // Asume 16bpb and 2 output chan
int chan_remain;
int len_mix;
int i;
// Clean
memset(stream,0,len);
// Mix all the channels
prevchan=NULL;
chan=_channels;
while(chan){
if(!chan->wave){
// Remove finished channels
AudioChan *aux_chan=chan->next;
chan->next=_free_channels;
_free_channels=chan;
chan=aux_chan;
if(prevchan){
prevchan->next=chan;
}else{
_channels=chan;
}
continue;
}
// Prepare the pointers
ptr_out=(signed short *)stream;
ptr_wave=((signed short *)chan->wave->buffer)+chan->pos;
wave=chan->wave;
// Determine mixing lenght
chan_remain=wave->len-chan->pos;
if(chan_remain>len){
len_mix=len;
}else{
len_mix=chan_remain;
chan->wave=NULL;
}
// Mix the buffer
for(i=0;i<len_mix;i++){
int temp;
// Left Channel
temp=ptr_out[0];
temp+=(ptr_wave[0]*chan->leftvol)>>8;
if(temp>(1<<14)){
ptr_out[0]=1<<14;
}else if(temp<-(1<<14)){
ptr_out[0]=-(1<<14);
}else{
ptr_out[0]=temp;
}
// Right Channel
temp=ptr_out[1];
temp+=(ptr_wave[0]*chan->rightvol)>>8;
if(temp>(1<<14)){
ptr_out[1]=1<<14;
}else if(temp<-(1<<14)){
ptr_out[1]=-(1<<14);
}else{
ptr_out[1]=temp;
}
// Next sample
ptr_out+=2;
ptr_wave++;
}
chan->pos+=len_mix;
// Next channel
prevchan=chan;
chan=chan->next;
}
}
/////////////////////////////
// Audio_Frame
//
// Notify a frame update to the audio subsystem.
void Audio_Frame(){
}
/////////////////////////////
// Audio_LoadSound
//
// Loads a sound, giving a reference.
AudioSnd Audio_LoadSound(char *filename){
AudioWave *wave;
// Allocate and load the sound
wave=malloc(sizeof(AudioWave));
if( SDL_LoadWAV(filename,
&wave->spec, &wave->buffer, &wave->len) == NULL )
{
printf("Audio_LoadSound: Failure Loading sound: %s\n",filename);
printf("Audio_LoadSound: SDL Error: %s\n",SDL_GetError());
free(wave);
return(NULL);
}
// Asert results
if( wave->spec.format != AUDIO_S16 ||
wave->spec.freq != 44100 ||
wave->spec.channels != 1 )
{
printf("Audio_LoadSound: Failure opening sound. (44.1Khz/16b/1c).\n");
SDL_FreeWAV(wave->buffer);
free(wave);
return(0);
}
// Correct the lenght
wave->len/=2;
// Take a reference
wave->next=_waves;
_waves=wave;
return((AudioSnd)wave);
}
/////////////////////////////
// Audio_PlaySound
//
// Loads a sound, giving a reference.
void Audio_PlaySound(AudioSnd snd,
float leftvol, float rightvol)
{
AudioChan *chan;
AudioWave *wave;
if(!snd)
return;
// Cast AudioSnd to AudioWave
wave=snd;
// Get a free channel
if(_free_channels){
chan=_free_channels;
_free_channels=chan->next;
chan->next=NULL;
}else{
chan=malloc(sizeof(AudioChan));
chan->next=NULL;
}
// Initialize the channel
chan->wave=wave;
chan->pos=0;
chan->rightvol=(rightvol*255);
chan->leftvol=(leftvol*255);
chan->next=_channels;
_channels=chan;
}