From 08acc60a8b1ead45e1e3c19f6cdf46f0a10db8d1 Mon Sep 17 00:00:00 2001 From: milek7 Date: Sat, 5 Aug 2017 22:18:59 +0200 Subject: [PATCH] sound works sound works 2 sound works 3 sound works sound works sound works sound works sound works sound fixes fix --- AdvSound.cpp | 181 --------- AdvSound.h | 50 --- CMakeLists.txt | 16 +- CMake_modules/Findlibsndfile.cmake | 34 ++ Classes.h | 4 +- Driver.cpp | 25 +- Driver.h | 2 +- DynObj.cpp | 601 +++++++++++++++-------------- DynObj.h | 52 ++- Event.h | 2 +- FadeSound.cpp | 92 ----- FadeSound.h | 40 -- Globals.h | 4 +- Ground.cpp | 28 +- Ground.h | 2 +- RealSound.cpp | 278 ------------- RealSound.h | 83 ---- Sound.cpp | 5 - Sound.h | 81 ---- Train.cpp | 544 +++++++++++++------------- Train.h | 78 ++-- World.cpp | 26 +- builds/cmake_win32.bat | 6 +- builds/cmake_win64.bat | 6 +- builds/download_windeps.bat | 2 +- sound.cpp | 561 +++++++++++++++++++++++++++ sound.h | 160 ++++++++ uilayer.cpp | 4 +- 28 files changed, 1468 insertions(+), 1499 deletions(-) delete mode 100644 AdvSound.cpp delete mode 100644 AdvSound.h create mode 100644 CMake_modules/Findlibsndfile.cmake delete mode 100644 FadeSound.cpp delete mode 100644 FadeSound.h delete mode 100644 RealSound.cpp delete mode 100644 RealSound.h delete mode 100644 Sound.cpp delete mode 100644 Sound.h create mode 100644 sound.cpp create mode 100644 sound.h diff --git a/AdvSound.cpp b/AdvSound.cpp deleted file mode 100644 index 7aefa52f..00000000 --- a/AdvSound.cpp +++ /dev/null @@ -1,181 +0,0 @@ -/* -This Source Code Form is subject to the -terms of the Mozilla Public License, v. -2.0. If a copy of the MPL was not -distributed with this file, You can -obtain one at -http://mozilla.org/MPL/2.0/. -*/ - -#include "stdafx.h" -#include "AdvSound.h" -#include "Timer.h" -//--------------------------------------------------------------------------- - -TAdvancedSound::~TAdvancedSound() -{ // Ra: stopowanie się sypie - // SoundStart.Stop(); - // SoundCommencing.Stop(); - // SoundShut.Stop(); -} - -void TAdvancedSound::Free() -{ -} - -void TAdvancedSound::Init( std::string const &NameOn, std::string const &Name, std::string const &NameOff, double DistanceAttenuation, - vector3 const &pPosition) -{ - SoundStart.Init(NameOn, DistanceAttenuation, pPosition.x, pPosition.y, pPosition.z, true); - SoundCommencing.Init(Name, DistanceAttenuation, pPosition.x, pPosition.y, pPosition.z, true); - SoundShut.Init(NameOff, DistanceAttenuation, pPosition.x, pPosition.y, pPosition.z, true); - fStartLength = SoundStart.GetWaveTime(); - fShutLength = SoundShut.GetWaveTime(); - SoundStart.AM = 1.0; - SoundStart.AA = 0.0; - SoundStart.FM = 1.0; - SoundStart.FA = 0.0; - SoundCommencing.AM = 1.0; - SoundCommencing.AA = 0.0; - SoundCommencing.FM = 1.0; - SoundCommencing.FA = 0.0; - defAM = 1.0; - defFM = 1.0; - SoundShut.AM = 1.0; - SoundShut.AA = 0.0; - SoundShut.FM = 1.0; - SoundShut.FA = 0.0; -} - -void TAdvancedSound::Load(cParser &Parser, vector3 const &pPosition) -{ - std::string nameon, name, nameoff; - double attenuation; - Parser.getTokens( 3, true, "\n\t ;," ); // samples separated with commas - Parser - >> nameon - >> name - >> nameoff; - Parser.getTokens( 1, false ); - Parser - >> attenuation; - Init( nameon, name, nameoff, attenuation, pPosition ); -} - -void TAdvancedSound::TurnOn(bool ListenerInside, vector3 NewPosition) -{ - // hunter-311211: nie trzeba czekac na ponowne odtworzenie dzwieku, az sie wylaczy - if ((State == ss_Off || State == ss_ShuttingDown) && (SoundStart.AM > 0)) - { - SoundStart.ResetPosition(); - SoundCommencing.ResetPosition(); - SoundStart.Play(1, 0, ListenerInside, NewPosition); - // SoundStart->SetVolume(-10000); - State = ss_Starting; - fTime = 0; - } -} - -void TAdvancedSound::TurnOff(bool ListenerInside, vector3 NewPosition) -{ - if ((State == ss_Commencing || State == ss_Starting) && (SoundShut.AM > 0)) - { - SoundStart.Stop(); - SoundCommencing.Stop(); - SoundShut.ResetPosition(); - SoundShut.Play(1, 0, ListenerInside, NewPosition); - State = ss_ShuttingDown; - fTime = fShutLength; - // SoundShut->SetVolume(0); - } -} - -void TAdvancedSound::Update(bool ListenerInside, vector3 NewPosition) -{ - if ((State == ss_Commencing) && (SoundCommencing.AM > 0)) - { - // SoundCommencing->SetFrequency(); - SoundShut.Stop(); // hunter-311211 - SoundCommencing.Play(1, DSBPLAY_LOOPING, ListenerInside, NewPosition); - } - else if (State == ss_Starting) - { - fTime += Timer::GetDeltaTime(); - // SoundStart->SetVolume(-1000*(4-fTime)/4); - if (fTime >= fStartLength) - { - State = ss_Commencing; - SoundCommencing.ResetPosition(); - SoundCommencing.Play(1, DSBPLAY_LOOPING, ListenerInside, NewPosition); - SoundStart.Stop(); - } - else - SoundStart.Play(1, 0, ListenerInside, NewPosition); - } - else if (State == ss_ShuttingDown) - { - fTime -= Timer::GetDeltaTime(); - // SoundShut->SetVolume(-1000*(4-fTime)/4); - if (fTime <= 0) - { - State = ss_Off; - SoundShut.Stop(); - } - else - SoundShut.Play(1, 0, ListenerInside, NewPosition); - } -} - -void TAdvancedSound::UpdateAF(double A, double F, bool ListenerInside, vector3 NewPosition) -{ // update, ale z amplituda i czestotliwoscia - if( State == ss_Off ) { - return; - } - - if ((State == ss_Commencing) && (SoundCommencing.AM > 0)) - { - SoundShut.Stop(); // hunter-311211 - SoundCommencing.Play(A, DSBPLAY_LOOPING, ListenerInside, NewPosition); - } - else if (State == ss_Starting) - { - fTime += Timer::GetDeltaTime(); - // SoundStart->SetVolume(-1000*(4-fTime)/4); - if (fTime >= fStartLength) - { - State = ss_Commencing; - SoundCommencing.ResetPosition(); - SoundCommencing.Play(A, DSBPLAY_LOOPING, ListenerInside, NewPosition); - SoundStart.Stop(); - } - else - SoundStart.Play(A, 0, ListenerInside, NewPosition); - } - else if (State == ss_ShuttingDown) - { - fTime -= Timer::GetDeltaTime(); - // SoundShut->SetVolume(-1000*(4-fTime)/4); - if (fTime <= 0) - { - State = ss_Off; - SoundShut.Stop(); - } - else - SoundShut.Play(A, 0, ListenerInside, NewPosition); - } - SoundCommencing.AdjFreq(F, Timer::GetDeltaTime()); -} - -void TAdvancedSound::CopyIfEmpty(TAdvancedSound &s) -{ // skopiowanie, gdyby był potrzebny, a nie został wczytany - if ((fStartLength > 0.0) || (fShutLength > 0.0)) - return; // coś jest - SoundStart = s.SoundStart; - SoundCommencing = s.SoundCommencing; - SoundShut = s.SoundShut; - State = s.State; - fStartLength = s.fStartLength; - fShutLength = s.fShutLength; - defAM = s.defAM; - defFM = s.defFM; -}; diff --git a/AdvSound.h b/AdvSound.h deleted file mode 100644 index 1049e750..00000000 --- a/AdvSound.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -This Source Code Form is subject to the -terms of the Mozilla Public License, v. -2.0. If a copy of the MPL was not -distributed with this file, You can -obtain one at -http://mozilla.org/MPL/2.0/. -*/ - -#ifndef AdvSoundH -#define AdvSoundH - -#include "RealSound.h" -#include "parser.h" - -typedef enum -{ - ss_Off, - ss_Starting, - ss_Commencing, - ss_ShuttingDown -} TSoundState; - -class TAdvancedSound -{ // klasa dźwięków mających początek, dowolnie długi środek oraz zakończenie (np. Rp1) - TRealSound SoundStart; - TRealSound SoundCommencing; - TRealSound SoundShut; - TSoundState State = ss_Off; - double fTime = 0.0; - double fStartLength = 0.0; - double fShutLength = 0.0; - double defAM = 0.0; - double defFM = 0.0; - - public: - TAdvancedSound() = default; - ~TAdvancedSound(); - void Init( std::string const &NameOn, std::string const &Name, std::string const &NameOff, double DistanceAttenuation, vector3 const &pPosition); - void Load(cParser &Parser, vector3 const &pPosition); - void TurnOn(bool ListenerInside, vector3 NewPosition); - void TurnOff(bool ListenerInside, vector3 NewPosition); - void Free(); - void Update(bool ListenerInside, vector3 NewPosition); - void UpdateAF(double A, double F, bool ListenerInside, vector3 NewPosition); - void CopyIfEmpty(TAdvancedSound &s); -}; - -//--------------------------------------------------------------------------- -#endif diff --git a/CMakeLists.txt b/CMakeLists.txt index 98f9ef1b..1fcf1d52 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,7 +16,6 @@ set(SOURCES "TrkFoll.cpp" "VBO.cpp" "World.cpp" -"AdvSound.cpp" "AirCoupler.cpp" "AnimModel.cpp" "Button.cpp" @@ -27,7 +26,6 @@ set(SOURCES "EU07.cpp" "Event.cpp" "EvLaunch.cpp" -"FadeSound.cpp" "Float3d.cpp" "Gauge.cpp" "Globals.cpp" @@ -45,7 +43,6 @@ set(SOURCES "parser.cpp" "renderer.cpp" "PyInt.cpp" -"RealSound.cpp" "ResourceManager.cpp" "sn_utils.cpp" "Segment.cpp" @@ -54,7 +51,7 @@ set(SOURCES "stars.cpp" "lightarray.cpp" "skydome.cpp" -"Sound.cpp" +"sound.cpp" "Spring.cpp" "shader.cpp" "frustum.cpp" @@ -116,4 +113,13 @@ target_link_libraries(${PROJECT_NAME} Threads::Threads) find_package(GLM REQUIRED) include_directories(${GLM_INCLUDE_DIRS}) -#set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize=undefined -g") +find_package(OpenAL REQUIRED) +include_directories(${OPENAL_INCLUDE_DIR}) +target_link_libraries(${PROJECT_NAME} ${OPENAL_LIBRARY}) + +find_package(libsndfile REQUIRED) +include_directories(${LIBSNDFILE_INCLUDE_DIR}) +target_link_libraries(${PROJECT_NAME} ${LIBSNDFILE_LIBRARY}) + +#set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -g") diff --git a/CMake_modules/Findlibsndfile.cmake b/CMake_modules/Findlibsndfile.cmake new file mode 100644 index 00000000..0d4e5dc8 --- /dev/null +++ b/CMake_modules/Findlibsndfile.cmake @@ -0,0 +1,34 @@ +# - Try to find libsndfile +# Once done, this will define +# +# LIBSNDFILE_FOUND - system has libsndfile +# LIBSNDFILE_INCLUDE_DIRS - the libsndfile include directories +# LIBSNDFILE_LIBRARIES - link these to use libsndfile + +# Use pkg-config to get hints about paths +find_package(PkgConfig QUIET) +if(PKG_CONFIG_FOUND) + pkg_check_modules(LIBSNDFILE_PKGCONF sndfile) +endif(PKG_CONFIG_FOUND) + +# Include dir +find_path(LIBSNDFILE_INCLUDE_DIR + NAMES sndfile.h + PATHS ${LIBSNDFILE_PKGCONF_INCLUDE_DIRS} +) + +# Library +find_library(LIBSNDFILE_LIBRARY + NAMES sndfile libsndfile-1 + PATHS ${LIBSNDFILE_PKGCONF_LIBRARY_DIRS} +) + +find_package(PackageHandleStandardArgs) +find_package_handle_standard_args(LibSndFile DEFAULT_MSG LIBSNDFILE_LIBRARY LIBSNDFILE_INCLUDE_DIR) + +if(LIBSNDFILE_FOUND) + set(LIBSNDFILE_LIBRARIES ${LIBSNDFILE_LIBRARY}) + set(LIBSNDFILE_INCLUDE_DIRS ${LIBSNDFILE_INCLUDE_DIR}) +endif(LIBSNDFILE_FOUND) + +mark_as_advanced(LIBSNDFILE_LIBRARY LIBSNDFILE_LIBRARIES LIBSNDFILE_INCLUDE_DIR LIBSNDFILE_INCLUDE_DIRS) diff --git a/Classes.h b/Classes.h index b8967103..504422d8 100644 --- a/Classes.h +++ b/Classes.h @@ -23,8 +23,8 @@ class TModel3d; //siatka modelu wspólna dla egzemplarzy class TSubModel; // fragment modelu (tu do wyświetlania terenu) class TMemCell; // komórka pamięci class cParser; -class TRealSound; // dźwięk ze współrzędnymi XYZ -class TTextSound; // dźwięk ze stenogramem +class sound; +class text_sound; class TEventLauncher; class TTraction; // drut class TTractionPowerSource; // zasilanie drutów diff --git a/Driver.cpp b/Driver.cpp index acd35636..d0c26dea 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -25,6 +25,7 @@ http://mozilla.org/MPL/2.0/. #include "World.h" #include "McZapkie/mctools.h" #include "McZapkie/MOVER.h" +#include "sound.h" #define LOGVELOCITY 0 #define LOGORDERS 1 @@ -1467,7 +1468,7 @@ void TController::CloseLog() TController::~TController() { // wykopanie mechanika z roboty - delete tsGuardSignal; + sound_man->destroy_sound(&tsGuardSignal); delete TrainParams; CloseLog(); }; @@ -2380,7 +2381,7 @@ bool TController::DecBrake() bool TController::IncSpeed() { // zwiększenie prędkości; zwraca false, jeśli dalej się nie da zwiększać if (tsGuardSignal) // jeśli jest dźwięk kierownika - if (tsGuardSignal->GetStatus() & DSBSTATUS_PLAYING) // jeśli gada, to nie jedziemy + if (tsGuardSignal->is_playing()) // jeśli gada, to nie jedziemy return false; bool OK = true; if( ( iDrivigFlags & moveDoorOpened ) @@ -2864,9 +2865,8 @@ bool TController::PutCommand(std::string NewCommand, double NewValue1, double Ne NewCommand = Global::asCurrentSceneryPath + NewCommand + ".wav"; // na razie jeden if (FileExists(NewCommand)) { // wczytanie dźwięku odjazdu podawanego bezpośrenido - tsGuardSignal = new TTextSound(NewCommand, 30, pVehicle->GetPosition().x, - pVehicle->GetPosition().y, pVehicle->GetPosition().z, - false); + tsGuardSignal = sound_man->create_text_sound(NewCommand); + tsGuardSignal->position(pVehicle->GetPosition()); // rsGuardSignal->Stop(); iGuardRadio = 0; // nie przez radio } @@ -2875,9 +2875,8 @@ bool TController::PutCommand(std::string NewCommand, double NewValue1, double Ne NewCommand = NewCommand.insert(NewCommand.find_last_of("."),"radio"); // wstawienie przed kropkč if (FileExists(NewCommand)) { // wczytanie dźwięku odjazdu w wersji radiowej (słychać tylko w kabinie) - tsGuardSignal = new TTextSound(NewCommand, -1, pVehicle->GetPosition().x, - pVehicle->GetPosition().y, pVehicle->GetPosition().z, - false); + tsGuardSignal = sound_man->create_text_sound(NewCommand); + tsGuardSignal->position(pVehicle->GetPosition()); iGuardRadio = iRadioChannel; } } @@ -4202,7 +4201,7 @@ bool TController::UpdateSituation(double dt) ->DoorOpenCtrl ) // jeśli drzwi niesterowane przez maszynistę Doors( false ); // a EZT zamknie dopiero po odegraniu komunikatu kierownika - tsGuardSignal->Stop(); + tsGuardSignal->stop(); // w zasadzie to powinien mieć flagę, czy jest dźwiękiem radiowym, czy // bezpośrednim // albo trzeba zrobić dwa dźwięki, jeden bezpośredni, słyszalny w @@ -4210,9 +4209,7 @@ bool TController::UpdateSituation(double dt) // na razie zakładam, że to nie jest dźwięk radiowy, bo trzeba by zrobić // obsługę kanałów radiowych itd. if (!iGuardRadio) // jeśli nie przez radio - tsGuardSignal->Play( - 1.0, 0, !FreeFlyModeFlag, - pVehicle->GetPosition()); // dla true jest głośniej + tsGuardSignal->position(pVehicle->GetPosition()).play(); else // if (iGuardRadio==iRadioChannel) //zgodność kanału // if (!FreeFlyModeFlag) //obserwator musi być w środku pojazdu @@ -4221,9 +4218,7 @@ bool TController::UpdateSituation(double dt) if (SquareMagnitude(pVehicle->GetPosition() - Global::pCameraPosition) < 2000 * 2000) // w odległości mniejszej niż 2km - tsGuardSignal->Play( - 1.0, 0, true, - pVehicle->GetPosition()); // dźwięk niby przez radio + tsGuardSignal->position(pVehicle->GetPosition()).play(); } } if (mvOccupied->V == 0.0) diff --git a/Driver.h b/Driver.h index 507bd675..702b4e28 100644 --- a/Driver.h +++ b/Driver.h @@ -232,7 +232,7 @@ class TController // AnsiString OrderCommand; //komenda pobierana z pojazdu // double OrderValue; //argument komendy int iRadioChannel = 1; // numer aktualnego kanału radiowego - TTextSound *tsGuardSignal = nullptr; // komunikat od kierownika + sound *tsGuardSignal = nullptr; // komunikat od kierownika int iGuardRadio = 0; // numer kanału radiowego kierownika (0, gdy nie używa radia) public: double AccPreferred = 0.0; // preferowane przyspieszenie (wg psychiki kierującego, zmniejszana przy wykryciu kolizji) diff --git a/DynObj.cpp b/DynObj.cpp index 18c0f561..2b20046a 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -31,6 +31,7 @@ http://mozilla.org/MPL/2.0/. #include "Camera.h" //bo likwidujemy trzęsienie #include "Console.h" #include "Traction.h" +#include "sound.h" // Ra: taki zapis funkcjonuje lepiej, ale może nie jest optymalny #define vWorldFront Math3D::vector3(0, 0, 1) @@ -1631,21 +1632,32 @@ TDynamicObject::~TDynamicObject() // parametrow fizycznych SafeDelete(Mechanik); SafeDelete(MoverParameters); - // Ra: wyłączanie dźwięków powinno być dodane w ich destruktorach, ale się - // sypie - /* to też się sypie - for (int i=0;idestroy_sound(&rsStukot[i]); + sound_man->destroy_sound(&rsSilnik); + sound_man->destroy_sound(&rsWentylator); + sound_man->destroy_sound(&rsPisk); + sound_man->destroy_sound(&rsDerailment); + sound_man->destroy_sound(&rsPrzekladnia); + sound_man->destroy_sound(&sHorn1); + sound_man->destroy_sound(&sHorn2); + sound_man->destroy_sound(&sCompressor); + sound_man->destroy_sound(&sConverter); + sound_man->destroy_sound(&sSmallCompressor); + sound_man->destroy_sound(&sDepartureSignal); + sound_man->destroy_sound(&sTurbo); + sound_man->destroy_sound(&sSand); + sound_man->destroy_sound(&sReleaser); + sound_man->destroy_sound(&sPantUp); + sound_man->destroy_sound(&sPantDown); + sound_man->destroy_sound(&rsDoorOpen); + sound_man->destroy_sound(&rsDoorClose); + sound_man->destroy_sound(&sBrakeAcc); + sound_man->destroy_sound(&rsUnbrake); + sound_man->destroy_sound(&rsDiesielInc); + sound_man->destroy_sound(&rscurve); + /* delete[] pAnimations; // obiekty obsługujące animację */ @@ -3044,7 +3056,8 @@ bool TDynamicObject::Update(double dt, double dt1) // McZapkie-270202 if (MyTrack->fSoundDistance != -1) { - if (ObjectDist < rsStukot[0].dSoundAtt * rsStukot[0].dSoundAtt * 15.0) + //m7todo: restore + //if (ObjectDist < rsStukot[0].dSoundAtt * rsStukot[0].dSoundAtt * 15.0) { vol = (20.0 + MyTrack->iDamageFlag) / 21; if (MyTrack->eEnvironment == e_tunnel) @@ -3079,16 +3092,15 @@ bool TDynamicObject::Update(double dt, double dt1) // McZapkie-040302 if (i == iAxles - 1) { - rsStukot[0].Stop(); + if (rsStukot[0]) rsStukot[0]->stop(); MoverParameters->AccV += 0.5 * GetVelocity() / (1 + MoverParameters->Vmax); } else { - rsStukot[i + 1].Stop(); + if (rsStukot[i + 1]) rsStukot[i + 1]->stop(); } - rsStukot[i].Play(vol, 0, MechInside, - vPosition); // poprawic pozycje o uklad osi + if (rsStukot[i]) rsStukot[i]->gain(vol).position(vPosition).play(); // poprawic pozycje o uklad osi if (i == 1) MoverParameters->AccV -= 0.5 * GetVelocity() / (1 + MoverParameters->Vmax); @@ -3105,11 +3117,10 @@ bool TDynamicObject::Update(double dt, double dt1) int flag = MoverParameters->Hamulec->GetSoundFlag(); if ((bBrakeAcc) && (TestFlag(flag, sf_Acc)) && (ObjectDist < 2500)) { - sBrakeAcc->SetVolume(-ObjectDist * 3 - (FreeFlyModeFlag ? 0 : 2000)); - sBrakeAcc->Play(0, 0, 0); - sBrakeAcc->SetPan(10000 * sin(ModCamRot)); + sBrakeAcc->gain(-ObjectDist * 3 - (FreeFlyModeFlag ? 0 : 2000)); + sBrakeAcc->play(); } - if ((rsUnbrake.AM != 0) && (ObjectDist < 5000)) + if ((rsUnbrake) && (ObjectDist < 5000)) { if ((TestFlag(flag, sf_CylU)) && ((MoverParameters->BrakePress * MoverParameters->MaxBrakePress[3]) > 0.05)) @@ -3120,11 +3131,10 @@ bool TDynamicObject::Update(double dt, double dt1) MoverParameters->MaxBrakePress[3]), 1); vol = vol + (FreeFlyModeFlag ? 0 : -0.5) - ObjectDist / 5000; - rsUnbrake.SetPan(10000 * sin(ModCamRot)); - rsUnbrake.Play(vol, DSBPLAY_LOOPING, MechInside, GetPosition()); + rsUnbrake->loop().gain(vol).position(GetPosition()).play(); } else - rsUnbrake.Stop(); + rsUnbrake->stop(); } // fragment z EXE Kursa @@ -3237,8 +3247,8 @@ bool TDynamicObject::Update(double dt, double dt1) && ( PantDiff < 0.01 ) ) // tolerancja niedolegania { if ((MoverParameters->PantFrontVolt == 0.0) && - (MoverParameters->PantRearVolt == 0.0)) - sPantUp.Play(vol, 0, MechInside, vPosition); + (MoverParameters->PantRearVolt == 0.0) && sPantUp) + sPantUp->gain(vol).position(vPosition).play(); if (p->hvPowerWire) // TODO: wyliczyć trzeba prąd przypadający na // pantograf i // wstawić do GetVoltage() @@ -3266,8 +3276,8 @@ bool TDynamicObject::Update(double dt, double dt1) && ( PantDiff < 0.01 ) ) { if ((MoverParameters->PantRearVolt == 0.0) && - (MoverParameters->PantFrontVolt == 0.0)) - sPantUp.Play(vol, 0, MechInside, vPosition); + (MoverParameters->PantFrontVolt == 0.0) && sPantUp) + sPantUp->gain(vol).position(vPosition).play(); if (p->hvPowerWire) // TODO: wyliczyć trzeba prąd przypadający na // pantograf i // wstawić do GetVoltage() @@ -3354,12 +3364,12 @@ bool TDynamicObject::Update(double dt, double dt1) } // koniec pętli po pantografach if ((MoverParameters->PantFrontSP == false) && (MoverParameters->PantFrontUp == false)) { - sPantDown.Play(vol, 0, MechInside, vPosition); + sPantDown->gain(vol).position(vPosition).play(); MoverParameters->PantFrontSP = true; } if ((MoverParameters->PantRearSP == false) && (MoverParameters->PantRearUp == false)) { - sPantDown.Play(vol, 0, MechInside, vPosition); + sPantDown->gain(vol).position(vPosition).play(); MoverParameters->PantRearSP = true; } /* @@ -3462,24 +3472,24 @@ bool TDynamicObject::Update(double dt, double dt1) // NBMX Obsluga drzwi, MC: zuniwersalnione if ((dDoorMoveL < MoverParameters->DoorMaxShiftL) && (MoverParameters->DoorLeftOpened)) { - rsDoorOpen.Play(1, 0, MechInside, vPosition); + rsDoorOpen->position(vPosition).play(); dDoorMoveL += dt1 * 0.5 * MoverParameters->DoorOpenSpeed; } if ((dDoorMoveL > 0) && (!MoverParameters->DoorLeftOpened)) { - rsDoorClose.Play(1, 0, MechInside, vPosition); + rsDoorClose->position(vPosition).play(); dDoorMoveL -= dt1 * MoverParameters->DoorCloseSpeed; if (dDoorMoveL < 0) dDoorMoveL = 0; } if ((dDoorMoveR < MoverParameters->DoorMaxShiftR) && (MoverParameters->DoorRightOpened)) { - rsDoorOpen.Play(1, 0, MechInside, vPosition); + rsDoorOpen->position(vPosition).play(); dDoorMoveR += dt1 * 0.5 * MoverParameters->DoorOpenSpeed; } if ((dDoorMoveR > 0) && (!MoverParameters->DoorRightOpened)) { - rsDoorClose.Play(1, 0, MechInside, vPosition); + rsDoorClose->position(vPosition).play(); dDoorMoveR -= dt1 * MoverParameters->DoorCloseSpeed; if (dDoorMoveR < 0) dDoorMoveR = 0; @@ -3658,7 +3668,7 @@ void TDynamicObject::RenderSounds() if (MoverParameters->Power > 0) { - if ((rsSilnik.AM != 0) + if ((rsSilnik) && ((MoverParameters->Mains) // McZapkie-280503: zeby dla dumb dzialal silnik na jalowych obrotach || (MoverParameters->EngineType == DieselEngine))) @@ -3666,39 +3676,33 @@ void TDynamicObject::RenderSounds() if ((fabs(MoverParameters->enrot) > 0.01) || (MoverParameters->EngineType == Dumb)) //&& (MoverParameters->EnginePower>0.1)) { - freq = rsSilnik.FM * fabs(MoverParameters->enrot) + rsSilnik.FA; + freq = fabs(MoverParameters->enrot); if (MoverParameters->EngineType == Dumb) freq = freq - 0.2 * MoverParameters->EnginePower / (1 + MoverParameters->Power * 1000); - rsSilnik.AdjFreq(freq, dt); + rsSilnik->pitch(freq); if (MoverParameters->EngineType == DieselEngine) { if (MoverParameters->enrot > 0) { if (MoverParameters->EnginePower > 0) - vol = rsSilnik.AM * MoverParameters->dizel_fill + rsSilnik.AA; + vol = MoverParameters->dizel_fill; else vol = - rsSilnik.AM * fabs(MoverParameters->enrot / MoverParameters->dizel_nmax) + - rsSilnik.AA * 0.9; + fabs(MoverParameters->enrot / MoverParameters->dizel_nmax); } else vol = 0; } else if (MoverParameters->EngineType == DieselElectric) - vol = rsSilnik.AM * - (MoverParameters->EnginePower / 1000 / MoverParameters->Power) + + vol = (MoverParameters->EnginePower / 1000 / MoverParameters->Power) + 0.2 * (MoverParameters->enrot * 60) / - (MoverParameters->DElist[MoverParameters->MainCtrlPosNo].RPM) + - rsSilnik.AA; + (MoverParameters->DElist[MoverParameters->MainCtrlPosNo].RPM); else if (MoverParameters->EngineType == ElectricInductionMotor) - vol = rsSilnik.AM * - (MoverParameters->EnginePower + fabs(MoverParameters->enrot * 2)) + - rsSilnik.AA; + vol = (MoverParameters->EnginePower + fabs(MoverParameters->enrot * 2)); else - vol = rsSilnik.AM * (MoverParameters->EnginePower / 1000 + - fabs(MoverParameters->enrot) * 60.0) + - rsSilnik.AA; + vol = (MoverParameters->EnginePower / 1000 + + fabs(MoverParameters->enrot) * 60.0); // McZapkie-250302 - natezenie zalezne od obrotow i mocy if ((vol < 1) && (MoverParameters->EngineType == ElectricSeriesMotor) && (MoverParameters->EnginePower < 100)) @@ -3731,11 +3735,11 @@ void TDynamicObject::RenderSounds() if (enginevolume > 0.0001) if (MoverParameters->EngineType != DieselElectric) { - rsSilnik.Play(enginevolume, DSBPLAY_LOOPING, MechInside, GetPosition()); + rsSilnik->loop().gain(enginevolume).position(GetPosition()).play(); } else { - sConverter.UpdateAF(vol, freq, MechInside, GetPosition()); + sConverter->gain(vol).pitch(freq).position(GetPosition()); float fincvol; fincvol = 0; @@ -3746,100 +3750,114 @@ void TDynamicObject::RenderSounds() (MoverParameters->enrot * 60)); fincvol /= (0.05 * MoverParameters->DElist[0].RPM); }; - if (fincvol > 0.02) - rsDiesielInc.Play(fincvol, DSBPLAY_LOOPING, MechInside, GetPosition()); - else - rsDiesielInc.Stop(); + if (rsDiesielInc) + { + if (fincvol > 0.02) + rsDiesielInc->loop().position(GetPosition()).gain(fincvol).play(); + else + rsDiesielInc->stop(); + } } } else - rsSilnik.Stop(); + rsSilnik->stop(); } enginevolume = (enginevolume + vol) * 0.5; if( enginevolume < 0.01 ) { - rsSilnik.Stop(); + rsSilnik->stop(); } - if ( ( MoverParameters->EngineType == ElectricSeriesMotor ) - || ( MoverParameters->EngineType == ElectricInductionMotor ) - && ( rsWentylator.AM != 0 ) ) + if ( (( MoverParameters->EngineType == ElectricSeriesMotor ) + || ( MoverParameters->EngineType == ElectricInductionMotor )) + && ( rsWentylator ) ) { if (MoverParameters->RventRot > 0.1) { // play ventilator sound if the ventilators are rotating fast enough... - freq = rsWentylator.FM * MoverParameters->RventRot + rsWentylator.FA; - rsWentylator.AdjFreq(freq, dt); + freq = MoverParameters->RventRot; + rsWentylator->pitch(freq); if( MoverParameters->EngineType == ElectricInductionMotor ) { - vol = rsWentylator.AM * std::sqrt( std::fabs( MoverParameters->dizel_fill ) ) + rsWentylator.AA; + vol = std::sqrt( std::fabs( MoverParameters->dizel_fill ) ); } else { - vol = rsWentylator.AM * MoverParameters->RventRot + rsWentylator.AA; + vol = MoverParameters->RventRot; } - rsWentylator.Play(vol, DSBPLAY_LOOPING, MechInside, GetPosition()); + rsWentylator->gain(vol).loop().position(GetPosition()).play(); } else { // ...otherwise shut down the sound - rsWentylator.Stop(); + rsWentylator->stop(); } } - if (MoverParameters->TrainType == dt_ET40) + if (MoverParameters->TrainType == dt_ET40 && rsPrzekladnia) { if (MoverParameters->Vel > 0.1) { - freq = rsPrzekladnia.FM * (MoverParameters->Vel) + rsPrzekladnia.FA; - rsPrzekladnia.AdjFreq(freq, dt); - vol = rsPrzekladnia.AM * (MoverParameters->Vel) + rsPrzekladnia.AA; - rsPrzekladnia.Play(vol, DSBPLAY_LOOPING, MechInside, GetPosition()); + freq = MoverParameters->Vel; + rsPrzekladnia->pitch(freq); + vol = MoverParameters->Vel; + rsPrzekladnia->loop().position(GetPosition()).gain(vol).play(); } else - rsPrzekladnia.Stop(); + rsPrzekladnia->stop(); } } // youBy: dzwiek ostrych lukow i ciasnych zwrotek - if ((ts.R * ts.R > 1) && (MoverParameters->Vel > 0)) - vol = MoverParameters->AccN * MoverParameters->AccN; - else - vol = 0; - // vol+=(50000/ts.R*ts.R); - - if (vol > 0.001) + if (rscurve) { - rscurve.Play(2 * vol, DSBPLAY_LOOPING, MechInside, GetPosition()); + if ((ts.R * ts.R > 1) && (MoverParameters->Vel > 0)) + vol = MoverParameters->AccN * MoverParameters->AccN; + else + vol = 0; + // vol+=(50000/ts.R*ts.R); + + if (vol > 0.001) + { + rscurve->gain(2 * vol).loop().position(GetPosition()).play(); + } + else + rscurve->stop(); } - else - rscurve.Stop(); // McZapkie-280302 - pisk mocno zacisnietych hamulcow - trzeba jeszcze // zabezpieczyc przed // brakiem deklaracji w mmedia.dta - if (rsPisk.AM != 0) + + if (rsPisk) { - if ((MoverParameters->Vel > (rsPisk.GetStatus() != 0 ? 0.01 : 0.5)) && - (!MoverParameters->SlippingWheels) && (MoverParameters->UnitBrakeForce > rsPisk.AM)) + if ((MoverParameters->Vel > (rsPisk->is_playing() != 0 ? 0.01 : 0.5)) && + (!MoverParameters->SlippingWheels) && (MoverParameters->UnitBrakeForce > rsPisk->gain_mul)) { - vol = MoverParameters->UnitBrakeForce / (rsPisk.AM + 1) + rsPisk.AA; - rsPisk.Play(vol, DSBPLAY_LOOPING, MechInside, GetPosition()); + vol = (MoverParameters->UnitBrakeForce / (rsPisk->gain_mul + 1)) / rsPisk->gain_mul; + rsPisk->gain(vol).loop().position(GetPosition()).play(); } else - rsPisk.Stop(); + rsPisk->stop(); } - if (MoverParameters->SandDose) // Dzwiek piasecznicy - sSand.TurnOn(MechInside, GetPosition()); - else - sSand.TurnOff(MechInside, GetPosition()); - sSand.Update(MechInside, GetPosition()); - if (MoverParameters->Hamulec->GetStatus() & b_rls) // Dzwiek odluzniacza - sReleaser.TurnOn(MechInside, GetPosition()); - else - sReleaser.TurnOff(MechInside, GetPosition()); - //sReleaser.Update(MechInside, GetPosition()); - double releaser_vol = 1; - if (MoverParameters->BrakePress < 0.1) - releaser_vol = MoverParameters->BrakePress * 10; - sReleaser.UpdateAF(releaser_vol, 1, MechInside, GetPosition()); + if (sSand) + { + if (MoverParameters->SandDose) // Dzwiek piasecznicy + sSand->position(GetPosition()).play(); + else + sSand->stop(); + } + + if (sReleaser) + { + if (MoverParameters->Hamulec->GetStatus() & b_rls) // Dzwiek odluzniacza + sReleaser->position(GetPosition()).play(); + else + sReleaser->stop(); + //sReleaser.Update(MechInside, GetPosition()); + double releaser_vol = 1; + if (MoverParameters->BrakePress < 0.1) + releaser_vol = MoverParameters->BrakePress * 10; + + sReleaser->gain(releaser_vol); + } // if ((MoverParameters->ConverterFlag==false) && // (MoverParameters->TrainType!=dt_ET22)) // if @@ -3851,51 +3869,59 @@ void TDynamicObject::RenderSounds() // MoverParameters->CompressorAllow=MoverParameters->ConverterFlag; // McZapkie! - dzwiek compressor.wav tylko gdy dziala sprezarka - if (MoverParameters->VeselVolume != 0) - { - if (MoverParameters->CompressorFlag) - sCompressor.TurnOn(MechInside, GetPosition()); - else - sCompressor.TurnOff(MechInside, GetPosition()); - sCompressor.Update(MechInside, GetPosition()); - } - if (MoverParameters->PantCompFlag) // Winger 160404 - dzwiek malej sprezarki - sSmallCompressor.TurnOn(MechInside, GetPosition()); - else - sSmallCompressor.TurnOff(MechInside, GetPosition()); - sSmallCompressor.Update(MechInside, GetPosition()); - // youBy - przenioslem, bo diesel tez moze miec turbo - if( (MoverParameters->TurboTest > 0) - && (MoverParameters->MainCtrlPos >= MoverParameters->TurboTest)) + if (sCompressor) { - // udawanie turbo: (6.66*(eng_vol-0.85)) - if (eng_turbo > 6.66 * (enginevolume - 0.8) + 0.2 * dt) - eng_turbo = eng_turbo - 0.2 * dt; // 0.125 - else if (eng_turbo < 6.66 * (enginevolume - 0.8) - 0.4 * dt) - eng_turbo = eng_turbo + 0.4 * dt; // 0.333 - else - eng_turbo = 6.66 * (enginevolume - 0.8); - - sTurbo.TurnOn(MechInside, GetPosition()); - // sTurbo.UpdateAF(eng_turbo,0.7+(eng_turbo*0.6),MechInside,GetPosition()); - sTurbo.UpdateAF(3 * eng_turbo - 1, 0.4 + eng_turbo * 0.4, MechInside, GetPosition()); - // eng_vol_act=enginevolume; - // eng_frq_act=eng_frq; + if (MoverParameters->VeselVolume != 0) + { + if (MoverParameters->CompressorFlag) + sCompressor->position(GetPosition()).play(); + else + sCompressor->stop(); + } + } + + if (sSmallCompressor) + { + if (MoverParameters->PantCompFlag) // Winger 160404 - dzwiek malej sprezarki + sSmallCompressor->position(GetPosition()).play(); + else + sSmallCompressor->stop(); + } + + if (sTurbo) + { + // youBy - przenioslem, bo diesel tez moze miec turbo + if( (MoverParameters->TurboTest > 0) + && (MoverParameters->MainCtrlPos >= MoverParameters->TurboTest)) + { + // udawanie turbo: (6.66*(eng_vol-0.85)) + if (eng_turbo > 6.66 * (enginevolume - 0.8) + 0.2 * dt) + eng_turbo = eng_turbo - 0.2 * dt; // 0.125 + else if (eng_turbo < 6.66 * (enginevolume - 0.8) - 0.4 * dt) + eng_turbo = eng_turbo + 0.4 * dt; // 0.333 + else + eng_turbo = 6.66 * (enginevolume - 0.8); + + sTurbo->gain(3 * eng_turbo - 1).pitch(0.4 + eng_turbo * 0.4).position(GetPosition()).play(); + } + else + sTurbo->stop(); } - else - sTurbo.TurnOff(MechInside, GetPosition()); if (MoverParameters->TrainType == dt_PseudoDiesel) { // ABu: udawanie woodwarda dla lok. spalinowych // jesli silnik jest podpiety pod dzwiek przetwornicy - if (MoverParameters->ConverterFlag) // NBMX dzwiek przetwornicy + if (sConverter) { - sConverter.TurnOn(MechInside, GetPosition()); + if (MoverParameters->ConverterFlag) // NBMX dzwiek przetwornicy + { + sConverter->position(GetPosition()).play(); + } + else + sConverter->stop(); } - else - sConverter.TurnOff(MechInside, GetPosition()); // glosnosc zalezy od stosunku mocy silnika el. do mocy max double eng_vol; @@ -3942,7 +3968,7 @@ void TDynamicObject::RenderSounds() if (eng_frq_act < defrot + 0.1 * dt) eng_frq_act = defrot; } - sConverter.UpdateAF(eng_vol_act, eng_frq_act + eng_dfrq, MechInside, GetPosition()); + sConverter->gain(eng_vol_act).pitch(eng_frq_act + eng_dfrq).position(GetPosition()); // udawanie turbo: (6.66*(eng_vol-0.85)) if (eng_turbo > 6.66 * (eng_vol - 0.8) + 0.2 * dt) eng_turbo = eng_turbo - 0.2 * dt; // 0.125 @@ -3951,62 +3977,67 @@ void TDynamicObject::RenderSounds() else eng_turbo = 6.66 * (eng_vol - 0.8); - sTurbo.TurnOn(MechInside, GetPosition()); + if (sTurbo) sTurbo->gain(3 * eng_turbo - 1).pitch(0.4 + eng_turbo * 0.4).position(GetPosition()).play(); // sTurbo.UpdateAF(eng_turbo,0.7+(eng_turbo*0.6),MechInside,GetPosition()); - sTurbo.UpdateAF(3 * eng_turbo - 1, 0.4 + eng_turbo * 0.4, MechInside, GetPosition()); eng_vol_act = eng_vol; // eng_frq_act=eng_frq; } else { - if (MoverParameters->ConverterFlag) // NBMX dzwiek przetwornicy - sConverter.TurnOn(MechInside, GetPosition()); - else - sConverter.TurnOff(MechInside, GetPosition()); - sConverter.Update(MechInside, GetPosition()); + if (sConverter) + { + if (MoverParameters->ConverterFlag) // NBMX dzwiek przetwornicy + { + sConverter->position(GetPosition()).play(); + } + else + sConverter->stop(); + } } - if( TestFlag( MoverParameters->WarningSignal, 1 ) ) { - sHorn1.TurnOn( MechInside, GetPosition() ); - } - else { - sHorn1.TurnOff( MechInside, GetPosition() ); - } - if( TestFlag( MoverParameters->WarningSignal, 2 ) ) { - sHorn2.TurnOn( MechInside, GetPosition() ); - } - else { - sHorn2.TurnOff( MechInside, GetPosition() ); + if (sHorn1) + { + if( TestFlag( MoverParameters->WarningSignal, 1 ) ) { + sHorn1->position(GetPosition()).play(); + } + else { + sHorn1->stop(); + } } - if (MoverParameters->DoorClosureWarning) + if (sHorn2) { - if (MoverParameters->DepartureSignal) // NBMX sygnal odjazdu, MC: pod warunkiem ze jest - // zdefiniowane w chk - sDepartureSignal.TurnOn(MechInside, GetPosition()); - else - sDepartureSignal.TurnOff(MechInside, GetPosition()); - sDepartureSignal.Update(MechInside, GetPosition()); + if( TestFlag( MoverParameters->WarningSignal, 2 ) ) { + sHorn2->position(GetPosition()).play(); + } + else { + sHorn2->stop(); + } } - sHorn1.Update(MechInside, GetPosition()); - sHorn2.Update(MechInside, GetPosition()); - // McZapkie: w razie wykolejenia - if (MoverParameters->EventFlag) + + if (sDepartureSignal) { - if (TestFlag(MoverParameters->DamageFlag, dtrain_out) && GetVelocity() > 0) - rsDerailment.Play(1, 0, true, GetPosition()); - if (GetVelocity() == 0) - rsDerailment.Stop(); + if (MoverParameters->DoorClosureWarning) + { + if (MoverParameters->DepartureSignal) // NBMX sygnal odjazdu, MC: pod warunkiem ze jest + // zdefiniowane w chk + sDepartureSignal->position(GetPosition()).play(); + else + sDepartureSignal->stop(); + } + } + + if (rsDerailment) + { + // McZapkie: w razie wykolejenia + if (MoverParameters->EventFlag) + { + if (TestFlag(MoverParameters->DamageFlag, dtrain_out) && GetVelocity() > 0) + rsDerailment->position(GetPosition()).play(); + if (GetVelocity() == 0) + rsDerailment->stop(); + } } - /* //Ra: dwa razy? - if (MoverParameters->EventFlag) - { - if (TestFlag(MoverParameters->DamageFlag,dtrain_out) && GetVelocity()>0) - rsDerailment.Play(1,0,true,GetPosition()); - if (GetVelocity()==0) - rsDerailment.Stop(); - } - */ }; // McZapkie-250202 @@ -4711,9 +4742,9 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName, parser.getTokens(); parser >> token; if( token != "end" ) { - rsStukot[ i ].Init( token, dSDist, GetPosition().x, - GetPosition().y + dWheelsPosition[ i ], GetPosition().z, - true ); + rsStukot[i] = sound_man->create_sound(token); + if (rsStukot[i]) rsStukot[i]->position(glm::vec3(GetPosition().x, + GetPosition().y + dWheelsPosition[ i ], GetPosition().z)).dist(dSDist); } } if( token != "end" ) { @@ -4730,32 +4761,31 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName, parser >> token >> attenuation; - rsSilnik.Init( - token, attenuation, - GetPosition().x, GetPosition().y, GetPosition().z, - true, true ); - if( rsSilnik.GetWaveTime() == 0 ) { - ErrorLog( "Missed sound: \"" + token + "\" for " + asFileName ); - } - parser.getTokens( 1, false ); - parser >> rsSilnik.AM; - if( MoverParameters->EngineType == DieselEngine ) { + rsSilnik = sound_man->create_sound(token); + if (rsSilnik) + { + rsSilnik->dist(attenuation); + parser.getTokens( 4, false ); - rsSilnik.AM /= ( MoverParameters->Power + MoverParameters->nmax * 60 ); - } - else if( MoverParameters->EngineType == DieselElectric ) { + parser >> rsSilnik->gain_mul; + if( MoverParameters->EngineType == DieselEngine ) { - rsSilnik.AM /= ( MoverParameters->Power * 3 ); - } - else { + rsSilnik->gain_mul /= ( MoverParameters->Power + MoverParameters->nmax * 60 ); + } + else if( MoverParameters->EngineType == DieselElectric ) { - rsSilnik.AM /= ( MoverParameters->Power + MoverParameters->nmax * 60 + MoverParameters->Power + MoverParameters->Power ); - } - parser.getTokens( 3, false ); - parser - >> rsSilnik.AA - >> rsSilnik.FM // MoverParameters->nmax; - >> rsSilnik.FA; + rsSilnik->gain_mul /= ( MoverParameters->Power * 3 ); + } + else { + + rsSilnik->gain_mul /= ( MoverParameters->Power + MoverParameters->nmax * 60 + MoverParameters->Power + MoverParameters->Power ); + } + + parser + >> rsSilnik->gain_off + >> rsSilnik->pitch_mul // MoverParameters->nmax; + >> rsSilnik->pitch_off; + } } else if( ( token == "ventilator:" ) @@ -4767,18 +4797,19 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName, parser >> token >> attenuation; - rsWentylator.Init( - token, attenuation, - GetPosition().x, GetPosition().y, GetPosition().z, - true, true ); - parser.getTokens( 4, false ); - parser - >> rsWentylator.AM - >> rsWentylator.AA - >> rsWentylator.FM - >> rsWentylator.FA; - rsWentylator.AM /= MoverParameters->RVentnmax; - rsWentylator.FM /= MoverParameters->RVentnmax; + rsWentylator = sound_man->create_sound(token); + if (rsWentylator) + { + rsWentylator->dist(attenuation); + parser.getTokens( 4, false ); + parser + >> rsWentylator->gain_mul + >> rsWentylator->gain_off + >> rsWentylator->pitch_mul + >> rsWentylator->pitch_off; + rsWentylator->gain_mul /= MoverParameters->RVentnmax; + rsWentylator->pitch_mul /= MoverParameters->RVentnmax; + } } else if( ( token == "transmission:" ) @@ -4789,14 +4820,15 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName, parser >> token >> attenuation; - rsPrzekladnia.Init( - token, attenuation, - GetPosition().x, GetPosition().y, GetPosition().z, - true ); - rsPrzekladnia.AM = 0.029; - rsPrzekladnia.AA = 0.1; - rsPrzekladnia.FM = 0.005; - rsPrzekladnia.FA = 1.0; + rsPrzekladnia = sound_man->create_sound(token); + if (rsPrzekladnia) + { + rsPrzekladnia->dist(attenuation); + rsPrzekladnia->gain_mul = 0.029; + rsPrzekladnia->gain_off = 0.1; + rsPrzekladnia->pitch_mul = 0.005; + rsPrzekladnia->pitch_off = 1.0; + } } else if( token == "brake:" ){ @@ -4806,26 +4838,27 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName, parser >> token >> attenuation; - rsPisk.Init( - token, attenuation, - GetPosition().x, GetPosition().y, GetPosition().z, - true ); - rsPisk.AM = parser.getToken(); - rsPisk.AA = parser.getToken() * ( 105 - Random( 10 ) ) / 100; - rsPisk.FM = 1.0; - rsPisk.FA = 0.0; + rsPisk = sound_man->create_sound(token); + if (rsPisk) + { + rsPisk->dist(attenuation); + rsPisk->gain_mul = parser.getToken(); + rsPisk->gain_off = parser.getToken() * ( 105 - Random( 10 ) ) / 100; + rsPisk->pitch_mul = 1.0; + rsPisk->pitch_off = 0.0; + } } else if( token == "brakeacc:" ) { // plik z przyspieszaczem (upust po zlapaniu hamowania) // sBrakeAcc.Init(str.c_str(),Parser->GetNextSymbol().ToDouble(),GetPosition().x,GetPosition().y,GetPosition().z,true); parser.getTokens( 1, false ); parser >> token; - sBrakeAcc = TSoundsManager::GetFromName( token, true ); + sBrakeAcc = sound_man->create_sound(token); bBrakeAcc = true; - // sBrakeAcc.AM=1.0; - // sBrakeAcc.AA=0.0; - // sBrakeAcc.FM=1.0; - // sBrakeAcc.FA=0.0; + // sBrakeAcc->gain_mul=1.0; + // sBrakeAcc->gain_off=0.0; + // sBrakeAcc->pitch_mul=1.0; + // sBrakeAcc->pitch_off=0.0; } else if( token == "unbrake:" ) { @@ -4835,14 +4868,9 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName, parser >> token >> attenuation; - rsUnbrake.Init( - token, attenuation, - GetPosition().x, GetPosition().y, GetPosition().z, - true ); - rsUnbrake.AM = 1.0; - rsUnbrake.AA = 0.0; - rsUnbrake.FM = 1.0; - rsUnbrake.FA = 0.0; + rsUnbrake = sound_man->create_sound(token); + if (rsUnbrake) + rsUnbrake->dist(attenuation); } else if( token == "derail:" ) { @@ -4852,14 +4880,9 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName, parser >> token >> attenuation; - rsDerailment.Init( - token, attenuation, - GetPosition().x, GetPosition().y, GetPosition().z, - true ); - rsDerailment.AM = 1.0; - rsDerailment.AA = 0.0; - rsDerailment.FM = 1.0; - rsDerailment.FA = 0.0; + rsDerailment = sound_man->create_sound(token); + if (rsDerailment) + rsDerailment->dist(attenuation); } else if( token == "dieselinc:" ) { @@ -4869,14 +4892,9 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName, parser >> token >> attenuation; - rsDiesielInc.Init( - token, attenuation, - GetPosition().x, GetPosition().y, GetPosition().z, - true ); - rsDiesielInc.AM = 1.0; - rsDiesielInc.AA = 0.0; - rsDiesielInc.FM = 1.0; - rsDiesielInc.FA = 0.0; + rsDiesielInc = sound_man->create_sound(token); + if (rsDiesielInc) + rsDiesielInc->dist(attenuation); } else if( token == "curve:" ) { @@ -4886,24 +4904,19 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName, parser >> token >> attenuation; - rscurve.Init( - token, attenuation, - GetPosition().x, GetPosition().y, GetPosition().z, - true ); - rscurve.AM = 1.0; - rscurve.AA = 0.0; - rscurve.FM = 1.0; - rscurve.FA = 0.0; + rscurve = sound_man->create_sound(token); + if (rscurve) + rscurve->dist(attenuation); } else if( token == "horn1:" ) { // pliki z trabieniem - sHorn1.Load( parser, GetPosition() ); + sHorn1 = sound_man->create_complex_sound(parser); } else if( token == "horn2:" ) { // pliki z trabieniem wysokoton. - sHorn2.Load( parser, GetPosition() ); + sHorn2 = sound_man->create_complex_sound(parser); if( iHornWarning ) { iHornWarning = 2; // numer syreny do użycia po otrzymaniu sygnału do jazdy } @@ -4911,74 +4924,62 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName, else if( token == "departuresignal:" ) { // pliki z sygnalem odjazdu - sDepartureSignal.Load( parser, GetPosition() ); + sDepartureSignal = sound_man->create_complex_sound(parser); } else if( token == "pantographup:" ) { // pliki dzwiekow pantografow parser.getTokens( 1, false ); parser >> token; - sPantUp.Init( - token, 50, - GetPosition().x, GetPosition().y, GetPosition().z, - true ); + sPantUp = sound_man->create_sound(token); } else if( token == "pantographdown:" ) { // pliki dzwiekow pantografow parser.getTokens( 1, false ); parser >> token; - sPantDown.Init( - token, 50, - GetPosition().x, GetPosition().y, GetPosition().z, - true ); + sPantDown = sound_man->create_sound(token); } else if( token == "compressor:" ) { // pliki ze sprezarka - sCompressor.Load( parser, GetPosition() ); + sCompressor = sound_man->create_complex_sound(parser); } else if( token == "converter:" ) { // pliki z przetwornica // if (MoverParameters->EngineType==DieselElectric) //będzie modulowany? - sConverter.Load( parser, GetPosition() ); + sConverter = sound_man->create_complex_sound(parser); } else if( token == "turbo:" ) { // pliki z turbogeneratorem - sTurbo.Load( parser, GetPosition() ); + sTurbo = sound_man->create_complex_sound(parser); } else if( token == "small-compressor:" ) { // pliki z przetwornica - sSmallCompressor.Load( parser, GetPosition() ); + sSmallCompressor = sound_man->create_complex_sound(parser); } else if( token == "dooropen:" ) { parser.getTokens( 1, false ); parser >> token; - rsDoorOpen.Init( - token, 50, - GetPosition().x, GetPosition().y, GetPosition().z, - true ); + rsDoorOpen = sound_man->create_sound(token); } else if( token == "doorclose:" ) { parser.getTokens( 1, false ); parser >> token; - rsDoorClose.Init( - token, 50, - GetPosition().x, GetPosition().y, GetPosition().z, - true ); + rsDoorClose = sound_man->create_sound(token); } else if( token == "sand:" ) { // pliki z piasecznica - sSand.Load( parser, GetPosition() ); + sSand = sound_man->create_complex_sound(parser); } else if( token == "releaser:" ) { // pliki z odluzniaczem - sReleaser.Load( parser, GetPosition() ); + sReleaser = sound_man->create_complex_sound(parser); } } while( ( token != "" ) diff --git a/DynObj.h b/DynObj.h index ea7c1cb1..1dbdf631 100644 --- a/DynObj.h +++ b/DynObj.h @@ -14,8 +14,6 @@ http://mozilla.org/MPL/2.0/. #include "TrkFoll.h" // McZapkie: -#include "RealSound.h" -#include "AdvSound.h" #include "Button.h" #include "AirCoupler.h" #include "Texture.h" @@ -307,28 +305,28 @@ public: // modele składowe pojazdu double dRailLength; double dRailPosition[MaxAxles]; // licznik pozycji osi w/m szyny double dWheelsPosition[MaxAxles]; // pozycja osi w/m srodka pojazdu - TRealSound rsStukot[MaxAxles]; // dzwieki poszczegolnych osi //McZapkie-270202 - TRealSound rsSilnik; // McZapkie-010302 - silnik - TRealSound rsWentylator; // McZapkie-030302 - TRealSound rsPisk; // McZapkie-260302 - TRealSound rsDerailment; // McZapkie-051202 - TRealSound rsPrzekladnia; - TAdvancedSound sHorn1; - TAdvancedSound sHorn2; - TAdvancedSound sCompressor; // NBMX wrzesien 2003 - TAdvancedSound sConverter; - TAdvancedSound sSmallCompressor; - TAdvancedSound sDepartureSignal; - TAdvancedSound sTurbo; - TAdvancedSound sSand; - TAdvancedSound sReleaser; + sound* rsStukot[MaxAxles] = { nullptr }; // dzwieki poszczegolnych osi //McZapkie-270202 + sound* rsSilnik = nullptr; // McZapkie-010302 - silnik + sound* rsWentylator = nullptr; // McZapkie-030302 + sound* rsPisk = nullptr; // McZapkie-260302 + sound* rsDerailment = nullptr; // McZapkie-051202 + sound* rsPrzekladnia = nullptr; + sound* sHorn1 = nullptr; + sound* sHorn2 = nullptr; + sound* sCompressor = nullptr; // NBMX wrzesien 2003 + sound* sConverter = nullptr; + sound* sSmallCompressor = nullptr; + sound* sDepartureSignal = nullptr; + sound* sTurbo = nullptr; + sound* sSand = nullptr; + sound* sReleaser = nullptr; // Winger 010304 - // TRealSound rsPanTup; //PSound sPantUp; - TRealSound sPantUp; - TRealSound sPantDown; - TRealSound rsDoorOpen; // Ra: przeniesione z kabiny - TRealSound rsDoorClose; + // sound* rsPanTup; //PSound sPantUp; + sound* sPantUp = nullptr; + sound* sPantDown = nullptr; + sound* rsDoorOpen = nullptr; // Ra: przeniesione z kabiny + sound* rsDoorClose = nullptr; double eng_vol_act; double eng_frq_act; @@ -339,10 +337,10 @@ public: // modele składowe pojazdu vector3 modelShake; bool renderme; // yB - czy renderowac - // TRealSound sBrakeAcc; //dźwięk przyspieszacza - PSound sBrakeAcc; + // sound* sBrakeAcc; //dźwięk przyspieszacza + sound* sBrakeAcc = nullptr; bool bBrakeAcc; - TRealSound rsUnbrake; // yB - odglos luzowania + sound* rsUnbrake = nullptr; // yB - odglos luzowania float ModCamRot; int iInventory; // flagi bitowe posiadanych submodeli (np. świateł) void TurnOff(); @@ -397,8 +395,8 @@ public: // modele składowe pojazdu return this ? asName : std::string(""); }; - TRealSound rsDiesielInc; // youBy - TRealSound rscurve; // youBy + sound* rsDiesielInc = nullptr; // youBy + sound* rscurve = nullptr; // youBy // std::ofstream PneuLogFile; //zapis parametrow pneumatycznych // youBy - dym // TSmoke Smog; diff --git a/Event.h b/Event.h index 7d020046..a3e9ff33 100644 --- a/Event.h +++ b/Event.h @@ -73,7 +73,7 @@ union TParam bool asBool; double asdouble; int asInt; - TTextSound *tsTextSound; + sound *tsTextSound; char *asText; TCommandType asCommand; TTractionPowerSource *psPower; diff --git a/FadeSound.cpp b/FadeSound.cpp deleted file mode 100644 index fff7273f..00000000 --- a/FadeSound.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* -This Source Code Form is subject to the -terms of the Mozilla Public License, v. -2.0. If a copy of the MPL was not -distributed with this file, You can -obtain one at -http://mozilla.org/MPL/2.0/. -*/ -/* - MaSzyna EU07 locomotive simulator - Copyright (C) 2001-2004 Marcin Wozniak and others - -*/ - -#include "stdafx.h" -#include "FadeSound.h" -#include "Timer.h" - -TFadeSound::~TFadeSound() -{ - Free(); -} - -void TFadeSound::Free() -{ -} - -void TFadeSound::Init(std::string const &Name, float fNewFade) -{ - Sound = TSoundsManager::GetFromName(Name, false); - if (Sound) - Sound->SetVolume(0); - fFade = fNewFade; - fTime = 0; -} - -void TFadeSound::TurnOn() -{ - State = ss_Starting; - Sound->Play(0, 0, DSBPLAY_LOOPING); - fTime = fFade; -} - -void TFadeSound::TurnOff() -{ - State = ss_ShuttingDown; -} - -void TFadeSound::Update() -{ - - if (State == ss_Starting) - { - fTime += Timer::GetDeltaTime(); - // SoundStart->SetVolume(-1000*(4-fTime)/4); - if (fTime >= fFade) - { - fTime = fFade; - State = ss_Commencing; - Sound->SetVolume(-2000 * (fFade - fTime) / fFade); - Sound->SetFrequency(44100 - 500 + 500 * (fTime) / fFade); - } - else if (Timer::GetSoundTimer()) - { - Sound->SetVolume(-2000 * (fFade - fTime) / fFade); - Sound->SetFrequency(44100 - 500 + 500 * (fTime) / fFade); - } - } - else if (State == ss_ShuttingDown) - { - fTime -= Timer::GetDeltaTime(); - - if (fTime <= 0) - { - State = ss_Off; - fTime = 0; - Sound->Stop(); - } - if (Timer::GetSoundTimer()) - { // DSBVOLUME_MIN - Sound->SetVolume(-2000 * (fFade - fTime) / fFade); - Sound->SetFrequency(44100 - 500 + 500 * fTime / fFade); - } - } -} -void TFadeSound::Volume(long vol) -{ - float glos = 1; - Sound->SetVolume(vol * glos); -} - -//--------------------------------------------------------------------------- diff --git a/FadeSound.h b/FadeSound.h deleted file mode 100644 index 6ce4e1b0..00000000 --- a/FadeSound.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -This Source Code Form is subject to the -terms of the Mozilla Public License, v. -2.0. If a copy of the MPL was not -distributed with this file, You can -obtain one at -http://mozilla.org/MPL/2.0/. -*/ - -#ifndef FadeSoundH -#define FadeSoundH - -#include "Sound.h" -#include "AdvSound.h" - -class TFadeSound -{ - PSound Sound = nullptr; - float fFade = 0.0f; - float dt = 0.0f, - fTime = 0.0f; - TSoundState State = ss_Off; - - public: - TFadeSound(); - ~TFadeSound(); - void Init(std::string const &Name, float fNewFade); - void TurnOn(); - void TurnOff(); - bool Playing() - { - return (State == ss_Commencing || State == ss_Starting); - }; - void Free(); - void Update(); - void Volume(long vol); -}; - -//--------------------------------------------------------------------------- -#endif diff --git a/Globals.h b/Globals.h index 81c159ed..50834b84 100644 --- a/Globals.h +++ b/Globals.h @@ -121,7 +121,7 @@ class TDynamicObject; class TAnimModel; // obiekt terenu class cParser; // nowy (powolny!) parser class TEvent; -class TTextSound; +class sound; class TTranscript { // klasa obsługująca linijkę napisu do dźwięku @@ -320,7 +320,7 @@ class Global static float4 UITextColor; // base color of UI text static std::string asLang; // domyślny język - http://tools.ietf.org/html/bcp47 static int iHiddenEvents; // czy łączyć eventy z torami poprzez nazwę toru - static TTextSound *tsRadioBusy[10]; // zajętość kanałów radiowych (wskaźnik na odgrywany dźwięk) + static sound *tsRadioBusy[10]; // zajętość kanałów radiowych (wskaźnik na odgrywany dźwięk) static int iPoKeysPWM[7]; // numery wejść dla PWM //randomizacja diff --git a/Ground.cpp b/Ground.cpp index c2d2bb23..e62e341b 100644 --- a/Ground.cpp +++ b/Ground.cpp @@ -26,7 +26,6 @@ http://mozilla.org/MPL/2.0/. #include "TractionPower.h" #include "Traction.h" #include "Track.h" -#include "RealSound.h" #include "AnimModel.h" #include "MemCell.h" #include "mtable.h" @@ -38,13 +37,16 @@ http://mozilla.org/MPL/2.0/. #include "Names.h" #include "World.h" #include "uilayer.h" +#include "sound.h" //--------------------------------------------------------------------------- +#ifdef _WIN32 extern "C" { - GLFWAPI HWND glfwGetWin32Window( GLFWwindow* window ); //m7todo: potrzebne do directsound + GLFWAPI HWND glfwGetWin32Window( GLFWwindow* window ); } +#endif bool bCondition; // McZapkie: do testowania warunku na event multiple std::string LogComment; @@ -231,13 +233,6 @@ void TGroundNode::RenderHidden() double mgn = SquareMagnitude(pCenter - Global::pCameraPosition); switch (iType) { - case TP_SOUND: // McZapkie - dzwiek zapetlony w zaleznosci od odleglosci - if ((tsStaticSound->GetStatus() & DSBSTATUS_PLAYING) == DSBPLAY_LOOPING) - { - tsStaticSound->Play(1, DSBPLAY_LOOPING, true, tsStaticSound->vSoundPosition); - tsStaticSound->AdjFreq(1.0, Timer::GetDeltaTime()); - } - return; case TP_EVLAUNCH: if (EvLaunch->Render()) if ((EvLaunch->dRadius < 0) || (mgn < EvLaunch->dRadius)) @@ -1060,8 +1055,11 @@ TGroundNode * TGround::AddGroundNode(cParser *parser) parser->getTokens(); *parser >> token; str = token; - //str = AnsiString(token.c_str()); - tmp->tsStaticSound = new TTextSound(str, sqrt(tmp->fSquareRadius), tmp->pCenter.x, tmp->pCenter.y, tmp->pCenter.z, false, false, rmin); + + tmp->tsStaticSound = sound_man->create_text_sound(str); + if (tmp->tsStaticSound) + tmp->tsStaticSound->position(tmp->pCenter).dist(sqrt(tmp->fSquareRadius)); + if (rmin < 0.0) rmin = 0.0; // przywrócenie poprawnej wartości, jeśli służyła do wyłączenia efektu Dopplera parser->getTokens(); @@ -3183,15 +3181,13 @@ bool TGround::CheckQuery() switch (tmpEvent->Params[0].asInt) { // trzy możliwe przypadki: case 0: - tmpEvent->Params[9].tsTextSound->Stop(); + tmpEvent->Params[9].tsTextSound->stop(); break; case 1: - tmpEvent->Params[9].tsTextSound->Play( - 1, 0, true, tmpEvent->Params[9].tsTextSound->vSoundPosition); + tmpEvent->Params[9].tsTextSound->play(); break; case -1: - tmpEvent->Params[9].tsTextSound->Play( - 1, DSBPLAY_LOOPING, true, tmpEvent->Params[9].tsTextSound->vSoundPosition); + tmpEvent->Params[9].tsTextSound->play(); break; } break; diff --git a/Ground.h b/Ground.h index 6c0b8b26..1ca1c34c 100644 --- a/Ground.h +++ b/Ground.h @@ -123,7 +123,7 @@ public: TEventLauncher *EvLaunch; // wyzwalacz zdarzeń TTraction *hvTraction; // drut zasilający TTractionPowerSource *psTractionPowerSource; // zasilanie drutu (zaniedbane w sceneriach) - TTextSound *tsStaticSound; // dźwięk przestrzenny + sound *tsStaticSound; // dźwięk przestrzenny TGroundNode *nNode; // obiekt renderujący grupowo ma tu wskaźnik na listę obiektów }; Math3D::vector3 pCenter; // współrzędne środka do przydzielenia sektora diff --git a/RealSound.cpp b/RealSound.cpp deleted file mode 100644 index 92d04108..00000000 --- a/RealSound.cpp +++ /dev/null @@ -1,278 +0,0 @@ -/* -This Source Code Form is subject to the -terms of the Mozilla Public License, v. -2.0. If a copy of the MPL was not -distributed with this file, You can -obtain one at -http://mozilla.org/MPL/2.0/. -*/ -/* - MaSzyna EU07 locomotive simulator - Copyright (C) 2001-2004 Marcin Wozniak, Maciej Czapkiewicz and others - -*/ - -#include "stdafx.h" -#include "RealSound.h" -#include "Globals.h" -#include "Logs.h" -//#include "math.h" -#include "Timer.h" -#include "McZapkie/mctools.h" -#include "usefull.h" - -TRealSound::TRealSound(std::string const &SoundName, double SoundAttenuation, double X, double Y, double Z, bool Dynamic, - bool freqmod, double rmin) -{ - Init(SoundName, SoundAttenuation, X, Y, Z, Dynamic, freqmod, rmin); -} - -TRealSound::~TRealSound() -{ - // if (this) if (pSound) pSound->Stop(); -} - -void TRealSound::Free() -{ -} - -void TRealSound::Init(std::string const &SoundName, double DistanceAttenuation, double X, double Y, double Z, - bool Dynamic, bool freqmod, double rmin) -{ - // Nazwa=SoundName; //to tak raczej nie zadziała, (SoundName) jest tymczasowe - pSound = TSoundsManager::GetFromName(SoundName, Dynamic, &fFrequency); - if (pSound) - { - if (freqmod) - if (fFrequency != 22050.0) - { // dla modulowanych nie może być zmiany mnożnika, bo częstotliwość w nagłówku byłą - // ignorowana, a mogła być inna niż 22050 - fFrequency = 22050.0; - ErrorLog("Bad sound: " + SoundName + ", as modulated, should have 22.05kHz in header"); - } - AM = 1.0; - pSound->SetVolume(DSBVOLUME_MIN); - } - else - { // nie ma dźwięku, to jest wysyp - AM = 0; - ErrorLog("Missed sound: " + SoundName); - } - if (DistanceAttenuation > 0.0) - { - dSoundAtt = DistanceAttenuation * DistanceAttenuation; - vSoundPosition.x = X; - vSoundPosition.y = Y; - vSoundPosition.z = Z; - if (rmin < 0) - iDoppler = 1; // wyłączenie efektu Dopplera, np. dla dźwięku ptaków - } - else - dSoundAtt = -1; -}; - -double TRealSound::ListenerDistance(vector3 ListenerPosition) -{ - if (dSoundAtt == -1) - { - return 0.0; - } - else - { - return SquareMagnitude(ListenerPosition - vSoundPosition); - } -} - -void TRealSound::Play(double Volume, int Looping, bool ListenerInside, vector3 NewPosition) -{ - if (!pSound) - return; - long int vol; - double dS = 0.0; - // double Distance; - DWORD stat; - if ((Global::bSoundEnabled) && (AM != 0)) - { - if (Volume > 1.0) - Volume = 1.0; - fPreviousDistance = fDistance; - fDistance = 0.0; //?? - if (dSoundAtt > 0.0) - { - vSoundPosition = NewPosition; - dS = dSoundAtt; //*dSoundAtt; //bo odleglosc podawana w kwadracie - fDistance = ListenerDistance(Global::pCameraPosition); - if (ListenerInside) // osłabianie dźwięków z odległością - Volume = Volume * dS / (dS + fDistance); - else - Volume = Volume * dS / (dS + 2 * fDistance); // podwójne dla ListenerInside=false - } - if (iDoppler) // - { // Ra 2014-07: efekt Dopplera nie zawsze jest wskazany - // if (FreeFlyModeFlag) //gdy swobodne latanie - nie sprawdza się to - fPreviousDistance = fDistance; // to efektu Dopplera nie będzie - } - if (Looping) // dźwięk zapętlony można wyłączyć i zostanie włączony w miarę potrzeby - bLoopPlay = true; // dźwięk wyłączony - // McZapkie-010302 - babranie tylko z niezbyt odleglymi dźwiękami - if ((dSoundAtt == -1) || (fDistance < 20.0 * dS)) - { - // vol=2*Volume+1; - // if (vol<1) vol=1; - // vol=10000*(log(vol)-1); - // vol=10000*(vol-1); - // int glos=1; - // Volume=Volume*glos; //Ra: whatta hella is this - if (Volume < 0.0) - Volume = 0.0; - vol = -5000.0 + 5000.0 * Volume; - if (vol >= 0) - vol = -1; - if (Timer::GetSoundTimer() || !Looping) // Ra: po co to jest? - pSound->SetVolume(vol); // Attenuation, in hundredths of a decibel (dB). - pSound->GetStatus(&stat); - if (!(stat & DSBSTATUS_PLAYING)) - pSound->Play(0, 0, Looping); - } - else // wylacz dzwiek bo daleko - { // Ra 2014-09: oddalanie się nie może być powodem do wyłączenie dźwięku - /* - // Ra: stara wersja, ale podobno lepsza - pSound->GetStatus(&stat); - if (bLoopPlay) //jeśli zapętlony, to zostanie ponownie włączony, o ile znajdzie się - bliżej - if (stat&DSBSTATUS_PLAYING) - pSound->Stop(); - // Ra: wyłączyłem, bo podobno jest gorzej niż wcześniej - //ZiomalCl: dźwięk po wyłączeniu sam się nie włączy, gdy wrócimy w rejon odtwarzania - pSound->SetVolume(DSBVOLUME_MIN); //dlatego lepiej go wyciszyć na czas oddalenia się - pSound->GetStatus(&stat); - if (!(stat&DSBSTATUS_PLAYING)) - pSound->Play(0,0,Looping); //ZiomalCl: włączenie odtwarzania rownież i tu, gdyż - jesli uruchamiamy dźwięk poza promieniem, nie uruchomi się on w ogóle - */ - } - } -}; - -void TRealSound::Start(){ - // włączenie dźwięku - -}; - -void TRealSound::Stop() -{ - DWORD stat; - if (pSound) - if ((Global::bSoundEnabled) && (AM != 0)) - { - bLoopPlay = false; // dźwięk wyłączony - pSound->GetStatus(&stat); - if (stat & DSBSTATUS_PLAYING) - pSound->Stop(); - } -}; - -void TRealSound::AdjFreq(double Freq, double dt) // McZapkie TODO: dorobic tu efekt Dopplera -// Freq moze byc liczba dodatnia mniejsza od 1 lub wieksza od 1 -{ - float df, Vlist; - if ((Global::bSoundEnabled) && (AM != 0) && (pSound != nullptr)) - { - if (dt > 0) - // efekt Dopplera - { - Vlist = (sqrt(fPreviousDistance) - sqrt(fDistance)) / dt; - df = Freq * (1 + Vlist / 299.8); - } - else - df = Freq; - if (Timer::GetSoundTimer()) - { - df = fFrequency * df; // TODO - brac czestotliwosc probkowania z wav - pSound->SetFrequency( clamp( df, static_cast(DSBFREQUENCY_MIN), static_cast(DSBFREQUENCY_MAX) ) ); - } - } -} - -double TRealSound::GetWaveTime() // McZapkie: na razie tylko dla 22KHz/8bps -{ // używana do pomiaru czasu dla dźwięków z początkiem i końcem - if (!pSound) - return 0.0; - double WaveTime; - DSBCAPS caps; - caps.dwSize = sizeof(caps); - pSound->GetCaps(&caps); - WaveTime = caps.dwBufferBytes; - return WaveTime / - fFrequency; //(pSound->); // wielkosc w bajtach przez czestotliwosc probkowania -} - -void TRealSound::SetPan(int Pan) -{ - pSound->SetPan(Pan); -} - -int TRealSound::GetStatus() -{ - DWORD stat; - if ((Global::bSoundEnabled) && (AM != 0)) - { - pSound->GetStatus(&stat); - return stat; - } - else - return 0; -} - -void TRealSound::ResetPosition() -{ - if (pSound) // Ra: znowu jakiś badziew! - pSound->SetCurrentPosition(0); -} - -TTextSound::TTextSound(std::string const &SoundName, double SoundAttenuation, double X, double Y, double Z, - bool Dynamic, bool freqmod, double rmin) - : TRealSound(SoundName, SoundAttenuation, X, Y, Z, Dynamic, freqmod, rmin) -{ - Init(SoundName, SoundAttenuation, X, Y, Z, Dynamic, freqmod, rmin); -} - -void TTextSound::Init(std::string const &SoundName, double SoundAttenuation, double X, double Y, double Z, - bool Dynamic, bool freqmod, double rmin) -{ // dodatkowo doczytuje plik tekstowy - //TRealSound::Init(SoundName, SoundAttenuation, X, Y, Z, Dynamic, freqmod, rmin); - fTime = GetWaveTime(); - std::string txt(SoundName); - txt.erase( txt.rfind( '.' ) ); // obcięcie rozszerzenia - for (size_t i = txt.length(); i > 0; --i) - if (txt[i] == '/') - txt[i] = '\\'; // bo nie rozumi - txt += "-" + Global::asLang + ".txt"; // już może być w różnych językach - if (!FileExists(txt)) - txt = "sounds\\" + txt; //ścieżka może nie być podana - if (FileExists(txt)) - { // wczytanie -/* TFileStream *ts = new TFileStream(txt, fmOpenRead); - asText = AnsiString::StringOfChar(' ', ts->Size); - ts->Read(asText.c_str(), ts->Size); - delete ts; -*/ std::ifstream inputfile( txt ); - asText.assign( std::istreambuf_iterator( inputfile ), std::istreambuf_iterator() ); - } -}; -void TTextSound::Play(double Volume, int Looping, bool ListenerInside, vector3 NewPosition) -{ - if (false == asText.empty()) - { // jeśli ma powiązany tekst - DWORD stat; - pSound->GetStatus(&stat); - if (!(stat & DSBSTATUS_PLAYING)) { - // jeśli nie jest aktualnie odgrywany - Global::tranTexts.Add( asText, fTime, true ); - } - } - TRealSound::Play(Volume, Looping, ListenerInside, NewPosition); -}; - -//--------------------------------------------------------------------------- diff --git a/RealSound.h b/RealSound.h deleted file mode 100644 index 91416d8a..00000000 --- a/RealSound.h +++ /dev/null @@ -1,83 +0,0 @@ -/* -This Source Code Form is subject to the -terms of the Mozilla Public License, v. -2.0. If a copy of the MPL was not -distributed with this file, You can -obtain one at -http://mozilla.org/MPL/2.0/. -*/ - -#ifndef RealSoundH -#define RealSoundH - -#include -#include "Sound.h" -#include "geometry.h" - -class TRealSound -{ - protected: - PSound pSound = nullptr; -// char *Nazwa; // dla celow odwszawiania NOTE: currently not used anywhere - double fDistance = 0.0, - fPreviousDistance = 0.0; // dla liczenia Dopplera - float fFrequency = 22050.0; // częstotliwość samplowania pliku - int iDoppler = 0; // Ra 2014-07: możliwość wyłączenia efektu Dopplera np. dla śpiewu ptaków - public: - vector3 vSoundPosition; // polozenie zrodla dzwieku - double dSoundAtt = -1.0; // odleglosc polowicznego zaniku dzwieku - double AM = 0.0; // mnoznik amplitudy - double AA = 0.0; // offset amplitudy - double FM = 0.0; // mnoznik czestotliwosci - double FA = 0.0; // offset czestotliwosci - bool bLoopPlay = false; // czy zapętlony dźwięk jest odtwarzany - TRealSound() = default; - TRealSound( std::string const &SoundName, double SoundAttenuation, double X, double Y, double Z, bool Dynamic, - bool freqmod = false, double rmin = 0.0); - ~TRealSound(); - void Free(); - void Init(std::string const &SoundName, double SoundAttenuation, double X, double Y, double Z, bool Dynamic, - bool freqmod = false, double rmin = 0.0); - double ListenerDistance(vector3 ListenerPosition); - void Play(double Volume, int Looping, bool ListenerInside, vector3 NewPosition); - void Start(); - void Stop(); - void AdjFreq(double Freq, double dt); - void SetPan(int Pan); - double GetWaveTime(); // McZapkie TODO: dorobic dla roznych bps - int GetStatus(); - void ResetPosition(); - // void FreqReset(float f=22050.0) {fFrequency=f;}; - bool Empty() { return ( pSound == nullptr ); } -}; - -class TTextSound : public TRealSound -{ // dźwięk ze stenogramem - std::string asText; - float fTime; // czas trwania - public: - TTextSound(std::string const &SoundName, double SoundAttenuation, double X, double Y, double Z, - bool Dynamic, bool freqmod = false, double rmin = 0.0); - void Init(std::string const &SoundName, double SoundAttenuation, double X, double Y, double Z, - bool Dynamic, bool freqmod = false, double rmin = 0.0); - void Play(double Volume, int Looping, bool ListenerInside, vector3 NewPosition); -}; - -class TSynthSound -{ // klasa generująca sygnał odjazdu (Rp12, Rp13), potem rozbudować o pracę manewrowego... - int iIndex[44]; // indeksy początkowe, gdy mamy kilka wariantów dźwięków składowych - // 0..9 - cyfry 0..9 - // 10..19 - liczby 10..19 - // 21..29 - dziesiątki (*21==*10?) - // 31..39 - setki 100,200,...,800,900 - // 40 - "tysiąc" - // 41 - "tysiące" - // 42 - indeksy początkowe dla "odjazd" - // 43 - indeksy początkowe dla "gotów" - PSound *sSound; // posortowana tablica dźwięków, rozmiar zależny od liczby znalezionych plików - // a może zamiast wielu plików/dźwięków zrobić jeden połączony plik i posługiwać się czasem - // od..do? -}; - -//--------------------------------------------------------------------------- -#endif diff --git a/Sound.cpp b/Sound.cpp deleted file mode 100644 index beb4bd58..00000000 --- a/Sound.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#ifdef _WIN32 -#include "WinSound.cpp" -#else -#include "DummySound.cpp" -#endif diff --git a/Sound.h b/Sound.h deleted file mode 100644 index 204595d8..00000000 --- a/Sound.h +++ /dev/null @@ -1,81 +0,0 @@ -/* -This Source Code Form is subject to the -terms of the Mozilla Public License, v. -2.0. If a copy of the MPL was not -distributed with this file, You can -obtain one at -http://mozilla.org/MPL/2.0/. -*/ - -#pragma once - -#include -#include - -#ifdef _WIN32 -#include -#else -#define DSBFREQUENCY_MIN 0 -#define DSBFREQUENCY_MAX 0 -#define DSBSTATUS_PLAYING 0 -#define DSBPLAY_LOOPING 0 -#define DSBVOLUME_MIN 0 -#define DSBVOLUME_MAX 0 -struct DSBCAPS -{ - uint16_t dwBufferBytes; - uint16_t dwSize; -}; -struct dummysb -{ - void Stop() {} - void SetCurrentPosition(int) {} - void SetVolume(int) {} - void Play(int, int, int) {} - void GetStatus(unsigned int *stat) { *stat = 0; } - void SetPan(int) {} - void SetFrequency(int) {} - void GetCaps(DSBCAPS *caps) { caps->dwBufferBytes = 0; } -}; -typedef dummysb* LPDIRECTSOUNDBUFFER; -typedef int LPDIRECTSOUNDNOTIFY; -typedef int LPDIRECTSOUND; -typedef int HWND; -#endif - -typedef LPDIRECTSOUNDBUFFER PSound; - -class TSoundContainer -{ -public: - int Concurrent; - int Oldest; - std::string m_name; - LPDIRECTSOUNDBUFFER DSBuffer; - float fSamplingRate; // częstotliwość odczytana z pliku - int iBitsPerSample; // ile bitów na próbkę - TSoundContainer *Next; - std::stack DSBuffers; - - TSoundContainer(LPDIRECTSOUND pDS, std::string const &Directory, std::string const &Filename, int NConcurrent); - ~TSoundContainer(); - LPDIRECTSOUNDBUFFER GetUnique( LPDIRECTSOUND pDS ); -}; - -class TSoundsManager -{ -private: - static LPDIRECTSOUND pDS; - static LPDIRECTSOUNDNOTIFY pDSNotify; - static TSoundContainer *First; - static int Count; - - static TSoundContainer * LoadFromFile( std::string const &Directory, std::string const &FileName, int Concurrent); - -public: - ~TSoundsManager(); - static void Init( HWND hWnd ); - static void Free(); - static LPDIRECTSOUNDBUFFER GetFromName( std::string const &Name, bool Dynamic, float *fSamplingRate = NULL ); - static void RestoreAll(); -}; diff --git a/Train.cpp b/Train.cpp index 20675cf5..c9103c75 100644 --- a/Train.cpp +++ b/Train.cpp @@ -21,6 +21,7 @@ http://mozilla.org/MPL/2.0/. #include "Timer.h" #include "Driver.h" #include "Console.h" +#include "sound.h" TCab::TCab() { @@ -290,6 +291,40 @@ TTrain::~TTrain() if (DynamicObject->Mechanik) DynamicObject->Mechanik->TakeControl( true); // likwidacja kabiny wymaga przejęcia przez AI + + sound_man->destroy_sound(&dsbNastawnikJazdy); + sound_man->destroy_sound(&dsbNastawnikBocz); + sound_man->destroy_sound(&dsbRelay); + sound_man->destroy_sound(&dsbPneumaticRelay); + sound_man->destroy_sound(&dsbSwitch); + sound_man->destroy_sound(&dsbPneumaticSwitch); + sound_man->destroy_sound(&dsbReverserKey); + sound_man->destroy_sound(&dsbCouplerAttach); + sound_man->destroy_sound(&dsbCouplerDetach); + sound_man->destroy_sound(&dsbDieselIgnition); + sound_man->destroy_sound(&dsbDoorClose); + sound_man->destroy_sound(&dsbDoorOpen); + sound_man->destroy_sound(&dsbPantUp); + sound_man->destroy_sound(&dsbPantDown); + sound_man->destroy_sound(&dsbWejscie_na_bezoporow); + sound_man->destroy_sound(&dsbWejscie_na_drugi_uklad); + sound_man->destroy_sound(&rsBrake); + sound_man->destroy_sound(&rsSlippery); + sound_man->destroy_sound(&rsHiss); + sound_man->destroy_sound(&rsHissU); + sound_man->destroy_sound(&rsHissE); + sound_man->destroy_sound(&rsHissX); + sound_man->destroy_sound(&rsHissT); + sound_man->destroy_sound(&rsSBHiss); + sound_man->destroy_sound(&rsRunningNoise); + sound_man->destroy_sound(&rsEngageSlippery); + sound_man->destroy_sound(&rsFadeSound); + sound_man->destroy_sound(&dsbHasler); + sound_man->destroy_sound(&dsbBuzzer); + sound_man->destroy_sound(&dsbSlipAlarm); + sound_man->destroy_sound(&dsbCouplerStretch); + sound_man->destroy_sound(&dsbEN57_CouplerStretch); + sound_man->destroy_sound(&dsbBufferClamp); } bool TTrain::Init(TDynamicObject *NewDynamicObject, bool e3d) @@ -538,7 +573,7 @@ void TTrain::OnCommand_secondcontrollerincrease( TTrain *Train, command_data con } else if( Train->mvControlled->IncScndCtrl( 1 ) ) { // sound feedback - Train->play_sound( Train->dsbNastawnikBocz, Train->dsbNastawnikJazdy, DSBVOLUME_MAX, 0 ); + Train->play_sound( Train->dsbNastawnikBocz, Train->dsbNastawnikJazdy); } } } @@ -549,7 +584,7 @@ void TTrain::OnCommand_secondcontrollerincreasefast( TTrain *Train, command_data // on press or hold if( Train->mvControlled->IncScndCtrl( 2 ) ) { // sound feedback - Train->play_sound( Train->dsbNastawnikBocz, Train->dsbNastawnikJazdy, DSBVOLUME_MAX, 0 ); + Train->play_sound( Train->dsbNastawnikBocz, Train->dsbNastawnikJazdy); } } } @@ -623,7 +658,7 @@ void TTrain::OnCommand_secondcontrollerdecrease( TTrain *Train, command_data con } else if( Train->mvControlled->DecScndCtrl( 1 ) ) { // sound feedback - Train->play_sound( Train->dsbNastawnikBocz, Train->dsbNastawnikJazdy, DSBVOLUME_MAX, 0 ); + Train->play_sound( Train->dsbNastawnikBocz, Train->dsbNastawnikJazdy); } } } @@ -634,7 +669,7 @@ void TTrain::OnCommand_secondcontrollerdecreasefast( TTrain *Train, command_data // on press or hold if( Train->mvControlled->DecScndCtrl( 2 ) ) { // sound feedback - Train->play_sound( Train->dsbNastawnikBocz, Train->dsbNastawnikJazdy, DSBVOLUME_MAX, 0 ); + Train->play_sound( Train->dsbNastawnikBocz, Train->dsbNastawnikJazdy); } } } @@ -1105,7 +1140,7 @@ void TTrain::OnCommand_reverserincrease( TTrain *Train, command_data const &Comm if( Train->mvOccupied->DirectionForward() ) { // sound feedback - Train->play_sound( Train->dsbReverserKey, Train->dsbSwitch, DSBVOLUME_MAX, 0 ); + Train->play_sound( Train->dsbReverserKey, Train->dsbSwitch); // aktualizacja skrajnych pojazdów w składzie if( ( Train->mvOccupied->ActiveDir ) && ( Train->DynamicObject->Mechanik ) ) { @@ -1122,7 +1157,7 @@ void TTrain::OnCommand_reverserdecrease( TTrain *Train, command_data const &Comm if( Train->mvOccupied->DirectionBackward() ) { // sound feedback - Train->play_sound( Train->dsbReverserKey, Train->dsbSwitch, DSBVOLUME_MAX, 0 ); + Train->play_sound( Train->dsbReverserKey, Train->dsbSwitch); // aktualizacja skrajnych pojazdów w składzie if( ( Train->mvOccupied->ActiveDir ) && ( Train->DynamicObject->Mechanik ) ) { @@ -3961,125 +3996,130 @@ bool TTrain::Update( double const Deltatime ) //------------------ double vol = 0; - // int freq=1; double dfreq; + glm::vec3 dynpos; + { + vector3 v = DynamicObject->GetPosition(); + dynpos = glm::make_vec3(&v.x); + } // McZapkie-280302 - syczenie if ((mvOccupied->BrakeHandle == FV4a) || (mvOccupied->BrakeHandle == FVel6)) { - if (rsHiss.AM != 0) // upuszczanie z PG + if (rsHiss) // upuszczanie z PG { fPPress = (1 * fPPress + mvOccupied->Handle->GetSound(s_fv4a_b)) / (2); if (fPPress > 0) { - vol = 2.0 * rsHiss.AM * fPPress; + vol = 2.0 * fPPress; } if (vol > 0.001) { - rsHiss.Play(vol, DSBPLAY_LOOPING, true, DynamicObject->GetPosition()); + rsHiss->loop().gain(vol).position(dynpos).play(); } else { - rsHiss.Stop(); + rsHiss->stop(); } } - if (rsHissU.AM != 0) // upuszczanie z PG + if (rsHissU) // upuszczanie z PG { fNPress = (1 * fNPress + mvOccupied->Handle->GetSound(s_fv4a_u)) / (2); + vol = 0.0; if (fNPress > 0) { - vol = rsHissU.AM * fNPress; + vol = fNPress; } if (vol > 0.001) { - rsHissU.Play(vol, DSBPLAY_LOOPING, true, DynamicObject->GetPosition()); + rsHissU->loop().gain(vol).position(dynpos).play(); } else { - rsHissU.Stop(); + rsHissU->stop(); } } - if (rsHissE.AM != 0) // upuszczanie przy naglym + if (rsHissE) // upuszczanie przy naglym { - vol = mvOccupied->Handle->GetSound(s_fv4a_e) * rsHissE.AM; + vol = mvOccupied->Handle->GetSound(s_fv4a_e); if (vol > 0.001) { - rsHissE.Play(vol, DSBPLAY_LOOPING, true, DynamicObject->GetPosition()); + rsHissE->loop().gain(vol).position(dynpos).play(); } else { - rsHissE.Stop(); + rsHissE->stop(); } } - if (rsHissX.AM != 0) // upuszczanie sterujacego fala + if (rsHissX) // upuszczanie sterujacego fala { - vol = mvOccupied->Handle->GetSound(s_fv4a_x) * rsHissX.AM; + vol = mvOccupied->Handle->GetSound(s_fv4a_x); if (vol > 0.001) { - rsHissX.Play(vol, DSBPLAY_LOOPING, true, DynamicObject->GetPosition()); + rsHissX->loop().gain(vol).position(dynpos).play(); } else { - rsHissX.Stop(); + rsHissX->stop(); } } - if (rsHissT.AM != 0) // upuszczanie z czasowego + if (rsHissT) // upuszczanie z czasowego { - vol = mvOccupied->Handle->GetSound(s_fv4a_t) * rsHissT.AM; + vol = mvOccupied->Handle->GetSound(s_fv4a_t); if (vol > 0.001) { - rsHissT.Play(vol, DSBPLAY_LOOPING, true, DynamicObject->GetPosition()); + rsHissT->loop().gain(vol).position(dynpos).play(); } else { - rsHissT.Stop(); + rsHissT->stop(); } } } // koniec FV4a else // jesli nie FV4a { - if (rsHiss.AM != 0.0) // upuszczanie z PG + if (rsHiss) // upuszczanie z PG { fPPress = (4.0f * fPPress + std::max(mvOccupied->dpLocalValve, mvOccupied->dpMainValve)) / (4.0f + 1.0f); if (fPPress > 0.0f) { - vol = 2.0 * rsHiss.AM * fPPress; + vol = 2.0 * fPPress; } if (vol > 0.01) { - rsHiss.Play(vol, DSBPLAY_LOOPING, true, DynamicObject->GetPosition()); + rsHiss->loop().gain(vol).position(dynpos).play(); } else { - rsHiss.Stop(); + rsHiss->stop(); } } - if (rsHissU.AM != 0.0) // napelnianie PG + if (rsHissU) // napelnianie PG { fNPress = (4.0f * fNPress + Min0R(mvOccupied->dpLocalValve, mvOccupied->dpMainValve)) / (4.0f + 1.0f); if (fNPress < 0.0f) { - vol = -1.0 * rsHissU.AM * fNPress; + vol = -1.0 * fNPress; } if (vol > 0.01) { - rsHissU.Play(vol, DSBPLAY_LOOPING, true, DynamicObject->GetPosition()); + rsHissU->loop().gain(vol).position(dynpos).play(); } else { - rsHissU.Stop(); + rsHissU->stop(); } } } // koniec nie FV4a // Winger-160404 - syczenie pomocniczego (luzowanie) - /* if (rsSBHiss.AM!=0) + /* if (rsSBHiss->gain_mul!=0) { fSPPress=(mvOccupied->LocalBrakeRatio())-(mvOccupied->LocalBrakePos); if (fSPPress>0) { - vol=2*rsSBHiss.AM*fSPPress; + vol=2*rsSBHiss->gain_mul*fSPPress; } if (vol>0.1) { @@ -4087,22 +4127,22 @@ bool TTrain::Update( double const Deltatime ) } else { - rsSBHiss.Stop(); + rsSBHiss->stop(); } } */ // szum w czasie jazdy vol = 0.0; dfreq = 1.0; - if (rsRunningNoise.AM != 0) + if (rsRunningNoise) { if (DynamicObject->GetVelocity() != 0) { if (!TestFlag(mvOccupied->DamageFlag, dtrain_wheelwear)) // McZpakie-221103: halas zalezny od kola { - dfreq = rsRunningNoise.FM * mvOccupied->Vel + rsRunningNoise.FA; - vol = rsRunningNoise.AM * mvOccupied->Vel + rsRunningNoise.AA; + dfreq = mvOccupied->Vel; + vol = mvOccupied->Vel; switch (tor->eEnvironment) { case e_tunnel: @@ -4127,8 +4167,8 @@ bool TTrain::Update( double const Deltatime ) else // uszkodzone kolo (podkucie) if (fabs(mvOccupied->nrot) > 0.01) { - dfreq = rsRunningNoise.FM * mvOccupied->Vel + rsRunningNoise.FA; - vol = rsRunningNoise.AM * mvOccupied->Vel + rsRunningNoise.AA; + dfreq = mvOccupied->Vel; + vol = mvOccupied->Vel; switch (tor->eEnvironment) { case e_tunnel: @@ -4153,66 +4193,63 @@ bool TTrain::Update( double const Deltatime ) mvOccupied->UnitBrakeForce / (1 + mvOccupied->MaxBrakeForce); // hamulce wzmagaja halas vol = vol * (20.0 + tor->iDamageFlag) / 21; - rsRunningNoise.AdjFreq(dfreq, 0); - rsRunningNoise.Play(vol, DSBPLAY_LOOPING, true, DynamicObject->GetPosition()); + rsRunningNoise->pitch(dfreq).gain(vol).position(dynpos).loop().play(); } else - rsRunningNoise.Stop(); + rsRunningNoise->stop(); } - if (rsBrake.AM != 0) + if (rsBrake) { if ((!mvOccupied->SlippingWheels) && (mvOccupied->UnitBrakeForce > 10.0) && (DynamicObject->GetVelocity() > 0.01)) { - // vol=rsBrake.AA+rsBrake.AM*(DynamicObject->GetVelocity()*100+mvOccupied->UnitBrakeForce); - vol = - rsBrake.AM * sqrt((DynamicObject->GetVelocity() * mvOccupied->UnitBrakeForce)); - dfreq = rsBrake.FA + rsBrake.FM * DynamicObject->GetVelocity(); - rsBrake.AdjFreq(dfreq, 0); - rsBrake.Play(vol, DSBPLAY_LOOPING, true, DynamicObject->GetPosition()); + // vol=rsBrake->gain_off+rsBrake->gain_mul*(DynamicObject->GetVelocity()*100+mvOccupied->UnitBrakeForce); + vol = sqrt((DynamicObject->GetVelocity() * mvOccupied->UnitBrakeForce)); + dfreq = DynamicObject->GetVelocity(); + rsBrake->pitch(dfreq).gain(vol).position(dynpos).loop().play(); } else { - rsBrake.Stop(); + rsBrake->stop(); } } - if (rsEngageSlippery.AM != 0) + if (rsEngageSlippery) { if /*((fabs(mvControlled->dizel_engagedeltaomega)>0.2) && */ ( mvControlled->dizel_engage > 0.1) { if (fabs(mvControlled->dizel_engagedeltaomega) > 0.2) { - dfreq = rsEngageSlippery.FA + - rsEngageSlippery.FM * fabs(mvControlled->dizel_engagedeltaomega); - vol = rsEngageSlippery.AA + rsEngageSlippery.AM * (mvControlled->dizel_engage); + dfreq = fabs(mvControlled->dizel_engagedeltaomega); + vol = mvControlled->dizel_engage; } else { dfreq = - 1; // rsEngageSlippery.FA+0.7*rsEngageSlippery.FM*(fabs(mvControlled->enrot)+mvControlled->nmax); + 1; // rsEngageSlippery->pitch_off+0.7*rsEngageSlippery->pitch_mul*(fabs(mvControlled->enrot)+mvControlled->nmax); if (mvControlled->dizel_engage > 0.2) vol = - rsEngageSlippery.AA + - 0.2 * rsEngageSlippery.AM * (mvControlled->enrot / mvControlled->nmax); + 0.2 * (mvControlled->enrot / mvControlled->nmax); else vol = 0; } - rsEngageSlippery.AdjFreq(dfreq, 0); - rsEngageSlippery.Play(vol, DSBPLAY_LOOPING, true, DynamicObject->GetPosition()); + rsEngageSlippery->pitch(dfreq).gain(vol).position(dynpos).loop().play(); } else { - rsEngageSlippery.Stop(); + rsEngageSlippery->stop(); } } - if (FreeFlyModeFlag) - rsFadeSound.Stop(); // wyłącz to cholerne cykanie! - else - rsFadeSound.Play(1, DSBPLAY_LOOPING, true, DynamicObject->GetPosition()); + if (rsFadeSound) + { + if (FreeFlyModeFlag) + rsFadeSound->stop(); // wyłącz to cholerne cykanie! + else + rsFadeSound->loop().position(dynpos).play(); + } // McZapkie! - to wazne - SoundFlag wystawiane jest przez moje moduly // gdy zachodza pewne wydarzenia komentowane dzwiekiem. @@ -4228,20 +4265,20 @@ bool TTrain::Update( double const Deltatime ) if (mvOccupied->EventFlag || TestFlag(mvOccupied->SoundFlag, sound_loud)) { mvOccupied->EventFlag = false; // Ra: w kabinie? - if( dsbRelay != nullptr ) { dsbRelay->SetVolume( DSBVOLUME_MAX ); } + if( dsbRelay != nullptr ) { dsbRelay->gain(1.0f); } } else { - if( dsbRelay != nullptr ) { dsbRelay->SetVolume( -40 ); } + if( dsbRelay != nullptr ) { dsbRelay->gain(0.5f); } } if (!TestFlag(mvOccupied->SoundFlag, sound_manyrelay)) - play_sound( dsbRelay ); + dsbRelay->play(); else { if (TestFlag(mvOccupied->SoundFlag, sound_loud)) - play_sound( dsbWejscie_na_bezoporow ); + dsbWejscie_na_bezoporow->play(); else - play_sound( dsbWejscie_na_drugi_uklad ); + dsbWejscie_na_drugi_uklad->play(); } } @@ -4249,40 +4286,43 @@ bool TTrain::Update( double const Deltatime ) if( TestFlag( mvOccupied->SoundFlag, sound_bufferclamp ) ) // zderzaki uderzaja o siebie { if( TestFlag( mvOccupied->SoundFlag, sound_loud ) ) - dsbBufferClamp->SetVolume( DSBVOLUME_MAX ); + dsbBufferClamp->gain(1.0f); else - dsbBufferClamp->SetVolume( -20 ); - play_sound( dsbBufferClamp ); + dsbBufferClamp->gain(0.5f); + dsbBufferClamp->play(); } } if (dsbCouplerStretch) if (TestFlag(mvOccupied->SoundFlag, sound_couplerstretch)) // sprzegi sie rozciagaja { if (TestFlag(mvOccupied->SoundFlag, sound_loud)) - dsbCouplerStretch->SetVolume(DSBVOLUME_MAX); + dsbCouplerStretch->gain(1.0f); else - dsbCouplerStretch->SetVolume(-20); - play_sound( dsbCouplerStretch ); + dsbCouplerStretch->gain(0.5f); + dsbCouplerStretch->play(); } if (mvOccupied->SoundFlag == 0) if (mvOccupied->EventFlag) if (TestFlag(mvOccupied->DamageFlag, dtrain_wheelwear)) { // Ra: przenieść do DynObj! - if (rsRunningNoise.AM != 0) + if (rsRunningNoise) { - rsRunningNoise.Stop(); - // float aa=rsRunningNoise.AA; - float am = rsRunningNoise.AM; - float fa = rsRunningNoise.FA; - float fm = rsRunningNoise.FM; - rsRunningNoise.Init("lomotpodkucia.wav", -1, 0, 0, 0, - true); // MC: zmiana szumu na lomot - if (rsRunningNoise.AM == 1) - rsRunningNoise.AM = am; - rsRunningNoise.AA = 0.7; - rsRunningNoise.FA = fa; - rsRunningNoise.FM = fm; + rsRunningNoise->stop(); + // float aa=rsRunningNoise->gain_off; + float am = rsRunningNoise->gain_mul; + float fa = rsRunningNoise->pitch_off; + float fm = rsRunningNoise->pitch_mul; + + // MC: zmiana szumu na lomot + sound_man->destroy_sound(&rsRunningNoise); + rsRunningNoise = sound_man->create_sound("lomotpodkucia.wav"); + + if (rsRunningNoise->gain_mul == 1) + rsRunningNoise->gain_mul = am; + rsRunningNoise->gain_off = 0.7; + rsRunningNoise->pitch_off = fa; + rsRunningNoise->pitch_mul = fm; } mvOccupied->EventFlag = false; } @@ -4473,29 +4513,29 @@ bool TTrain::Update( double const Deltatime ) { if (fabs(mvControlled->Im) > 10.0) btLampkaPoslizg.TurnOn(); - rsSlippery.Play(-rsSlippery.AM * veldiff + rsSlippery.AA, DSBPLAY_LOOPING, true, DynamicObject->GetPosition()); + rsSlippery->gain(-veldiff).loop().position(dynpos).play(); if (mvControlled->TrainType == dt_181) // alarm przy poslizgu dla 181/182 - BOMBARDIER if (dsbSlipAlarm) - play_sound( dsbSlipAlarm, DSBPLAY_LOOPING ); + dsbSlipAlarm->loop().play(); } else { if ((mvOccupied->UnitBrakeForce > 100.0) && (DynamicObject->GetVelocity() > 1.0)) { - rsSlippery.Play(rsSlippery.AM * veldiff + rsSlippery.AA, DSBPLAY_LOOPING, true, DynamicObject->GetPosition()); + rsSlippery->gain(veldiff).loop().position(dynpos).play(); if (mvControlled->TrainType == dt_181) if (dsbSlipAlarm) - dsbSlipAlarm->Stop(); + dsbSlipAlarm->stop(); } } } else { btLampkaPoslizg.TurnOff(); - rsSlippery.Stop(); + rsSlippery->stop(); if (mvControlled->TrainType == dt_181) if (dsbSlipAlarm) - dsbSlipAlarm->Stop(); + dsbSlipAlarm->stop(); } if ((mvControlled->Mains) || (mvControlled->TrainType == dt_EZT)) @@ -5065,28 +5105,20 @@ bool TTrain::Update( double const Deltatime ) { if (dsbBuzzer) { - dsbBuzzer->GetStatus(&stat); - if (!(stat & DSBSTATUS_PLAYING)) - { - play_sound( dsbBuzzer, DSBVOLUME_MAX, DSBPLAY_LOOPING ); + dsbBuzzer->loop().play(); #ifdef _WIN32 - Console::BitsSet(1 << 14); // ustawienie bitu 16 na PoKeys + Console::BitsSet(1 << 14); // ustawienie bitu 16 na PoKeys #endif - } } } else { if (dsbBuzzer) { - dsbBuzzer->GetStatus(&stat); - if (stat & DSBSTATUS_PLAYING) - { - dsbBuzzer->Stop(); + dsbBuzzer->stop(); #ifdef _WIN32 - Console::BitsClear(1 << 14); // ustawienie bitu 16 na PoKeys + Console::BitsClear(1 << 14); // ustawienie bitu 16 na PoKeys #endif - } } } } @@ -5096,12 +5128,7 @@ bool TTrain::Update( double const Deltatime ) btLampkaSHP.TurnOff(); if (dsbBuzzer) { - dsbBuzzer->GetStatus(&stat); - if (stat & DSBSTATUS_PLAYING) - { - dsbBuzzer->Stop(); - Console::BitsClear(1 << 14); // ustawienie bitu 16 na PoKeys - } + dsbBuzzer->stop(); } } @@ -5155,7 +5182,7 @@ bool TTrain::Update( double const Deltatime ) // mvControlled->StLinFlag=true; //WSem nie wrzucilo na ta // pozycje po jego zalaczeniu //yBARC - co to tutaj robi?! if (mvControlled->EngineType == DieselEngine) - dsbDieselIgnition->Play(0, 0, 0); + dsbDieselIgnition->play(); } } else @@ -5168,7 +5195,7 @@ bool TTrain::Update( double const Deltatime ) // zerowania timera if ((mvControlled->Mains != true) && (fMainRelayTimer > 0)) { - dsbRelay->Play(0, 0, 0); + dsbRelay->play(); fMainRelayTimer = 0; } ggMainOnButton.UpdateValue(0); @@ -5178,7 +5205,7 @@ bool TTrain::Update( double const Deltatime ) { ggMainOffButton.PutValue(1); if (mvControlled->MainSwitch(false)) - dsbRelay->Play(0, 0, 0); + dsbRelay->play(); } else ggMainOffButton.UpdateValue(0); @@ -5581,7 +5608,7 @@ bool TTrain::Update( double const Deltatime ) if ((mvOccupied->TrainType == dt_EZT) && (mvControlled->Mains) && (mvControlled->ActiveDir != 0)) { - play_sound( dsbPneumaticSwitch ); + dsbPneumaticSwitch->play(); } } #endif @@ -5669,14 +5696,14 @@ bool TTrain::Update( double const Deltatime ) ggAntiSlipButton.UpdateValue(1); if (mvOccupied->SwitchEPBrake(1)) { - play_sound( dsbPneumaticSwitch ); + dsbPneumaticSwitch->play(); } } else { if (mvOccupied->SwitchEPBrake(0)) { - play_sound( dsbPneumaticSwitch ); + dsbPneumaticSwitch->play(); } } @@ -5712,7 +5739,7 @@ bool TTrain::Update( double const Deltatime ) if (ggNextCurrentButton.SubModel) { ggNextCurrentButton.UpdateValue(1); - play_sound( dsbSwitch ); + dsbSwitch->play(); ShowNextCurrent = true; } } @@ -5725,7 +5752,7 @@ bool TTrain::Update( double const Deltatime ) { // Ra: było pod GLFW_KEY_F3 if ((mvOccupied->EpFuseSwitch(true))) { - play_sound( dsbPneumaticSwitch ); + dsbPneumaticSwitch->play(); } } } @@ -5737,7 +5764,7 @@ bool TTrain::Update( double const Deltatime ) { if ((mvOccupied->EpFuseSwitch(false))) { - play_sound( dsbPneumaticSwitch ); + dsbPneumaticSwitch->play(); } } } @@ -5751,7 +5778,7 @@ bool TTrain::Update( double const Deltatime ) if (ggNextCurrentButton.SubModel) { ggNextCurrentButton.UpdateValue(0); - play_sound( dsbSwitch ); + dsbSwitch->play(); ShowNextCurrent = false; } } @@ -5820,15 +5847,11 @@ bool TTrain::Update( double const Deltatime ) // if (fabs(DynamicObject->GetVelocity())>0.5) if( dsbHasler != nullptr ) { if( ( false == FreeFlyModeFlag ) && ( fTachoCount > maxtacho ) ) { - dsbHasler->GetStatus( &stat ); - if( !( stat & DSBSTATUS_PLAYING ) ) - play_sound( dsbHasler, DSBVOLUME_MAX, DSBPLAY_LOOPING ); + dsbHasler->loop().play(); } else { if( ( true == FreeFlyModeFlag ) || ( fTachoCount < 1 ) ) { - dsbHasler->GetStatus( &stat ); - if( stat & DSBSTATUS_PLAYING ) - dsbHasler->Stop(); + dsbHasler->stop(); } } } @@ -6022,11 +6045,11 @@ bool TTrain::LoadMMediaFile(std::string const &asFileName) //Wartości domyślne by nie wysypywało przy wybrakowanych mmd @240816 Stele // NOTE: should be no longer needed as safety checks were added, // but leaving the defaults for the sake of incomplete mmd files - dsbPneumaticSwitch = TSoundsManager::GetFromName("silence1.wav", true); - dsbBufferClamp = TSoundsManager::GetFromName("en57_bufferclamp.wav", true); - dsbCouplerDetach = TSoundsManager::GetFromName("couplerdetach.wav", true); - dsbCouplerStretch = TSoundsManager::GetFromName("en57_couplerstretch.wav", true); - dsbCouplerAttach = TSoundsManager::GetFromName("couplerattach.wav", true); + dsbPneumaticSwitch = sound_man->create_sound("silence1.wav"); + dsbBufferClamp = sound_man->create_sound("en57_bufferclamp.wav"); + dsbCouplerDetach = sound_man->create_sound("couplerdetach.wav"); + dsbCouplerStretch = sound_man->create_sound("en57_couplerstretch.wav"); + dsbCouplerAttach = sound_man->create_sound("couplerattach.wav"); std::string token; do @@ -6049,214 +6072,214 @@ bool TTrain::LoadMMediaFile(std::string const &asFileName) { // nastawnik: dsbNastawnikJazdy = - TSoundsManager::GetFromName(parser.getToken(), true); + sound_man->create_sound(parser.getToken()); } else if (token == "ctrlscnd:") { // hunter-081211: nastawnik bocznikowania dsbNastawnikBocz = - TSoundsManager::GetFromName(parser.getToken(), true); + sound_man->create_sound(parser.getToken()); } else if (token == "reverserkey:") { // hunter-131211: dzwiek kierunkowego dsbReverserKey = - TSoundsManager::GetFromName(parser.getToken(), true); + sound_man->create_sound(parser.getToken()); } else if (token == "buzzer:") { // bzyczek shp: dsbBuzzer = - TSoundsManager::GetFromName(parser.getToken(), true); + sound_man->create_sound(parser.getToken()); } else if (token == "slipalarm:") { // Bombardier 011010: alarm przy poslizgu: dsbSlipAlarm = - TSoundsManager::GetFromName(parser.getToken(), true); + sound_man->create_sound(parser.getToken()); } else if (token == "tachoclock:") { // cykanie rejestratora: dsbHasler = - TSoundsManager::GetFromName(parser.getToken(), true); + sound_man->create_sound(parser.getToken()); } else if (token == "switch:") { // przelaczniki: dsbSwitch = - TSoundsManager::GetFromName(parser.getToken(), true); + sound_man->create_sound(parser.getToken()); } else if (token == "pneumaticswitch:") { // stycznik EP: dsbPneumaticSwitch = - TSoundsManager::GetFromName(parser.getToken(), true); + sound_man->create_sound(parser.getToken()); } else if (token == "wejscie_na_bezoporow:") { // hunter-111211: wydzielenie wejscia na bezoporowa i na drugi uklad do pliku dsbWejscie_na_bezoporow = - TSoundsManager::GetFromName(parser.getToken(), true); + sound_man->create_sound(parser.getToken()); } else if (token == "wejscie_na_drugi_uklad:") { dsbWejscie_na_drugi_uklad = - TSoundsManager::GetFromName(parser.getToken(), true); + sound_man->create_sound(parser.getToken()); } else if (token == "relay:") { // styczniki itp: dsbRelay = - TSoundsManager::GetFromName(parser.getToken(), true); + sound_man->create_sound(parser.getToken()); if (!dsbWejscie_na_bezoporow) { // hunter-111211: domyslne, gdy brak dsbWejscie_na_bezoporow = - TSoundsManager::GetFromName("wejscie_na_bezoporow.wav", true); + sound_man->create_sound("wejscie_na_bezoporow.wav"); } if (!dsbWejscie_na_drugi_uklad) { dsbWejscie_na_drugi_uklad = - TSoundsManager::GetFromName("wescie_na_drugi_uklad.wav", true); + sound_man->create_sound("wescie_na_drugi_uklad.wav"); } } else if (token == "pneumaticrelay:") { // wylaczniki pneumatyczne: dsbPneumaticRelay = - TSoundsManager::GetFromName(parser.getToken(), true); + sound_man->create_sound(parser.getToken()); } else if (token == "couplerattach:") { // laczenie: dsbCouplerAttach = - TSoundsManager::GetFromName(parser.getToken(), true); + sound_man->create_sound(parser.getToken()); } else if (token == "couplerstretch:") { // laczenie: dsbCouplerStretch = - TSoundsManager::GetFromName(parser.getToken(), true); + sound_man->create_sound(parser.getToken()); } else if (token == "couplerdetach:") { // rozlaczanie: dsbCouplerDetach = - TSoundsManager::GetFromName(parser.getToken(), true); + sound_man->create_sound(parser.getToken()); } else if (token == "bufferclamp:") { // laczenie: dsbBufferClamp = - TSoundsManager::GetFromName(parser.getToken(), true); + sound_man->create_sound(parser.getToken()); } else if (token == "ignition:") { // odpalanie silnika dsbDieselIgnition = - TSoundsManager::GetFromName(parser.getToken(), true); + sound_man->create_sound(parser.getToken()); } else if (token == "brakesound:") { // hamowanie zwykle: - rsBrake.Init(parser.getToken(), -1, 0, 0, 0, true, true); + rsBrake = sound_man->create_sound(parser.getToken()); parser.getTokens(4, false); - parser >> rsBrake.AM >> rsBrake.AA >> rsBrake.FM >> rsBrake.FA; - rsBrake.AM /= (1 + mvOccupied->MaxBrakeForce * 1000); - rsBrake.FM /= (1 + mvOccupied->Vmax); + parser >> rsBrake->gain_mul >> rsBrake->gain_off >> rsBrake->pitch_mul >> rsBrake->pitch_off; + rsBrake->gain_mul /= (1 + mvOccupied->MaxBrakeForce * 1000); + rsBrake->pitch_mul /= (1 + mvOccupied->Vmax); } else if (token == "slipperysound:") { // sanie: - rsSlippery.Init(parser.getToken(), -1, 0, 0, 0, true); + rsSlippery = sound_man->create_sound(parser.getToken()); parser.getTokens(2, false); - parser >> rsSlippery.AM >> rsSlippery.AA; - rsSlippery.FM = 0.0; - rsSlippery.FA = 1.0; - rsSlippery.AM /= (1 + mvOccupied->Vmax); + parser >> rsSlippery->gain_mul >> rsSlippery->gain_off; + rsSlippery->pitch_mul = 0.0; + rsSlippery->pitch_off = 1.0; + rsSlippery->gain_mul /= (1 + mvOccupied->Vmax); } else if (token == "airsound:") { // syk: - rsHiss.Init(parser.getToken(), -1, 0, 0, 0, true); + rsHiss = sound_man->create_sound(parser.getToken()); parser.getTokens(2, false); - parser >> rsHiss.AM >> rsHiss.AA; - rsHiss.FM = 0.0; - rsHiss.FA = 1.0; + parser >> rsHiss->gain_mul >> rsHiss->gain_off; + rsHiss->pitch_mul = 0.0; + rsHiss->pitch_off = 1.0; } else if (token == "airsound2:") { // syk: - rsHissU.Init(parser.getToken(), -1, 0, 0, 0, true); + rsHissU = sound_man->create_sound(parser.getToken()); parser.getTokens(2, false); - parser >> rsHissU.AM >> rsHissU.AA; - rsHissU.FM = 0.0; - rsHissU.FA = 1.0; + parser >> rsHissU->gain_mul >> rsHissU->gain_off; + rsHissU->pitch_mul = 0.0; + rsHissU->pitch_off = 1.0; } else if (token == "airsound3:") { // syk: - rsHissE.Init(parser.getToken(), -1, 0, 0, 0, true); + rsHissE = sound_man->create_sound(parser.getToken()); parser.getTokens(2, false); - parser >> rsHissE.AM >> rsHissE.AA; - rsHissE.FM = 0.0; - rsHissE.FA = 1.0; + parser >> rsHissE->gain_mul >> rsHissE->gain_off; + rsHissE->pitch_mul = 0.0; + rsHissE->pitch_off = 1.0; } else if (token == "airsound4:") { // syk: - rsHissX.Init(parser.getToken(), -1, 0, 0, 0, true); + rsHissX = sound_man->create_sound(parser.getToken()); parser.getTokens(2, false); - parser >> rsHissX.AM >> rsHissX.AA; - rsHissX.FM = 0.0; - rsHissX.FA = 1.0; + parser >> rsHissX->gain_mul >> rsHissX->gain_off; + rsHissX->pitch_mul = 0.0; + rsHissX->pitch_off = 1.0; } else if (token == "airsound5:") { // syk: - rsHissT.Init(parser.getToken(), -1, 0, 0, 0, true); + rsHissT = sound_man->create_sound(parser.getToken()); parser.getTokens(2, false); - parser >> rsHissT.AM >> rsHissT.AA; - rsHissT.FM = 0.0; - rsHissT.FA = 1.0; + parser >> rsHissT->gain_mul >> rsHissT->gain_off; + rsHissT->pitch_mul = 0.0; + rsHissT->pitch_off = 1.0; } else if (token == "fadesound:") { // syk: - rsFadeSound.Init(parser.getToken(), -1, 0, 0, 0, true); - rsFadeSound.AM = 1.0; - rsFadeSound.AA = 1.0; - rsFadeSound.FM = 1.0; - rsFadeSound.FA = 1.0; + rsFadeSound = sound_man->create_sound(parser.getToken()); + rsFadeSound->gain_mul = 1.0; + rsFadeSound->gain_off = 1.0; + rsFadeSound->pitch_mul = 1.0; + rsFadeSound->pitch_off = 1.0; } else if (token == "localbrakesound:") { // syk: - rsSBHiss.Init(parser.getToken(), -1, 0, 0, 0, true); + rsSBHiss = sound_man->create_sound(parser.getToken()); parser.getTokens(2, false); - parser >> rsSBHiss.AM >> rsSBHiss.AA; - rsSBHiss.FM = 0.0; - rsSBHiss.FA = 1.0; + parser >> rsSBHiss->gain_mul >> rsSBHiss->gain_off; + rsSBHiss->pitch_mul = 0.0; + rsSBHiss->pitch_off = 1.0; } else if (token == "runningnoise:") { // szum podczas jazdy: - rsRunningNoise.Init(parser.getToken(), -1, 0, 0, 0, true, true); + rsRunningNoise = sound_man->create_sound(parser.getToken()); parser.getTokens(4, false); - parser >> rsRunningNoise.AM >> rsRunningNoise.AA >> rsRunningNoise.FM >> - rsRunningNoise.FA; - rsRunningNoise.AM /= (1 + mvOccupied->Vmax); - rsRunningNoise.FM /= (1 + mvOccupied->Vmax); + parser >> rsRunningNoise->gain_mul >> rsRunningNoise->gain_off >> rsRunningNoise->pitch_mul >> + rsRunningNoise->pitch_off; + rsRunningNoise->gain_mul /= (1 + mvOccupied->Vmax); + rsRunningNoise->pitch_mul /= (1 + mvOccupied->Vmax); } else if (token == "engageslippery:") { // tarcie tarcz sprzegla: - rsEngageSlippery.Init(parser.getToken(), -1, 0, 0, 0, true, true); + rsEngageSlippery = sound_man->create_sound(parser.getToken()); parser.getTokens(4, false); - parser >> rsEngageSlippery.AM >> rsEngageSlippery.AA >> rsEngageSlippery.FM >> - rsEngageSlippery.FA; - rsEngageSlippery.FM /= (1 + mvOccupied->nmax); + parser >> rsEngageSlippery->gain_mul >> rsEngageSlippery->gain_off >> rsEngageSlippery->pitch_mul >> + rsEngageSlippery->pitch_off; + rsEngageSlippery->pitch_mul /= (1 + mvOccupied->nmax); } else if (token == "mechspring:") { @@ -6273,25 +6296,25 @@ bool TTrain::LoadMMediaFile(std::string const &asFileName) { // podniesienie patyka: dsbPantUp = - TSoundsManager::GetFromName(parser.getToken(), true); + sound_man->create_sound(parser.getToken()); } else if (token == "pantographdown:") { // podniesienie patyka: dsbPantDown = - TSoundsManager::GetFromName(parser.getToken(), true); + sound_man->create_sound(parser.getToken()); } else if (token == "doorclose:") { // zamkniecie drzwi: dsbDoorClose = - TSoundsManager::GetFromName(parser.getToken(), true); + sound_man->create_sound(parser.getToken()); } else if (token == "dooropen:") { // otwarcie drzwi: dsbDoorOpen = - TSoundsManager::GetFromName(parser.getToken(), true); + sound_man->create_sound(parser.getToken()); } } while (token != ""); @@ -6483,7 +6506,7 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName) // HACK: for some reason simulation at the start is slow until a sound is played // until we do a proper fix, try to play a 'silent' sound when cab is entered // TBD: it could be instead a legit sound of door closing - play_sound( dsbSwitch, DSBVOLUME_MIN ); + play_sound( dsbSwitch, 0.0f ); return true; } return (token == "none"); @@ -6578,62 +6601,73 @@ void TTrain::DynamicSet(TDynamicObject *d) void TTrain::Silence() { // wyciszenie dźwięków przy wychodzeniu if (dsbNastawnikJazdy) - dsbNastawnikJazdy->Stop(); + dsbNastawnikJazdy->stop(); if (dsbNastawnikBocz) - dsbNastawnikBocz->Stop(); + dsbNastawnikBocz->stop(); if (dsbRelay) - dsbRelay->Stop(); + dsbRelay->stop(); if (dsbPneumaticRelay) - dsbPneumaticRelay->Stop(); + dsbPneumaticRelay->stop(); if (dsbSwitch) - dsbSwitch->Stop(); + dsbSwitch->stop(); if (dsbPneumaticSwitch) - dsbPneumaticSwitch->Stop(); + dsbPneumaticSwitch->stop(); if (dsbReverserKey) - dsbReverserKey->Stop(); + dsbReverserKey->stop(); if (dsbCouplerAttach) - dsbCouplerAttach->Stop(); + dsbCouplerAttach->stop(); if (dsbCouplerDetach) - dsbCouplerDetach->Stop(); + dsbCouplerDetach->stop(); if (dsbDieselIgnition) - dsbDieselIgnition->Stop(); + dsbDieselIgnition->stop(); if (dsbDoorClose) - dsbDoorClose->Stop(); + dsbDoorClose->stop(); if (dsbDoorOpen) - dsbDoorOpen->Stop(); + dsbDoorOpen->stop(); if (dsbPantUp) - dsbPantUp->Stop(); + dsbPantUp->stop(); if (dsbPantDown) - dsbPantDown->Stop(); + dsbPantDown->stop(); if (dsbWejscie_na_bezoporow) - dsbWejscie_na_bezoporow->Stop(); + dsbWejscie_na_bezoporow->stop(); if (dsbWejscie_na_drugi_uklad) - dsbWejscie_na_drugi_uklad->Stop(); - rsBrake.Stop(); - rsSlippery.Stop(); - rsHiss.Stop(); - rsHissU.Stop(); - rsHissE.Stop(); - rsHissX.Stop(); - rsHissT.Stop(); - rsSBHiss.Stop(); - rsRunningNoise.Stop(); - rsEngageSlippery.Stop(); - rsFadeSound.Stop(); + dsbWejscie_na_drugi_uklad->stop(); + if (rsBrake) + rsBrake->stop(); + if (rsSlippery) + rsSlippery->stop(); + if (rsHiss) + rsHiss->stop(); + if (rsHissU) + rsHissU->stop(); + if (rsHissE) + rsHissE->stop(); + if (rsHissX) + rsHissX->stop(); + if (rsHissT) + rsHissT->stop(); + if (rsSBHiss) + rsSBHiss->stop(); + if (rsRunningNoise) + rsRunningNoise->stop(); + if (rsEngageSlippery) + rsEngageSlippery->stop(); + if (rsFadeSound) + rsFadeSound->stop(); if (dsbHasler) - dsbHasler->Stop(); // wyłączenie dźwięków opuszczanej kabiny + dsbHasler->stop(); // wyłączenie dźwięków opuszczanej kabiny if (dsbBuzzer) - dsbBuzzer->Stop(); + dsbBuzzer->stop(); if (dsbSlipAlarm) - dsbSlipAlarm->Stop(); // dźwięk alarmu przy poślizgu - // sConverter.Stop(); - // sSmallCompressor->Stop(); + dsbSlipAlarm->stop(); // dźwięk alarmu przy poślizgu + // sConverter->stop(); + // sSmallCompressor->stop(); if (dsbCouplerStretch) - dsbCouplerStretch->Stop(); + dsbCouplerStretch->stop(); if (dsbEN57_CouplerStretch) - dsbEN57_CouplerStretch->Stop(); + dsbEN57_CouplerStretch->stop(); if (dsbBufferClamp) - dsbBufferClamp->Stop(); + dsbBufferClamp->stop(); }; void TTrain::SetLights() @@ -7734,29 +7768,19 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con } void -TTrain::play_sound( PSound Sound, int const Volume, DWORD const Flags ) { +TTrain::play_sound( sound* Sound, float gain ) { if( Sound ) { - - Sound->SetCurrentPosition( 0 ); - Sound->SetVolume( Volume ); - Sound->Play( 0, 0, Flags ); - return; + Sound->gain(gain).play(); } } void -TTrain::play_sound( PSound Sound, PSound Fallbacksound, int const Volume, DWORD const Flags ) { +TTrain::play_sound( sound* Sound, sound* Fallbacksound, float gain ) { - if( Sound ) { - - play_sound( Sound, Volume, Flags ); - return; - } - if( Fallbacksound ) { - - play_sound( Fallbacksound, Volume, Flags ); - return; - } + if( Sound ) + play_sound( Sound, gain); + else if( Fallbacksound ) + play_sound( Fallbacksound, gain ); } diff --git a/Train.h b/Train.h index 2c70dc70..d77466b3 100644 --- a/Train.h +++ b/Train.h @@ -14,8 +14,6 @@ http://mozilla.org/MPL/2.0/. #include "Button.h" #include "Gauge.h" #include "Spring.h" -#include "AdvSound.h" -#include "FadeSound.h" #include "PyInt.h" #include "command.h" @@ -99,8 +97,8 @@ class TTrain bool initialize_button(cParser &Parser, std::string const &Label, int const Cabindex); // plays specified sound, or fallback sound if the primary sound isn't presend // NOTE: temporary routine until sound system is sorted out and paired with switches - void play_sound( PSound Sound, int const Volume = DSBVOLUME_MAX, DWORD const Flags = 0 ); - void play_sound( PSound Sound, PSound Fallbacksound, int const Volume, DWORD const Flags ); + void play_sound( sound* Sound, float gain = 1.0f); + void play_sound( sound* Sound, sound* Fallbacksound, float gain = 1.0f ); // helper, returns true for EMU with oerlikon brake bool is_eztoer() const; // command handlers @@ -379,48 +377,48 @@ public: // reszta może by?publiczna double fMechRoll; double fMechPitch; - PSound dsbNastawnikJazdy; - PSound dsbNastawnikBocz; // hunter-081211 - PSound dsbRelay; - PSound dsbPneumaticRelay; - PSound dsbSwitch; - PSound dsbPneumaticSwitch; - PSound dsbReverserKey; // hunter-121211 + sound* dsbNastawnikJazdy = nullptr; + sound* dsbNastawnikBocz = nullptr; // hunter-081211 + sound* dsbRelay = nullptr; + sound* dsbPneumaticRelay = nullptr; + sound* dsbSwitch = nullptr; + sound* dsbPneumaticSwitch = nullptr; + sound* dsbReverserKey = nullptr; // hunter-121211 - PSound dsbCouplerAttach; // Ra: w kabinie???? - PSound dsbCouplerDetach; // Ra: w kabinie??? + sound* dsbCouplerAttach = nullptr; // Ra: w kabinie???? + sound* dsbCouplerDetach = nullptr; // Ra: w kabinie??? - PSound dsbDieselIgnition; // Ra: w kabinie??? + sound* dsbDieselIgnition = nullptr; // Ra: w kabinie??? - PSound dsbDoorClose; // Ra: w kabinie??? - PSound dsbDoorOpen; // Ra: w kabinie??? + sound* dsbDoorClose = nullptr; // Ra: w kabinie??? + sound* dsbDoorOpen = nullptr; // Ra: w kabinie??? // Winger 010304 - PSound dsbPantUp; - PSound dsbPantDown; + sound* dsbPantUp = nullptr; + sound* dsbPantDown = nullptr; - PSound dsbWejscie_na_bezoporow; - PSound dsbWejscie_na_drugi_uklad; // hunter-081211: poprawka literowki + sound* dsbWejscie_na_bezoporow = nullptr; + sound* dsbWejscie_na_drugi_uklad = nullptr; // hunter-081211: poprawka literowki - // PSound dsbHiss1; - // PSound dsbHiss2; + // sound* dsbHiss1; + // sound* dsbHiss2; // McZapkie-280302 - TRealSound rsBrake; - TRealSound rsSlippery; - TRealSound rsHiss; // upuszczanie - TRealSound rsHissU; // napelnianie - TRealSound rsHissE; // nagle - TRealSound rsHissX; // fala - TRealSound rsHissT; // czasowy - TRealSound rsSBHiss; - TRealSound rsRunningNoise; - TRealSound rsEngageSlippery; - TRealSound rsFadeSound; + sound* rsBrake = nullptr; + sound* rsSlippery = nullptr; + sound* rsHiss = nullptr; // upuszczanie + sound* rsHissU = nullptr; // napelnianie + sound* rsHissE = nullptr; // nagle + sound* rsHissX = nullptr; // fala + sound* rsHissT = nullptr; // czasowy + sound* rsSBHiss = nullptr; + sound* rsRunningNoise = nullptr; + sound* rsEngageSlippery = nullptr; + sound* rsFadeSound = nullptr; - PSound dsbHasler; - PSound dsbBuzzer; - PSound dsbSlipAlarm; // Bombardier 011010: alarm przy poslizgu dla 181/182 + sound* dsbHasler = nullptr; + sound* dsbBuzzer = nullptr; + sound* dsbSlipAlarm = nullptr; // Bombardier 011010: alarm przy poslizgu dla 181/182 // TFadeSound sConverter; //przetwornica // TFadeSound sSmallCompressor; //przetwornica @@ -432,10 +430,10 @@ public: // reszta może by?publiczna vector3 MirrorPosition(bool lewe); private: - // PSound dsbBuzzer; - PSound dsbCouplerStretch; - PSound dsbEN57_CouplerStretch; - PSound dsbBufferClamp; + // sound* dsbBuzzer; + sound* dsbCouplerStretch = nullptr; + sound* dsbEN57_CouplerStretch = nullptr; + sound* dsbBufferClamp = nullptr; // TSubModel *smCzuwakShpOn; // TSubModel *smCzuwakOn; // TSubModel *smShpOn; diff --git a/World.cpp b/World.cpp index 89e0d316..c33ebb97 100644 --- a/World.cpp +++ b/World.cpp @@ -21,7 +21,7 @@ http://mozilla.org/MPL/2.0/. #include "renderer.h" #include "Timer.h" #include "mtable.h" -#include "Sound.h" +#include "sound.h" #include "Camera.h" #include "ResourceManager.h" #include "Event.h" @@ -217,7 +217,7 @@ TWorld::~TWorld() Global::bManageNodes = false; // Ra: wyłączenie wyrejestrowania, bo się sypie TrainDelete(); // Ground.Free(); //Ra: usunięcie obiektów przed usunięciem dźwięków - sypie się - TSoundsManager::Free(); + delete sound_man; TModelsManager::Free(); } @@ -304,12 +304,9 @@ bool TWorld::Init( GLFWwindow *Window ) { std::shared_ptr initpanel = std::make_shared(85, 600); -#ifdef _WIN32 - TSoundsManager::Init( glfwGetWin32Window( window ) ); -#else - TSoundsManager::Init( 0 ); -#endif + sound_man = new sound_manager(); WriteLog("Sound Init OK"); + TModelsManager::Init(); WriteLog("Models init OK"); @@ -760,8 +757,7 @@ void TWorld::OnKeyDown(int cKey) temp->MoverParameters->DecBrakeMult()) if (Train) { // dźwięk oczywiście jest w kabinie - Train->dsbSwitch->SetVolume(DSBVOLUME_MAX); - Train->dsbSwitch->Play(0, 0, 0); + Train->dsbSwitch->gain(1.0f).play(); } } } @@ -790,8 +786,7 @@ void TWorld::OnKeyDown(int cKey) tmp->iLights[CouplNr] = (tmp->iLights[CouplNr] & ~mask) | set; if (Train) { // Ra: ten dźwięk z kabiny to przegięcie, ale na razie zostawiam - Train->dsbSwitch->SetVolume(DSBVOLUME_MAX); - Train->dsbSwitch->Play(0, 0, 0); + Train->dsbSwitch->gain(1.0f).play(); } } } @@ -811,8 +806,7 @@ void TWorld::OnKeyDown(int cKey) if (temp->MoverParameters->IncLocalBrakeLevelFAST()) if (Train) { // dźwięk oczywiście jest w kabinie - Train->dsbPneumaticRelay->SetVolume(-80); - Train->dsbPneumaticRelay->Play(0, 0, 0); + Train->dsbPneumaticRelay->gain(0.5f).play(); } } } @@ -831,8 +825,7 @@ void TWorld::OnKeyDown(int cKey) if (temp->MoverParameters->DecLocalBrakeLevelFAST()) if (Train) { // dźwięk oczywiście jest w kabinie - Train->dsbPneumaticRelay->SetVolume(-80); - Train->dsbPneumaticRelay->Play(0, 0, 0); + Train->dsbPneumaticRelay->gain(0.5f).play(); } } } @@ -1125,6 +1118,9 @@ bool TWorld::Update() dt = Timer::GetDeltaRenderTime(); // nie uwzględnia pauzowania ani mnożenia czasu + sound_man->set_listener(Camera.Pos, Camera.LookAt, Camera.vUp); + sound_man->update(dt); + // fixed step render time routines fTime50Hz += dt; // w pauzie też trzeba zliczać czas, bo przy dużym FPS będzie problem z odczytem ramek diff --git a/builds/cmake_win32.bat b/builds/cmake_win32.bat index 7237e543..51ab4f24 100644 --- a/builds/cmake_win32.bat +++ b/builds/cmake_win32.bat @@ -11,5 +11,9 @@ cmake ../.. -T v140_xp ^ -DPNG_PNG_INCLUDE_DIR=%DEPS_DIR%/libpng/include ^ -DPNG_LIBRARY=%DEPS_DIR%/libpng/lib/win32/libpng16.lib ^ -DZLIB_INCLUDE_DIR=%DEPS_DIR%/zlib-1.2.11 ^ --DGLM_ROOT_DIR=%DEPS_DIR%/glm-0.9.8.4 +-DGLM_ROOT_DIR=%DEPS_DIR%/glm-0.9.8.4 ^ +-DOPENAL_INCLUDE_DIR=%DEPS_DIR%/openal/include ^ +-DOPENAL_LIBRARY=%DEPS_DIR%/openal/lib/win32/OpenAL32.lib ^ +-DLIBSNDFILE_INCLUDE_DIR=%DEPS_DIR%/libsndfile/include ^ +-DLIBSNDFILE_LIBRARY=%DEPS_DIR%/libsndfile/lib/win32/libsndfile-1.lib popd \ No newline at end of file diff --git a/builds/cmake_win64.bat b/builds/cmake_win64.bat index 7e350eb6..9b35e9fe 100644 --- a/builds/cmake_win64.bat +++ b/builds/cmake_win64.bat @@ -11,5 +11,9 @@ cmake ../.. -A x64 ^ -DPNG_PNG_INCLUDE_DIR=%DEPS_DIR%/libpng/include ^ -DPNG_LIBRARY=%DEPS_DIR%/libpng/lib/win64/libpng16.lib ^ -DZLIB_INCLUDE_DIR=%DEPS_DIR%/zlib-1.2.11 ^ --DGLM_ROOT_DIR=%DEPS_DIR%/glm-0.9.8.4 +-DGLM_ROOT_DIR=%DEPS_DIR%/glm-0.9.8.4 ^ +-DOPENAL_INCLUDE_DIR=%DEPS_DIR%/openal/include ^ +-DOPENAL_LIBRARY=%DEPS_DIR%/openal/lib/win64/OpenAL32.lib ^ +-DLIBSNDFILE_INCLUDE_DIR=%DEPS_DIR%/libsndfile/include ^ +-DLIBSNDFILE_LIBRARY=%DEPS_DIR%/libsndfile/lib/win64/libsndfile-1.lib popd \ No newline at end of file diff --git a/builds/download_windeps.bat b/builds/download_windeps.bat index 58f75e46..76f660fc 100644 --- a/builds/download_windeps.bat +++ b/builds/download_windeps.bat @@ -1,2 +1,2 @@ -powershell "$wc = New-Object System.Net.WebClient; $wc.DownloadFile(\"https://milek7.pl/.stuff/eu07exe/builddep1.zip\", \"%cd%\deps_win.zip\")" +powershell "$wc = New-Object System.Net.WebClient; $wc.DownloadFile(\"https://milek7.pl/.stuff/eu07exe/builddep2.zip\", \"%cd%\deps_win.zip\")" powershell "$s = New-Object -ComObject shell.application; $z = $s.Namespace(\"%cd%\deps_win.zip\"); foreach ($i in $z.items()) { $s.Namespace(\"%cd%\").CopyHere($i) }" \ No newline at end of file diff --git a/sound.cpp b/sound.cpp new file mode 100644 index 00000000..e0d07a5d --- /dev/null +++ b/sound.cpp @@ -0,0 +1,561 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public +* License, v. 2.0. If a copy of the MPL was not distributed with this +* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "stdafx.h" +#include "McZapkie/mctools.h" +#include "Globals.h" +#include "sound.h" +#include "Logs.h" +#include +#include +#include + +load_error::load_error(std::string const &f) : std::runtime_error("sound: cannot find " + f) +{ + +} + +sound_manager::sound_manager() +{ + dev = alcOpenDevice(0); + if (!dev) + throw std::runtime_error("sound: cannot open device"); + + ALCint attr[3] = { ALC_MONO_SOURCES, 20000, 0 }; + // we're requesting horrible max amount of sources here + // because we create AL source object for each sound object, + // even if not active currently. considier creating AL source + // object only when source is played and destroying it afterwards + + ctx = alcCreateContext(dev, attr); + if (!ctx) + throw std::runtime_error("sound: cannot create context"); + + if (!alcMakeContextCurrent(ctx)) + throw std::runtime_error("sound: cannot select context"); + + alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED); + + alGetError(); +} + +sound_manager::~sound_manager() +{ + alcMakeContextCurrent(0); + alcDestroyContext(ctx); + alcCloseDevice(dev); +} + +sound_buffer* sound_manager::find_buffer(std::string name) +{ + name.erase(name.rfind('.')); + std::replace(name.begin(), name.end(), '\\', '/'); + + auto search = buffers.find(name); + if (search != buffers.end()) + return search->second; + else + return nullptr; +} + +std::string sound_manager::find_file(std::string name) +{ + if (FileExists(name)) + return name; + + name.erase(name.rfind('.')); + std::vector exts { ".wav", ".flac", ".ogg" }; + for (auto const &ext : exts) + if (FileExists(name + ext)) + return name + ext; + + return ""; +} + +sound_buffer* sound_manager::get_buffer(std::string const &name) +{ + sound_buffer* buf = find_buffer(Global::asCurrentDynamicPath + name); + if (buf) + return buf; + + buf = find_buffer("sounds/" + name); + if (buf) + return buf; + + std::string file = find_file(Global::asCurrentDynamicPath + name); + if (!file.size()) + file = find_file("sounds/" + name); + + if (!file.size()) + throw load_error(name); + + std::replace(file.begin(), file.end(), '\\', '/'); + + buf = new sound_buffer(file); + + file.erase(file.rfind('.')); + buffers.emplace(file, buf); + + return buf; +} + +simple_sound* sound_manager::create_sound(std::string const &file) +{ + try + { + WriteLog("creating source with " + file); + simple_sound *s = new simple_sound(get_buffer(file)); + sounds.emplace(s); + return s; + } + catch (load_error& e) + { + WriteLog(e.what()); + } + return nullptr; +} + +text_sound* sound_manager::create_text_sound(std::string const &file) +{ + try + { + WriteLog("creating source with " + file); + text_sound *s = new text_sound(get_buffer(file)); + sounds.emplace(s); + return s; + } + catch (load_error& e) + { + WriteLog(e.what()); + } + return nullptr; +} + +complex_sound* sound_manager::create_complex_sound(std::string const &pre, std::string const &main, std::string const &post) +{ + try + { + WriteLog("creating source with " + pre + ", " + main + ", " + post); + complex_sound *s = new complex_sound(get_buffer(pre), get_buffer(main), get_buffer(post)); + sounds.emplace(s); + return s; + } + catch (load_error& e) + { + WriteLog(e.what()); + } + return nullptr; +} + +complex_sound* sound_manager::create_complex_sound(cParser &parser) +{ + std::string pre, main, post; + double attenuation; + + parser.getTokens(3, true, "\n\t ;,"); // samples separated with commas + parser >> pre >> main >> post; + parser.getTokens(1, false); + parser >> attenuation; + + complex_sound* s = create_complex_sound(pre, main, post); + if (s) + s->dist(attenuation); + return s; +} + +void sound_manager::destroy_sound(sound **s) +{ + if (*s != nullptr) + { + sounds.erase(*s); + delete *s; + *s = nullptr; + } +} + +void sound_manager::update(float dt) +{ + ALenum err = alGetError(); + if (err != AL_NO_ERROR) + { + std::string errname; + if (err == AL_INVALID_NAME) + errname = "AL_INVALID_NAME"; + else if (err == AL_INVALID_ENUM) + errname = "AL_INVALID_ENUM"; + else if (err == AL_INVALID_VALUE) + errname = "AL_INVALID_VALUE"; + else if (err == AL_INVALID_OPERATION) + errname = "AL_INVALID_OPERATION"; + else if (err == AL_OUT_OF_MEMORY) + errname = "AL_OUT_OF_MEMORY"; + else + errname = "?"; + + throw std::runtime_error("sound: al error: " + errname); + } + + auto now = std::chrono::steady_clock::now(); + auto it = buffers.begin(); + while (it != buffers.end()) + { + if (now - it->second->unused_since() > gc_time) + { + delete it->second; + it = buffers.erase(it); + } + else + it++; + } + + glm::vec3 velocity = (pos - last_pos) / dt; + alListenerfv(AL_VELOCITY, glm::value_ptr(velocity)); + last_pos = pos; + + for (auto &s : sounds) + s->update(dt); +} + +void sound_manager::set_listener(glm::vec3 const &p, glm::vec3 const &at, glm::vec3 const &up) +{ + pos = p; + alListenerfv(AL_POSITION, glm::value_ptr(p)); + glm::vec3 ori[] = { at, up }; + alListenerfv(AL_ORIENTATION, (ALfloat*)ori); +} + +void sound_manager::set_listener(Math3D::vector3 const &p, Math3D::vector3 const &at, Math3D::vector3 const &up) +{ + set_listener((glm::vec3)glm::make_vec3(&p.x), (glm::vec3)glm::make_vec3(&at.x), (glm::vec3)glm::make_vec3(&up.x)); +} + +sound::sound() +{ + id = 0; + alGenSources(1, &id); + if (!id) + throw std::runtime_error("sound: cannot generate source"); + alSourcei(id, AL_SOURCE_RELATIVE, AL_TRUE); + dist(5.0f * 3.82f); + spatial = false; + gain_off = 0.0f; + gain_mul = 1.0f; + pitch_off = 0.0f; + pitch_mul = 1.0f; +} + +simple_sound::simple_sound(sound_buffer *buf) : sound::sound() +{ + looping = false; + playing = false; + buffer = buf; + alSourcei(id, AL_BUFFER, buffer->get_id()); + buffer->ref(); +} + +sound::~sound() +{ + alDeleteSources(1, &id); +} + +simple_sound::~simple_sound() +{ + buffer->unref(); +} + +sound& sound::position(glm::vec3 const &p) +{ + if (!spatial) + { + alSourcei(id, AL_SOURCE_RELATIVE, AL_FALSE); + spatial = true; + last_pos = p; + } + + if (p != pos) + { + pos = p; + pos_dirty = true; + + alSourcefv(id, AL_POSITION, glm::value_ptr(p)); + } + return *this; +} + +sound& sound::position(Math3D::vector3 const &pos) +{ + position((glm::vec3)glm::make_vec3(&pos.x)); + return *this; +} + +sound& sound::dist(float dist) +{ + max_dist = dist; + alSourcef(id, AL_MAX_DISTANCE, dist); + alSourcef(id, AL_REFERENCE_DISTANCE, dist / 3.82f); + return *this; +} + +void simple_sound::play() +{ + if (playing || (spatial && glm::distance(pos, sound_man->pos) > max_dist)) + return; + + alSourcePlay(id); + playing = true; +} + +void simple_sound::stop() +{ + if (!playing) + return; + + alSourceStop(id); + playing = false; +} + +void sound::update(float dt) +{ + if (spatial && pos_dirty) + { + glm::vec3 velocity = (pos - last_pos) / dt; // m/s + alSourcefv(id, AL_VELOCITY, glm::value_ptr(velocity)); + last_pos = pos; + pos_dirty = false; + } +} + +void simple_sound::update(float dt) +{ + sound::update(dt); + + if (playing) + { + ALint v; + alGetSourcei(id, AL_SOURCE_STATE, &v); + if (v != AL_PLAYING) + playing = false; + else if (spatial && glm::distance(pos, sound_man->pos) > max_dist) + stop(); + } +} + +sound& sound::gain(float gain) +{ + gain = std::min(std::max(0.0f, gain * gain_mul + gain_off), 1.0f); + alSourcef(id, AL_GAIN, gain); + return *this; +} + +sound& sound::pitch(float pitch) +{ + pitch = std::min(std::max(0.05f, pitch * pitch_mul + pitch_off), 20.0f); + alSourcef(id, AL_PITCH, pitch); + return *this; +} + +sound& simple_sound::loop(bool loop) +{ + if (loop != looping) + { + alSourcei(id, AL_LOOPING, (ALint)loop); + looping = loop; + } + return *this; +} + +bool simple_sound::is_playing() +{ + return playing; +} + +//m7todo: implement text_sound +text_sound::text_sound(sound_buffer *buf) : simple_sound::simple_sound(buf) +{ + +} + +void text_sound::play() +{ + simple_sound::play(); +} + +complex_sound::complex_sound(sound_buffer* pre, sound_buffer* main, sound_buffer* post) : sound::sound() +{ + this->pre = pre; + this->buffer = main; + this->post = post; + + pre->ref(); + buffer->ref(); + post->ref(); + + cs = state::post; +} + +complex_sound::~complex_sound() +{ + pre->unref(); + buffer->unref(); + post->unref(); +} + +void complex_sound::play() +{ + if (cs != state::post) + return; + + if (spatial && glm::distance(pos, sound_man->pos) > max_dist) + return; + + alSourceRewind(id); + + alSourcei(id, AL_LOOPING, AL_FALSE); + alSourcei(id, AL_BUFFER, 0); + ALuint buffers[] = { pre->get_id(), buffer->get_id() }; + alSourceQueueBuffers(id, 2, buffers); + + alSourcePlay(id); + + cs = state::premain; +} + +void complex_sound::stop() +{ + if (cs == state::main) + { + alSourceRewind(id); + + alSourcei(id, AL_LOOPING, AL_FALSE); + alSourcei(id, AL_BUFFER, 0); + alSourcei(id, AL_BUFFER, post->get_id()); + + alSourcePlay(id); + + cs = state::post; + } + else if (cs == state::premain) + cs = state::prepost; +} + +void complex_sound::update(float dt) +{ + sound::update(dt); + + if (cs == state::premain || cs == state::prepost) + { + ALint processed; + alGetSourcei(id, AL_BUFFERS_PROCESSED, &processed); + if (processed > 0) // already processed pre + { + if (cs == state::premain) + { + cs = state::main; + + ALuint pre_id = pre->get_id(); + alSourceUnqueueBuffers(id, 1, &pre_id); + alSourcei(id, AL_LOOPING, AL_TRUE); + if (processed > 1) // underrun occured + alSourcePlay(id); + + } + else if (cs == state::prepost) + { + cs = state::main; + stop(); + } + } + } + + if (cs == state::main) + if (spatial && glm::distance(pos, sound_man->pos) > max_dist) + stop(); +} + +sound& complex_sound::loop(bool loop) +{ + throw std::runtime_error("cannot loop complex_sound"); + return *this; +} + +bool complex_sound::is_playing() +{ + return cs != state::post; // almost accurate +} + +sound_buffer::sound_buffer(std::string &file) +{ + WriteLog("creating sound buffer from " + file); + + SF_INFO si; + si.format = 0; + + SNDFILE *sf = sf_open(file.c_str(), SFM_READ, &si); + if (sf == nullptr) + throw std::runtime_error("sound: sf_open failed"); + + int16_t *fbuf = new int16_t[si.frames * si.channels]; + if (sf_readf_short(sf, fbuf, si.frames) != si.frames) + throw std::runtime_error("sound: incomplete file"); + + sf_close(sf); + + int16_t *buf = nullptr; + if (si.channels == 1) + buf = fbuf; + else + { + WriteLog("sound: warning: mixing multichannel file to mono"); + buf = new int16_t[si.frames]; + for (size_t i = 0; i < si.frames; i++) + { + int32_t accum = 0; + for (size_t j = 0; j < si.channels; j++) + accum += fbuf[i * si.channels + j]; + buf[i] = accum / si.channels; + } + } + + id = 0; + alGenBuffers(1, &id); + if (!id) + throw std::runtime_error("sound: cannot generate buffer"); + + alBufferData(id, AL_FORMAT_MONO16, buf, si.frames * 2, si.samplerate); + + if (si.channels != 1) + delete[] buf; + delete[] fbuf; +} + +sound_buffer::~sound_buffer() +{ + alDeleteBuffers(1, &id); +} + +void sound_buffer::ref() +{ + refcount++; +} + +void sound_buffer::unref() +{ + refcount--; + last_unref = std::chrono::steady_clock::now(); +} + +ALuint sound_buffer::get_id() +{ + return id; +} + +std::chrono::time_point sound_buffer::unused_since() +{ + if (refcount > 0) + return std::chrono::time_point::max(); + + return last_unref; +} + +sound_manager* sound_man; diff --git a/sound.h b/sound.h new file mode 100644 index 00000000..b63ee250 --- /dev/null +++ b/sound.h @@ -0,0 +1,160 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public +* License, v. 2.0. If a copy of the MPL was not distributed with this +* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include "dumb3d.h" +#include "parser.h" + +class load_error : public std::runtime_error +{ +public: + load_error(std::string const &f); +}; + +class sound_buffer +{ + ALuint id; + uint32_t refcount; + std::chrono::time_point last_unref; + +public: + sound_buffer(std::string &file); + ~sound_buffer(); + + ALuint get_id(); + void ref(); + void unref(); + std::chrono::time_point unused_since(); +}; + +//m7todo: make constructor/destructor private friend to sound_manager +class sound +{ + bool pos_dirty; + glm::vec3 last_pos; + +protected: + float max_dist; + bool spatial; + glm::vec3 pos; + + ALuint id; + sound(); + +public: + float gain_off; + float gain_mul; + float pitch_off; + float pitch_mul; + + virtual ~sound(); + + virtual bool is_playing() = 0; + + virtual void play() = 0; + virtual void stop() = 0; + virtual void update(float dt); + + sound& dist(float); + sound& gain(float); + sound& pitch(float); + virtual sound& loop(bool loop = true) = 0; + + sound& position(glm::vec3 const &); + sound& position(Math3D::vector3 const &); +}; + +class simple_sound : public sound +{ + sound_buffer *buffer; + + bool looping; + bool playing; + +public: + simple_sound(sound_buffer *buf); + ~simple_sound(); + + void play(); + void stop(); + void update(float dt); + + sound& loop(bool loop = true); + + bool is_playing(); +}; + +class complex_sound : public sound +{ + sound_buffer *pre, *buffer, *post; + + enum class state + { + premain, // playing pre and continue to main + prepost, // playing pre and jump to post + main, //playing main + post // playing post or idling + } cs; + +public: + complex_sound(sound_buffer* pre, sound_buffer* main, sound_buffer* post); + ~complex_sound(); + + bool is_playing(); + + void play(); + void stop(); + void update(float dt); + + sound& loop(bool loop = true); +}; + +class text_sound : public simple_sound +{ +public: + text_sound(sound_buffer *buf); + + void play(); +}; + +class sound_manager +{ + ALCdevice *dev; + ALCcontext *ctx; + + const std::chrono::duration gc_time = std::chrono::duration(60.0f); + std::unordered_map buffers; + std::unordered_set sounds; + + std::string find_file(std::string); + sound_buffer* find_buffer(std::string); + + sound_buffer* get_buffer(std::string const &); + +public: + glm::vec3 pos, last_pos; + + sound_manager(); + ~sound_manager(); + + simple_sound* create_sound(std::string const &file); + text_sound* create_text_sound(std::string const &file); + complex_sound* create_complex_sound(std::string const &pre, std::string const &main, std::string const &post); + complex_sound* create_complex_sound(cParser &); + void destroy_sound(sound**); + + void update(float dt); + void set_listener(glm::vec3 const &pos, glm::vec3 const &at, glm::vec3 const &up); + void set_listener(Math3D::vector3 const &pos, Math3D::vector3 const &at, Math3D::vector3 const &up); +}; + +extern sound_manager* sound_man; diff --git a/uilayer.cpp b/uilayer.cpp index e897712f..f3662ac2 100644 --- a/uilayer.cpp +++ b/uilayer.cpp @@ -9,10 +9,12 @@ ui_layer UILayer; +#ifdef _WIN32 extern "C" { - GLFWAPI HWND glfwGetWin32Window( GLFWwindow* window ); //m7todo: potrzebne do directsound + GLFWAPI HWND glfwGetWin32Window( GLFWwindow* window ); } +#endif ui_layer::~ui_layer() { /*