From fdb99eedc646bc7ef6e83883239a9a9eac6434db Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Tue, 2 Jan 2018 20:30:38 +0100 Subject: [PATCH] sound transcripts, event-started sound persistence --- Event.cpp | 4 ++-- Globals.cpp | 23 +++-------------------- Globals.h | 2 +- audio.cpp | 16 ++++++++++++++++ audio.h | 7 ++++++- audiorenderer.h | 7 +++++-- scene.cpp | 21 +-------------------- scene.h | 8 -------- sound.cpp | 20 ++++++++++++++++++-- sound.h | 12 ++++++++---- 10 files changed, 60 insertions(+), 60 deletions(-) diff --git a/Event.cpp b/Event.cpp index 85489d22..58d67788 100644 --- a/Event.cpp +++ b/Event.cpp @@ -1039,12 +1039,12 @@ event_manager::CheckQuery() { static_cast( m_workevent->Params[ 1 ].asdouble ) ); } else { - m_workevent->Params[ 9 ].tsTextSound->play( sound_flags::exclusive ); + m_workevent->Params[ 9 ].tsTextSound->play( sound_flags::exclusive | sound_flags::event ); } break; } 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; } default: { diff --git a/Globals.cpp b/Globals.cpp index 7ed2f2e2..098a9ba6 100644 --- a/Globals.cpp +++ b/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 if (true == txt.empty()) 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 cParser parser( asciitext ); 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; 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 ); transcript = ""; parser >> transcript; } diff --git a/Globals.h b/Globals.h index 145ca3f7..6bdc090e 100644 --- a/Globals.h +++ b/Globals.h @@ -133,7 +133,7 @@ private: ~TTranscripts(); void AddLine(std::string const &txt, float show, float hide, bool it); // 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ę) void Update(); }; diff --git a/audio.cpp b/audio.cpp index e3b4f6e1..63c36a5d 100644 --- a/audio.cpp +++ b/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 // TBD, TODO: delay data fetching and transfers until the buffer is actually used? std::vector().swap( data ); + + fetch_caption(); } // 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( inputfile ), std::istreambuf_iterator() ); + } +} + buffer_manager::~buffer_manager() { diff --git a/audio.h b/audio.h index 8bec3f11..f9642600 100644 --- a/audio.h +++ b/audio.h @@ -20,11 +20,16 @@ ALuint const null_resource{ ~( ALuint { 0 } ) }; struct openal_buffer { // members 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 caption; // constructors openal_buffer() = default; explicit openal_buffer( std::string const &Filename ); +// methods + // retrieves sound caption in currently set language + void + fetch_caption(); private: // methods diff --git a/audiorenderer.h b/audiorenderer.h index 4ab63ec4..e20608f2 100644 --- a/audiorenderer.h +++ b/audiorenderer.h @@ -162,8 +162,11 @@ openal_source::bind( sound_source *Controller, uint32_sequence Sounds, Iterator_ std::vector buffers; std::for_each( First, Last, - [&]( audio::buffer_handle const &buffer ) { - buffers.emplace_back( audio::renderer.buffer( buffer ).id ); } ); + [&]( audio::buffer_handle const &bufferhandle ) { + 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 ) { ::alSourceQueueBuffers( id, static_cast( buffers.size() ), buffers.data() ); diff --git a/scene.cpp b/scene.cpp index 22bda992..9487a7b6 100644 --- a/scene.cpp +++ b/scene.cpp @@ -122,16 +122,9 @@ basic_cell::update_events() { void basic_cell::update_sounds() { - // sounds auto const deltatime = Timer::GetDeltaRenderTime(); for( auto *sound : m_sounds ) { -#ifdef EU07_USE_OLD_SOUNDCODE - if( ( sound->GetStatus() & DSBSTATUS_PLAYING ) == DSBPLAY_LOOPING ) { - sound->Play( 1, DSBPLAY_LOOPING, true, sound->vSoundPosition ); - sound->AdjFreq( 1.0, deltatime ); - } -#else -#endif + sound->play_event(); } // TBD, TODO: move to sound renderer for( auto *path : m_paths ) { @@ -350,11 +343,7 @@ basic_cell::insert( TAnimModel *Instance ) { // adds provided sound instance to the cell void -#ifdef EU07_USE_OLD_SOUNDCODE -basic_cell::insert( TTextSound *Sound ) { -#else basic_cell::insert( sound_source *Sound ) { -#endif m_active = true; @@ -1177,13 +1166,7 @@ basic_region::insert_instance( TAnimModel *Instance, scratch_data &Scratchpad ) // inserts provided sound in the region 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 ) { -#endif - -#ifdef EU07_USE_OLD_SOUNDCODE // NOTE: bounding area isn't present/filled until track class and wrapper refactoring is done 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 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 diff --git a/scene.h b/scene.h index ce1db91f..c5e7e620 100644 --- a/scene.h +++ b/scene.h @@ -149,11 +149,7 @@ private: using path_sequence = std::vector; using traction_sequence = std::vector; using instance_sequence = std::vector; -#ifdef EU07_USE_OLD_SOUNDCODE - using sound_sequence = std::vector; -#else using sound_sequence = std::vector; -#endif using eventlauncher_sequence = std::vector; // methods void @@ -320,11 +316,7 @@ public: insert_instance( TAnimModel *Instance, scratch_data &Scratchpad ); // inserts provided sound in the region void -#ifdef EU07_USE_OLD_SOUNDCODE - insert_sound( TTextSound *Sound, scratch_data &Scratchpad ); -#else insert_sound( sound_source *Sound, scratch_data &Scratchpad ); -#endif // inserts provided event launcher in the region void insert_launcher( TEventLauncher *Launcher, scratch_data &Scratchpad ); diff --git a/sound.cpp b/sound.cpp index be90f6e2..9f768644 100644 --- a/sound.cpp +++ b/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 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 ) { auto const cutoffrange { m_range * 5 }; 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( Random( 97.5, 102.5 ) ); } - m_flags = Flags; - if( sound( sound_id::main ).buffer != null_handle ) { // basic variant: single main sound, with optional bookends play_basic(); @@ -401,12 +403,26 @@ sound_source::compute_combined_point() const { ) * 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 void 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 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; } diff --git a/sound.h b/sound.h index b1590c4b..816cfdcc 100644 --- a/sound.h +++ b/sound.h @@ -30,7 +30,8 @@ enum sound_parameters { enum sound_flags { 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 { @@ -64,6 +65,9 @@ public: // issues contextual play commands for the audio renderer void play( int const Flags = 0 ); + // maintains playback of sounds started by event + void + play_event(); // stops currently active play commands controlled by this emitter void stop( bool const Skipend = false ); @@ -194,15 +198,15 @@ private: sound_placement m_placement; float m_range { 50.f }; // audible range of the emitted sounds 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 - 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_playbeginning { true }; // indicates started sounds should be preceeded by opening bookend if there's one std::array m_sounds { {} }; // basic sounds emitted by the source, main and optional bookends std::vector 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 - 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