openalbridge/openalwrap.c
changeset 2191 20c62f787a4d
child 2194 1597710c6118
equal deleted inserted replaced
2190:cfcad6142d48 2191:20c62f787a4d
       
     1 /*
       
     2  * OpenAL Bridge - a simple portable library for OpenAL interface
       
     3  * Copyright (c) 2009 Vittorio Giovara <vittorio.giovara@gmail.com>
       
     4  *
       
     5  * This program is free software; you can redistribute it and/or modify
       
     6  * it under the terms of the GNU General Public License as published by
       
     7  * the Free Software Foundation; version 2 of the License
       
     8  *
       
     9  * This program is distributed in the hope that it will be useful,
       
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    12  * GNU General Public License for more details.
       
    13  *
       
    14  * You should have received a copy of the GNU General Public License
       
    15  * along with this program; if not, write to the Free Software
       
    16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
       
    17  */
       
    18 
       
    19 #include <stdio.h>
       
    20 #include <stdlib.h>
       
    21 #include <stdint.h>
       
    22 #include "al.h"
       
    23 #include "alc.h"
       
    24 #include "openalwrap.h"
       
    25 #include "loaders.h"
       
    26 #include "wrappers.h"
       
    27 #include "endianness.h"
       
    28 
       
    29 #ifdef __CPLUSPLUS
       
    30 extern "C" {
       
    31 #endif 
       
    32 	
       
    33 	// Sources are points emitting sound.
       
    34 	ALuint *Sources;
       
    35 	// Buffers hold sound data.
       
    36 	ALuint *Buffers;
       
    37 	//index for Sources and Buffers
       
    38 	ALuint globalindex, globalsize;
       
    39 	// Position of the source sound.
       
    40 	ALfloat **SourcePos;
       
    41 	// Velocity of the source sound.
       
    42 	ALfloat **SourceVel;
       
    43 	
       
    44 	
       
    45 	ALint openal_close(void) {
       
    46 		/* This function stops all the sounds, deallocates all memory and closes OpenAL */
       
    47 		int i;
       
    48 		ALCcontext *context;
       
    49 		ALCdevice  *device;
       
    50 		
       
    51 		alSourceStopv	(globalsize, Sources);
       
    52 		alDeleteSources (globalsize, Sources);
       
    53 		alDeleteBuffers (globalsize, Buffers);
       
    54 		
       
    55 		for (i = 0; i < globalsize; i++) {
       
    56 			free(SourcePos[i]);
       
    57 			free(SourceVel[i]);
       
    58 		}
       
    59 		free(SourcePos);
       
    60 		free(SourceVel);
       
    61 		free(Sources);
       
    62 		free(Buffers);
       
    63 		
       
    64 		context = alcGetCurrentContext();
       
    65 		device  = alcGetContextsDevice(context);
       
    66 		
       
    67 		alcMakeContextCurrent(NULL);
       
    68 		alcDestroyContext(context);
       
    69 		alcCloseDevice(device);
       
    70 		return AL_TRUE;
       
    71 	}
       
    72 	
       
    73 	
       
    74 	ALint openal_init(int memorysize) {	
       
    75 		/* This function initializes an OpenAL contex, allocates memory space for data and prepares OpenAL buffers*/
       
    76 		ALCcontext *context;
       
    77 		ALCdevice *device;
       
    78 		ALenum error;
       
    79 
       
    80 		const ALCchar *default_device;
       
    81 		// Position of the listener.
       
    82 		ALfloat ListenerPos[] = { 0.0, 0.0, 0.0 };
       
    83 		// Velocity of the listener.
       
    84 		ALfloat ListenerVel[] = { 0.0, 0.0, 0.0 };
       
    85 		// Orientation of the listener. (first 3 elements are "at", second 3 are "up")
       
    86 		ALfloat ListenerOri[] = { 0.0, 0.0, -1.0,  0.0, 1.0, 0.0 };
       
    87 		
       
    88 		default_device = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
       
    89 		
       
    90 		fprintf(stderr, "Using default device: %s\n", default_device);
       
    91 		
       
    92 		if ((device = alcOpenDevice(default_device)) == NULL) {
       
    93 			fprintf(stderr, "ERROR %d: Failed to open sound device\n", error);
       
    94 			return AL_FALSE;
       
    95 		}
       
    96 		context = alcCreateContext(device, NULL);
       
    97 		alcMakeContextCurrent(context);
       
    98 		alcProcessContext(context);
       
    99 		
       
   100 		if (AlGetError("ERROR %d: Creating a new contex\n") != AL_TRUE)
       
   101 			return AL_FALSE;
       
   102 		
       
   103 		//allocate memory space for buffers and sources
       
   104 		globalsize = memorysize;
       
   105 		Buffers   = (ALuint*)   Malloc(sizeof(ALuint  )*globalsize);
       
   106 		Sources   = (ALuint*)   Malloc(sizeof(ALuint  )*globalsize);
       
   107 		SourcePos = (ALfloat**) Malloc(sizeof(ALfloat*)*globalsize);
       
   108 		SourceVel = (ALfloat**) Malloc(sizeof(ALfloat*)*globalsize);
       
   109 		
       
   110 		//set the listener gain, position (on xyz axes), velocity (one value for each axe) and orientation
       
   111 		alListenerf (AL_GAIN,		 1.0f		);
       
   112 		alListenerfv(AL_POSITION,    ListenerPos);
       
   113 		alListenerfv(AL_VELOCITY,    ListenerVel);
       
   114 		alListenerfv(AL_ORIENTATION, ListenerOri);
       
   115 		
       
   116 		if (AlGetError("ERROR %d: Setting Listener properties\n") != AL_TRUE)
       
   117 			return AL_FALSE;
       
   118 		
       
   119 		alGetError();  /* clear any AL errors beforehand */
       
   120 		return AL_TRUE;
       
   121 	}
       
   122 	
       
   123 	
       
   124 	int openal_loadfile (const char *filename){
       
   125 		/* This function opens a file, loads into memory and allocates the Source buffer for playing*/
       
   126 		ALenum format;
       
   127 		ALsizei bitsize;
       
   128 		ALsizei freq;
       
   129 		uint8_t *data;
       
   130 		uint32_t fileformat;
       
   131 		int i, error;
       
   132 		FILE *fp;
       
   133 		
       
   134 		
       
   135 		/*detect the file format, as written in the first 4 bytes of the header*/
       
   136 		fp = Fopen (filename, "rb");
       
   137 		if (fp == NULL)
       
   138 			return -1;
       
   139 		error = fread (&fileformat, sizeof(uint32_t), 1, fp);
       
   140 		fclose (fp);
       
   141 		
       
   142 		if (error < 0) {
       
   143 			fprintf(stderr, "ERROR: file %s is too short \n", filename);
       
   144 			return -2;
       
   145 		}
       
   146 		
       
   147 		//prepare the buffers to receive data
       
   148 		alGenBuffers(1, &Buffers[globalindex]);
       
   149 		
       
   150 		if (AlGetError("ERROR %d: Allocating memory for buffers\n") != AL_TRUE)
       
   151 			return -3;
       
   152 		
       
   153 		//prepare the sources to emit sound
       
   154 		alGenSources(1, &Sources[globalindex]);
       
   155 		
       
   156 		if (AlGetError("ERROR %d: Allocating memory for sources\n") != AL_TRUE)
       
   157 			return -4;
       
   158 				
       
   159 		
       
   160 		if (fileformat == 0x5367674F) //check if ogg
       
   161 			error = load_OggVorbis (filename, &format, &data, &bitsize, &freq);
       
   162 		else {
       
   163 			if (fileformat == 0x46464952) //check if wav
       
   164 				error = load_WavPcm (filename, &format, &data, &bitsize, &freq);
       
   165 			else {
       
   166 				fprintf(stderr, "ERROR: File format (%08X) not supported!\n", invert_endianness(fileformat));
       
   167 				return -5;
       
   168 			}
       
   169 		}
       
   170 		
       
   171 		//copy pcm data in one buffer
       
   172 		alBufferData(Buffers[globalindex], format, data, bitsize, freq);
       
   173 		free(data);		//deallocate data to save memory
       
   174 		
       
   175 		if (AlGetError("ERROR %d: Writing data to buffer\n") != AL_TRUE)
       
   176 			return -5;
       
   177 		
       
   178 		//memory allocation for source position and velocity
       
   179 		SourcePos[globalindex] = (ALfloat*) Malloc(sizeof(ALfloat)*3);
       
   180 		SourceVel[globalindex] = (ALfloat*) Malloc(sizeof(ALfloat)*3);
       
   181 		
       
   182 		if (SourcePos[globalindex] == NULL || SourceVel[globalindex] == NULL)
       
   183 			return -6;
       
   184 			
       
   185 		//source properties that it will use when it's in playback
       
   186 		for (i = 0; i < 3; i++) {
       
   187 			SourcePos[globalindex][i] = 0.0;
       
   188 			SourceVel[globalindex][i] = 0.1;
       
   189 		}	
       
   190 		alSourcei (Sources[globalindex], AL_BUFFER,   Buffers[globalindex]  );
       
   191 		alSourcef (Sources[globalindex], AL_PITCH,    1.0f					);
       
   192 		alSourcef (Sources[globalindex], AL_GAIN,     1.0f					);
       
   193 		alSourcefv(Sources[globalindex], AL_POSITION, SourcePos[globalindex]);
       
   194 		alSourcefv(Sources[globalindex], AL_VELOCITY, SourceVel[globalindex]);
       
   195 		alSourcei (Sources[globalindex], AL_LOOPING,  0						);
       
   196 		
       
   197 		if (AlGetError("ERROR %d: Setting source properties\n") != AL_TRUE)
       
   198 			return -7;
       
   199 		
       
   200 		alGetError();  /* clear any AL errors beforehand */
       
   201 		
       
   202 		//returns the index of the source you just loaded, increments it and exits
       
   203 		return globalindex++;
       
   204 	}
       
   205 	
       
   206 	
       
   207 	ALint openal_toggleloop (int index){
       
   208 		/*Set or unset looping mode*/
       
   209 		ALint loop;
       
   210 		
       
   211 		if (index >= globalsize) {
       
   212 			fprintf(stderr, "ERROR: index out of bounds (got %d, max %d)", index, globalindex);
       
   213 			return AL_FALSE;
       
   214 		}
       
   215 		
       
   216 		alGetSourcei (Sources[index], AL_LOOPING, &loop);
       
   217 		alSourcei (Sources[index], AL_LOOPING, !((uint8_t) loop) & 0x00000001);
       
   218 		if (AlGetError("ERROR %d: Getting or setting loop property\n") != AL_TRUE)
       
   219 			return AL_FALSE;
       
   220 		
       
   221 		alGetError();  /* clear any AL errors beforehand */
       
   222 
       
   223 		return AL_TRUE;
       
   224 	}
       
   225 	
       
   226 	
       
   227 	ALint openal_setvolume (int index, unsigned char percentage) {
       
   228 		/*Set volume for sound number index*/
       
   229 		if (index >= globalindex) {
       
   230 			fprintf(stderr, "ERROR: index out of bounds (got %d, max %d)", index, globalindex);
       
   231 			return AL_FALSE;
       
   232 		}
       
   233 		
       
   234 		if (percentage > 100)
       
   235 			percentage = 100;
       
   236 		alSourcef (Sources[index], AL_GAIN, (ALfloat) percentage/100.0f);
       
   237 		if (AlGetError("ERROR %d: Setting volume for last sound\n") != AL_TRUE)
       
   238 			return AL_FALSE;
       
   239 		
       
   240 		alGetError();  /* clear any AL errors beforehand */
       
   241 
       
   242 		return AL_TRUE;
       
   243 	}
       
   244 	
       
   245 	
       
   246 	ALint openal_setglobalvolume (unsigned char percentage) {
       
   247 		/*Set volume for all sounds*/		
       
   248 		if (percentage > 100)
       
   249 			percentage = 100;
       
   250 		alListenerf (AL_GAIN, (ALfloat) percentage/100.0f);
       
   251 		if (AlGetError("ERROR %d: Setting global volume\n") != AL_TRUE)
       
   252 			return AL_FALSE;
       
   253 		
       
   254 		alGetError();  /* clear any AL errors beforehand */
       
   255 
       
   256 		return AL_TRUE;
       
   257 	}
       
   258 	
       
   259 	
       
   260 	ALint openal_togglemute () {
       
   261 		/*Mute or unmute sound*/
       
   262 		ALfloat mute;
       
   263 		
       
   264 		alGetListenerf (AL_GAIN, &mute);
       
   265 		if (mute > 0) 
       
   266 			mute = 0;
       
   267 		else
       
   268 			mute = 1.0;
       
   269 		alListenerf (AL_GAIN, mute);
       
   270 		if (AlGetError("ERROR %d: Setting mute property\n") != AL_TRUE)
       
   271 			return AL_FALSE;
       
   272 		
       
   273 		alGetError();  /* clear any AL errors beforehand */
       
   274 
       
   275 		return AL_TRUE;
       
   276 	}
       
   277 	
       
   278 	
       
   279 	ALint openal_fadeout(int index, unsigned int quantity) {
       
   280 		ALfloat gain;
       
   281 		
       
   282 		if (index >= globalindex) {
       
   283 			fprintf(stderr, "ERROR: index out of bounds (got %d, max %d)", index, globalindex);
       
   284 			return AL_FALSE;
       
   285 		}
       
   286 		
       
   287 		alGetSourcef(Sources[index], AL_GAIN, &gain);
       
   288 
       
   289 		for ( ; gain >= 0.00f; gain -= (float) quantity/10000){
       
   290 #ifdef DEBUG
       
   291 			fprintf(stderr, "Fade-out: Set gain to: %f\n", gain);
       
   292 #endif
       
   293 			alSourcef(Sources[index], AL_GAIN, gain);
       
   294 			usleep(10000);
       
   295 		}
       
   296 		
       
   297 		if (AlGetError("ERROR %d: Setting fade out volume\n") != AL_TRUE)
       
   298 			return AL_FALSE;
       
   299 		
       
   300 		//stop that sound and reset its gain
       
   301 		alSourceStop (Sources[index]);
       
   302 		alSourcef (Sources[index], AL_GAIN, 1.0f);
       
   303 
       
   304 		alGetError();  /* clear any AL errors beforehand */
       
   305 
       
   306 		return AL_TRUE;
       
   307 	}
       
   308 	
       
   309 	
       
   310 	ALint openal_fadein(int index, unsigned int quantity) {
       
   311 		ALfloat gain;
       
   312 		
       
   313 		if (index >= globalindex) {
       
   314 			fprintf(stderr, "ERROR: index out of bounds (got %d, max %d)", index, globalindex);
       
   315 			return AL_FALSE;
       
   316 		}
       
   317 		
       
   318 		gain = 0.0f;
       
   319 		alSourcef(Sources[index], AL_GAIN, gain);
       
   320 		alSourcePlay(Sources[index]);
       
   321 		
       
   322 		for ( ; gain <= 1.00f; gain += (float) quantity/10000){
       
   323 #ifdef DEBUG
       
   324 			fprintf(stderr, "Fade-in: Set gain to: %f\n", gain);
       
   325 #endif
       
   326 			alSourcef(Sources[index], AL_GAIN, gain);
       
   327 			usleep(10000);
       
   328 		}
       
   329 		
       
   330 		if (AlGetError("ERROR %d: Setting fade in volume\n") != AL_TRUE)
       
   331 			return AL_FALSE;
       
   332 		
       
   333 		alGetError();  /* clear any AL errors beforehand */
       
   334 
       
   335 		return AL_TRUE;
       
   336 	}
       
   337 	
       
   338 	
       
   339 	ALint openal_playsound(int index){
       
   340 		/*Play sound number index*/
       
   341 		if (index >= globalindex) {
       
   342 			fprintf(stderr, "ERROR: index out of bounds (got %d, max %d)", index, globalindex);
       
   343 			return AL_FALSE;
       
   344 		}
       
   345 		alSourcePlay(Sources[index]);
       
   346 		if (AlGetError("ERROR %d: Playing last sound\n") != AL_TRUE)
       
   347 			return AL_FALSE;
       
   348 		
       
   349 		alGetError();  /* clear any AL errors beforehand */
       
   350 
       
   351 		return AL_TRUE;
       
   352 	}
       
   353 	
       
   354 	
       
   355 	ALint openal_pausesound(int index){
       
   356 		/*Pause sound number index*/
       
   357 		if (index >= globalindex) {
       
   358 			fprintf(stderr, "ERROR: index out of bounds (got %d, max %d)", index, globalindex);
       
   359 			return AL_FALSE;
       
   360 		}
       
   361 		alSourcePause(Sources[index]);
       
   362 		if (AlGetError("ERROR %d: Pausing last sound\n") != AL_TRUE)
       
   363 			return AL_FALSE;
       
   364 		
       
   365 		return AL_TRUE;
       
   366 	}
       
   367 	
       
   368 	
       
   369 	ALint openal_stopsound(int index){
       
   370 		/*Stop sound number index*/
       
   371 		if (index >= globalindex) {
       
   372 			fprintf(stderr, "ERROR: index out of bounds (got %d, max %d)", index, globalindex);
       
   373 			return AL_FALSE;
       
   374 		}
       
   375 		alSourceStop(Sources[index]);
       
   376 		if (AlGetError("ERROR %d: Stopping last sound\n") != AL_TRUE)
       
   377 			return AL_FALSE;
       
   378 		
       
   379 		alGetError();  /* clear any AL errors beforehand */
       
   380 
       
   381 		return AL_TRUE;
       
   382 	}
       
   383 	
       
   384 #ifdef __CPLUSPLUS
       
   385 }
       
   386 #endif