You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
244 lines
6.6 KiB
244 lines
6.6 KiB
//===================== Copyright (c) Valve Corporation. All Rights Reserved. ======================
|
|
//
|
|
//
|
|
//
|
|
//==================================================================================================
|
|
|
|
#ifndef SOUNDSCHEMA_H
|
|
#define SOUNDSCHEMA_H
|
|
#ifdef _WIN32
|
|
#pragma once
|
|
#endif
|
|
|
|
#ifndef SOURCE1
|
|
#include "resourcefile/resourcefile.h"
|
|
#include "resourcefile/resourcetype.h"
|
|
#endif
|
|
|
|
FORWARD_DECLARE_HANDLE( memhandle_t );
|
|
|
|
schema struct CEmphasisSample_t
|
|
{
|
|
public:
|
|
TYPEMETA( MNoScatter );
|
|
DECLARE_SCHEMA_DATA_CLASS(CEmphasisSample_t)
|
|
|
|
float32 time;
|
|
float32 value;
|
|
};
|
|
|
|
schema struct CBasePhonemeTag_t
|
|
{
|
|
public:
|
|
TYPEMETA( MNoScatter );
|
|
DECLARE_SCHEMA_DATA_CLASS(CBasePhonemeTag_t)
|
|
|
|
float GetStartTime() const { return m_flStartTime; }
|
|
float GetEndTime() const { return m_flEndTime; }
|
|
int GetPhonemeCode() const { return m_nPhonemeCode; }
|
|
|
|
public:
|
|
float32 m_flStartTime;
|
|
float32 m_flEndTime;
|
|
uint16 m_nPhonemeCode;
|
|
};
|
|
|
|
// A sentence can be closed captioned
|
|
// The default case is the entire sentence shown at start time
|
|
//
|
|
// "<persist:2.0><clr:255,0,0,0>The <I>default<I> case"
|
|
// "<sameline>is the <U>entire<U> sentence shown at <B>start time<B>"
|
|
|
|
// Commands that aren't closed at end of phrase are automatically terminated
|
|
//
|
|
// Commands
|
|
// <linger:2.0> The line should persist for 2.0 seconds beyond m_flEndTime
|
|
// <sameline> Don't go to new line for next phrase on stack
|
|
// <clr:r,g,b,a> Push current color onto stack and start drawing with new
|
|
// color until we reach the next <clr> marker or a <clr> with no commands which
|
|
// means restore the previous color
|
|
// <U> Underline text (start/end)
|
|
// <I> Italics text (start/end)
|
|
// <B> Bold text (start/end)
|
|
// <position:where> Draw caption at special location ??? needed
|
|
// <cr> Go to new line
|
|
|
|
// Close Captioning Support
|
|
// The phonemes drive the mouth in english, but the CC text can
|
|
// be one of several languages
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: A sentence is a box of words, and words contain phonemes
|
|
//-----------------------------------------------------------------------------
|
|
schema class CSentence_t
|
|
{
|
|
public:
|
|
TYPEMETA( MNoScatter );
|
|
DECLARE_SCHEMA_DATA_CLASS(CSentence_t)
|
|
|
|
inline float GetIntensity( float time, float endtime );
|
|
inline CEmphasisSample_t *GetBoundedSample( int number, float endtime );
|
|
int GetNumSamples( void ) { return m_EmphasisSamples.Count(); }
|
|
CEmphasisSample_t *GetSample( int index ) { return &m_EmphasisSamples[ index ]; }
|
|
|
|
bool GetVoiceDuck() const { return m_bShouldVoiceDuck; }
|
|
|
|
int GetRuntimePhonemeCount() const { return m_RunTimePhonemes.Count(); }
|
|
const CBasePhonemeTag_t *GetRuntimePhoneme( int i ) const { return &m_RunTimePhonemes[ i ]; }
|
|
|
|
public:
|
|
bool m_bShouldVoiceDuck;
|
|
|
|
CResourceArray< CBasePhonemeTag_t > m_RunTimePhonemes;
|
|
|
|
// Phoneme emphasis data
|
|
CResourceArray< CEmphasisSample_t > m_EmphasisSamples;
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Input : number -
|
|
// Output : CEmphasisSample_t
|
|
//-----------------------------------------------------------------------------
|
|
inline CEmphasisSample_t *CSentence_t::GetBoundedSample( int number, float endtime )
|
|
{
|
|
// Search for two samples which span time f
|
|
static CEmphasisSample_t nullstart;
|
|
nullstart.time = 0.0f;
|
|
nullstart.value = 0.5f;
|
|
static CEmphasisSample_t nullend;
|
|
nullend.time = endtime;
|
|
nullend.value = 0.5f;
|
|
|
|
if ( number < 0 )
|
|
{
|
|
return &nullstart;
|
|
}
|
|
else if ( number >= GetNumSamples() )
|
|
{
|
|
return &nullend;
|
|
}
|
|
|
|
return GetSample( number );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Input : time -
|
|
// type -
|
|
// Output : float
|
|
//-----------------------------------------------------------------------------
|
|
inline float CSentence_t::GetIntensity( float time, float endtime )
|
|
{
|
|
float zeroValue = 0.5f;
|
|
|
|
int c = GetNumSamples();
|
|
|
|
if ( c <= 0 )
|
|
{
|
|
return zeroValue;
|
|
}
|
|
|
|
int i;
|
|
for ( i = -1 ; i < c; i++ )
|
|
{
|
|
CEmphasisSample_t *s = GetBoundedSample( i, endtime );
|
|
CEmphasisSample_t *n = GetBoundedSample( i + 1, endtime );
|
|
if ( !s || !n )
|
|
continue;
|
|
|
|
if ( time >= s->time && time <= n->time )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
int prev = i - 1;
|
|
int start = i;
|
|
int end = i + 1;
|
|
int next = i + 2;
|
|
|
|
prev = MAX( -1, prev );
|
|
start = MAX( -1, start );
|
|
end = MIN( end, GetNumSamples() );
|
|
next = MIN( next, GetNumSamples() );
|
|
|
|
CEmphasisSample_t *esPre = GetBoundedSample( prev, endtime );
|
|
CEmphasisSample_t *esStart = GetBoundedSample( start, endtime );
|
|
CEmphasisSample_t *esEnd = GetBoundedSample( end, endtime );
|
|
CEmphasisSample_t *esNext = GetBoundedSample( next, endtime );
|
|
|
|
float dt = esEnd->time - esStart->time;
|
|
dt = clamp( dt, 0.01f, 1.0f );
|
|
|
|
Vector vPre( esPre->time, esPre->value, 0 );
|
|
Vector vStart( esStart->time, esStart->value, 0 );
|
|
Vector vEnd( esEnd->time, esEnd->value, 0 );
|
|
Vector vNext( esNext->time, esNext->value, 0 );
|
|
|
|
float f2 = ( time - esStart->time ) / ( dt );
|
|
f2 = clamp( f2, 0.0f, 1.0f );
|
|
|
|
Vector vOut;
|
|
Catmull_Rom_Spline(
|
|
vPre,
|
|
vStart,
|
|
vEnd,
|
|
vNext,
|
|
f2,
|
|
vOut );
|
|
|
|
float retval = clamp( vOut.y, 0.0f, 1.0f );
|
|
return retval;
|
|
}
|
|
|
|
// Used for bitpacking
|
|
struct soundinfoheader_t
|
|
{
|
|
unsigned int m_Type : 2; // 0 1 2 or 3
|
|
unsigned int m_bits : 5; // 0 to 31
|
|
unsigned int m_channels : 2; // 1 or 2
|
|
unsigned int m_sampleSize : 3; // 1 2 or 4
|
|
unsigned int m_format : 2; // 1 == PCM, 2 == ADPCM
|
|
unsigned int m_rate : 17; // 0 to 64 K
|
|
};
|
|
|
|
schema struct VSound_t
|
|
{
|
|
DECLARE_SCHEMA_DATA_CLASS(VSound_t)
|
|
|
|
uint32 m_bitpackedsoundinfo;
|
|
|
|
const soundinfoheader_t &info() const { return *(soundinfoheader_t *)&m_bitpackedsoundinfo; };
|
|
|
|
int m_Type() const { return info().m_Type; };
|
|
int m_bits() const { return info().m_bits; };
|
|
int m_channels() const { return info().m_channels; };
|
|
int m_sampleSize() const { return info().m_sampleSize; };
|
|
int m_format() const { return info().m_format; };
|
|
int m_rate() const { return info().m_rate; };
|
|
|
|
int32 m_loopStart; // -1 for no loop
|
|
uint32 m_sampleCount;
|
|
|
|
float32 m_flDuration; // Duration in seconds
|
|
|
|
// Phoneme stream (optional)
|
|
CResourcePointer< CSentence_t > m_Sentence;
|
|
// Raw wave header (reinterpreted based on m_Type())
|
|
CResourceArray< uint8 > m_pHeader;
|
|
|
|
uint32 m_nStreamingDataSize;
|
|
|
|
// Any data after header is the raw sample data (PCM, ADPCM, .mp3, whatever)
|
|
uint32 m_nStreamingDataOffset; META( MNoSchema );
|
|
memhandle_t m_hStreamDataCacheHandle; META( MNoSchema );
|
|
};
|
|
|
|
#ifndef SOURCE1
|
|
#define RESOURCE_TYPE_SOUND RESOURCE_TYPE('s','n','d', 0)
|
|
DEFINE_RESOURCE_TYPE( VSound_t, RESOURCE_TYPE_SOUND, HSound, HSoundStrong );
|
|
#define SOUND_HANDLE_INVALID ( (HSound)0 )
|
|
#endif
|
|
|
|
#endif // SOUNDSCHEMA_H
|