Supporting both WAV and OGG for sound effects.

Supporting "_desc" and "_desc_ll" (localized) descriptive sound effects
(see recent Catalan OGGs added to tuxpaint-stamps!)
This commit is contained in:
William Kendrick 2006-08-26 23:45:29 +00:00
parent ad42ce58d6
commit d12bef8753
2 changed files with 142 additions and 32 deletions

View file

@ -38,6 +38,11 @@ $Id$
* Sound effects take advantage of stereo. (e.g., paint brush sounds come * Sound effects take advantage of stereo. (e.g., paint brush sounds come
more from the left speaker when painting on the left.) more from the left speaker when painting on the left.)
* Stamp sound effects may be in either OGG or WAV format.
* Stamps may now include a second sound effect, used as a spoken description.
(stampname_desc.ogg or .wav and localized stampname_desc_ll.ogg or .wav)
* Tool improvements: * Tool improvements:
------------------------ ------------------------
* Magic Sparkles can now be different colors. * Magic Sparkles can now be different colors.

View file

@ -22,7 +22,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
(See COPYING.txt) (See COPYING.txt)
June 14, 2002 - June 2, 2006 June 14, 2002 - August 26, 2006
$Id$ $Id$
*/ */
@ -76,6 +76,8 @@
#error No alt print method defined! #error No alt print method defined!
#endif #endif
#define MAX_PATH 256
/* Compile-time options: */ /* Compile-time options: */
@ -880,6 +882,7 @@ typedef struct stamp_type {
char *stxt; char *stxt;
#ifndef NOSOUND #ifndef NOSOUND
Mix_Chunk *ssnd; Mix_Chunk *ssnd;
Mix_Chunk *sdesc;
#endif #endif
SDL_Surface *thumbnail; SDL_Surface *thumbnail;
@ -890,6 +893,7 @@ typedef struct stamp_type {
unsigned processed : 1; // got *.dat, computed size limits, etc. unsigned processed : 1; // got *.dat, computed size limits, etc.
unsigned no_sound : 1; unsigned no_sound : 1;
unsigned no_descsound : 1;
unsigned no_txt : 1; unsigned no_txt : 1;
// unsigned no_local_sound : 1; // to remember, if code written to discard sound // unsigned no_local_sound : 1; // to remember, if code written to discard sound
@ -1070,6 +1074,8 @@ static char * loaddesc(const char * const fname);
static double loadinfo(const char * const fname, stamp_type *inf); static double loadinfo(const char * const fname, stamp_type *inf);
#ifndef NOSOUND #ifndef NOSOUND
static Mix_Chunk * loadsound(const char * const fname); static Mix_Chunk * loadsound(const char * const fname);
static Mix_Chunk * loaddescsound(const char * const fname);
static void playstampdesc(int chan);
#endif #endif
static void do_wait(int counter); static void do_wait(int counter);
static void load_current(void); static void load_current(void);
@ -1137,6 +1143,7 @@ static int charsize(char c);
#define MAX_UTF8_CHAR_LENGTH 6 #define MAX_UTF8_CHAR_LENGTH 6
#define USEREVENT_TEXT_UPDATE 1 #define USEREVENT_TEXT_UPDATE 1
#define USEREVENT_PLAYDESCSOUND 2
#define TP_SDL_MOUSEBUTTONSCROLL (SDL_USEREVENT + 1) #define TP_SDL_MOUSEBUTTONSCROLL (SDL_USEREVENT + 1)
@ -2439,11 +2446,33 @@ static void mainloop(void)
else if (cur_tool == TOOL_STAMP) else if (cur_tool == TOOL_STAMP)
{ {
#ifndef NOSOUND #ifndef NOSOUND
if (toolopt_changed) // Only play when picking a different stamp
if (toolopt_changed && !mute)
{ {
// Only play when picking a different stamp // If there's an SFX, play it!
if (stamp_data[cur_thing]->ssnd != NULL && !mute)
if (stamp_data[cur_thing]->ssnd != NULL)
{
Mix_ChannelFinished(NULL); // Prevents multiple clicks from toggling between SFX and desc sound, rather than always playing SFX first, then desc sound...
Mix_PlayChannel(2, stamp_data[cur_thing]->ssnd, 0); Mix_PlayChannel(2, stamp_data[cur_thing]->ssnd, 0);
// If there's a description sound, play it after the SFX!
if (stamp_data[cur_thing]->sdesc != NULL)
{
Mix_ChannelFinished(playstampdesc);
}
}
else
{
// No SFX? If there's a description sound, play it now!
if (stamp_data[cur_thing]->sdesc != NULL)
{
Mix_PlayChannel(2, stamp_data[cur_thing]->sdesc, 0);
}
}
} }
#endif #endif
@ -2845,6 +2874,25 @@ static void mainloop(void)
else else
draw_tux_text(TUX_GREAT, "", 1); draw_tux_text(TUX_GREAT, "", 1);
} }
else if (event.user.code == USEREVENT_PLAYDESCSOUND)
{
/* Play a stamp's spoken description (because the sound effect just finished) */
/* (This event is pushed into the queue by playstampdesc(), which
is a callback from Mix_ChannelFinished() when playing a stamp SFX) */
debug("Playing description sound...");
Mix_ChannelFinished(NULL); // Kill the callback, so we don't get stuck in a loop!
if (event.user.data1 != NULL)
{
if ((int) event.user.data1 == cur_stamp) // Don't play old stamp's sound...
{
if (!mute && stamp_data[(int) event.user.data1]->sdesc != NULL)
Mix_PlayChannel(2, stamp_data[(int) event.user.data1]->sdesc, 0);
}
}
}
} }
else if (event.type == SDL_MOUSEBUTTONUP) else if (event.type == SDL_MOUSEBUTTONUP)
{ {
@ -5193,8 +5241,21 @@ static void get_stamp_thumb(stamp_type *sd)
// damn thing wants a .png extension; give it one // damn thing wants a .png extension; give it one
memcpy(buf+len, ".png", 5); memcpy(buf+len, ".png", 5);
sd->ssnd = loadsound(buf); sd->ssnd = loadsound(buf);
if (sd->ssnd == NULL)
printf("ssnd NULL!\n");
sd->no_sound = !sd->ssnd; sd->no_sound = !sd->ssnd;
} }
// ...and the description
if(!sd->no_descsound && !sd->sdesc && use_sound)
{
// damn thing wants a .png extension; give it one
memcpy(buf+len, ".png", 5);
sd->sdesc = loaddescsound(buf);
if (sd->sdesc == NULL)
printf("sdesc NULL!\n");
sd->no_descsound = !sd->sdesc;
}
#endif #endif
if(!sd->no_txt && !sd->stxt) if(!sd->no_txt && !sd->stxt)
@ -9099,20 +9160,38 @@ static void wordwrap_text(const char * const str, SDL_Color color,
} }
#ifndef NOSOUND
static void playstampdesc(int chan)
{
static SDL_Event playsound_event;
if (chan == 2) // Only do this when the channel playing the stamp sfx has ended!
{
debug("Stamp SFX ended. Pushing event to play description sound...");
playsound_event.type = SDL_USEREVENT;
playsound_event.user.code = USEREVENT_PLAYDESCSOUND;
playsound_event.user.data1 = (void*) cur_stamp;
SDL_PushEvent(&playsound_event);
}
}
#endif
/* Load a file's sound: */ /* Load a file's sound: */
#ifndef NOSOUND #ifndef NOSOUND
static Mix_Chunk * loadsound(const char * const fname) static Mix_Chunk * loadsound_extra(const char * const fname, const char * extra)
{ {
char * snd_fname; char * snd_fname;
char tmp_str[64], ext[5]; char tmp_str[MAX_PATH], ext[5];
Mix_Chunk * tmp_snd; Mix_Chunk * tmp_snd;
debug(fname);
if (strcasestr(fname, ".png") != NULL) if (strcasestr(fname, ".png") != NULL)
{ {
strcpy(ext, ".png"); strcpy(ext, ".png");
@ -9127,44 +9206,65 @@ static Mix_Chunk * loadsound(const char * const fname)
/* First, check for localized version of sound: */ /* First, check for localized version of sound: */
snd_fname = malloc(strlen(fname) + strlen(lang_prefix) + 2); snd_fname = malloc(strlen(fname) + strlen(lang_prefix) + 16);
strcpy(snd_fname, fname); strcpy(snd_fname, fname);
snprintf(tmp_str, sizeof(tmp_str), "_%s.wav", lang_prefix); snprintf(tmp_str, sizeof(tmp_str), "%s_%s.ogg", extra, lang_prefix);
strcpy((char *) strcasestr(snd_fname, ext), tmp_str); strcpy((char *) strcasestr(snd_fname, ext), tmp_str);
debug(snd_fname); debug(snd_fname);
tmp_snd = Mix_LoadWAV(snd_fname); tmp_snd = Mix_LoadWAV(snd_fname);
if (tmp_snd == NULL) if (tmp_snd == NULL)
{ {
debug("...No local version of sound!"); debug("...No local version of sound (OGG)!");
/* Now, check for default sound: */ strcpy(snd_fname, fname);
snprintf(tmp_str, sizeof(tmp_str), "%s_%s.wav", extra, lang_prefix);
free(snd_fname); strcpy((char *) strcasestr(snd_fname, ext), tmp_str);
snd_fname = strdup(fname);
strcpy((char *) strcasestr(snd_fname, ext), ".wav");
debug(snd_fname); debug(snd_fname);
tmp_snd = Mix_LoadWAV(snd_fname); tmp_snd = Mix_LoadWAV(snd_fname);
free(snd_fname);
if (tmp_snd == NULL) if (tmp_snd == NULL)
{ {
debug("...No default version of sound!"); debug("...No local version of sound (WAV)!");
return NULL;
}
return (tmp_snd); /* Now, check for default sound: */
}
else strcpy(snd_fname, fname);
{ snprintf(tmp_str, sizeof(tmp_str), "%s.ogg", extra);
return NULL; strcpy((char *) strcasestr(snd_fname, ext), tmp_str);
debug(snd_fname);
tmp_snd = Mix_LoadWAV(snd_fname);
if (tmp_snd == NULL)
{
debug("...No default version of sound (OGG)!");
strcpy(snd_fname, fname);
snprintf(tmp_str, sizeof(tmp_str), "%s.wav", extra);
strcpy((char *) strcasestr(snd_fname, ext), tmp_str);
debug(snd_fname);
tmp_snd = Mix_LoadWAV(snd_fname);
if (tmp_snd == NULL)
debug("...No default version of sound (WAV)!");
}
}
} }
free(snd_fname);
return (tmp_snd);
}
static Mix_Chunk * loadsound(const char * const fname)
{
return(loadsound_extra(fname, ""));
}
static Mix_Chunk * loaddescsound(const char * const fname)
{
return(loadsound_extra(fname, "_desc"));
} }
#endif #endif
@ -10178,6 +10278,11 @@ static void cleanup(void)
Mix_FreeChunk(stamp_data[i]->ssnd); Mix_FreeChunk(stamp_data[i]->ssnd);
stamp_data[i]->ssnd = NULL; stamp_data[i]->ssnd = NULL;
} }
if (stamp_data[i]->sdesc)
{
Mix_FreeChunk(stamp_data[i]->sdesc);
stamp_data[i]->sdesc = NULL;
}
#endif #endif
if (stamp_data[i]->stxt) if (stamp_data[i]->stxt)
{ {