sound works

sound works 2

sound works 3

sound works

sound works

sound works

sound works

sound works

sound fixes

fix
This commit is contained in:
milek7
2017-08-05 22:18:59 +02:00
parent 06f00ebdeb
commit 08acc60a8b
28 changed files with 1468 additions and 1499 deletions

View File

@@ -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;
};

View File

@@ -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

View File

@@ -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")

View File

@@ -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)

View File

@@ -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

View File

@@ -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)

View File

@@ -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)

View File

@@ -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;i<MaxAxles;++i)
rsStukot[i].Stop(); //dzwieki poszczegolnych osi
rsSilnik.Stop();
rsWentylator.Stop();
rsPisk.Stop();
rsDerailment.Stop();
sPantUp.Stop();
sPantDown.Stop();
sBrakeAcc.Stop(); //dzwiek przyspieszacza
rsDiesielInc.Stop();
rscurve.Stop();
*/
for (size_t i = 0; i < MaxAxles; i++)
sound_man->destroy_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<double>();
rsPisk.AA = parser.getToken<double>() * ( 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<double>();
rsPisk->gain_off = parser.getToken<double>() * ( 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 != "" )

View File

@@ -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;

View File

@@ -73,7 +73,7 @@ union TParam
bool asBool;
double asdouble;
int asInt;
TTextSound *tsTextSound;
sound *tsTextSound;
char *asText;
TCommandType asCommand;
TTractionPowerSource *psPower;

View File

@@ -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);
}
//---------------------------------------------------------------------------

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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<float>(DSBFREQUENCY_MIN), static_cast<float>(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<char>( inputfile ), std::istreambuf_iterator<char>() );
}
};
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);
};
//---------------------------------------------------------------------------

View File

@@ -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 <string>
#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

View File

@@ -1,5 +0,0 @@
#ifdef _WIN32
#include "WinSound.cpp"
#else
#include "DummySound.cpp"
#endif

81
Sound.h
View File

@@ -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 <stack>
#include <cinttypes>
#ifdef _WIN32
#include <dsound.h>
#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<LPDIRECTSOUNDBUFFER> 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();
};

544
Train.cpp

File diff suppressed because it is too large Load Diff

78
Train.h
View File

@@ -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;

View File

@@ -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<ui_panel> initpanel = std::make_shared<ui_panel>(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

View File

@@ -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

View File

@@ -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

View File

@@ -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) }"

561
sound.cpp Normal file
View File

@@ -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 <sndfile.h>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/string_cast.hpp>
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<std::string> 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<std::chrono::steady_clock> sound_buffer::unused_since()
{
if (refcount > 0)
return std::chrono::time_point<std::chrono::steady_clock>::max();
return last_unref;
}
sound_manager* sound_man;

160
sound.h Normal file
View File

@@ -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 <AL/al.h>
#include <AL/alc.h>
#include <cinttypes>
#include <chrono>
#include <unordered_map>
#include <unordered_set>
#include <glm/glm.hpp>
#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<std::chrono::steady_clock> last_unref;
public:
sound_buffer(std::string &file);
~sound_buffer();
ALuint get_id();
void ref();
void unref();
std::chrono::time_point<std::chrono::steady_clock> 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<float> gc_time = std::chrono::duration<float>(60.0f);
std::unordered_map<std::string, sound_buffer*> buffers;
std::unordered_set<sound*> 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;

View File

@@ -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() {
/*