bool CarSound::Load( const std::string & carpath, const std::string & carname, Sound & sound, ContentManager & content, std::ostream & error_output) { assert(!psound); // check for sound specification file std::string path_aud = carpath + "/" + carname + ".aud"; std::ifstream file_aud(path_aud.c_str()); if (file_aud.good()) { PTree aud; read_ini(file_aud, aud); enginesounds.reserve(aud.size()); for (const auto & i : aud) { const PTree & audi = i.second; std::string filename; std::shared_ptr<SoundBuffer> soundptr; if (!audi.get("filename", filename, error_output)) return false; enginesounds.push_back(EngineSoundInfo()); EngineSoundInfo & info = enginesounds.back(); if (!audi.get("MinimumRPM", info.minrpm, error_output)) return false; if (!audi.get("MaximumRPM", info.maxrpm, error_output)) return false; if (!audi.get("NaturalRPM", info.naturalrpm, error_output)) return false; bool powersetting; if (!audi.get("power", powersetting, error_output)) return false; if (powersetting) info.power = EngineSoundInfo::POWERON; else if (!powersetting) info.power = EngineSoundInfo::POWEROFF; else info.power = EngineSoundInfo::BOTH; info.sound_source = sound.AddSource(soundptr, 0, true, true); sound.SetSourceGain(info.sound_source, 0); } // set blend start and end locations -- requires multiple passes std::map <EngineSoundInfo *, EngineSoundInfo *> temporary_to_actual_map; std::list <EngineSoundInfo> poweron_sounds, poweroff_sounds; for (auto & info : enginesounds) { if (info.power == EngineSoundInfo::POWERON) { poweron_sounds.push_back(info); temporary_to_actual_map[&poweron_sounds.back()] = &info; } else if (info.power == EngineSoundInfo::POWEROFF) { poweroff_sounds.push_back(info); temporary_to_actual_map[&poweroff_sounds.back()] = &info; } } poweron_sounds.sort(); poweroff_sounds.sort(); // we only support 2 overlapping sounds at once each for poweron and poweroff; this // algorithm fails for other cases (undefined behavior) std::list <EngineSoundInfo> * cursounds = &poweron_sounds; for (int n = 0; n < 2; n++) { if (n == 1) cursounds = &poweroff_sounds; for (auto i = (*cursounds).begin(); i != (*cursounds).end(); ++i) { // set start blend if (i == (*cursounds).begin()) i->fullgainrpmstart = i->minrpm; // set end blend auto inext = i; inext++; if (inext == (*cursounds).end()) i->fullgainrpmend = i->maxrpm; else { i->fullgainrpmend = inext->minrpm; inext->fullgainrpmstart = i->maxrpm; } } // now assign back to the actual infos for (auto & info : *cursounds) { assert(temporary_to_actual_map.find(&info) != temporary_to_actual_map.end()); *temporary_to_actual_map[&info] = info; } } } else { std::shared_ptr<SoundBuffer> soundptr; content.load(soundptr, carpath, "engine"); enginesounds.push_back(EngineSoundInfo()); enginesounds.back().sound_source = sound.AddSource(soundptr, 0, true, true); } //set up tire squeal sounds for (int i = 0; i < 4; ++i) { std::shared_ptr<SoundBuffer> soundptr; content.load(soundptr, carpath, "tire_squeal"); tiresqueal[i] = sound.AddSource(soundptr, i * 0.25, true, true); } //set up tire gravel sounds for (int i = 0; i < 4; ++i) { std::shared_ptr<SoundBuffer> soundptr; content.load(soundptr, carpath, "gravel"); gravelsound[i] = sound.AddSource(soundptr, i * 0.25, true, true); } //set up tire grass sounds for (int i = 0; i < 4; ++i) { std::shared_ptr<SoundBuffer> soundptr; content.load(soundptr, carpath, "grass"); grasssound[i] = sound.AddSource(soundptr, i * 0.25, true, true); } //set up bump sounds for (int i = 0; i < 4; ++i) { std::shared_ptr<SoundBuffer> soundptr; if (i >= 2) { content.load(soundptr, carpath, "bump_rear"); } else { content.load(soundptr, carpath, "bump_front"); } tirebump[i] = sound.AddSource(soundptr, 0, true, false); } //set up crash sound { std::shared_ptr<SoundBuffer> soundptr; content.load(soundptr, carpath, "crash"); crashsound = sound.AddSource(soundptr, 0, true, false); } //set up gear sound { std::shared_ptr<SoundBuffer> soundptr; content.load(soundptr, carpath, "gear"); gearsound = sound.AddSource(soundptr, 0, true, false); } //set up brake sound { std::shared_ptr<SoundBuffer> soundptr; content.load(soundptr, carpath, "brake"); brakesound = sound.AddSource(soundptr, 0, true, false); } //set up handbrake sound { std::shared_ptr<SoundBuffer> soundptr; content.load(soundptr, carpath, "handbrake"); handbrakesound = sound.AddSource(soundptr, 0, true, false); } { std::shared_ptr<SoundBuffer> soundptr; content.load(soundptr, carpath, "wind"); roadnoise = sound.AddSource(soundptr, 0, true, true); } psound = &sound; return true; }