mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-22 03:29:19 +02:00
sound transcripts, event-started sound persistence
This commit is contained in:
@@ -1039,12 +1039,12 @@ event_manager::CheckQuery() {
|
|||||||
static_cast<int>( m_workevent->Params[ 1 ].asdouble ) );
|
static_cast<int>( m_workevent->Params[ 1 ].asdouble ) );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_workevent->Params[ 9 ].tsTextSound->play( sound_flags::exclusive );
|
m_workevent->Params[ 9 ].tsTextSound->play( sound_flags::exclusive | sound_flags::event );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case -1: {
|
case -1: {
|
||||||
m_workevent->Params[ 9 ].tsTextSound->play( sound_flags::exclusive | sound_flags::looping );
|
m_workevent->Params[ 9 ].tsTextSound->play( sound_flags::exclusive | sound_flags::looping | sound_flags::event );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
|
|||||||
23
Globals.cpp
23
Globals.cpp
@@ -1050,28 +1050,11 @@ void TTranscripts::AddLine(std::string const &txt, float show, float hide, bool
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
};
|
};
|
||||||
void TTranscripts::Add(std::string const &txt, float len, bool backgorund)
|
void TTranscripts::Add(std::string const &txt, bool backgorund)
|
||||||
{ // dodanie tekstów, długość dźwięku, czy istotne
|
{ // dodanie tekstów, długość dźwięku, czy istotne
|
||||||
if (true == txt.empty())
|
if (true == txt.empty())
|
||||||
return; // pusty tekst
|
return; // pusty tekst
|
||||||
/*
|
|
||||||
int i = 0, j = int(0.5 + 10.0 * len); //[0.1s]
|
|
||||||
if (*txt == '[')
|
|
||||||
{ // powinny być dwa nawiasy
|
|
||||||
while (*++txt ? *txt != ']' : false)
|
|
||||||
if ((*txt >= '0') && (*txt <= '9'))
|
|
||||||
i = 10 * i + int(*txt - '0'); // pierwsza liczba aż do ]
|
|
||||||
if (*txt ? *++txt == '[' : false)
|
|
||||||
{
|
|
||||||
j = 0; // drugi nawias określa czas zakończenia wyświetlania
|
|
||||||
while (*++txt ? *txt != ']' : false)
|
|
||||||
if ((*txt >= '0') && (*txt <= '9'))
|
|
||||||
j = 10 * j + int(*txt - '0'); // druga liczba aż do ]
|
|
||||||
if (*txt)
|
|
||||||
++txt; // pominięcie drugiego ]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
std::string asciitext{ txt }; win1250_to_ascii( asciitext ); // TODO: launch relevant conversion table based on language
|
std::string asciitext{ txt }; win1250_to_ascii( asciitext ); // TODO: launch relevant conversion table based on language
|
||||||
cParser parser( asciitext );
|
cParser parser( asciitext );
|
||||||
while( true == parser.getTokens( 3, false, "[]\n" ) ) {
|
while( true == parser.getTokens( 3, false, "[]\n" ) ) {
|
||||||
@@ -1088,7 +1071,7 @@ void TTranscripts::Add(std::string const &txt, float len, bool backgorund)
|
|||||||
std::string transcript; parser >> transcript;
|
std::string transcript; parser >> transcript;
|
||||||
while( false == transcript.empty() ) {
|
while( false == transcript.empty() ) {
|
||||||
|
|
||||||
WriteLog( "Transcript text with no display/hide times: \"" + transcript + "\"" );
|
// WriteLog( "Transcript text with no display/hide times: \"" + transcript + "\"" );
|
||||||
AddLine( transcript, 0.0, 0.12 * transcript.size(), false );
|
AddLine( transcript, 0.0, 0.12 * transcript.size(), false );
|
||||||
transcript = ""; parser >> transcript;
|
transcript = ""; parser >> transcript;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ private:
|
|||||||
~TTranscripts();
|
~TTranscripts();
|
||||||
void AddLine(std::string const &txt, float show, float hide, bool it);
|
void AddLine(std::string const &txt, float show, float hide, bool it);
|
||||||
// dodanie tekstów, długość dźwięku, czy istotne
|
// dodanie tekstów, długość dźwięku, czy istotne
|
||||||
void Add(std::string const &txt, float len, bool background = false);
|
void Add(std::string const &txt, bool background = false);
|
||||||
// usuwanie niepotrzebnych (ok. 10 razy na sekundę)
|
// usuwanie niepotrzebnych (ok. 10 razy na sekundę)
|
||||||
void Update();
|
void Update();
|
||||||
};
|
};
|
||||||
|
|||||||
16
audio.cpp
16
audio.cpp
@@ -65,6 +65,8 @@ openal_buffer::openal_buffer( std::string const &Filename ) :
|
|||||||
// and get rid of the source, we shouldn't need it anymore
|
// and get rid of the source, we shouldn't need it anymore
|
||||||
// TBD, TODO: delay data fetching and transfers until the buffer is actually used?
|
// TBD, TODO: delay data fetching and transfers until the buffer is actually used?
|
||||||
std::vector<std::int16_t>().swap( data );
|
std::vector<std::int16_t>().swap( data );
|
||||||
|
|
||||||
|
fetch_caption();
|
||||||
}
|
}
|
||||||
|
|
||||||
// mix specified number of interleaved multi-channel data, down to mono
|
// mix specified number of interleaved multi-channel data, down to mono
|
||||||
@@ -87,6 +89,20 @@ openal_buffer::narrow_to_mono( std::uint16_t const Channelcount ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// retrieves sound caption in currently set language
|
||||||
|
void
|
||||||
|
openal_buffer::fetch_caption() {
|
||||||
|
|
||||||
|
std::string captionfilename { name };
|
||||||
|
captionfilename.erase( captionfilename.rfind( '.' ) ); // obcięcie rozszerzenia
|
||||||
|
captionfilename += "-" + Global::asLang + ".txt"; // już może być w różnych językach
|
||||||
|
if( true == FileExists( captionfilename ) ) {
|
||||||
|
// wczytanie
|
||||||
|
std::ifstream inputfile( captionfilename );
|
||||||
|
caption.assign( std::istreambuf_iterator<char>( inputfile ), std::istreambuf_iterator<char>() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
buffer_manager::~buffer_manager() {
|
buffer_manager::~buffer_manager() {
|
||||||
|
|||||||
7
audio.h
7
audio.h
@@ -20,11 +20,16 @@ ALuint const null_resource{ ~( ALuint { 0 } ) };
|
|||||||
struct openal_buffer {
|
struct openal_buffer {
|
||||||
// members
|
// members
|
||||||
ALuint id { null_resource }; // associated AL resource
|
ALuint id { null_resource }; // associated AL resource
|
||||||
unsigned int rate { 0 }; // sample rate of the data
|
unsigned int rate {}; // sample rate of the data
|
||||||
std::string name;
|
std::string name;
|
||||||
|
std::string caption;
|
||||||
// constructors
|
// constructors
|
||||||
openal_buffer() = default;
|
openal_buffer() = default;
|
||||||
explicit openal_buffer( std::string const &Filename );
|
explicit openal_buffer( std::string const &Filename );
|
||||||
|
// methods
|
||||||
|
// retrieves sound caption in currently set language
|
||||||
|
void
|
||||||
|
fetch_caption();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// methods
|
// methods
|
||||||
|
|||||||
@@ -162,8 +162,11 @@ openal_source::bind( sound_source *Controller, uint32_sequence Sounds, Iterator_
|
|||||||
std::vector<ALuint> buffers;
|
std::vector<ALuint> buffers;
|
||||||
std::for_each(
|
std::for_each(
|
||||||
First, Last,
|
First, Last,
|
||||||
[&]( audio::buffer_handle const &buffer ) {
|
[&]( audio::buffer_handle const &bufferhandle ) {
|
||||||
buffers.emplace_back( audio::renderer.buffer( buffer ).id ); } );
|
auto const &buffer { audio::renderer.buffer( bufferhandle ) };
|
||||||
|
buffers.emplace_back( buffer.id );
|
||||||
|
if( false == buffer.caption.empty() ) {
|
||||||
|
Global::tranTexts.Add( buffer.caption ); } } );
|
||||||
|
|
||||||
if( id != audio::null_resource ) {
|
if( id != audio::null_resource ) {
|
||||||
::alSourceQueueBuffers( id, static_cast<ALsizei>( buffers.size() ), buffers.data() );
|
::alSourceQueueBuffers( id, static_cast<ALsizei>( buffers.size() ), buffers.data() );
|
||||||
|
|||||||
21
scene.cpp
21
scene.cpp
@@ -122,16 +122,9 @@ basic_cell::update_events() {
|
|||||||
void
|
void
|
||||||
basic_cell::update_sounds() {
|
basic_cell::update_sounds() {
|
||||||
|
|
||||||
// sounds
|
|
||||||
auto const deltatime = Timer::GetDeltaRenderTime();
|
auto const deltatime = Timer::GetDeltaRenderTime();
|
||||||
for( auto *sound : m_sounds ) {
|
for( auto *sound : m_sounds ) {
|
||||||
#ifdef EU07_USE_OLD_SOUNDCODE
|
sound->play_event();
|
||||||
if( ( sound->GetStatus() & DSBSTATUS_PLAYING ) == DSBPLAY_LOOPING ) {
|
|
||||||
sound->Play( 1, DSBPLAY_LOOPING, true, sound->vSoundPosition );
|
|
||||||
sound->AdjFreq( 1.0, deltatime );
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
// TBD, TODO: move to sound renderer
|
// TBD, TODO: move to sound renderer
|
||||||
for( auto *path : m_paths ) {
|
for( auto *path : m_paths ) {
|
||||||
@@ -350,11 +343,7 @@ basic_cell::insert( TAnimModel *Instance ) {
|
|||||||
|
|
||||||
// adds provided sound instance to the cell
|
// adds provided sound instance to the cell
|
||||||
void
|
void
|
||||||
#ifdef EU07_USE_OLD_SOUNDCODE
|
|
||||||
basic_cell::insert( TTextSound *Sound ) {
|
|
||||||
#else
|
|
||||||
basic_cell::insert( sound_source *Sound ) {
|
basic_cell::insert( sound_source *Sound ) {
|
||||||
#endif
|
|
||||||
|
|
||||||
m_active = true;
|
m_active = true;
|
||||||
|
|
||||||
@@ -1177,13 +1166,7 @@ basic_region::insert_instance( TAnimModel *Instance, scratch_data &Scratchpad )
|
|||||||
|
|
||||||
// inserts provided sound in the region
|
// inserts provided sound in the region
|
||||||
void
|
void
|
||||||
#ifdef EU07_USE_OLD_SOUNDCODE
|
|
||||||
basic_region::insert_sound( TTextSound *Sound, scratch_data &Scratchpad ) {
|
|
||||||
#else
|
|
||||||
basic_region::insert_sound( sound_source *Sound, scratch_data &Scratchpad ) {
|
basic_region::insert_sound( sound_source *Sound, scratch_data &Scratchpad ) {
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef EU07_USE_OLD_SOUNDCODE
|
|
||||||
// NOTE: bounding area isn't present/filled until track class and wrapper refactoring is done
|
// NOTE: bounding area isn't present/filled until track class and wrapper refactoring is done
|
||||||
auto location = Sound->location();
|
auto location = Sound->location();
|
||||||
|
|
||||||
@@ -1195,8 +1178,6 @@ basic_region::insert_sound( sound_source *Sound, scratch_data &Scratchpad ) {
|
|||||||
// tracks are guaranteed to hava a name so we can skip the check
|
// tracks are guaranteed to hava a name so we can skip the check
|
||||||
ErrorLog( "Bad scenario: sound node \"" + Sound->name() + "\" placed in location outside region bounds (" + to_string( location ) + ")" );
|
ErrorLog( "Bad scenario: sound node \"" + Sound->name() + "\" placed in location outside region bounds (" + to_string( location ) + ")" );
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// inserts provided event launcher in the region
|
// inserts provided event launcher in the region
|
||||||
|
|||||||
8
scene.h
8
scene.h
@@ -149,11 +149,7 @@ private:
|
|||||||
using path_sequence = std::vector<TTrack *>;
|
using path_sequence = std::vector<TTrack *>;
|
||||||
using traction_sequence = std::vector<TTraction *>;
|
using traction_sequence = std::vector<TTraction *>;
|
||||||
using instance_sequence = std::vector<TAnimModel *>;
|
using instance_sequence = std::vector<TAnimModel *>;
|
||||||
#ifdef EU07_USE_OLD_SOUNDCODE
|
|
||||||
using sound_sequence = std::vector<TTextSound *>;
|
|
||||||
#else
|
|
||||||
using sound_sequence = std::vector<sound_source *>;
|
using sound_sequence = std::vector<sound_source *>;
|
||||||
#endif
|
|
||||||
using eventlauncher_sequence = std::vector<TEventLauncher *>;
|
using eventlauncher_sequence = std::vector<TEventLauncher *>;
|
||||||
// methods
|
// methods
|
||||||
void
|
void
|
||||||
@@ -320,11 +316,7 @@ public:
|
|||||||
insert_instance( TAnimModel *Instance, scratch_data &Scratchpad );
|
insert_instance( TAnimModel *Instance, scratch_data &Scratchpad );
|
||||||
// inserts provided sound in the region
|
// inserts provided sound in the region
|
||||||
void
|
void
|
||||||
#ifdef EU07_USE_OLD_SOUNDCODE
|
|
||||||
insert_sound( TTextSound *Sound, scratch_data &Scratchpad );
|
|
||||||
#else
|
|
||||||
insert_sound( sound_source *Sound, scratch_data &Scratchpad );
|
insert_sound( sound_source *Sound, scratch_data &Scratchpad );
|
||||||
#endif
|
|
||||||
// inserts provided event launcher in the region
|
// inserts provided event launcher in the region
|
||||||
void
|
void
|
||||||
insert_launcher( TEventLauncher *Launcher, scratch_data &Scratchpad );
|
insert_launcher( TEventLauncher *Launcher, scratch_data &Scratchpad );
|
||||||
|
|||||||
20
sound.cpp
20
sound.cpp
@@ -289,6 +289,10 @@ sound_source::play( int const Flags ) {
|
|||||||
// if the sound is disabled altogether or nothing can be emitted from this source, no point wasting time
|
// if the sound is disabled altogether or nothing can be emitted from this source, no point wasting time
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: we cache the flags early, even if the sound is out of range, to mark activated event sounds
|
||||||
|
m_flags = Flags;
|
||||||
|
|
||||||
if( m_range > 0 ) {
|
if( m_range > 0 ) {
|
||||||
auto const cutoffrange { m_range * 5 };
|
auto const cutoffrange { m_range * 5 };
|
||||||
if( glm::length2( location() - glm::dvec3 { Global::pCameraPosition } ) > std::min( 2750.f * 2750.f, cutoffrange * cutoffrange ) ) {
|
if( glm::length2( location() - glm::dvec3 { Global::pCameraPosition } ) > std::min( 2750.f * 2750.f, cutoffrange * cutoffrange ) ) {
|
||||||
@@ -304,8 +308,6 @@ sound_source::play( int const Flags ) {
|
|||||||
m_pitchvariation = 0.01f * static_cast<float>( Random( 97.5, 102.5 ) );
|
m_pitchvariation = 0.01f * static_cast<float>( Random( 97.5, 102.5 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
m_flags = Flags;
|
|
||||||
|
|
||||||
if( sound( sound_id::main ).buffer != null_handle ) {
|
if( sound( sound_id::main ).buffer != null_handle ) {
|
||||||
// basic variant: single main sound, with optional bookends
|
// basic variant: single main sound, with optional bookends
|
||||||
play_basic();
|
play_basic();
|
||||||
@@ -401,12 +403,26 @@ sound_source::compute_combined_point() const {
|
|||||||
) * 100.f;
|
) * 100.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// maintains playback of sounds started by event
|
||||||
|
void
|
||||||
|
sound_source::play_event() {
|
||||||
|
|
||||||
|
if( true == TestFlag( m_flags, ( sound_flags::event | sound_flags::looping ) ) ) {
|
||||||
|
// events can potentially start scenery sounds out of the sound's audible range
|
||||||
|
// such sounds are stopped on renderer side, but unless stopped by the simulation keep their activation flags
|
||||||
|
// we use this to discern event-started sounds which should be re-activated if the listener gets close enough
|
||||||
|
play( m_flags );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// stops currently active play commands controlled by this emitter
|
// stops currently active play commands controlled by this emitter
|
||||||
void
|
void
|
||||||
sound_source::stop( bool const Skipend ) {
|
sound_source::stop( bool const Skipend ) {
|
||||||
|
|
||||||
// if the source was stopped on simulation side, we should play the opening bookend next time it's activated
|
// if the source was stopped on simulation side, we should play the opening bookend next time it's activated
|
||||||
m_playbeginning = true;
|
m_playbeginning = true;
|
||||||
|
// clear the event flags to discern between manual stop and out-of-range/sound-end stop
|
||||||
|
m_flags = 0;
|
||||||
|
|
||||||
if( false == is_playing() ) { return; }
|
if( false == is_playing() ) { return; }
|
||||||
|
|
||||||
|
|||||||
12
sound.h
12
sound.h
@@ -30,7 +30,8 @@ enum sound_parameters {
|
|||||||
|
|
||||||
enum sound_flags {
|
enum sound_flags {
|
||||||
looping = 0x1, // the main sample will be looping; implied for multi-sounds
|
looping = 0x1, // the main sample will be looping; implied for multi-sounds
|
||||||
exclusive = 0x2 // the source won't dispatch more than one active instance of the sound; implied for multi-sounds
|
exclusive = 0x2, // the source won't dispatch more than one active instance of the sound; implied for multi-sounds
|
||||||
|
event = 0x80 // sound was activated by an event; we should keep note of the activation state for the update() calls it may receive
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class sound_placement {
|
enum class sound_placement {
|
||||||
@@ -64,6 +65,9 @@ public:
|
|||||||
// issues contextual play commands for the audio renderer
|
// issues contextual play commands for the audio renderer
|
||||||
void
|
void
|
||||||
play( int const Flags = 0 );
|
play( int const Flags = 0 );
|
||||||
|
// maintains playback of sounds started by event
|
||||||
|
void
|
||||||
|
play_event();
|
||||||
// stops currently active play commands controlled by this emitter
|
// stops currently active play commands controlled by this emitter
|
||||||
void
|
void
|
||||||
stop( bool const Skipend = false );
|
stop( bool const Skipend = false );
|
||||||
@@ -194,15 +198,15 @@ private:
|
|||||||
sound_placement m_placement;
|
sound_placement m_placement;
|
||||||
float m_range { 50.f }; // audible range of the emitted sounds
|
float m_range { 50.f }; // audible range of the emitted sounds
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
int m_flags { 0 }; // requested playback parameters
|
int m_flags {}; // requested playback parameters
|
||||||
sound_properties m_properties; // current properties of the emitted sounds
|
sound_properties m_properties; // current properties of the emitted sounds
|
||||||
float m_pitchvariation { 0.f }; // emitter-specific shift in base pitch
|
float m_pitchvariation {}; // emitter-specific shift in base pitch
|
||||||
bool m_stop { false }; // indicates active sample instances should be terminated
|
bool m_stop { false }; // indicates active sample instances should be terminated
|
||||||
bool m_playbeginning { true }; // indicates started sounds should be preceeded by opening bookend if there's one
|
bool m_playbeginning { true }; // indicates started sounds should be preceeded by opening bookend if there's one
|
||||||
std::array<sound_data, 3> m_sounds { {} }; // basic sounds emitted by the source, main and optional bookends
|
std::array<sound_data, 3> m_sounds { {} }; // basic sounds emitted by the source, main and optional bookends
|
||||||
std::vector<soundchunk_pair> m_soundchunks; // table of samples activated when associated variable is within certain range
|
std::vector<soundchunk_pair> m_soundchunks; // table of samples activated when associated variable is within certain range
|
||||||
bool m_soundchunksempty { true }; // helper, cached check whether sample table is linked with any actual samples
|
bool m_soundchunksempty { true }; // helper, cached check whether sample table is linked with any actual samples
|
||||||
int m_crossfaderange {}; // range of transition from one chunk to another
|
int m_crossfaderange {}; // range of transition from one chunk to another
|
||||||
};
|
};
|
||||||
|
|
||||||
// owner setter/getter
|
// owner setter/getter
|
||||||
|
|||||||
Reference in New Issue
Block a user