Mercurial > almixer_isolated
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(¤t_time); | 315 QueryPerformanceCounter(¤t_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, ¤t_time); | 322 clock_gettime(CLOCK_MONOTONIC, ¤t_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 |