mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-19 07:39:19 +02:00
Set dp branch as trunk
This commit is contained in:
277
RealSound.cpp
Normal file
277
RealSound.cpp
Normal file
@@ -0,0 +1,277 @@
|
||||
//---------------------------------------------------------------------------
|
||||
/*
|
||||
MaSzyna EU07 locomotive simulator
|
||||
Copyright (C) 2001-2004 Marcin Wozniak, Maciej Czapkiewicz and others
|
||||
|
||||
*/
|
||||
|
||||
#include "system.hpp"
|
||||
#include "classes.hpp"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "math.h"
|
||||
#include "RealSound.h"
|
||||
#include "Globals.h"
|
||||
#include "Timer.h"
|
||||
#include "Logs.h"
|
||||
#include "McZapkie\mctools.hpp"
|
||||
|
||||
__fastcall TRealSound::TRealSound()
|
||||
{
|
||||
pSound=NULL;
|
||||
dSoundAtt=-1;
|
||||
AM=0.0;
|
||||
AA=0.0;
|
||||
FM=0.0;
|
||||
FA=0.0;
|
||||
vSoundPosition.x=0;
|
||||
vSoundPosition.y=0;
|
||||
vSoundPosition.z=0;
|
||||
fDistance=fPreviousDistance=0.0;
|
||||
fFrequency=22050.0; //częstotliwość samplowania pliku
|
||||
iDoppler=0; //normlanie jest załączony; !=0 - modyfikacje
|
||||
bLoopPlay=false; //dźwięk wyłączony
|
||||
}
|
||||
|
||||
__fastcall TRealSound::~TRealSound()
|
||||
{
|
||||
//if (this) if (pSound) pSound->Stop();
|
||||
}
|
||||
|
||||
void __fastcall TRealSound::Free()
|
||||
{
|
||||
}
|
||||
|
||||
void __fastcall TRealSound::Init(char *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: "+AnsiString(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: "+AnsiString(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 __fastcall TRealSound::ListenerDistance(vector3 ListenerPosition)
|
||||
{
|
||||
if (dSoundAtt==-1)
|
||||
{ return 0.0; }
|
||||
else
|
||||
{ return SquareMagnitude(ListenerPosition-vSoundPosition); }
|
||||
}
|
||||
|
||||
void __fastcall TRealSound::Play(double Volume, int Looping, bool ListenerInside, vector3 NewPosition)
|
||||
{
|
||||
if (!pSound) return;
|
||||
long int vol;
|
||||
double dS;
|
||||
// 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 __fastcall TRealSound::Start()
|
||||
{//włączenie dźwięku
|
||||
|
||||
};
|
||||
|
||||
void __fastcall 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 __fastcall 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, Vsrc;
|
||||
if ((Global::bSoundEnabled) && (AM!=0))
|
||||
{
|
||||
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(( df<DSBFREQUENCY_MIN ? DSBFREQUENCY_MIN : (df>DSBFREQUENCY_MAX ? DSBFREQUENCY_MAX : df) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 __fastcall 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 __fastcall TRealSound::ResetPosition()
|
||||
{
|
||||
if (pSound) //Ra: znowu jakiś badziew!
|
||||
pSound->SetCurrentPosition(0);
|
||||
}
|
||||
|
||||
void __fastcall TTextSound::Init(char *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();
|
||||
AnsiString txt=AnsiString(SoundName);
|
||||
txt.Delete(txt.Length()-3,4); //obcięcie rozszerzenia
|
||||
for (int 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;
|
||||
}
|
||||
};
|
||||
void __fastcall TTextSound::Play(double Volume,int Looping,bool ListenerInside,vector3 NewPosition)
|
||||
{
|
||||
if (!asText.IsEmpty())
|
||||
{//jeśli ma powiązany tekst
|
||||
DWORD stat;
|
||||
pSound->GetStatus(&stat);
|
||||
if (!(stat&DSBSTATUS_PLAYING)) //jeśli nie jest aktualnie odgrywany
|
||||
{
|
||||
int i;
|
||||
AnsiString t=asText;
|
||||
do
|
||||
{//na razie zrobione jakkolwiek, docelowo przenieść teksty do tablicy nazw
|
||||
i=t.Pos("\r"); //znak nowej linii
|
||||
if (!i)
|
||||
Global::tranTexts.Add(t.c_str(),fTime,true);
|
||||
else
|
||||
{
|
||||
Global::tranTexts.Add(t.SubString(1,i-1).c_str(),fTime,true);
|
||||
t.Delete(1,i);
|
||||
while (t.IsEmpty()?false:(unsigned char)(t[1])<33)
|
||||
t.Delete(1,1);
|
||||
}
|
||||
} while (i>0);
|
||||
}
|
||||
}
|
||||
TRealSound::Play(Volume,Looping,ListenerInside,NewPosition);
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
#pragma package(smart_init)
|
||||
|
||||
Reference in New Issue
Block a user