static void pcm_play_demo(void) { struct deca_feature_config deca_config; struct snd_feature_config snd_config; UINT32 i, j; struct pcm_output pcm; INT32 *p_pcm_sp; g_decv_dev = dev_get_by_id(HLD_DEV_TYPE_DECV, 0); g_deca_dev = dev_get_by_id(HLD_DEV_TYPE_DECA, 0); if (RET_SUCCESS != deca_open(g_deca_dev, 0, 0, 0, 0, 0)) { PRINTF("deca_open failed!!\n"); ASSERT(0); } if (RET_SUCCESS != snd_open(g_snd_dev)) { PRINTF("snd_open failed!!\n"); ASSERT(0); } MEMSET(&pcm, 0, sizeof(struct pcm_output)); pcm.ch_num = 2; pcm.ch_mod = DUAL_CHANNEL; pcm.ch_left = pcm_left_ch; pcm.ch_right = pcm_right_ch; pcm.samp_num = 1152; snd_set_spdif_type(g_snd_dev, SND_OUT_SPDIF_PCM); snd_set_volume(g_snd_dev, SND_SUB_OUT, 100); snd_set_duplicate(g_snd_dev, SND_DUP_NONE); /*assumes PCM data is in address __MM_AUDIO_PATTERN_ADDR, 400*4608 samples, Preset PCM sample rate is 48000, each sample occupy 1 double word (32 bits)*/ while (1) { p_pcm_sp = (INT32 *)__MM_AUDIO_PATTERN_ADDR; for (i = 0;i < PCM_FRM_NUM;i++) { for (j = 0;j < pcm.samp_num;j++) { /*for dual channel mode, 2 channels should have different samples, herel fills the same samples to 2 channels for demo. If only have 1 channel PCM, you can only fill 1 channel (left or right), but you should call snd_set_duplicate(g_snd_dev, SND_DUP_L); or snd_set_duplicate(g_snd_dev, SND_DUP_R); before play.*/ pcm_left_ch[j] = (*p_pcm_sp) << 5; pcm_right_ch[j] = (*p_pcm_sp) << 5; p_pcm_sp++; } libc_demo_pcm_output(&pcm); } } }
// ---------------------------------------------------------------------------- // afterburners_update() // // Update the state of the afterburner fuel remaining for an object using the // afterburner. // // for the player ship, key_up_time() is called for the afterburner key to // detect when afterburners disengage. // // input: *objp => pointer to the object starting afterburners // fl_frametime => time in seconds of the last frame // void afterburners_update(object* objp, float fl_frametime) { Assert(objp != NULL); Assert(objp->type == OBJ_SHIP); Assert(objp->instance >= 0 && objp->instance < MAX_SHIPS); ship_info* sip; ship* shipp; static int volume_chg_timer = 1; shipp = &Ships[objp->instance]; Assert(shipp->ship_info_index >= 0 && shipp->ship_info_index < Num_ship_classes); sip = &Ship_info[shipp->ship_info_index]; if ((objp->flags & OF_PLAYER_SHIP) && (Game_mode & GM_DEAD)) { return; } if (!(sip->flags & SIF_AFTERBURNER)) { return; // nothing to update, afterburners are not even on the ship } //shut the afterburners off if we're using the booster tertiary //shut the afterburners off if we're in glide mode. if ((objp->phys_info.flags & PF_AFTERBURNER_ON) && ((objp->phys_info.flags & PF_BOOSTER_ON) || (objp->phys_info.flags & PF_GLIDING))) { if (objp == Player_obj) afterburner_stop_sounds(); afterburners_stop(objp); return; } if (objp == Player_obj) { if (!timestamp_elapsed(Player_disengage_timer)) { float remaining; remaining = timestamp_until(Player_disengage_timer) / i2fl(DISENGAGE_TIME); if (remaining <= 0) { afterburner_stop_sounds(); } else { if (remaining > 1.0f) { remaining = 1.0f; } snd_set_volume(Player_afterburner_loop_id, remaining * Player_afterburner_vol); } } else { if (Player_disengage_timer != 1) { afterburner_stop_sounds(); } } } // single player, multiplayer servers, and clients for their own ships if (!(Game_mode & GM_MULTIPLAYER) || MULTIPLAYER_MASTER || (objp == Player_obj)) { if (!(objp->phys_info.flags & PF_AFTERBURNER_ON)) { // Recover afterburner fuel if (shipp->afterburner_fuel < sip->afterburner_fuel_capacity) { float recharge_scale; recharge_scale = Energy_levels[shipp->engine_recharge_index] * 2.0f * The_mission.ai_profile-> afterburner_recharge_scale[Game_skill_level]; shipp->afterburner_fuel += (sip->afterburner_recover_rate * fl_frametime * recharge_scale); if (shipp->afterburner_fuel > sip->afterburner_fuel_capacity) { shipp->afterburner_fuel = sip->afterburner_fuel_capacity; } } return; } else { // Check if there is enough afterburner fuel if (shipp->afterburner_fuel <= 0) { shipp->afterburner_fuel = 0.0f; afterburners_stop(objp); return; } } // afterburners are firing at this point // Reduce the afterburner fuel shipp->afterburner_fuel -= (sip->afterburner_burn_rate * fl_frametime); if (shipp->afterburner_fuel < 0.0f) { shipp->afterburner_fuel = 0.0f; } } if (objp == Player_obj) { if ((Viewer_mode & VM_NOT_COCKPIT)) { // stop afterburner sound if it is playing if (Player_afterburner_loop_id != -1) { snd_stop(Player_afterburner_loop_id); Player_afterburner_loop_id = -1; } return; } if (timestamp_elapsed(Player_afterburner_loop_delay)) { Player_afterburner_vol = Snds[SND_ABURN_LOOP].default_volume; Player_afterburner_loop_delay = timestamp(50); if (Player_afterburner_loop_id == -1) { Player_afterburner_loop_id = snd_play_looping(&Snds[SND_ABURN_LOOP], 0.0f, -1, -1, Player_afterburner_vol); //snd_set_volume(Player_afterburner_loop_id, Player_afterburner_vol); // nprintf(("Alan","PLAY LOOPING SOUND\n")); } } // Reduce the volume of the afterburner sound if near the end if (timestamp_elapsed(volume_chg_timer)) { float percent_afterburner_left; percent_afterburner_left = shipp->afterburner_fuel / sip->afterburner_fuel_capacity; volume_chg_timer = timestamp(AFTERBURNER_VOLUME_UPDATE); if (percent_afterburner_left < AFTERBURNER_PERCENT_VOL_ATTENUATE) { Player_afterburner_vol = percent_afterburner_left * (1 / AFTERBURNER_PERCENT_VOL_ATTENUATE) * Snds[SND_ABURN_LOOP].default_volume; snd_set_volume(Player_afterburner_loop_id, Player_afterburner_vol); } } // end if (timestamp_elapsed(volume_chg_timer)) } }
// ---------------------------------------------------------------------------- // afterburners_start() will be called when a ship engages the afterburners. // This function should only be called once when afterburners first start. This is // to start an appropriate sound effect and do any one-time initializations. // // parameters: *objp ==> pointer to the object starting afterburners // void afterburners_start(object* objp) { ship_info* sip; ship* shipp; float percent_left; Assert(objp != NULL); if (objp->type == OBJ_OBSERVER) return; Assert(objp->type == OBJ_SHIP); Assert(objp->instance >= 0 && objp->instance < MAX_SHIPS); shipp = &Ships[objp->instance]; Assert(shipp->ship_info_index >= 0 && shipp->ship_info_index < Num_ship_classes); sip = &Ship_info[shipp->ship_info_index]; // When the ship has no afterburner, leave without doing anything. // Caller should have tested ship equipment before deciding to start afterburners. if (!(sip->flags & SIF_AFTERBURNER)) { nprintf(("Warning", "Ship type %s does not have afterburner capability\n", sip->name)); return; } // bail if afterburners are locked if (shipp->flags2 & SF2_AFTERBURNER_LOCKED) { return; } if (objp->phys_info.flags & PF_GLIDING) { return; } if ((objp->flags & OF_PLAYER_SHIP) && (objp == Player_obj)) { unsigned int now; now = timer_get_milliseconds(); if ((now - Player_afterburner_start_time) < 1300) { if (Viewer_mode & VM_NOT_COCKPIT) { snd_play_3d(&Snds[SND_ABURN_FAIL], &objp->pos, &View_position, objp->radius); } else { snd_play(&Snds[SND_ABURN_FAIL]); } return; } if (objp->phys_info.flags & PF_AFTERBURNER_WAIT) { return; } } if (objp->phys_info.flags & PF_AFTERBURNER_ON) { return; // afterburners are already engaged, nothing to do here } //boosters take precedence if (objp->phys_info.flags & PF_BOOSTER_ON) return; // Check if there is enough afterburner fuel if ((shipp->afterburner_fuel < MIN_AFTERBURNER_FUEL_TO_ENGAGE) && !MULTIPLAYER_CLIENT) { if (objp == Player_obj) { if (Viewer_mode & VM_NOT_COCKPIT) { snd_play_3d(&Snds[SND_ABURN_FAIL], &objp->pos, &View_position, objp->radius); } else { snd_play(&Snds[SND_ABURN_FAIL]); } } return; } objp->phys_info.flags |= PF_AFTERBURNER_ON; objp->phys_info.afterburner_decay = timestamp(ABURN_DECAY_TIME); percent_left = shipp->afterburner_fuel / sip->afterburner_fuel_capacity; //Do anim model_anim_start_type(shipp, TRIGGER_TYPE_AFTERBURNER, ANIMATION_SUBTYPE_ALL, 1); if (objp == Player_obj) { Player_afterburner_start_time = timer_get_milliseconds(); Player_disengage_timer = 1; Player_afterburner_vol = Snds[SND_ABURN_LOOP].default_volume; snd_set_volume(Player_afterburner_loop_id, Player_afterburner_vol); if (percent_left > AFTERBURNER_PERCENT_FOR_LOOP_SND) { Player_afterburner_loop_delay = timestamp(AFTERBURNER_LOOP_DELAY); } else { Player_afterburner_loop_delay = 0; } if (Viewer_mode & VM_NOT_COCKPIT) { snd_play_3d(&Snds[SND_ABURN_ENGAGE], &objp->pos, &View_position, objp->radius); } else { snd_play(&Snds[SND_ABURN_ENGAGE], 0.0f, 1.0f, SND_PRIORITY_MUST_PLAY); } joy_ff_afterburn_on(); } else { snd_play_3d(&Snds[SND_ABURN_ENGAGE], &objp->pos, &View_position, objp->radius); } objp->phys_info.flags |= PF_AFTERBURNER_WAIT; }
/** * Update the state of the afterburner fuel remaining for an object using the afterburner. * * For the player ship, key_up_time() is called for the afterburner key to * detect when afterburners disengage. * * @param *objp pointer to the object starting afterburners * @param fl_frametime time in seconds of the last frame */ void afterburners_update(object *objp, float fl_frametime) { Assert( objp != NULL ); Assert( objp->type == OBJ_SHIP ); Assert( objp->instance >= 0 && objp->instance < MAX_SHIPS ); ship_info *sip; ship *shipp; static int volume_chg_timer = 1; shipp = &Ships[objp->instance]; Assert( shipp->ship_info_index >= 0 && shipp->ship_info_index < static_cast<int>(Ship_info.size()) ); sip = &Ship_info[shipp->ship_info_index]; if ( (objp->flags[Object::Object_Flags::Player_ship] ) && (Game_mode & GM_DEAD) ) { return; } if ( !(sip->flags[Ship::Info_Flags::Afterburner]) ) { return; // nothing to update, afterburners are not even on the ship } //shut the afterburners off if we're using the booster tertiary if ( objp->phys_info.flags & PF_BOOSTER_ON) { if (objp==Player_obj) afterburner_stop_sounds(); afterburners_stop(objp); return; } if ( objp == Player_obj ) { if ( !timestamp_elapsed(Player_disengage_timer) ) { float remaining; remaining = timestamp_until(Player_disengage_timer) / i2fl(DISENGAGE_TIME); if ( remaining <= 0 ) { afterburner_stop_sounds(); } else { snd_set_volume( Player_afterburner_loop_id, remaining*Player_afterburner_vol); } } else { if ( Player_disengage_timer != 1 ) { afterburner_stop_sounds(); } } } // single player, multiplayer servers, and clients for their own ships if(!(Game_mode & GM_MULTIPLAYER) || MULTIPLAYER_MASTER || (objp == Player_obj)) { if ( !(objp->phys_info.flags & PF_AFTERBURNER_ON) ) { // Recover afterburner fuel if ( shipp->afterburner_fuel < sip->afterburner_fuel_capacity ) { float recharge_scale; recharge_scale = Energy_levels[shipp->engine_recharge_index] * 2.0f * The_mission.ai_profile->afterburner_recharge_scale[Game_skill_level]; shipp->afterburner_fuel += (sip->afterburner_recover_rate * fl_frametime * recharge_scale); if ( shipp->afterburner_fuel > sip->afterburner_fuel_capacity){ shipp->afterburner_fuel = sip->afterburner_fuel_capacity; } } return; } else { // Check if there is enough afterburner fuel if ( shipp->afterburner_fuel <= 0 ) { shipp->afterburner_fuel = 0.0f; afterburners_stop(objp); return; } } // afterburners are firing at this point // Reduce the afterburner fuel shipp->afterburner_fuel -= (sip->afterburner_burn_rate * fl_frametime); if ( shipp->afterburner_fuel < 0.0f ) { shipp->afterburner_fuel = 0.0f; } } if ( objp == Player_obj ) { if ( timestamp_elapsed(Player_afterburner_loop_delay) ) { Player_afterburner_vol = AFTERBURNER_DEFAULT_VOL; Player_afterburner_loop_delay = 0; if ( Player_afterburner_loop_id == -1 ) { Player_afterburner_loop_id = snd_play_looping( gamesnd_get_game_sound(ship_get_sound(objp, GameSounds::ABURN_LOOP)), 0.0f , -1, -1); snd_set_volume(Player_afterburner_loop_id, Player_afterburner_vol); } } // Reduce the volume of the afterburner sound if near the end if ( timestamp_elapsed(volume_chg_timer) ) { float percent_afterburner_left; percent_afterburner_left = shipp->afterburner_fuel / sip->afterburner_fuel_capacity; volume_chg_timer = timestamp(AFTERBURNER_VOLUME_UPDATE); if ( percent_afterburner_left < AFTERBURNER_PERCENT_VOL_ATTENUATE ) { Player_afterburner_vol = percent_afterburner_left*(1/AFTERBURNER_PERCENT_VOL_ATTENUATE)*AFTERBURNER_DEFAULT_VOL; snd_set_volume(Player_afterburner_loop_id, Player_afterburner_vol); } } // end if (timestamp_elapsed(volume_chg_timer)) } }