static int I_SDL_StartSound(sfxinfo_t *sfxinfo, int channel, int vol, int sep) { allocated_sound_t *snd; if (!sound_initialized || channel < 0 || channel >= NUM_CHANNELS) { return -1; } // Release a sound effect if there is already one playing // on this channel ReleaseSoundOnChannel(channel); // Get the sound data if (!LockSound(sfxinfo)) { return -1; } snd = sfxinfo->driver_data; // play sound Mix_PlayChannelTimed(channel, &snd->chunk, 0, -1); channels_playing[channel] = sfxinfo; // set separation, etc. I_SDL_UpdateSoundParams(channel, vol, sep); return channel; }
// // Starting a sound means adding it // to the current list of active sounds // in the internal channels. // As the SFX info struct contains // e.g. a pointer to the raw data, // it is ignored. // As our sound handling does not handle // priority, it is ignored. // Pitching (that is, increased speed of playback) // is set, but currently not used by mixing. // int I_SDL_StartSound(sfxinfo_t *sfxinfo, int channel, int vol, int sep, int pitch) { allocated_sound_t *snd; if (!sound_initialized || channel < 0 || channel >= NUM_CHANNELS) return -1; // Release a sound effect if there is already one playing // on this channel ReleaseSoundOnChannel(channel); // Get the sound data if (!LockSound(sfxinfo)) return -1; snd = GetAllocatedSoundBySfxInfoAndPitch(sfxinfo, pitch); if (!snd) { allocated_sound_t *newsnd; // fetch the base sound effect, un-pitch-shifted snd = GetAllocatedSoundBySfxInfoAndPitch(sfxinfo, NORM_PITCH); if (!snd) return -1; if (s_randompitch) { newsnd = PitchShift(snd, pitch); if (newsnd) { LockAllocatedSound(newsnd); UnlockAllocatedSound(snd); snd = newsnd; } } } else LockAllocatedSound(snd); // play sound Mix_PlayChannel(channel, &snd->chunk, 0); channels_playing[channel] = snd; // set separation, etc. I_SDL_UpdateSoundParams(channel, vol, sep); return channel; }
// 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; }