PageRenderTime 44ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/code/iphone/iphone_sound.c

https://github.com/nickfloyd/DoomClassic
C | 291 lines | 169 code | 58 blank | 64 comment | 37 complexity | c3e09046f23ea8608fd0d4ebf7cffde7 MD5 | raw file
  1. /*
  2. Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company.
  3. Copyright (C) 2009 Id Software, Inc.
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  15. */
  16. #include "../doomiphone.h"
  17. #import <AudioToolbox/AudioServices.h>
  18. typedef struct {
  19. unsigned sourceName; // OpenAL sourceName
  20. pkWav_t *sfx; // NULL if unused
  21. float volume; // stored for showSound display
  22. } channel_t;
  23. static ALCcontext *Context;
  24. static ALCdevice *Device;
  25. #define MAX_CHANNELS 16
  26. static channel_t s_channels[ MAX_CHANNELS ];
  27. cvar_t *s_sfxVolume;
  28. void Sound_StartLocalSound( const char *filename ) {
  29. Sound_StartLocalSoundAtVolume( filename, 1.0f );
  30. }
  31. void Sound_StartLocalSoundAtVolume( const char *filename, float volume ) {
  32. pkWav_t *sfx;
  33. sfx = PK_FindWav( filename );
  34. if( ! sfx ) {
  35. Com_Printf( "Sound_StartLocalSound: could not cache (%s)\n", filename );
  36. return;
  37. }
  38. // printf( "sound:%s\n", filename );
  39. // channel 0 is reserved for UI sounds, the other channels
  40. // are for DOOM sounds
  41. channel_t *ch = &s_channels[ 0 ];
  42. ch->sfx = sfx;
  43. ch->volume = s_sfxVolume->value * volume;
  44. alSourceStop( ch->sourceName );
  45. alSourcef( ch->sourceName, AL_GAIN, ch->volume );
  46. alSourcei( ch->sourceName, AL_BUFFER, sfx->alBufferNum );
  47. alSourcef( ch->sourceName, AL_PITCH, 1.0f );
  48. alSourcePlay( ch->sourceName );
  49. }
  50. static void Sound_Play_f( void ) {
  51. if( Cmd_Argc() == 1 ) {
  52. Com_Printf( "Usage: play <soundfile>\n" );
  53. return;
  54. }
  55. Sound_StartLocalSound( Cmd_Argv( 1 ) );
  56. }
  57. // we won't allow music to be toggled on or off in the menu when this is true
  58. int otherAudioIsPlaying;
  59. int SysIPhoneOtherAudioIsPlaying() {
  60. return otherAudioIsPlaying;
  61. }
  62. void interruptionListener( void *inUserData, UInt32 inInterruption)
  63. {
  64. printf("Session interrupted! --- %s ---\n", inInterruption == kAudioSessionBeginInterruption ? "Begin Interruption" : "End Interruption");
  65. if ( inInterruption == kAudioSessionBeginInterruption ) {
  66. printf("Audio interrupted.\n" );
  67. iphonePauseMusic();
  68. alcMakeContextCurrent( NULL );
  69. AudioSessionSetActive( false );
  70. } else if ( inInterruption == kAudioSessionEndInterruption ) {
  71. printf("Audio restored.\n" );
  72. OSStatus r = AudioSessionSetActive( true );
  73. if ( r != kAudioSessionNoError ) {
  74. printf( "AudioSessionSetActive( true ) failed: 0x%x\n", r );
  75. } else {
  76. printf( "AudioSessionSetActive( true ) succeeded.\n" );
  77. }
  78. alcMakeContextCurrent( Context );
  79. if( alcGetError( Device ) != ALC_NO_ERROR ) {
  80. Com_Error( "Failed to alcMakeContextCurrent\n" );
  81. }
  82. iphoneResumeMusic();
  83. }
  84. }
  85. void Sound_Init( void ) {
  86. Com_Printf( "\n------- Sound Initialization -------\n" );
  87. s_sfxVolume = Cvar_Get( "s_sfxVolume", "1.0", 0 );
  88. Cmd_AddCommand( "play", Sound_Play_f );
  89. // make sure background ipod music mixes with our sound effects
  90. Com_Printf( "...Initializing AudioSession\n" );
  91. OSStatus status = 0;
  92. status = AudioSessionInitialize(NULL, NULL, interruptionListener, NULL); // else "couldn't initialize audio session"
  93. // if there is iPod music playing in the background, we want to use
  94. // the AmbientSound catagory, otherwise we will leave it at the default.
  95. // If we always set it to AmbientSound, then the mp3 background music
  96. // playback goes to software on 3.0 for a huge slowdown.
  97. UInt32 propOtherAudioIsPlaying = 'othr'; // kAudioSessionProperty_OtherAudioIsPlaying
  98. UInt32 size = sizeof( otherAudioIsPlaying );
  99. AudioSessionGetProperty( propOtherAudioIsPlaying, &size, &otherAudioIsPlaying );
  100. Com_Printf("OtherAudioIsPlaying = %d\n", otherAudioIsPlaying );
  101. if ( otherAudioIsPlaying ) {
  102. UInt32 audioCategory = kAudioSessionCategory_AmbientSound;
  103. status = AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(audioCategory), &audioCategory);
  104. }
  105. status = AudioSessionSetActive(true); // else "couldn't set audio session active\n"
  106. Com_Printf( "...Initializing OpenAL subsystem\n" );
  107. // get the OpenAL device
  108. Device = alcOpenDevice( NULL );
  109. if( Device == NULL ) {
  110. Com_Printf( "Failed to alcOpenDevice\n" );
  111. }
  112. // Create context(s)
  113. Context = alcCreateContext( Device, NULL );
  114. if( Context == NULL ) {
  115. Com_Error( "Failed to alcCreateContext\n" );
  116. }
  117. // Set active context
  118. alcGetError( Device );
  119. alcMakeContextCurrent( Context );
  120. if( alcGetError( Device ) != ALC_NO_ERROR ) {
  121. Com_Error( "Failed to alcMakeContextCurrent\n" );
  122. }
  123. // allocate all the channels we are going to use
  124. channel_t *ch;
  125. int i;
  126. for( i = 0, ch = s_channels ; i < MAX_CHANNELS ; ++i, ++ch ) {
  127. alGenSources( 1, &ch->sourceName );
  128. if( alGetError() != AL_NO_ERROR ) {
  129. Com_Error( "Allocating AL sound sources" );
  130. }
  131. alSourcei( ch->sourceName, AL_SOURCE_RELATIVE, AL_FALSE );
  132. }
  133. Com_Printf( "------------------------------------\n" );
  134. }
  135. /*
  136. ==================
  137. ShowSound
  138. Display active sound channels
  139. ==================
  140. */
  141. void ShowSound() {
  142. if ( !showSound->value ) {
  143. return;
  144. }
  145. channel_t *ch;
  146. int i;
  147. for( i = 0, ch = s_channels ; i < MAX_CHANNELS ; ++i, ++ch ) {
  148. int state;
  149. alGetSourcei( ch->sourceName, AL_SOURCE_STATE, &state );
  150. if ( state != AL_PLAYING ) {
  151. continue;
  152. }
  153. int v = ch->volume * 255;
  154. if ( v > 255 ) {
  155. v = 255;
  156. }
  157. color4_t color = { v, v, v, 255 };
  158. R_Draw_Fill( i*16, 0, 12, 12, color );
  159. }
  160. }
  161. /*
  162. ==================================================================
  163. PrBoom interface
  164. ==================================================================
  165. */
  166. // Init at program start...
  167. void I_InitSound(void) {}
  168. // ... shut down and relase at program termination.
  169. void I_ShutdownSound(void) {}
  170. // Initialize channels?
  171. void I_SetChannels(void) {}
  172. // Get raw data lump index for sound descriptor.
  173. int I_GetSfxLumpNum (sfxinfo_t *sfx) {
  174. // find the pkWav_t for this sfxinfo
  175. char upper[16], *d = upper;
  176. for ( const char *c = sfx->name ; *c ; c++ ) {
  177. *d++ = toupper( *c );
  178. }
  179. *d = 0;
  180. pkWav_t *pkwav = PK_FindWav( va( "newsfx/DS%s.wav", upper ) );
  181. return pkwav - pkWavs;
  182. }
  183. // Starts a sound in a particular sound channel.
  184. // volume ranges 0 - 64
  185. // seperation tanges is 128 straight ahead, 0 = all left ear, 255 = all right ear
  186. // pitch centers around 128
  187. int I_StartSound(int sfx_id, int channel, int vol, int sep, int pitch, int priority) {
  188. sfxinfo_t *dsfx = &S_sfx[sfx_id];
  189. assert( dsfx->lumpnum >= 0 && dsfx->lumpnum < pkHeader->wavs.count );
  190. pkWav_t *sfx = &pkWavs[dsfx->lumpnum];
  191. // printf( "sound: %s chan:%i vol:%i sep:%i pitch:%i priority:%i\n", sfx->wavData->name.name, channel, vol, sep, pitch, priority );
  192. assert( channel >= 0 && channel < MAX_CHANNELS - 1 );
  193. channel_t *ch = &s_channels[ 1+channel ];
  194. alSourceStop( ch->sourceName );
  195. if ( ch->sfx == sfx ) {
  196. // restarting the same sound
  197. alSourceRewind( ch->sourceName );
  198. } else {
  199. alSourcei( ch->sourceName, AL_BUFFER, sfx->alBufferNum );
  200. }
  201. ch->sfx = sfx;
  202. ch->volume = s_sfxVolume->value * vol / 64.0;
  203. alSourcef( ch->sourceName, AL_GAIN, ch->volume );
  204. alSourcef( ch->sourceName, AL_PITCH, pitch / 128.0f );
  205. alSourcePlay( ch->sourceName );
  206. return (int)ch;
  207. }
  208. // Stops a sound channel.
  209. void I_StopSound(int handle) {}
  210. // Called by S_*() functions
  211. // to see if a channel is still playing.
  212. // Returns 0 if no longer playing, 1 if playing.
  213. boolean I_SoundIsPlaying(int handle) {
  214. channel_t *ch = (channel_t *)handle;
  215. if ( !ch ) {
  216. return false;
  217. }
  218. int state;
  219. alGetSourcei( ch->sourceName, AL_SOURCE_STATE, &state );
  220. return state == AL_PLAYING;
  221. }
  222. // Called by m_menu.c to let the quit sound play and quit right after it stops
  223. boolean I_AnySoundStillPlaying(void) { return false; }
  224. // Updates the volume, separation,
  225. // and pitch of a sound channel.
  226. void I_UpdateSoundParams(int handle, int vol, int sep, int pitch) {}