comparison ALmixer.c @ 12:bfe90b4f3d87

Bug fixes to FadeIn. Documentation fixes Minor API changes w.r.t. return types. (ALboolean instead of ALint)
author Eric Wing <ewing . public |-at-| gmail . com>
date Fri, 05 Nov 2010 20:59:13 -0700
parents c808684660a7
children 54aa96ae8912
comparison
equal deleted inserted replaced
11:eca6f008fad0 12:bfe90b4f3d87
12 #include "SoundDecoder.h" 12 #include "SoundDecoder.h"
13 #else 13 #else
14 #include "SDL_sound.h" 14 #include "SDL_sound.h"
15 #endif 15 #endif
16 16
17 #include "al.h" /* OpenAL */ 17 #ifdef ANDROID_NDK
18 #include "alc.h" /* For creating OpenAL contexts */ 18 #include <AL/al.h>
19 #include <AL/alc.h>
20 #else
21 #include "al.h" /* OpenAL */
22 #include "alc.h" /* For creating OpenAL contexts */
23 #endif
19 24
20 #ifdef __APPLE__ 25 #ifdef __APPLE__
21 /* For performance things like ALC_CONVERT_DATA_UPON_LOADING */ 26 /* For performance things like ALC_CONVERT_DATA_UPON_LOADING */
22 /* Note: ALC_CONVERT_DATA_UPON_LOADING used to be in the alc.h header. 27 /* Note: ALC_CONVERT_DATA_UPON_LOADING used to be in the alc.h header.
23 * But in the Tiger OpenAL 1.1 release (10.4.7 and Xcode 2.4), the 28 * But in the Tiger OpenAL 1.1 release (10.4.7 and Xcode 2.4), the
307 return (ALuint)((CACurrentMediaTime()-s_ticksBaseTime)*1000.0); 312 return (ALuint)((CACurrentMediaTime()-s_ticksBaseTime)*1000.0);
308 #elif defined(_WIN32) 313 #elif defined(_WIN32)
309 LARGE_INTEGER current_time; 314 LARGE_INTEGER current_time;
310 QueryPerformanceCounter(&current_time); 315 QueryPerformanceCounter(&current_time);
311 return (ALuint)((current_time.QuadPart - s_ticksBaseTime.QuadPart) * 1000 * s_hiResSecondsPerTick); 316 return (ALuint)((current_time.QuadPart - s_ticksBaseTime.QuadPart) * 1000 * s_hiResSecondsPerTick);
317 #elif ANDROID_NDK
312 318
313 #else /* assuming POSIX */ 319 #else /* assuming POSIX */
314 /* clock_gettime is POSIX.1-2001 */ 320 /* clock_gettime is POSIX.1-2001 */
315 struct timespec current_time; 321 struct timespec current_time;
316 clock_gettime(CLOCK_MONOTONIC, &current_time); 322 clock_gettime(CLOCK_MONOTONIC, &current_time);
317 return (ALuint)((current_time.tv_sec - s_ticksBaseTime.tv_sec)*1000.0 + (current_time.tv_nec - s_ticksBaseTime.tv_nsec) / 1000000); 323 return (ALuint)((current_time.tv_sec - s_ticksBaseTime.tv_sec)*1000.0 + (current_time.tv_nsec - s_ticksBaseTime.tv_nsec) / 1000000);
318 #endif 324 #endif
319 } 325 }
320 static void ALmixer_Delay(ALuint milliseconds_delay) 326 static void ALmixer_Delay(ALuint milliseconds_delay)
321 { 327 {
322 #if defined(_WIN32) 328 #if defined(_WIN32)
2014 2020
2015 /* This will rewind the SDL_Sound sample for streamed 2021 /* This will rewind the SDL_Sound sample for streamed
2016 * samples and start buffering up the data for the next 2022 * samples and start buffering up the data for the next
2017 * playback. This may require samples to be halted 2023 * playback. This may require samples to be halted
2018 */ 2024 */
2019 static ALint Internal_RewindData(ALmixer_Data* data) 2025 static ALboolean Internal_RewindData(ALmixer_Data* data)
2020 { 2026 {
2021 ALint retval = 0; 2027 ALint retval = 0;
2022 /* 2028 /*
2023 ALint bytes_returned; 2029 ALint bytes_returned;
2024 ALint i; 2030 ALint i;
2025 */ 2031 */
2026 if(NULL == data) 2032 if(NULL == data)
2027 { 2033 {
2028 ALmixer_SetError("Cannot rewind because data is NULL\n"); 2034 ALmixer_SetError("Cannot rewind because data is NULL\n");
2029 return -1; 2035 return AL_FALSE;
2030 } 2036 }
2031 2037
2032 2038
2033 /* Might have to require Halt */ 2039 /* Might have to require Halt */
2034 /* Okay, we assume Halt or natural stop has already 2040 /* Okay, we assume Halt or natural stop has already
2054 data->eof = 0; 2060 data->eof = 0;
2055 2061
2056 #if 0 2062 #if 0
2057 #if defined(DISABLE_PREDECODED_SEEK) 2063 #if defined(DISABLE_PREDECODED_SEEK)
2058 /* Since we can't seek predecoded stuff, it should be rewound */ 2064 /* Since we can't seek predecoded stuff, it should be rewound */
2059 return 0; 2065 return AL_TRUE;
2060 #elif !defined(DISABLE_SEEK_MEMORY_OPTIMIZATION) 2066 #elif !defined(DISABLE_SEEK_MEMORY_OPTIMIZATION)
2061 /* This case is if the Sound_Sample has been deleted. 2067 /* This case is if the Sound_Sample has been deleted.
2062 * It assumes the data is already at the beginning. 2068 * It assumes the data is already at the beginning.
2063 */ 2069 */
2064 if(NULL == data->sample) 2070 if(NULL == data->sample)
2065 { 2071 {
2066 return 0; 2072 return AL_TRUE;
2067 } 2073 }
2068 /* Else, the sample has already been reallocated, 2074 /* Else, the sample has already been reallocated,
2069 * and we can fall to normal behavior 2075 * and we can fall to normal behavior
2070 */ 2076 */
2071 #endif 2077 #endif
2075 * If it's NULL, we can't do anything, but 2081 * If it's NULL, we can't do anything, but
2076 * it should already be "rewound". 2082 * it should already be "rewound".
2077 */ 2083 */
2078 if(NULL == data->sample) 2084 if(NULL == data->sample)
2079 { 2085 {
2080 return 0; 2086 return AL_TRUE;
2081 } 2087 }
2082 /* Else, the sample has already been reallocated, 2088 /* Else, the sample has already been reallocated,
2083 * and we can fall to normal behavior 2089 * and we can fall to normal behavior
2084 */ 2090 */
2085 2091
2086 Set_Predecoded_Seek_Position(data, 0); 2092 Set_Predecoded_Seek_Position(data, 0);
2087 /* 2093 /*
2088 return data->total_bytes; 2094 return data->total_bytes;
2089 */ 2095 */
2090 return 0; 2096 return AL_TRUE;
2091 } 2097 }
2092 2098
2093 /* Remaining stuff for streamed data */ 2099 /* Remaining stuff for streamed data */
2094 2100
2095 data->eof = 0; 2101 data->eof = 0;
2096 retval = Sound_Rewind(data->sample); 2102 retval = Sound_Rewind(data->sample);
2097 if(0 == retval) 2103 if(0 == retval)
2098 { 2104 {
2099 ALmixer_SetError( Sound_GetError() ); 2105 ALmixer_SetError( Sound_GetError() );
2100 return -1; 2106 return AL_FALSE;
2101 } 2107 }
2102 #if 0 2108 #if 0
2103 /* Clear error */ 2109 /* Clear error */
2104 alGetError(); 2110 alGetError();
2105 for(i=0; i<data->num_buffers; i++) 2111 for(i=0; i<data->num_buffers; i++)
2106 { 2112 {
2107 bytes_returned = GetMoreData(data, data->buffer[i]); 2113 bytes_returned = GetMoreData(data, data->buffer[i]);
2108 if(-1 == bytes_returned) 2114 if(-1 == bytes_returned)
2109 { 2115 {
2110 return -1; 2116 return AL_FALSE;
2111 } 2117 }
2112 else if(0 == bytes_returned) 2118 else if(0 == bytes_returned)
2113 { 2119 {
2114 return -1; 2120 return AL_FALSE;
2115 } 2121 }
2116 retval += bytes_returned; 2122 retval += bytes_returned;
2117 2123
2118 } 2124 }
2119 #endif 2125 #endif
2120 2126
2121 2127
2122 2128
2123 return retval; 2129 return AL_TRUE;
2124 } 2130 }
2125 2131
2126 2132
2127 2133
2128 2134
2129 static ALint Internal_RewindChannel(ALint channel) 2135 static ALint Internal_RewindChannel(ALint channel)
2130 { 2136 {
2131 ALint retval = 0; 2137 ALint retval = 0;
2132 ALenum error; 2138 ALenum error;
2133 ALint state; 2139 ALint state;
2140 ALint running_count = 0;
2134 2141
2135 if(channel >= Number_of_Channels_global) 2142 if(channel >= Number_of_Channels_global)
2136 { 2143 {
2137 ALmixer_SetError("Cannot rewind channel %d because it exceeds maximum number of channels (%d)\n", channel, Number_of_Channels_global); 2144 ALmixer_SetError("Cannot rewind channel %d because it exceeds maximum number of channels (%d)\n", channel, Number_of_Channels_global);
2138 return -1; 2145 return -1;
2290 * does no good. Rewinding the data will have an 2297 * does no good. Rewinding the data will have an
2291 * effect, but it will be lagged based on how 2298 * effect, but it will be lagged based on how
2292 * much data is queued. Recommend users call Halt 2299 * much data is queued. Recommend users call Halt
2293 * before rewind if they want immediate results. 2300 * before rewind if they want immediate results.
2294 */ 2301 */
2295 retval = Internal_RewindData(ALmixer_Channel_List[i].almixer_data); 2302 running_count += Internal_RewindData(ALmixer_Channel_List[i].almixer_data);
2296 } 2303 }
2297 } 2304 }
2298 } 2305 }
2299 } 2306 }
2300 return retval; 2307 if(-1 == retval)
2308 {
2309 return -1;
2310 }
2311 else
2312 {
2313 return running_count;
2314 }
2315
2301 } 2316 }
2302 2317
2303 2318
2304 static ALint Internal_RewindSource(ALuint source) 2319 static ALint Internal_RewindSource(ALuint source)
2305 { 2320 {
3096 3111
3097 3112
3098 /* Might consider setting eof to 0 as a "feature" 3113 /* Might consider setting eof to 0 as a "feature"
3099 * This will allow seek to end to stay there because 3114 * This will allow seek to end to stay there because
3100 * Play automatically rewinds if at the end */ 3115 * Play automatically rewinds if at the end */
3101 static ALint Internal_SeekData(ALmixer_Data* data, ALuint msec) 3116 static ALboolean Internal_SeekData(ALmixer_Data* data, ALuint msec)
3102 { 3117 {
3103 ALint retval; 3118 ALint retval;
3104 3119
3105 if(NULL == data) 3120 if(NULL == data)
3106 { 3121 {
3107 ALmixer_SetError("Cannot Seek because data is NULL"); 3122 ALmixer_SetError("Cannot Seek because data is NULL");
3108 return -1; 3123 return AL_FALSE;
3109 } 3124 }
3110 3125
3111 /* Seek for predecoded files involves moving the chunk pointer around */ 3126 /* Seek for predecoded files involves moving the chunk pointer around */
3112 if(data->decoded_all) 3127 if(data->decoded_all)
3113 { 3128 {
3120 * I can't shut them down myself, so I have to return an error. 3135 * I can't shut them down myself, so I have to return an error.
3121 */ 3136 */
3122 if(data->in_use) 3137 if(data->in_use)
3123 { 3138 {
3124 ALmixer_SetError("Cannot seek on predecoded data while instances are playing"); 3139 ALmixer_SetError("Cannot seek on predecoded data while instances are playing");
3125 return -1; 3140 return AL_FALSE;
3126 } 3141 }
3127 #if 0 3142 #if 0
3128 #if defined(DISABLE_PREDECODED_SEEK) 3143 #if defined(DISABLE_PREDECODED_SEEK)
3129 ALmixer_SetError("Seek support for predecoded samples was not compiled in"); 3144 ALmixer_SetError("Seek support for predecoded samples was not compiled in");
3130 return -1; 3145 return AL_FALSE;
3131 3146
3132 #elif !defined(DISABLE_SEEK_MEMORY_OPTIMIZATION) 3147 #elif !defined(DISABLE_SEEK_MEMORY_OPTIMIZATION)
3133 /* By default, ALmixer frees the Sound_Sample for predecoded 3148 /* By default, ALmixer frees the Sound_Sample for predecoded
3134 * samples because of the potential memory waste. 3149 * samples because of the potential memory waste.
3135 * However, to seek a sample, we need to have a full 3150 * However, to seek a sample, we need to have a full
3141 */ 3156 */
3142 if(NULL == data->sample) 3157 if(NULL == data->sample)
3143 { 3158 {
3144 if( -1 == Reconstruct_Sound_Sample(data) ) 3159 if( -1 == Reconstruct_Sound_Sample(data) )
3145 { 3160 {
3146 return -1; 3161 return AL_FALSE;
3147 } 3162 }
3148 } 3163 }
3149 #endif 3164 #endif
3150 #endif 3165 #endif
3151 /* If access_data was set, then we still have the 3166 /* If access_data was set, then we still have the
3156 * get access to the buffers 3171 * get access to the buffers
3157 */ 3172 */
3158 if(NULL == data->sample) 3173 if(NULL == data->sample)
3159 { 3174 {
3160 ALmixer_SetError("Cannot seek because access_data flag was set false when data was initialized"); 3175 ALmixer_SetError("Cannot seek because access_data flag was set false when data was initialized");
3161 return -1; 3176 return AL_FALSE;
3162 } 3177 }
3163 3178
3164 byte_position = Convert_Msec_To_Byte_Pos(&data->sample->desired, msec); 3179 byte_position = Convert_Msec_To_Byte_Pos(&data->sample->desired, msec);
3165 return( Set_Predecoded_Seek_Position(data, byte_position) ); 3180 retval = Set_Predecoded_Seek_Position(data, byte_position);
3181 if(-1 == retval)
3182 {
3183 return AL_FALSE;
3184 }
3185 else
3186 {
3187 return AL_TRUE;
3188 }
3189
3166 } 3190 }
3167 else 3191 else
3168 { 3192 {
3169 /* Reset eof flag?? */ 3193 /* Reset eof flag?? */
3170 data->eof = 0; 3194 data->eof = 0;
3176 fprintf(stderr, "Sound seek error: %s\n", ALmixer_GetError()); 3200 fprintf(stderr, "Sound seek error: %s\n", ALmixer_GetError());
3177 /* Try rewinding to clean up? */ 3201 /* Try rewinding to clean up? */
3178 /* 3202 /*
3179 Internal_RewindData(data); 3203 Internal_RewindData(data);
3180 */ 3204 */
3181 return -1; 3205 return AL_FALSE;
3182 } 3206 }
3183 return 0; 3207 return AL_TRUE;
3184 } 3208 }
3185 3209
3186 return 0; 3210 return AL_TRUE;
3187 } 3211 }
3188 3212
3189 3213
3190 3214
3191 static ALint Internal_FadeInChannelTimed(ALint channel, ALmixer_Data* data, ALint loops, ALuint fade_ticks, ALint expire_ticks) 3215 static ALint Internal_FadeInChannelTimed(ALint channel, ALmixer_Data* data, ALint loops, ALuint fade_ticks, ALint expire_ticks)
4664 * so t = current_time-start_time / (end_time-start_time) 4688 * so t = current_time-start_time / (end_time-start_time)
4665 * 4689 *
4666 */ 4690 */
4667 delta_time = current_time - ALmixer_Channel_List[i].fade_start_time; 4691 delta_time = current_time - ALmixer_Channel_List[i].fade_start_time;
4668 t = (ALfloat) delta_time * ALmixer_Channel_List[i].fade_inv_time; 4692 t = (ALfloat) delta_time * ALmixer_Channel_List[i].fade_inv_time;
4669
4670 current_volume = (1.0f-t) * ALmixer_Channel_List[i].fade_start_volume 4693 current_volume = (1.0f-t) * ALmixer_Channel_List[i].fade_start_volume
4671 + t * ALmixer_Channel_List[i].fade_end_volume; 4694 + t * ALmixer_Channel_List[i].fade_end_volume;
4695 fprintf(stderr, "start_vol=%f, end_vol:%f, current_volume: %f\n", ALmixer_Channel_List[i].fade_start_volume, ALmixer_Channel_List[i].fade_end_volume, current_volume);
4672 4696
4673 /* Set the volume */ 4697 /* Set the volume */
4674 alSourcef(ALmixer_Channel_List[i].alsource, 4698 alSourcef(ALmixer_Channel_List[i].alsource,
4675 AL_MAX_GAIN, current_volume); 4699 AL_GAIN, current_volume);
4676 if((error = alGetError()) != AL_NO_ERROR) 4700 if((error = alGetError()) != AL_NO_ERROR)
4677 { 4701 {
4678 fprintf(stderr, "04Testing errpr before unqueue because getting stuff, for OS X this is expected: %s\n", 4702 fprintf(stderr, "04Testing errpr before unqueue because getting stuff, for OS X this is expected: %s\n",
4679 alGetString(error)); 4703 alGetString(error));
4680 } 4704 }
8303 8327
8304 /* This will rewind the SDL_Sound sample for streamed 8328 /* This will rewind the SDL_Sound sample for streamed
8305 * samples and start buffering up the data for the next 8329 * samples and start buffering up the data for the next
8306 * playback. This may require samples to be halted 8330 * playback. This may require samples to be halted
8307 */ 8331 */
8308 ALint ALmixer_RewindData(ALmixer_Data* data) 8332 ALboolean ALmixer_RewindData(ALmixer_Data* data)
8309 { 8333 {
8310 ALint retval; 8334 ALboolean retval;
8311 #ifdef ENABLE_ALMIXER_THREADS 8335 #ifdef ENABLE_ALMIXER_THREADS
8312 SDL_LockMutex(s_simpleLock); 8336 SDL_LockMutex(s_simpleLock);
8313 #endif 8337 #endif
8314 retval = Internal_RewindData(data); 8338 retval = Internal_RewindData(data);
8315 #ifdef ENABLE_ALMIXER_THREADS 8339 #ifdef ENABLE_ALMIXER_THREADS
8397 } 8421 }
8398 8422
8399 /* Might consider setting eof to 0 as a "feature" 8423 /* Might consider setting eof to 0 as a "feature"
8400 * This will allow seek to end to stay there because 8424 * This will allow seek to end to stay there because
8401 * Play automatically rewinds if at the end */ 8425 * Play automatically rewinds if at the end */
8402 ALint ALmixer_SeekData(ALmixer_Data* data, ALuint msec) 8426 ALboolean ALmixer_SeekData(ALmixer_Data* data, ALuint msec)
8403 { 8427 {
8404 ALint retval; 8428 ALboolean retval;
8405 #ifdef ENABLE_ALMIXER_THREADS 8429 #ifdef ENABLE_ALMIXER_THREADS
8406 SDL_LockMutex(s_simpleLock); 8430 SDL_LockMutex(s_simpleLock);
8407 #endif 8431 #endif
8408 retval = Internal_SeekData(data, msec); 8432 retval = Internal_SeekData(data, msec);
8409 #ifdef ENABLE_ALMIXER_THREADS 8433 #ifdef ENABLE_ALMIXER_THREADS