Fix segfault sound-thread (mutex), Add Portal sound
Major changes to sound.c:
    - add mutex (fixes segfault, free erros)
    - allow only one sound at a time, wait for previous to finish
    - outsource init function
    - add global variables
    - return if successfully played
			
			
This commit is contained in:
		
							parent
							
								
									52c0838dec
								
							
						
					
					
						commit
						6b4bcb09a8
					
				| @ -7,7 +7,7 @@ | ||||
| //======== playSound ========
 | ||||
| //===========================
 | ||||
| //abstract function that plays sound with provided path to .wav file
 | ||||
| //wait parameter blocks program until playback finished (otherwise launched in another thread)
 | ||||
| //'wait' parameter blocks program until playback is finished (otherwise launched in another thread)
 | ||||
| int playSound(const char * filePath, bool wait); | ||||
| 
 | ||||
| 
 | ||||
| @ -15,6 +15,6 @@ int playSound(const char * filePath, bool wait); | ||||
| //===== playSoundAsync =====
 | ||||
| //==========================
 | ||||
| //launches playSound in another thread to prevent delay
 | ||||
| //due to loading file taking up to 300ms
 | ||||
| //due to loading of wav file taking up to 300ms
 | ||||
| //(equivalent to playsound() with parameter wait=false)
 | ||||
| void playSoundAsync(const char *filePath); | ||||
| int playSoundAsync(const char *filePath); | ||||
							
								
								
									
										
											BIN
										
									
								
								sounds/portal1_short.wav
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								sounds/portal1_short.wav
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								sounds/portal2_oscillate.wav
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								sounds/portal2_oscillate.wav
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								sounds/portal3_in-out.wav
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								sounds/portal3_in-out.wav
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								sounds/portal4_ramp.wav
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								sounds/portal4_ramp.wav
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								sounds/space-gun.wav
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								sounds/space-gun.wav
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| @ -69,8 +69,15 @@ void handlePortals() | ||||
|         portal_t p = game.map.portals[i]; //copy curren portal (code more readable)
 | ||||
|         // is at portal
 | ||||
|         if (game.snake.headX == p.posX && game.snake.headY == p.posY){ | ||||
|             //-- update head pos ---
 | ||||
|             snakeSetHeadPos(p.targetX, p.targetY); | ||||
|             LOGI("game: entered portal i=%d at x=%d, y=%d -> set head to x=%d y=%d\n", i, p.posX, p.posY, p.targetX, p.targetY); | ||||
|             //--- play sound ---
 | ||||
|             //playSoundAsync("../sounds/portal1_short.wav"); //too short
 | ||||
|             //playSoundAsync("../sounds/portal2_oscillate.wav"); //too much bass
 | ||||
|             //playSoundAsync("../sounds/space-gun.wav"); //too loud
 | ||||
|             playSoundAsync("../sounds/portal3_in-out.wav"); | ||||
|             //playSoundAsync("../sounds/portal4_ramp.wav");
 | ||||
|             return; | ||||
|         } | ||||
|     } | ||||
|  | ||||
							
								
								
									
										86
									
								
								src/sound.c
									
									
									
									
									
								
							
							
						
						
									
										86
									
								
								src/sound.c
									
									
									
									
									
								
							| @ -6,6 +6,36 @@ | ||||
| #include "sound.h" | ||||
| 
 | ||||
| 
 | ||||
| //--- global variables in sound.c ---
 | ||||
| // mutex to prevent segfaults while working with multiple threads
 | ||||
| pthread_mutex_t mutexSoundPlaying; | ||||
| // initialize audio only once
 | ||||
| static bool audioIsInitialized = false; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| //---------------------------
 | ||||
| //-------- initAudio --------
 | ||||
| //---------------------------
 | ||||
| // initialize SDL audio and mutex if not done already
 | ||||
| int initAudio() | ||||
| { | ||||
|     if (!audioIsInitialized) | ||||
|     { | ||||
|         //--- initialize mutex ---
 | ||||
|         pthread_mutex_init(&mutexSoundPlaying, NULL); | ||||
|         //--- initialize SDL audio ---
 | ||||
|         if (SDL_Init(SDL_INIT_AUDIO) < 0) | ||||
|         { | ||||
|             printf("SDL: could not init audio!\n"); | ||||
|             return 1; | ||||
|         } | ||||
|         audioIsInitialized = true; | ||||
|         LOGI("sound: initialized SDL audio\n"); | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| //===========================
 | ||||
| //======== playSound ========
 | ||||
| @ -14,41 +44,24 @@ | ||||
| //wait parameter blocks program until playback finished
 | ||||
| int playSound(const char *filePath, bool wait) | ||||
| { | ||||
|     //TODO add volume % option
 | ||||
| 
 | ||||
|     //--- run async when wait is not set ---
 | ||||
|     if (!wait){ | ||||
|         playSoundAsync(filePath); | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
|     //--- variables ---
 | ||||
|     static bool soundInitialized = false; | ||||
|     static bool deviceExists = false; | ||||
|     static uint8_t *wavBuffer; | ||||
|     static SDL_AudioDeviceID deviceId; | ||||
|     SDL_AudioSpec wavSpec; | ||||
|     uint32_t wavLength; | ||||
| 
 | ||||
|     //--- initialize SDL audio ---
 | ||||
|     if (!soundInitialized) | ||||
|     { | ||||
|         if (SDL_Init(SDL_INIT_AUDIO) < 0) | ||||
|         { | ||||
|             printf("SDL: could not init audio!\n"); | ||||
|             return 1; | ||||
|         } | ||||
|         LOGI("sound: initialized SDL audio\n"); | ||||
|     //--- initialize audio --- 
 | ||||
|     // initializes if not done already, exit if failed
 | ||||
|     if (initAudio()) return 1; | ||||
| 
 | ||||
|     //--- run async when wait is not set ---
 | ||||
|     if (!wait){ | ||||
|         return playSoundAsync(filePath); | ||||
|     } | ||||
| 
 | ||||
|     //--- close device and free memory of previous sound ---
 | ||||
|     //note: also cancels currently playing sound
 | ||||
|     if (deviceExists) | ||||
|     { | ||||
|         SDL_CloseAudioDevice(deviceId); | ||||
|         // free memory of previously played file
 | ||||
|         SDL_FreeWAV(wavBuffer); | ||||
|     } | ||||
|     //=== lock mutex ===
 | ||||
|     pthread_mutex_lock(&mutexSoundPlaying); | ||||
| 
 | ||||
|     //--- load file ---
 | ||||
|     if (SDL_LoadWAV(filePath, &wavSpec, &wavBuffer, &wavLength) == NULL) | ||||
| @ -62,14 +75,21 @@ int playSound(const char *filePath, bool wait) | ||||
|     deviceExists = true; | ||||
|     SDL_QueueAudio(deviceId, wavBuffer, wavLength); | ||||
|     SDL_PauseAudioDevice(deviceId, 0); | ||||
|     LOGI("sound: success, playing file '%s'\n", filePath); | ||||
|     LOGI("sound: playing file '%s'\n", filePath); | ||||
| 
 | ||||
|     //--- wait until playback is finished --- (if desired)
 | ||||
|     //--- wait until playback is finished ---
 | ||||
|     while (SDL_GetQueuedAudioSize(deviceId) > 0) | ||||
|     { | ||||
|         SDL_Delay(100); | ||||
|     } | ||||
| 
 | ||||
|     //--- close device and free memory ---
 | ||||
|     SDL_CloseAudioDevice(deviceId); | ||||
|     SDL_FreeWAV(wavBuffer); | ||||
| 
 | ||||
|     //=== unlock mutex ===
 | ||||
|     pthread_mutex_unlock(&mutexSoundPlaying); | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| @ -95,12 +115,16 @@ void *playSoundThread(void *filePath) { | ||||
| // play audio file asynchronously
 | ||||
| // creates separate thread which runs playSound 
 | ||||
| // -> program does not get blocked by up to 300ms for loading the file
 | ||||
| void playSoundAsync(const char *filePath) { | ||||
| int playSoundAsync(const char *filePath) { | ||||
|     //--- initialize audio --- 
 | ||||
|     // initializes if not done already, exit if failed
 | ||||
|     if (initAudio()) return 1; | ||||
| 
 | ||||
|     //--- allocate memory for filePath ---
 | ||||
|     char *filePathCopy = strdup(filePath); | ||||
|     if (filePathCopy == NULL) { | ||||
|         fprintf(stderr, "Memory allocation failed\n"); | ||||
|         return; | ||||
|         return 1; | ||||
|     } | ||||
| 
 | ||||
|     //--- create new thread ---
 | ||||
| @ -108,8 +132,10 @@ void playSoundAsync(const char *filePath) { | ||||
|     if (pthread_create(&thread, NULL, playSoundThread, filePathCopy) != 0) { | ||||
|         fprintf(stderr, "Failed to create thread\n"); | ||||
|         free(filePathCopy); | ||||
|         return 1; | ||||
|     } else { | ||||
|         // detach the thread to clean up automatically when it exits
 | ||||
|         pthread_detach(thread); | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user