int32_t S_PlayMusic(const char *fn) { if (!ud.config.MusicToggle || fn == NULL) return 0; int32_t fp = S_OpenAudio(fn, 0, 1); if (EDUKE32_PREDICT_FALSE(fp < 0)) { OSD_Printf(OSD_ERROR "S_PlayMusic(): error: can't open \"%s\" for playback!\n",fn); return 0; } S_StopMusic(); int32_t MusicLen = kfilelength(fp); if (EDUKE32_PREDICT_FALSE(MusicLen < 4)) { OSD_Printf(OSD_ERROR "S_PlayMusic(): error: empty music file \"%s\"\n", fn); kclose(fp); return 0; } ALIGNED_FREE_AND_NULL(MusicPtr); // in case the following allocation was never freed MusicPtr = (char *)Xaligned_alloc(16, MusicLen); g_musicSize = kread(fp, (char *)MusicPtr, MusicLen); if (EDUKE32_PREDICT_FALSE(g_musicSize != MusicLen)) { OSD_Printf(OSD_ERROR "S_PlayMusic(): error: read %d bytes from \"%s\", expected %d\n", g_musicSize, fn, MusicLen); kclose(fp); g_musicSize = 0; return 0; } kclose(fp); if (!Bmemcmp(MusicPtr, "MThd", 4)) { MUSIC_PlaySong(MusicPtr, MUSIC_LoopSong); MusicIsWaveform = 0; } else { int32_t const mvol = MASTER_VOLUME(ud.config.MusicVolume); MusicVoice = FX_PlayLoopedAuto(MusicPtr, MusicLen, 0, 0, 0, mvol, mvol, mvol, FX_MUSIC_PRIORITY, MUSIC_ID); if (MusicVoice > FX_Ok) MusicIsWaveform = 1; } return 0; }
void playmusic(char *fn) { int fp; char * testfn, * extension; if(MusicToggle == 0) return; if(MusicDevice < 0) return; stopmusic(); testfn = (char *) malloc( strlen(fn) + 5 ); printf("Playing song: %s\n", fn); strcpy(testfn, fn); extension = strrchr(testfn, '.'); do { if (extension && !Bstrcasecmp(extension, ".mid")) { // we've been asked to load a .mid file, but first // let's see if there's an ogg with the same base name // lying around strcpy(extension, ".ogg"); fp = kopen4load(testfn, 0); if (fp >= 0) { printf("OGG found: %s\n", testfn); free(testfn); break; } } free(testfn); // just use what we've been given fp = kopen4load(fn, 0); } while (0); if (fp < 0) return; MusicLen = kfilelength( fp ); MusicPtr = (char *) malloc(MusicLen); kread( fp, MusicPtr, MusicLen); kclose( fp ); if (!memcmp(MusicPtr, "MThd", 4)) { MUSIC_PlaySong( MusicPtr, MusicLen, MUSIC_LoopSong ); MusicIsWaveform = 0; } else { MusicVoice = FX_PlayLoopedAuto(MusicPtr, MusicLen, 0, 0, 0, MusicVolume, MusicVolume, MusicVolume, FX_MUSIC_PRIORITY, MUSIC_ID); MusicIsWaveform = 1; } MusicPaused = 0; }
// NOTE: If v3df_follow == 1, x,y,z are considered literal coordinates int PlaySound(int num, int *x, int *y, int *z, Voc3D_Flags flags) { VOC_INFOp vp; VOC3D_INFOp v3p; int pitch = 0; short angle, sound_dist; int tx, ty, tz; uint8_t priority; SPRITEp sp=NULL; // DEBUG //extern SWBOOL Pachinko_Win_Cheat; // Don't play game sounds when in menus //if (UsingMenus && (*x!=0 || *y!=0 || *z!=0)) return(-1); // Weed out parental lock sounds if PLock is active if (gs.ParentalLock || Global_PLock) { unsigned i; for (i=0; i<sizeof(PLocked_Sounds); i++) { if (num == PLocked_Sounds[i]) return -1; } } if (Prediction) return -1; if (!gs.FxOn) return -1; PRODUCTION_ASSERT(num >= 0 && num < DIGI_MAX); // Reset voice voice = -1; // This is used for updating looping sounds in Update3DSounds if (Use_SoundSpriteNum && SoundSpriteNum >= 0) { ASSERT(SoundSpriteNum >= 0 && SoundSpriteNum < MAXSPRITES); sp = &sprite[SoundSpriteNum]; } if (gs.Ambient && TEST(flags,v3df_ambient) && !TEST(flags,v3df_nolookup)) // Look for invalid ambient numbers { if (num < 0 || num > MAX_AMBIENT_SOUNDS) { sprintf(ds,"Invalid or out of range ambient sound number %d\n",num); PutStringInfo(Player+screenpeek, ds); return -1; } } // Call queue management to add sound to play list. // 3D sound manager will update playing sound 10x per second until // the sound ends, at which time it is removed from both the 3D // sound list as well as the actual cache. v3p = Insert3DSound(); // If the ambient flag is set, do a name conversion to point to actual // digital sound entry. v3p->num = num; v3p->priority = 0; v3p->FX_Ok = FALSE; // Hasn't played yet if (gs.Ambient && TEST(flags,v3df_ambient) && !TEST(flags,v3df_nolookup)) { v3p->maxtics = STD_RANDOM_RANGE(ambarray[num].maxtics); flags |= ambarray[num].ambient_flags; // Add to flags if any num = ambarray[num].diginame; } PRODUCTION_ASSERT(num >= 0 && num < DIGI_MAX); // Assign voc to voc pointer vp = &voc[num]; if (UsingMenus && *x==0 && *y==0 && *z==0) // Menus sound outdo everything priority = 100; else priority = vp->priority; v3p->vp = vp; // Assign voc info to 3d struct for future reference v3p->x = x; v3p->y = y; v3p->z = z; v3p->fx = *x; v3p->fy = *y; v3p->fz = *z; v3p->flags = flags; if (flags & v3df_follow) { tx = *x; ty = *y; if (!z) tz = 0; // Some sound calls don't have a z // value else tz = *z; } else { // Don't use pointers to coordinate values. tx = v3p->fx; ty = v3p->fy; tz = v3p->fz; } // Special case stuff for sounds being played in a level if (*x==0 && *y==0 && *z==0) tx = ty = tz = 0; if ((vp->voc_flags & vf_loop) && Use_SoundSpriteNum && SoundSpriteNum >= 0 && sp) { tx=sp->x; ty=sp->y; tz=sp->z; //CON_Message("Using sp to set tx=%ld,ty=%ld,tz=%ld",tx,ty,tz); } // Calculate sound angle if (flags & v3df_dontpan) // If true, don't do panning angle = 0; else angle = SoundAngle(tx, ty); // Calculate sound distance if (tx == 0 && ty == 0 && tz == 0) sound_dist = 255; // Special case for menus sounds,etc. else sound_dist = SoundDist(tx, ty, tz, vp->voc_distance); v3p->doplr_delta = sound_dist; // Save of distance for doppler // effect // //DSPRINTF(ds,"sound dist = %d\n",sound_dist); // MONO_PRINT(ds); // Can the ambient sound see the player? If not, tone it down some. if ((vp->voc_flags & vf_loop) && Use_SoundSpriteNum && SoundSpriteNum >= 0) { PLAYERp pp = Player+screenpeek; //MONO_PRINT("PlaySound:Checking sound cansee"); if (!FAFcansee(tx, ty, tz, sp->sectnum,pp->posx, pp->posy, pp->posz, pp->cursectnum)) { //MONO_PRINT("PlaySound:Reducing sound distance"); sound_dist += ((sound_dist/2)+(sound_dist/4)); // Play more quietly if (sound_dist > 255) sound_dist = 255; // Special Cases if (num == DIGI_WHIPME) sound_dist = 255; } } // Assign ambient priorities based on distance if (gs.Ambient && TEST(flags, v3df_ambient)) { v3p->priority = v3p->vp->priority - (sound_dist / 26); priority = v3p->priority; } if (!CacheSound(num, CACHE_SOUND_PLAY)) { v3p->flags = v3df_kill; v3p->handle = -1; v3p->dist = 0; v3p->deleted = TRUE; // Sound init failed, remove it! return -1; } LockSound(num); if (sound_dist < 5) angle = 0; // Check for pitch bending if (vp->pitch_lo > vp->pitch_hi) ASSERT(vp->pitch_lo <= vp->pitch_hi); if (vp->pitch_hi == vp->pitch_lo) pitch = vp->pitch_lo; else if (vp->pitch_hi != vp->pitch_lo) pitch = vp->pitch_lo + (STD_RANDOM_RANGE(vp->pitch_hi - vp->pitch_lo)); #if 0 // DEBUG if (Pachinko_Win_Cheat) { CheckSndData(__FILE__, __LINE__); Pachinko_Win_Cheat = FALSE; CON_Message("S O U N D S C H E C K E D"); } #endif // Request playback and play it as a looping sound if flag is set. if (vp->voc_flags & vf_loop) { short loopvol=0; if ((loopvol = 255-sound_dist) <= 0) loopvol = 0; if (sound_dist < 255 || (flags & v3df_init)) { voice = FX_PlayLoopedAuto((char *)vp->data, vp->datalen, 0, 0, pitch, loopvol, loopvol, loopvol, priority, num); } else voice = -1; } else //if(!flags & v3df_init) // If not initing sound, play it if (tx==0 && ty==0 && tz==0) // It's a non-inlevel sound { voice = FX_PlayAuto((char *)vp->data, vp->datalen, pitch, 255, 255, 255, priority, num); } else // It's a 3d sound { if (sound_dist < 255) { voice = FX_PlayAuto3D((char *)vp->data, vp->datalen, FX_ONESHOT, pitch, angle, sound_dist, priority, num); } else voice = -1; } // If sound played, update our counter if (voice > FX_Ok) { //vp->playing++; v3p->FX_Ok = TRUE; } else { vp->lock--; } // Assign voc info to 3d struct for future reference v3p->handle = voice; // Save the current voc handle in struct v3p->dist = sound_dist; v3p->tics = 0; // Reset tics if (flags & v3df_init) v3p->flags ^= v3df_init; // Turn init off now return voice; }
SWBOOL PlaySong(char *song_file_name, int cdaudio_track, SWBOOL loop, SWBOOL restart) { if (!gs.MusicOn) { return FALSE; } if (DemoMode) return FALSE; if (!restart) { if (SongType == SongTypeWave) { if (SongTrack > 0 && SongTrack == cdaudio_track) { // ogg replacement for a CD track return TRUE; } else if (SongName && song_file_name && !strcmp(SongName, song_file_name)) { return TRUE; } } else if (SongType == SongTypeMIDI) { if (SongName && song_file_name && !strcmp(SongName, song_file_name)) { return TRUE; } } } StopSong(); if (!SW_SHAREWARE) { if (cdaudio_track >= 0) { char waveformtrack[MAXWAVEFORMTRACKLENGTH]; Bstrncpy(waveformtrack, gs.WaveformTrackName, MAXWAVEFORMTRACKLENGTH - 1); char *numPos = Bstrstr(waveformtrack, "??"); if (numPos && (numPos-waveformtrack) < MAXWAVEFORMTRACKLENGTH - 2) { static const char *tracktypes[] = { ".flac", ".ogg" }; const size_t tracknamebaselen = Bstrlen(waveformtrack); size_t i; numPos[0] = '0' + (cdaudio_track / 10) % 10; numPos[1] = '0' + cdaudio_track % 10; for (i = 0; i < ARRAY_SIZE(tracktypes); ++i) { waveformtrack[tracknamebaselen] = '\0'; Bstrncat(waveformtrack, tracktypes[i], MAXWAVEFORMTRACKLENGTH); if (LoadSong(waveformtrack)) { SongVoice = FX_PlayLoopedAuto(SongPtr, SongLength, 0, 0, 0, 255, 255, 255, FX_MUSIC_PRIORITY, MUSIC_ID); if (SongVoice > FX_Ok) { SongType = SongTypeWave; SongTrack = cdaudio_track; SongName = Bstrdup(waveformtrack); return TRUE; } } } buildprintf("Can't find CD track %i!\n", cdaudio_track); } else { buildprintf("Make sure to have \"??\" as a placeholder for the track number in your WaveformTrackName!\n"); buildprintf(" e.g. WaveformTrackName = \"MUSIC/Track??\"\n"); } } } if (!song_file_name || !LoadSong(song_file_name)) { return FALSE; } if (!memcmp(SongPtr, "MThd", 4)) { MUSIC_PlaySong(SongPtr, /*SongLength,*/ MUSIC_LoopSong); SongType = SongTypeMIDI; SongName = strdup(song_file_name); return TRUE; } else { SongVoice = FX_PlayLoopedAuto(SongPtr, SongLength, 0, 0, 0, 255, 255, 255, FX_MUSIC_PRIORITY, MUSIC_ID); if (SongVoice > FX_Ok) { SongType = SongTypeWave; SongName = strdup(song_file_name); return TRUE; } } return FALSE; }