|
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef PHONEEDITOR_H
#define PHONEEDITOR_H
#ifdef _WIN32
#pragma once
#endif
#include <mxtk/mx.h>
class CAudioSource; class CAudioMixer; class mxBitmapButton; class mxButton;
#include "utlvector.h"
#include "faceposertoolwindow.h"
#define IDC_PHONEME_SCROLL 1001
#define IDC_PHONEME_PLAY_ORIG 1002
#define IDC_EDIT_PHONEME 1004
#define IDC_EDIT_INSERTPHONEMEBEFORE 1005
#define IDC_EDIT_INSERTPHONEMEAFTER 1006
#define IDC_EDIT_DELETEPHONEME 1007
#define IDC_PLAY_EDITED_SELECTION 1008
#define IDC_REDO_PHONEMEEXTRACTION 1009
#define IDC_REDO_PHONEMEEXTRACTION_SELECTION 1010
#define IDC_DESELECT 1011
#define IDC_PLAY_EDITED 1012
#define IDC_SAVE_LINGUISTIC 1013
#define IDC_CANCELPLAYBACK 1014
#define IDC_EDITWORDLIST 1015
#define IDC_SNAPWORDS 1016
#define IDC_SEPARATEWORDS 1017
#define IDC_LOADWAVEFILE 1018
#define IDC_SNAPPHONEMES 1019
#define IDC_SEPARATEPHONEMES 1020
#define IDC_COMMITEXTRACTED 1021
#define IDC_CLEAREXTRACTED 1022
#define IDC_ADDTAG 1023
#define IDC_DELETETAG 1024
#define IDC_CVUNDO 1025
#define IDC_CVREDO 1026
#define IDC_EDIT_DELETEWORD 1027
#define IDC_EDIT_WORD 1028
#define IDC_EDIT_INSERTWORDBEFORE 1029
#define IDC_EDIT_INSERTWORDAFTER 1030
#define IDC_EDIT_INSERTFIRSTPHONEMEOFWORD 1031
#define IDC_SELECT_WORDSRIGHT 1032
#define IDC_SELECT_WORDSLEFT 1033
#define IDC_SELECT_PHONEMESRIGHT 1034
#define IDC_SELECT_PHONEMESLEFT 1035
#define IDC_DESELECT_PHONEMESANDWORDS 1036
#define IDC_CLEANUP 1037
#define IDC_CLEARUNDO 1038
#define IDC_PLAYBUTTON 1039
#define IDC_MODE_TAB 1040
#define IDC_EMPHASIS_DELETE 1041
#define IDC_EMPHASIS_DESELECT 1042
#define IDC_EMPHASIS_SELECTALL 1043
#define IDC_PLAYBACKRATE 1044
#define IDC_REALIGNPHONEMES 1045
#define IDC_REALIGNWORDS 1046
// Support for multiple speech api's
#define IDC_API_SAPI 1050
#define IDC_API_LIPSINC 1051
#define IDC_EXPORT_SENTENCE 1075
#define IDC_IMPORT_SENTENCE 1076
#define IDC_TOGGLE_VOICEDUCK 1077
#define IDC_PE_LANGUAGESTART 1100
// #define IDC_PE_LANGUAGEEND 1106 or so
class IterateOutputRIFF; class IterateRIFF; class CChoreoWidgetDrawHelper; class CChoreoEvent; class CEventRelativeTag; class CChoreoView; class IPhonemeExtractor; class CPhonemeModeTab; class mxPopupMenu;
#include "sentence.h"
enum { COLOR_PHONEME_BACKGROUND = 0, COLOR_PHONEME_TEXT, COLOR_PHONEME_LIGHTTEXT, COLOR_PHONEME_PLAYBACKTICK, COLOR_PHONEME_WAVDATA, COLOR_PHONEME_TIMELINE, COLOR_PHONEME_TIMELINE_MAJORTICK, COLOR_PHONEME_TIMELINE_MINORTICK, COLOR_PHONEME_EXTRACTION_RESULT_FAIL, COLOR_PHONEME_EXTRACTION_RESULT_SUCCESS, COLOR_PHONEME_EXTRACTION_RESULT_ERROR, COLOR_PHONEME_EXTRACTION_RESULT_OTHER, COLOR_PHONEME_TAG_BORDER, COLOR_PHONEME_TAG_BORDER_SELECTED, COLOR_PHONEME_TAG_FILLER_NORMAL, COLOR_PHONEME_TAG_SELECTED, COLOR_PHONEME_TAG_TEXT, COLOR_PHONEME_TAG_TEXT_SELECTED, COLOR_PHONEME_WAV_ENDPOINT, COLOR_PHONEME_AB, COLOR_PHONEME_AB_LINE, COLOR_PHONEME_AB_TEXT,
COLOR_PHONEME_ACTIVE_BORDER, COLOR_PHONEME_SELECTED_BORDER, COLOR_PHONEME_TIMING_TAG,
COLOR_PHONEME_EMPHASIS_BG, COLOR_PHONEME_EMPHASIS_BG_STRONG, COLOR_PHONEME_EMPHASIS_BG_WEAK,
COLOR_PHONEME_EMPHASIS_BORDER, COLOR_PHONEME_EMPHASIS_LINECOLOR, COLOR_PHONEME_EMPHASIS_DOTCOLOR, COLOR_PHONEME_EMPHASIS_DOTCOLOR_SELECTED, COLOR_PHONEME_EMPHASIS_TEXT, COLOR_PHONEME_EMPHASIS_MIDLINE,
NUM_COLORS, };
//-----------------------------------------------------------------------------
// Purpose: Shows WAV data and allows blanking it out and tweaking phoneme tags
//-----------------------------------------------------------------------------
class PhonemeEditor : public mxWindow, public IFacePoserToolWindow { public: enum { BOUNDARY_NONE = 0, BOUNDARY_PHONEME, BOUNDARY_WORD, };
typedef enum { MODE_PHONEMES = 0, MODE_EMPHASIS } EditorMode;
// Construction
PhonemeEditor( mxWindow *parent ); ~PhonemeEditor( void );
virtual void Think( float dt );
virtual void OnDelete(); virtual bool CanClose();
void ValidateSpeechAPIIndex();
virtual int handleEvent( mxEvent *event ); virtual void redraw( void ); virtual bool PaintBackground( void );
EditorMode GetMode( void ) const; void SetupPhonemeEditorColors( void ); COLORREF PEColor( int colornum ); void OnModeChanged( void );
// Change wave file being edited
void SetCurrentWaveFile( const char *wavefile, bool force = false, CChoreoEvent *event = NULL );
// called when scene is unloaded in choreview or when event/channel/actor gets deleted
// so we don't have dangling pointers to tags, events, scene
void ClearEvent( void );
void Play();
private: void DrawWords( CChoreoWidgetDrawHelper& drawHelper, RECT& rcWorkSpace, CSentence &sentence, int type, bool showactive = true ); void DrawPhonemes( CChoreoWidgetDrawHelper& drawHelper, RECT& rcWorkSpace, CSentence &sentence, int type, bool showactive = true ); void DrawRelativeTags( CChoreoWidgetDrawHelper& drawHelper, RECT& rc );
void Emphasis_Redraw( CChoreoWidgetDrawHelper& drawHelper, RECT& rcWorkSpace ); void Emphasis_GetRect( RECT const & rcWorkSpace, RECT& rcEmphasis );
void Emphasis_Init( void ); CEmphasisSample *Emphasis_GetSampleUnderMouse( mxEvent *event ); void Emphasis_DeselectAll( void ); void Emphasis_SelectAll( void ); void Emphasis_Delete( void ); void Emphasis_AddSample( CEmphasisSample const& sample ); void Emphasis_CountSelected( void ); void Emphasis_ShowContextMenu( mxEvent *event ); void Emphasis_MouseDrag( int x, int y ); bool Emphasis_IsValid( void ); void Emphasis_SelectPoints( void ); // Data
int m_nNumSelected;
// Readjust slider
void MoveTimeSliderToPos( int x );
// Handle scrollbar
void SetTimeZoomScale( int scale ); float GetTimeZoomScale( void ); float GetPixelsPerSecond( void ); // Adjust scroll bars
void RepositionHSlider( void );
// Edit commands
void EditPhoneme( CPhonemeTag *pPhoneme, bool positionDialog = false ); void EditPhoneme( void ); void EditInsertPhonemeBefore( void ); void EditInsertPhonemeAfter( void ); void EditDeletePhoneme( void );
void SelectPhonemes( bool forward );
void EditInsertFirstPhonemeOfWord( void );
void EditWord( CWordTag *pWord, bool positionDialog = false ); void EditWord( void ); void EditInsertWordBefore( void ); void EditInsertWordAfter( void ); void EditDeleteWord( void );
void SelectWords( bool forward );
// Edit word list
void EditWordList( void ); void SentenceFromString( CSentence& sentence, char const *str );
// Wav processing commands
void RedoPhonemeExtraction( void ); // Redo extraction of selected words only
void RedoPhonemeExtractionSelected( void ); void Deselect( void );
void PlayEditedWave( bool selection = false ); void CommitChanges( void );
// Context menu
void ShowPhonemeMenu( CPhonemeTag *pho, int mx, int my ); void ShowWordMenu( CWordTag *word, int mx, int my );
void ShowContextMenu( int mx, int my ); void ShowContextMenu_Phonemes( int mx, int my ); void ShowContextMenu_Emphasis( int mx, int my );
// UI helpers
void GetWorkspaceRect( RECT &rc );
bool IsMouseOverWordRow( int my ); bool IsMouseOverPhonemeRow( int my );
int IsMouseOverBoundary( mxEvent *event ); int GetWordUnderMouse( int mx, int my ); int ComputeHPixelsNeeded( void ); void DrawFocusRect( char *reason ); void StartDragging( int dragtype, int startx, int starty, HCURSOR cursor );
void FinishPhonemeMove( int startx, int endx ); void FinishPhonemeDrag( int startx, int endx ); void FinishWordMove( int startx, int endx ); void FinishWordDrag( int startx, int endx );
float GetTimeForPixel( int mx ); void GetScreenStartAndEndTime( float &starttime, float& endtime ); float GetTimePerPixel( void ); int GetSampleForMouse( int mx ); int GetPixelForSample( int sample );
bool FindSpanningPhonemes( float time, CPhonemeTag **pp1, CPhonemeTag **pp2 ); bool FindSpanningWords( float time, CWordTag **pp1, CWordTag **pp2 ); int FindWordForTime( float time ); CPhonemeTag *FindPhonemeForTime( float time ); void DeselectWords( void ); void SnapWords( void ); void SeparateWords( void );
void DeselectPhonemes( void ); void SnapPhonemes( void ); void SeparatePhonemes( void );
void CreateEvenWordDistribution( const char *wordlist );
// Dirty flag
void SetDirty( bool dirty, bool clearundo = true ); bool GetDirty( void );
// FIXME: Do something else here
void ResampleChunk( IterateOutputRIFF& store, void *format, int chunkname, char *buffer, int buffersize, int start_silence = 0, int end_silence = 0 );
// Mouse control over selected samples
void SelectSamples( int start, int end ); void FinishSelect( int startx, int mx ); void FinishMoveSelection( int startx, int mx ); void FinishMoveSelectionStart( int startx, int mx ); void FinishMoveSelectionEnd( int startx, int mx );
bool IsMouseOverSamples( int mx, int my ); bool IsMouseOverSelection( int mx, int my ); bool IsMouseOverSelectionStartEdge( mxEvent *event ); bool IsMouseOverSelectionEndEdge( mxEvent *event );
bool IsMouseOverTag( int mx, int my ); void FinishEventTagDrag( int startx, int endx ); CEventRelativeTag *GetTagUnderMouse( int mx ); bool IsMouseOverTagRow( int my ); void ShowTagMenu( int mx, int my ); void AddTag( void ); void DeleteTag( void );
// After running liset/sapi, retrieve phoneme tag data from stream
void RetrieveLinguisticData( void );
// Copy current phoneme chunk over existing data chunk of .wav file
void SaveLinguisticData( void ); void StoreValveDataChunk( IterateOutputRIFF& store );
void ExportValveDataChunk( char const *tempfile ); void ImportValveDataChunk( char const *tempfile );
void OnImport(); void OnExport();
// Playback (returns true if sound had been playing)
bool StopPlayback( void );
CPhonemeTag *GetPhonemeTagUnderMouse( int mx, int my ); CWordTag *GetWordTagUnderMouse( int mx, int my );
void ReadLinguisticTags( void );
void LoadWaveFile( void );
void GetPhonemeTrayTopBottom( RECT& rc ); void GetWordTrayTopBottom( RECT& rc );
void GetWordRect( const CWordTag *tag, RECT& rc ); void GetPhonemeRect( const CPhonemeTag *tag, RECT& rc ); int GetMouseForTime( float time );
void CommitExtracted( void ); void ClearExtracted( void );
const char * GetExtractionResultString( int resultCode );
void AddFocusRect( RECT& rc );
void CountSelected( void );
typedef void (PhonemeEditor::*PEWORDITERFUNC)( CWordTag *word, float fparam ); typedef void (PhonemeEditor::*PEPHONEMEITERFUNC)( CPhonemeTag *phoneme, CWordTag *word, float fparam );
void TraverseWords( PEWORDITERFUNC pfn, float fparam ); void TraversePhonemes( PEPHONEMEITERFUNC pfn, float fparam );
// Iteration functions
void ITER_MoveSelectedWords( CWordTag *word, float amount ); void ITER_MoveSelectedPhonemes( CPhonemeTag *phoneme, CWordTag *word, float amount );
void ITER_ExtendSelectedPhonemeEndTimes( CPhonemeTag *phoneme, CWordTag *word, float amount ); void ITER_ExtendSelectedWordEndTimes( CWordTag *word, float amount );
void ITER_AddFocusRectSelectedWords( CWordTag *word, float amount ); void ITER_AddFocusRectSelectedPhonemes( CPhonemeTag *phoneme, CWordTag *word, float amount );
void ITER_CountSelectedWords( CWordTag *word, float amount ); void ITER_CountSelectedPhonemes( CPhonemeTag *phoneme, CWordTag *word, float amount );
void ITER_SelectSpanningWords( CWordTag *word, float amount );
// Undo/Redo
void Undo( void ); void Redo( void ); void ClearUndo( void );
// Do push before changes
void PushUndo( void ); // Do this push after changes, must match pushundo 1for1
void PushRedo( void );
void WipeUndo( void ); void WipeRedo( void );
CPhonemeTag *GetClickedPhoneme( void ); CWordTag *GetClickedWord( void ); void SetClickedPhoneme( int word, int phoneme );
void ShiftSelectedPhoneme( int direction ); void ExtendSelectedPhonemeEndTime( int direction ); void SelectNextPhoneme( int direction ); void SelectNextWord( int direction ); bool IsPhonemeSelected( CWordTag *word ); void ShiftSelectedWord( int direction ); void ExtendSelectedWordEndTime( int direction );
float GetTimeGapToNextWord( bool forward, CWordTag *currentWord, CWordTag **ppNextWord = NULL ); float GetTimeGapToNextPhoneme( bool forward, CPhonemeTag *currentPhoneme, CWordTag **ppword = NULL, CPhonemeTag **phoneme = NULL ); int IndexOfWord( CWordTag *word ); CPhonemeTag *GetSelectedPhoneme( void ); CWordTag *GetSelectedWord( void );
void OnMouseMove( mxEvent *event );
bool AreSelectedWordsContiguous( void ); bool AreSelectedPhonemesContiguous( void );
bool CreateCroppedWave( char const *filename, int startsample, int endsample ); void CleanupWordsAndPhonemes( bool prepareundo ); void RealignPhonemesToWords( bool prepareundo ); void RealignWordsToPhonemes( bool prepareundo ); void SortWords( bool prepareundo ); void SortPhonemes( bool prepareundo );
float ComputeMaxWordShift( bool forward, bool allowcrop ); float ComputeMaxPhonemeShift( bool forward, bool allowcrop );
int PixelsForDeltaTime( float dt );
void ClearDragLimit( void ); void SetDragLimit( int dragtype ); void LimitDrag( int& mousex );
void SelectExpression( CPhonemeTag *tag );
void OnSAPI( void ); void OnLipSinc( void );
bool CheckSpeechAPI( void ); char const *GetSpeechAPIName( void );
void LoadPhonemeConverters(); void UnloadPhonemeConverters();
bool IsMouseOverScrubHandle( mxEvent *event ); bool IsMouseOverScrubArea( mxEvent *event ); void GetScrubHandleRect( RECT& rcHandle, bool clipped = false ); void GetScrubAreaRect( RECT& rcArea ); void DrawScrubHandle();
void DrawScrubHandle( CChoreoWidgetDrawHelper& drawHelper ); void ScrubThink( float dt, bool scrubbing );
void SetScrubTime( float t ); void SetScrubTargetTime( float t );
float GetTimeForSample( int sample ); void ClampTimeToSelectionInterval( float& timeval ); void OnToggleVoiceDuck();
// Data
private: // Type of mouse movement
enum { DRAGTYPE_NONE = 0, DRAGTYPE_PHONEME , DRAGTYPE_WORD, DRAGTYPE_SELECTSAMPLES, DRAGTYPE_MOVESELECTION, DRAGTYPE_MOVESELECTIONSTART, DRAGTYPE_MOVESELECTIONEND, DRAGTYPE_MOVEWORD, DRAGTYPE_MOVEPHONEME, DRAGTYPE_EVENTTAG_MOVE, DRAGTYPE_EMPHASIS_SELECT, DRAGTYPE_EMPHASIS_MOVE, DRAGTYPE_SCRUBBER };
float m_flScrub; float m_flScrubTarget;
EditorMode m_CurrentMode; // Graph scale
float m_flPixelsPerSecond; // Graph scale
int m_nTimeZoom; int m_nTimeZoomStep;
int m_nTickHeight;
// Current wave file
CAudioSource *m_pWaveFile; CAudioMixer *m_pMixer; CChoreoEvent *m_pEvent; int m_nClickX;
struct CWorkFile { public: char m_szWaveFile[ 256 ]; char m_szWorkingFile[ 256 ]; char m_szBasePath[ 256 ]; bool m_bDirty; }; CWorkFile m_WorkFile;
mxScrollbar *m_pHorzScrollBar; // Current sb value
int m_nLeftOffset;
CPhonemeModeTab *m_pModeTab;
mxSlider *m_pPlaybackRate; float m_flPlaybackRate;
mxButton *m_btnRedoPhonemeExtraction; mxButton *m_btnSave; mxButton *m_btnLoad;
mxButton *m_btnPlay; // selection or full depending
// Mouse dragging
HCURSOR m_hPrevCursor;
int m_nStartX; int m_nStartY; int m_nLastX; int m_nLastY; int m_nDragType; struct CFocusRect { RECT m_rcOrig; RECT m_rcFocus; }; CUtlVector < CFocusRect > m_FocusRects;
int m_nClickedPhoneme; int m_nClickedWord;
// Current set of tags
CSentence m_Tags;
CSentence m_TagsExt;
int m_nSelection[ 2 ]; bool m_bSelectionActive;
int m_nLastExtractionResult;
int m_nSelectedPhonemeCount; int m_nSelectedWordCount;
bool m_bWordsActive;
struct PEUndo { CSentence *undo; CSentence *redo; };
CUtlVector< PEUndo * > m_UndoStack; int m_nUndoLevel; bool m_bRedoPending;
bool m_bLimitDrag; int m_nLeftLimit; int m_nRightLimit;
IPhonemeExtractor *m_pPhonemeExtractor; float m_flScrubberTimeOffset; };
extern PhonemeEditor *g_pPhonemeEditor;
#endif // PHONEEDITOR_H
|