/* * S_PlaySample */ void S_PlaySample(const vec3_t org, int ent_num, s_sample_t *sample, int atten) { s_channel_t *ch; int i; if (!s_env.initialized) return; if (!sample) return; if (sample->name[0] == '*') sample = S_LoadModelSample(&cl.entities[ent_num].current, sample->name); if (!sample->chunk) return; if ((i = S_AllocChannel()) == -1) return; ch = &s_env.channels[i]; if (org) { // positioned sound VectorCopy(org, ch->org); ch->ent_num = -1; } else // entity sound ch->ent_num = ent_num; ch->atten = atten; ch->sample = sample; S_SpatializeChannel(ch); Mix_PlayChannel(i, ch->sample->chunk, 0); }
/* * S_LoopSample */ void S_LoopSample(const vec3_t org, s_sample_t *sample) { s_channel_t *ch; vec3_t delta; int i; if (!sample || !sample->chunk) return; ch = NULL; for (i = 0; i < MAX_CHANNELS; i++) { // find existing loop sound if (s_env.channels[i].ent_num != -1) continue; if (s_env.channels[i].sample == sample) { VectorSubtract(s_env.channels[i].org, org, delta); if (VectorLength(delta) < 512.0) { ch = &s_env.channels[i]; break; } } } if (ch) { // update existing loop sample ch->count++; VectorMix(ch->org, org, 1.0 / ch->count, ch->org); } else { // or allocate a new one if ((i = S_AllocChannel()) == -1) return; ch = &s_env.channels[i]; VectorCopy(org, ch->org); ch->ent_num = -1; ch->count = 1; ch->atten = ATTN_IDLE; ch->sample = sample; Mix_PlayChannel(i, ch->sample->chunk, 0); } S_SpatializeChannel(ch); }
static void I_OGGMus_PlayNext (int looping) { const char *track; sfx_t *cd_sfx, *sfx; wavinfo_t *info = 0; if (!play_list) return; if (PL_Type (play_list) == QFString) { track = PL_String (play_list); play_pos = 0; } else { play_pos++; if (play_pos >= PL_A_NumObjects (play_list)) play_pos = 0; track = PL_String (PL_ObjectAtIndex (play_list, play_pos)); looping = 0; } if (cd_channel) { S_ChannelStop (cd_channel); cd_channel = 0; } if (!(cd_channel = S_AllocChannel ())) return; if (!(cd_sfx = S_LoadSound (track)) || !(sfx = cd_sfx->open (cd_sfx))) { S_ChannelStop (cd_channel); cd_channel = 0; return; } Sys_Printf ("Playing: %s.\n", track); if (sfx->wavinfo) info = sfx->wavinfo (sfx); if (info) { if (looping == true) info->loopstart = 0; else info->loopstart = -1; } cd_channel->sfx = sfx; set_volume (); playing = true; }
/** * @brief Adds a loop sample for e.g. ambient sounds */ void S_LoopSample (const vec3_t org, s_sample_t* sample, float relVolume, float attenuation) { s_channel_t* ch; int i; if (!sample || !sample->chunk) return; ch = nullptr; for (i = 0; i < MAX_CHANNELS; i++){ /* find existing loop sound */ if (s_env.channels[i].sample == sample) { vec3_t delta; VectorSubtract(s_env.channels[i].org, org, delta); if (VectorLength(delta) < 255.0) { ch = &s_env.channels[i]; break; } } } if (ch) { /* update existing loop sample */ ch->count++; VectorMix(ch->org, org, 1.0 / ch->count, ch->org); } else { /* or allocate a new one */ float volume; if ((i = S_AllocChannel()) == -1) return; ch = &s_env.channels[i]; sample->lastPlayed = CL_Milliseconds(); VectorCopy(org, ch->org); ch->count = 1; ch->atten = attenuation; ch->sample = sample; volume = snd_volume->value * relVolume * MIX_MAX_VOLUME; Mix_VolumeChunk(ch->sample->chunk, volume); Mix_PlayChannel(i, ch->sample->chunk, 0); } S_SpatializeChannel(ch); }
/** * @brief Validates the parms and queues the sound up * @param[in] origin if this is @c nullptr, the sound will be dynamically sourced from the entity * @param[in] sample The soundfile to play * @param[in] atten Attenuation of sound to be played (for example, @c fireAttenuation * or @c impactAttenuation from @c fireDef_s). * @param[in] relVolume Max mixer volume factor (0.0 - 1.0) * @sa S_StartLocalSample * @sa S_SetVolume */ void S_PlaySample (const vec3_t origin, s_sample_t* sample, float atten, float relVolume) { s_channel_t* ch; int i; float volume; if (!s_env.initialized) return; if (!sample) return; /* if the last mix of this particular sample is less than half a second ago, skip it */ if (sample->lastPlayed > CL_Milliseconds() - s_env.sampleRepeatRate) return; if ((i = S_AllocChannel()) == -1) return; sample->lastPlayed = CL_Milliseconds(); ch = &s_env.channels[i]; ch->atten = atten; ch->sample = sample; if (origin != nullptr) { VectorCopy(origin, ch->org); S_SpatializeChannel(ch); } volume = snd_volume->value * relVolume * MIX_MAX_VOLUME; Com_DPrintf(DEBUG_SOUND, "%i: Playing sample '%s' at volume %f at channel %i\n", CL_Milliseconds(), sample->name, volume, i); Mix_VolumeChunk(ch->sample->chunk, volume); Mix_PlayChannel(i, ch->sample->chunk, 0); }
/** * @brief */ void S_AddSample(const s_play_sample_t *play) { if (!s_env.initialized) { return; } if (!s_volume->value) { return; } if (!play) { return; } if (!play->sample) { return; } if (play->entity >= MAX_ENTITIES) { return; } switch (s_ambient->integer) { case 0: if (play->flags & S_PLAY_AMBIENT) { return; } break; case 2: if (!(play->flags & S_PLAY_AMBIENT)) { return; } break; default: break; } const s_sample_t *sample = play->sample; const char *name = sample->media.name; if (name[0] == '*') { if (play->entity != -1) { const entity_state_t *ent = &cl.entities[play->entity].current; sample = S_LoadEntitySample(ent, sample->media.name); if (sample == NULL) { Com_Debug(DEBUG_SOUND, "Failed to load player model sound %s\n", name); return; } } else { Com_Warn("Player model sound %s requested without entity\n", name); return; } } // for sounds added every frame, if an instance of the sound already exists, cull this one if (play->flags & S_PLAY_FRAME) { s_channel_t *ch = s_env.channels; for (int32_t i = 0; i < MAX_CHANNELS; i++, ch++) { if (ch->sample && (ch->play.flags & S_PLAY_FRAME)) { if (memcmp(play, &ch->play, sizeof(*play)) == 0) { ch->frame = cl.frame.frame_num; return; } } } } const int32_t i = S_AllocChannel(); if (i != -1) { s_env.channels[i].play = *play; s_env.channels[i].sample = sample; s_env.channels[i].frame = cl.frame.frame_num; } }