/* ================== S_RegisterSound Creates a default buzz sound if the file can't be loaded ================== */ sfxHandle_t S_Base_RegisterSound( const char *name, qboolean compressed ) { sfx_t *sfx; compressed = qfalse; if (!s_soundStarted) { return 0; } if ( strlen( name ) >= MAX_QPATH ) { Com_Printf( "Sound name exceeds MAX_QPATH\n" ); return 0; } sfx = S_FindName( name ); if ( sfx->soundData ) { if ( sfx->defaultSound ) { Com_Printf( S_COLOR_YELLOW "WARNING: could not find %s - using default\n", sfx->soundName ); return 0; } return sfx - s_knownSfx; } sfx->inMemory = qfalse; sfx->soundCompressed = compressed; S_memoryLoad(sfx); if ( sfx->defaultSound ) { Com_Printf( S_COLOR_YELLOW "WARNING: could not find %s - using default\n", sfx->soundName ); return 0; } return sfx - s_knownSfx; }
/* ================== S_TouchSound ================== */ void S_TouchSound (char *name) { sfx_t *sfx; sfx = S_FindName (name); Cache_Check (&sfx->cache); }
/** * @brief Creates a default buzz sound if the file can't be loaded */ sfxHandle_t S_Base_RegisterSound(const char *name, qboolean compressed) { sfx_t *sfx; compressed = qfalse; // FIXME: non WAV if (!s_soundStarted) { return 0; } if (!name) { Com_DPrintf(S_COLOR_RED "ERROR: [S_AL_RegisterSound: NULL"); return 0; } if (!name[0]) { Com_DPrintf(S_COLOR_RED "ERROR: [S_AL_RegisterSound: empty name"); return 0; } if (strlen(name) >= MAX_QPATH) { Com_DPrintf(S_COLOR_RED "ERROR: [S_Base_RegisterSound] Sound name exceeds MAX_QPATH - %s\n", name); return 0; } sfx = S_FindName(name); if (!sfx) { return 0; } if (sfx->soundData) { if (sfx->defaultSound) { Com_DPrintf(S_COLOR_YELLOW "WARNING: [S_Base_RegisterSound]: could not find %s - using default\n", sfx->soundName); return 0; } return sfx - knownSfx; } sfx->inMemory = qfalse; sfx->soundCompressed = compressed; S_memoryLoad(sfx); if (sfx->defaultSound) { Com_DPrintf(S_COLOR_YELLOW "WARNING: [S_Base_RegisterSound] could not find %s - using default\n", sfx->soundName); return 0; } return sfx - knownSfx; }
/* ================== S_TouchSound ================== */ void S_TouchSound (char *name) { sfx_t *sfx; if (!sound_started) return; sfx = S_FindName (name); Cache_Check (&sfx->cache); }
struct sfx_s *S_RegisterSexedSound (entity_state_t *ent, char *base) { int n; char *p; struct sfx_s *sfx; FILE *f; char model[MAX_QPATH]; char sexedFilename[MAX_QPATH]; char maleFilename[MAX_QPATH]; // determine what model the client is using model[0] = 0; n = CS_PLAYERSKINS + ent->number - 1; if (cl.configstrings[n][0]) { p = strchr(cl.configstrings[n], '\\'); if (p) { p += 1; strcpy(model, p); p = strchr(model, '/'); if (p) *p = 0; } } // if we can't figure it out, they're male if (!model[0]) strcpy(model, "male"); // see if we already know of the model specific sound Com_sprintf (sexedFilename, sizeof(sexedFilename), "#players/%s/%s", model, base+1); sfx = S_FindName (sexedFilename, false); if (!sfx) { // no, so see if it exists FS_FOpenFile (&sexedFilename[1], &f); if (f) { // yes, close the file and register it FS_FCloseFile (f); sfx = S_RegisterSound (sexedFilename); } else { // no, revert to the male sound in the pak0.pak Com_sprintf (maleFilename, sizeof(maleFilename), "player/%s/%s", "male", base+1); sfx = S_AliasName (sexedFilename, maleFilename); } } return sfx; }
/* ================== S_RegisterSound ================== */ sfx_t *S_RegisterSound (const char *name) { sfx_t *sfx; if (!sound_started) return NULL; sfx = S_FindName (name, true); if (!s_registering) S_LoadSound(sfx); return sfx; }
/* ================== S_RegisterSound ================== */ sfx_t *S_RegisterSound (char *name) { sfx_t *sfx; if (!sound_started) return NULL; sfx = S_FindName (name, true); sfx->registration_sequence = s_registration_sequence; if (!s_registering) S_LoadSound (sfx); return sfx; }
sfx_t *S_RegisterSound(const char *name) { if (!sound_started) return NULL; sfx_t *sfx = S_FindName(name, true); sfx->registration_sequence = s_registration_sequence; if (!s_registering) S_LoadSound(sfx); else if (name[0] != '#' && name[0] != '*' && !GFileSystem->FileExists(va("sound/%s", name))) sfx->absent = true; return sfx; }
/* ================== S_PrecacheSound ================== */ sfx_t *S_PrecacheSound (char *name) { sfx_t *sfx; if (!snd_initialized) return NULL; sfx = S_FindName (name); // cache it in if (!s_nosound.value || s_precache.value) S_LoadSound (sfx); return sfx; }
/* ================== S_PrecacheSound ================== */ sfx_t *S_PrecacheSound (char *name) { sfx_t *sfx; if (!sound_started || nosound.value) return NULL; sfx = S_FindName (name); // cache it in if (precache.value) S_LoadSound (sfx); return sfx; }
static sfx_t *GetPlayerSound(clEntityState_t *ent, const char *base) { clientInfo_t &ci = cl.clientInfo[ent->number - 1]; // may use ent->skinnum & 0xFF too ... bool isFemale = ci.modelGender == 'f'; // see if we already know of the model specific sound TString<MAX_QPATH> LocalFilename; LocalFilename.sprintf("#players/%s/%s", *ci.ModelName, base+1); sfx_t *sfx = S_FindName(LocalFilename, false); if (sfx) return sfx; // try sound in Quake2 model directory ("players/[model_name]/[sound]") if (GFileSystem->FileExists(LocalFilename + 1)) { sfx = S_RegisterSound(LocalFilename); if (sfx) return sfx; } // try sound in Quake3 model directory ("sound/player/[model_name]/[sound]") static const struct { const char *q2name, *q3name; } convert[] = { {"death4.wav", "death1.wav"}, {"fall2.wav", "fall1.wav"}, {"pain25_2.wav", "pain25_1.wav"}, {"pain50_2.wav", "pain50_1.wav"}, {"pain75_2.wav", "pain75_1.wav"}, {"pain100_2.wav","pain100_1.wav"} }; // Quake3 models have no some Quake2 sounds const char *newName = base + 1; for (int i = 0; i < ARRAY_COUNT(convert); i++) if (!stricmp(newName, convert[i].q2name)) { newName = convert[i].q3name; break; } TString<MAX_QPATH> FileName2; FileName2.sprintf("sound/player/%s/%s", *ci.ModelName, newName); // NOTE: used below as filename2+6 too if (GFileSystem->FileExists(FileName2)) { sfx = S_AliasName(LocalFilename, FileName2 + 6 /* skip "sound/" */); if (sfx) return sfx; } // setup as default sound return S_AliasName(LocalFilename, va("player/%smale/%s", isFemale ? "fe" : "", base+1)); }
static struct sfx_s *S_RegisterSexedSound (int entnum, const char *base) { int n; char *p; struct sfx_s *sfx; char model[MAX_QPATH]; char sexedFilename[MAX_QPATH]; char maleFilename[MAX_QPATH]; // determine what model the client is using model[0] = 0; n = CS_PLAYERSKINS + entnum - 1; if (cl.configstrings[n][0]) { p = strchr(cl.configstrings[n], '\\'); if (p) { Q_strncpyz(model, p + 1, sizeof(model)); p = strchr(model, '/'); if (p) *p = 0; } } // if we can't figure it out, they're male if (!model[0]) strcpy(model, "male"); // see if we already know of the model specific sound Com_sprintf (sexedFilename, sizeof(sexedFilename), "#players/%s/%s", model, base+1); sfx = S_FindName (sexedFilename, false); if (!sfx) { // no, so see if it exists if (FS_LoadFile(sexedFilename + 1, NULL) > 0) { // yes, close the file and register it sfx = S_RegisterSound(sexedFilename); } else { // no, revert to the male sound in the pak0.pak Com_sprintf(maleFilename, sizeof(maleFilename), "player/%s/%s", "male", base+1); sfx = S_AliasName(sexedFilename, maleFilename); } } return sfx; }
void S_Play_f (void) { static int hash=345; int i; char name[256]; sfx_t *sfx; if (!sound_started || s_nosound.value) return; for (i=1; i < Cmd_Argc(); i++) { strcpy(name, Cmd_Argv(i)); FS_DefaultExtension (name, ".wav", sizeof(name)); sfx = S_FindName(name); S_StartSound(hash++, 0, sfx, listener_origin, 1.0, ATTN_NONE); } }
void S_PlayVol_f (void) { static int hash=543; int i; float vol; char name[256]; sfx_t *sfx; if (!sound_started || s_nosound.value) return; for (i=1; i < Cmd_Argc(); i+=2) { strcpy(name, Cmd_Argv(i)); FS_DefaultExtension (name, ".wav", sizeof(name)); sfx = S_FindName(name); vol = Q_atof(Cmd_Argv(i+1)); S_StartSound(hash++, 0, sfx, listener_origin, vol, ATTN_NONE); } }
sfx_t *S_PrecacheSound (char *name) { sfx_t *sfx; if (!snd_initialized || s_nosound.value) return NULL; if (name == NULL || name[0] == 0) return NULL; sfx = S_FindName (name); if (sfx == NULL) return NULL; // cache it in if (s_precache.value) S_LoadSound (sfx); return sfx; }
// link all sounds in sentence, start playing first word. void VOX_LoadSound( channel_t *pchan, const char *pszin ) { char buffer[512]; int i, cword; char pathbuffer[64]; char szpath[32]; voxword_t rgvoxword[CVOXWORDMAX]; char *psz; if( !pszin || !*pszin ) return; Q_memset( rgvoxword, 0, sizeof( voxword_t ) * CVOXWORDMAX ); Q_memset( buffer, 0, sizeof( buffer )); // lookup actual string in g_Sentences, // set pointer to string data psz = VOX_LookupString( pszin, NULL ); if( !psz ) { MsgDev( D_ERROR, "VOX_LoadSound: no sentence named %s\n", pszin ); return; } // get directory from string, advance psz psz = VOX_GetDirectory( szpath, psz ); if( Q_strlen( psz ) > sizeof( buffer ) - 1 ) { MsgDev( D_ERROR, "VOX_LoadSound: sentence is too long %s\n", psz ); return; } // copy into buffer Q_strcpy( buffer, psz ); psz = buffer; // parse sentence (also inserts null terminators between words) VOX_ParseString( psz ); // for each word in the sentence, construct the filename, // lookup the sfx and save each pointer in a temp array i = 0; cword = 0; while( rgpparseword[i] ) { // Get any pitch, volume, start, end params into voxword if( VOX_ParseWordParams( rgpparseword[i], &rgvoxword[cword], i == 0 )) { // this is a valid word (as opposed to a parameter block) Q_strcpy( pathbuffer, szpath ); Q_strncat( pathbuffer, rgpparseword[i], sizeof( pathbuffer )); Q_strncat( pathbuffer, ".wav", sizeof( pathbuffer )); // find name, if already in cache, mark voxword // so we don't discard when word is done playing rgvoxword[cword].sfx = S_FindName( pathbuffer, &( rgvoxword[cword].fKeepCached )); cword++; } i++; } VOX_LoadFirstWord( pchan, rgvoxword ); pchan->isSentence = true; pchan->sfx = rgvoxword[0].sfx; }
void R_CheckMP3s( const char *psDir ) { // Com_Printf(va("Scanning Dir: %s\n",psDir)); Com_Printf("."); // stops useful info scrolling off screen char **sysFiles, **dirFiles; int numSysFiles, i, numdirs; dirFiles = FS_ListFiles( psDir, "/", &numdirs); if (numdirs > 2) { for (i=2;i<numdirs;i++) { char sDirName[MAX_QPATH]; sprintf(sDirName, "%s\\%s", psDir, dirFiles[i]); R_CheckMP3s(sDirName); } } sysFiles = FS_ListFiles( psDir, ".mp3", &numSysFiles ); for(i=0; i<numSysFiles; i++) { char sFilename[MAX_QPATH]; sprintf(sFilename,"%s\\%s", psDir, sysFiles[i]); Com_Printf("%sFound file: %s",!i?"\n":"",sFilename); iFilesFound++; // read it in... // byte *pbData = NULL; int iSize = FS_ReadFile( sFilename, (void **)&pbData); if (pbData) { id3v1_1* pTAG; // do NOT check 'qbForceRescan' here as an opt, because we need to actually fill in 'pTAG' if there is one... // qboolean qbTagNeedsUpdating = (/* qbForceRescan || */ !MP3_ReadSpecialTagInfo(pbData, iSize, &pTAG))?qtrue:qfalse; if (pTAG == NULL || qbTagNeedsUpdating || qbForceRescan) { Com_Printf(" ( Updating )\n"); // I need to scan this file to get the volume... // // For EF1 I used a temp sfx_t struct, but I can't do that now with this new alloc scheme, // I have to ask for it legally, so I'll keep re-using one, and restoring it's name after use. // (slightly dodgy, but works ok if no-one else changes stuff) // //sfx_t SFX = {0}; extern sfx_t *S_FindName( const char *name ); // static sfx_t *pSFX = NULL; const char sReservedSFXEntrynameForMP3[] = "reserved_for_mp3"; // ( strlen() < MAX_QPATH ) if (pSFX == NULL) // once only { pSFX = S_FindName(sReservedSFXEntrynameForMP3); // always returns, else ERR_FATAL } if (MP3_IsValid(sFilename,pbData, iSize, qbForceStereo)) { wavinfo_t info; int iRawPCMDataSize = MP3_GetUnpackedSize(sFilename, pbData, iSize, qtrue, qbForceStereo); if (iRawPCMDataSize) // should always be true, unless file is f****d, in which case, stop this conversion process { float fMaxVol = 128; // any old default int iActualUnpackedSize = iRawPCMDataSize; // default, override later if not doing music if (!qbForceStereo) // no point for stereo files, which are for music and therefore no lip-sync { byte *pbUnpackBuffer = (byte *) Z_Malloc ( iRawPCMDataSize+10, TAG_TEMP_WORKSPACE ); // won't return if fails iActualUnpackedSize = MP3_UnpackRawPCM( sFilename, pbData, iSize, pbUnpackBuffer ); if (iActualUnpackedSize != iRawPCMDataSize) { Com_Error(ERR_DROP, "******* Whoah! MP3 %s unpacked to %d bytes, but size calc said %d!\n",sFilename,iActualUnpackedSize,iRawPCMDataSize); } // fake up a WAV structure so I can use the other post-load sound code such as volume calc for lip-synching // MP3_FakeUpWAVInfo( sFilename, pbData, iSize, iActualUnpackedSize, // these params are all references... info.format, info.rate, info.width, info.channels, info.samples, info.dataofs ); extern void S_LoadSound_Finalize(wavinfo_t *info, sfx_t *sfx, byte *data); S_LoadSound_Finalize(&info, pSFX, pbUnpackBuffer); // all this just for lipsynch. Oh well. fMaxVol = pSFX->fVolRange; // free sfx->data... // { // Hunk_FreeTempMemory( SFX.data ); // this will have been allocated inside S_LoadSound_Finalise() // // I want a big thankyou from the Mac guys for providing this define... :-) -ste // // #ifndef INT_MIN // #define INT_MIN (-2147483647 - 1) /* minimum (signed) int value */ // #endif // pSFX->iLastTimeUsed = INT_MIN; // force this to be oldest sound file, therefore disposable... pSFX->bInMemory = qtrue; SND_FreeOldestSound(); // ... and do the disposal // now set our temp SFX struct back to default name so nothing else accidentally uses it... // strcpy(pSFX->sSoundName, sReservedSFXEntrynameForMP3); pSFX->bDefaultSound = qfalse; } // other stuff... // Z_Free(pbUnpackBuffer); } // well, time to update the file now... // fileHandle_t f = FS_FOpenFileWrite( sFilename ); if (f) { // write the file back out, but omitting the tag if there was one... // int iWritten = FS_Write(pbData, iSize-(pTAG?sizeof(*pTAG):0), f); if (iWritten) { // make up a new tag if we didn't find one in the original file... // id3v1_1 TAG; if (!pTAG) { pTAG = &TAG; memset(&TAG,0,sizeof(TAG)); strncpy(pTAG->id,"TAG",3); } strncpy(pTAG->title, Filename_WithoutPath(Filename_WithoutExt(sFilename)), sizeof(pTAG->title)); strncpy(pTAG->artist, "Raven Software", sizeof(pTAG->artist) ); strncpy(pTAG->year, "2001", sizeof(pTAG->year) ); strncpy(pTAG->comment, va("%s %g",sKEY_MAXVOL,fMaxVol), sizeof(pTAG->comment) ); strncpy(pTAG->album, va("%s %d",sKEY_UNCOMP,iActualUnpackedSize),sizeof(pTAG->album) ); if (FS_Write( pTAG, sizeof(*pTAG), f )) // NZ = success { iFilesUpdated++; } else { Com_Printf("*********** Failed write to file!\n"); iErrors++; } } else { Com_Printf("*********** Failed write to file!\n"); iErrors++; } FS_FCloseFile( f ); } else { Com_Printf("*********** Failed to re-open for write!\n"); iErrors++; } } else { Com_Error(ERR_DROP, "******* This MP3 should be deleted: %s\n",sFilename); } } else { Com_Printf("*********** File was not a valid MP3!\n"); iErrors++; } } else { Com_Printf(" ( OK )\n"); } FS_FreeFile( pbData ); } } FS_FreeFileList( sysFiles ); FS_FreeFileList( dirFiles ); }