sound transcripts, event-started sound persistence

This commit is contained in:
tmj-fstate
2018-01-02 20:30:38 +01:00
parent 04398e9fcf
commit fdb99eedc6
10 changed files with 60 additions and 60 deletions

View File

@@ -1039,12 +1039,12 @@ event_manager::CheckQuery() {
static_cast<int>( 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: {

View File

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

View File

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

View File

@@ -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<std::int16_t>().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<char>( inputfile ), std::istreambuf_iterator<char>() );
}
}
buffer_manager::~buffer_manager() {

View File

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

View File

@@ -162,8 +162,11 @@ openal_source::bind( sound_source *Controller, uint32_sequence Sounds, Iterator_
std::vector<ALuint> 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<ALsizei>( buffers.size() ), buffers.data() );

View File

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

View File

@@ -149,11 +149,7 @@ private:
using path_sequence = std::vector<TTrack *>;
using traction_sequence = std::vector<TTraction *>;
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 *>;
#endif
using eventlauncher_sequence = std::vector<TEventLauncher *>;
// 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 );

View File

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

12
sound.h
View File

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