Team Fortress 2 Source Code as on 22/4/2020
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.

591 lines
16 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #ifndef PHONEEDITOR_H
  8. #define PHONEEDITOR_H
  9. #ifdef _WIN32
  10. #pragma once
  11. #endif
  12. #include <mxtk/mx.h>
  13. class CAudioSource;
  14. class CAudioMixer;
  15. class mxBitmapButton;
  16. class mxButton;
  17. #include "utlvector.h"
  18. #include "faceposertoolwindow.h"
  19. #define IDC_PHONEME_SCROLL 1001
  20. #define IDC_PHONEME_PLAY_ORIG 1002
  21. #define IDC_EDIT_PHONEME 1004
  22. #define IDC_EDIT_INSERTPHONEMEBEFORE 1005
  23. #define IDC_EDIT_INSERTPHONEMEAFTER 1006
  24. #define IDC_EDIT_DELETEPHONEME 1007
  25. #define IDC_PLAY_EDITED_SELECTION 1008
  26. #define IDC_REDO_PHONEMEEXTRACTION 1009
  27. #define IDC_REDO_PHONEMEEXTRACTION_SELECTION 1010
  28. #define IDC_DESELECT 1011
  29. #define IDC_PLAY_EDITED 1012
  30. #define IDC_SAVE_LINGUISTIC 1013
  31. #define IDC_CANCELPLAYBACK 1014
  32. #define IDC_EDITWORDLIST 1015
  33. #define IDC_SNAPWORDS 1016
  34. #define IDC_SEPARATEWORDS 1017
  35. #define IDC_LOADWAVEFILE 1018
  36. #define IDC_SNAPPHONEMES 1019
  37. #define IDC_SEPARATEPHONEMES 1020
  38. #define IDC_COMMITEXTRACTED 1021
  39. #define IDC_CLEAREXTRACTED 1022
  40. #define IDC_ADDTAG 1023
  41. #define IDC_DELETETAG 1024
  42. #define IDC_CVUNDO 1025
  43. #define IDC_CVREDO 1026
  44. #define IDC_EDIT_DELETEWORD 1027
  45. #define IDC_EDIT_WORD 1028
  46. #define IDC_EDIT_INSERTWORDBEFORE 1029
  47. #define IDC_EDIT_INSERTWORDAFTER 1030
  48. #define IDC_EDIT_INSERTFIRSTPHONEMEOFWORD 1031
  49. #define IDC_SELECT_WORDSRIGHT 1032
  50. #define IDC_SELECT_WORDSLEFT 1033
  51. #define IDC_SELECT_PHONEMESRIGHT 1034
  52. #define IDC_SELECT_PHONEMESLEFT 1035
  53. #define IDC_DESELECT_PHONEMESANDWORDS 1036
  54. #define IDC_CLEANUP 1037
  55. #define IDC_CLEARUNDO 1038
  56. #define IDC_PLAYBUTTON 1039
  57. #define IDC_MODE_TAB 1040
  58. #define IDC_EMPHASIS_DELETE 1041
  59. #define IDC_EMPHASIS_DESELECT 1042
  60. #define IDC_EMPHASIS_SELECTALL 1043
  61. #define IDC_PLAYBACKRATE 1044
  62. #define IDC_REALIGNPHONEMES 1045
  63. #define IDC_REALIGNWORDS 1046
  64. // Support for multiple speech api's
  65. #define IDC_API_SAPI 1050
  66. #define IDC_API_LIPSINC 1051
  67. #define IDC_EXPORT_SENTENCE 1075
  68. #define IDC_IMPORT_SENTENCE 1076
  69. #define IDC_TOGGLE_VOICEDUCK 1077
  70. #define IDC_PE_LANGUAGESTART 1100
  71. // #define IDC_PE_LANGUAGEEND 1106 or so
  72. class IterateOutputRIFF;
  73. class IterateRIFF;
  74. class CChoreoWidgetDrawHelper;
  75. class CChoreoEvent;
  76. class CEventRelativeTag;
  77. class CChoreoView;
  78. class IPhonemeExtractor;
  79. class CPhonemeModeTab;
  80. class mxPopupMenu;
  81. #include "sentence.h"
  82. enum
  83. {
  84. COLOR_PHONEME_BACKGROUND = 0,
  85. COLOR_PHONEME_TEXT,
  86. COLOR_PHONEME_LIGHTTEXT,
  87. COLOR_PHONEME_PLAYBACKTICK,
  88. COLOR_PHONEME_WAVDATA,
  89. COLOR_PHONEME_TIMELINE,
  90. COLOR_PHONEME_TIMELINE_MAJORTICK,
  91. COLOR_PHONEME_TIMELINE_MINORTICK,
  92. COLOR_PHONEME_EXTRACTION_RESULT_FAIL,
  93. COLOR_PHONEME_EXTRACTION_RESULT_SUCCESS,
  94. COLOR_PHONEME_EXTRACTION_RESULT_ERROR,
  95. COLOR_PHONEME_EXTRACTION_RESULT_OTHER,
  96. COLOR_PHONEME_TAG_BORDER,
  97. COLOR_PHONEME_TAG_BORDER_SELECTED,
  98. COLOR_PHONEME_TAG_FILLER_NORMAL,
  99. COLOR_PHONEME_TAG_SELECTED,
  100. COLOR_PHONEME_TAG_TEXT,
  101. COLOR_PHONEME_TAG_TEXT_SELECTED,
  102. COLOR_PHONEME_WAV_ENDPOINT,
  103. COLOR_PHONEME_AB,
  104. COLOR_PHONEME_AB_LINE,
  105. COLOR_PHONEME_AB_TEXT,
  106. COLOR_PHONEME_ACTIVE_BORDER,
  107. COLOR_PHONEME_SELECTED_BORDER,
  108. COLOR_PHONEME_TIMING_TAG,
  109. COLOR_PHONEME_EMPHASIS_BG,
  110. COLOR_PHONEME_EMPHASIS_BG_STRONG,
  111. COLOR_PHONEME_EMPHASIS_BG_WEAK,
  112. COLOR_PHONEME_EMPHASIS_BORDER,
  113. COLOR_PHONEME_EMPHASIS_LINECOLOR,
  114. COLOR_PHONEME_EMPHASIS_DOTCOLOR,
  115. COLOR_PHONEME_EMPHASIS_DOTCOLOR_SELECTED,
  116. COLOR_PHONEME_EMPHASIS_TEXT,
  117. COLOR_PHONEME_EMPHASIS_MIDLINE,
  118. NUM_COLORS,
  119. };
  120. //-----------------------------------------------------------------------------
  121. // Purpose: Shows WAV data and allows blanking it out and tweaking phoneme tags
  122. //-----------------------------------------------------------------------------
  123. class PhonemeEditor : public mxWindow, public IFacePoserToolWindow
  124. {
  125. public:
  126. enum
  127. {
  128. BOUNDARY_NONE = 0,
  129. BOUNDARY_PHONEME,
  130. BOUNDARY_WORD,
  131. };
  132. typedef enum
  133. {
  134. MODE_PHONEMES = 0,
  135. MODE_EMPHASIS
  136. } EditorMode;
  137. // Construction
  138. PhonemeEditor( mxWindow *parent );
  139. ~PhonemeEditor( void );
  140. virtual void Think( float dt );
  141. virtual void OnDelete();
  142. virtual bool CanClose();
  143. void ValidateSpeechAPIIndex();
  144. virtual int handleEvent( mxEvent *event );
  145. virtual void redraw( void );
  146. virtual bool PaintBackground( void );
  147. EditorMode GetMode( void ) const;
  148. void SetupPhonemeEditorColors( void );
  149. COLORREF PEColor( int colornum );
  150. void OnModeChanged( void );
  151. // Change wave file being edited
  152. void SetCurrentWaveFile( const char *wavefile, bool force = false, CChoreoEvent *event = NULL );
  153. // called when scene is unloaded in choreview or when event/channel/actor gets deleted
  154. // so we don't have dangling pointers to tags, events, scene
  155. void ClearEvent( void );
  156. void Play();
  157. private:
  158. void DrawWords( CChoreoWidgetDrawHelper& drawHelper, RECT& rcWorkSpace, CSentence &sentence, int type, bool showactive = true );
  159. void DrawPhonemes( CChoreoWidgetDrawHelper& drawHelper, RECT& rcWorkSpace, CSentence &sentence, int type, bool showactive = true );
  160. void DrawRelativeTags( CChoreoWidgetDrawHelper& drawHelper, RECT& rc );
  161. void Emphasis_Redraw( CChoreoWidgetDrawHelper& drawHelper, RECT& rcWorkSpace );
  162. void Emphasis_GetRect( RECT const & rcWorkSpace, RECT& rcEmphasis );
  163. void Emphasis_Init( void );
  164. CEmphasisSample *Emphasis_GetSampleUnderMouse( mxEvent *event );
  165. void Emphasis_DeselectAll( void );
  166. void Emphasis_SelectAll( void );
  167. void Emphasis_Delete( void );
  168. void Emphasis_AddSample( CEmphasisSample const& sample );
  169. void Emphasis_CountSelected( void );
  170. void Emphasis_ShowContextMenu( mxEvent *event );
  171. void Emphasis_MouseDrag( int x, int y );
  172. bool Emphasis_IsValid( void );
  173. void Emphasis_SelectPoints( void );
  174. // Data
  175. int m_nNumSelected;
  176. // Readjust slider
  177. void MoveTimeSliderToPos( int x );
  178. // Handle scrollbar
  179. void SetTimeZoomScale( int scale );
  180. float GetTimeZoomScale( void );
  181. float GetPixelsPerSecond( void );
  182. // Adjust scroll bars
  183. void RepositionHSlider( void );
  184. // Edit commands
  185. void EditPhoneme( CPhonemeTag *pPhoneme, bool positionDialog = false );
  186. void EditPhoneme( void );
  187. void EditInsertPhonemeBefore( void );
  188. void EditInsertPhonemeAfter( void );
  189. void EditDeletePhoneme( void );
  190. void SelectPhonemes( bool forward );
  191. void EditInsertFirstPhonemeOfWord( void );
  192. void EditWord( CWordTag *pWord, bool positionDialog = false );
  193. void EditWord( void );
  194. void EditInsertWordBefore( void );
  195. void EditInsertWordAfter( void );
  196. void EditDeleteWord( void );
  197. void SelectWords( bool forward );
  198. // Edit word list
  199. void EditWordList( void );
  200. void SentenceFromString( CSentence& sentence, char const *str );
  201. // Wav processing commands
  202. void RedoPhonemeExtraction( void );
  203. // Redo extraction of selected words only
  204. void RedoPhonemeExtractionSelected( void );
  205. void Deselect( void );
  206. void PlayEditedWave( bool selection = false );
  207. void CommitChanges( void );
  208. // Context menu
  209. void ShowPhonemeMenu( CPhonemeTag *pho, int mx, int my );
  210. void ShowWordMenu( CWordTag *word, int mx, int my );
  211. void ShowContextMenu( int mx, int my );
  212. void ShowContextMenu_Phonemes( int mx, int my );
  213. void ShowContextMenu_Emphasis( int mx, int my );
  214. // UI helpers
  215. void GetWorkspaceRect( RECT &rc );
  216. bool IsMouseOverWordRow( int my );
  217. bool IsMouseOverPhonemeRow( int my );
  218. int IsMouseOverBoundary( mxEvent *event );
  219. int GetWordUnderMouse( int mx, int my );
  220. int ComputeHPixelsNeeded( void );
  221. void DrawFocusRect( char *reason );
  222. void StartDragging( int dragtype, int startx, int starty, HCURSOR cursor );
  223. void FinishPhonemeMove( int startx, int endx );
  224. void FinishPhonemeDrag( int startx, int endx );
  225. void FinishWordMove( int startx, int endx );
  226. void FinishWordDrag( int startx, int endx );
  227. float GetTimeForPixel( int mx );
  228. void GetScreenStartAndEndTime( float &starttime, float& endtime );
  229. float GetTimePerPixel( void );
  230. int GetSampleForMouse( int mx );
  231. int GetPixelForSample( int sample );
  232. bool FindSpanningPhonemes( float time, CPhonemeTag **pp1, CPhonemeTag **pp2 );
  233. bool FindSpanningWords( float time, CWordTag **pp1, CWordTag **pp2 );
  234. int FindWordForTime( float time );
  235. CPhonemeTag *FindPhonemeForTime( float time );
  236. void DeselectWords( void );
  237. void SnapWords( void );
  238. void SeparateWords( void );
  239. void DeselectPhonemes( void );
  240. void SnapPhonemes( void );
  241. void SeparatePhonemes( void );
  242. void CreateEvenWordDistribution( const char *wordlist );
  243. // Dirty flag
  244. void SetDirty( bool dirty, bool clearundo = true );
  245. bool GetDirty( void );
  246. // FIXME: Do something else here
  247. void ResampleChunk( IterateOutputRIFF& store, void *format, int chunkname, char *buffer, int buffersize, int start_silence = 0, int end_silence = 0 );
  248. // Mouse control over selected samples
  249. void SelectSamples( int start, int end );
  250. void FinishSelect( int startx, int mx );
  251. void FinishMoveSelection( int startx, int mx );
  252. void FinishMoveSelectionStart( int startx, int mx );
  253. void FinishMoveSelectionEnd( int startx, int mx );
  254. bool IsMouseOverSamples( int mx, int my );
  255. bool IsMouseOverSelection( int mx, int my );
  256. bool IsMouseOverSelectionStartEdge( mxEvent *event );
  257. bool IsMouseOverSelectionEndEdge( mxEvent *event );
  258. bool IsMouseOverTag( int mx, int my );
  259. void FinishEventTagDrag( int startx, int endx );
  260. CEventRelativeTag *GetTagUnderMouse( int mx );
  261. bool IsMouseOverTagRow( int my );
  262. void ShowTagMenu( int mx, int my );
  263. void AddTag( void );
  264. void DeleteTag( void );
  265. // After running liset/sapi, retrieve phoneme tag data from stream
  266. void RetrieveLinguisticData( void );
  267. // Copy current phoneme chunk over existing data chunk of .wav file
  268. void SaveLinguisticData( void );
  269. void StoreValveDataChunk( IterateOutputRIFF& store );
  270. void ExportValveDataChunk( char const *tempfile );
  271. void ImportValveDataChunk( char const *tempfile );
  272. void OnImport();
  273. void OnExport();
  274. // Playback (returns true if sound had been playing)
  275. bool StopPlayback( void );
  276. CPhonemeTag *GetPhonemeTagUnderMouse( int mx, int my );
  277. CWordTag *GetWordTagUnderMouse( int mx, int my );
  278. void ReadLinguisticTags( void );
  279. void LoadWaveFile( void );
  280. void GetPhonemeTrayTopBottom( RECT& rc );
  281. void GetWordTrayTopBottom( RECT& rc );
  282. void GetWordRect( const CWordTag *tag, RECT& rc );
  283. void GetPhonemeRect( const CPhonemeTag *tag, RECT& rc );
  284. int GetMouseForTime( float time );
  285. void CommitExtracted( void );
  286. void ClearExtracted( void );
  287. const char * GetExtractionResultString( int resultCode );
  288. void AddFocusRect( RECT& rc );
  289. void CountSelected( void );
  290. typedef void (PhonemeEditor::*PEWORDITERFUNC)( CWordTag *word, float fparam );
  291. typedef void (PhonemeEditor::*PEPHONEMEITERFUNC)( CPhonemeTag *phoneme, CWordTag *word, float fparam );
  292. void TraverseWords( PEWORDITERFUNC pfn, float fparam );
  293. void TraversePhonemes( PEPHONEMEITERFUNC pfn, float fparam );
  294. // Iteration functions
  295. void ITER_MoveSelectedWords( CWordTag *word, float amount );
  296. void ITER_MoveSelectedPhonemes( CPhonemeTag *phoneme, CWordTag *word, float amount );
  297. void ITER_ExtendSelectedPhonemeEndTimes( CPhonemeTag *phoneme, CWordTag *word, float amount );
  298. void ITER_ExtendSelectedWordEndTimes( CWordTag *word, float amount );
  299. void ITER_AddFocusRectSelectedWords( CWordTag *word, float amount );
  300. void ITER_AddFocusRectSelectedPhonemes( CPhonemeTag *phoneme, CWordTag *word, float amount );
  301. void ITER_CountSelectedWords( CWordTag *word, float amount );
  302. void ITER_CountSelectedPhonemes( CPhonemeTag *phoneme, CWordTag *word, float amount );
  303. void ITER_SelectSpanningWords( CWordTag *word, float amount );
  304. // Undo/Redo
  305. void Undo( void );
  306. void Redo( void );
  307. void ClearUndo( void );
  308. // Do push before changes
  309. void PushUndo( void );
  310. // Do this push after changes, must match pushundo 1for1
  311. void PushRedo( void );
  312. void WipeUndo( void );
  313. void WipeRedo( void );
  314. CPhonemeTag *GetClickedPhoneme( void );
  315. CWordTag *GetClickedWord( void );
  316. void SetClickedPhoneme( int word, int phoneme );
  317. void ShiftSelectedPhoneme( int direction );
  318. void ExtendSelectedPhonemeEndTime( int direction );
  319. void SelectNextPhoneme( int direction );
  320. void SelectNextWord( int direction );
  321. bool IsPhonemeSelected( CWordTag *word );
  322. void ShiftSelectedWord( int direction );
  323. void ExtendSelectedWordEndTime( int direction );
  324. float GetTimeGapToNextWord( bool forward, CWordTag *currentWord, CWordTag **ppNextWord = NULL );
  325. float GetTimeGapToNextPhoneme( bool forward, CPhonemeTag *currentPhoneme, CWordTag **ppword = NULL, CPhonemeTag **phoneme = NULL );
  326. int IndexOfWord( CWordTag *word );
  327. CPhonemeTag *GetSelectedPhoneme( void );
  328. CWordTag *GetSelectedWord( void );
  329. void OnMouseMove( mxEvent *event );
  330. bool AreSelectedWordsContiguous( void );
  331. bool AreSelectedPhonemesContiguous( void );
  332. bool CreateCroppedWave( char const *filename, int startsample, int endsample );
  333. void CleanupWordsAndPhonemes( bool prepareundo );
  334. void RealignPhonemesToWords( bool prepareundo );
  335. void RealignWordsToPhonemes( bool prepareundo );
  336. void SortWords( bool prepareundo );
  337. void SortPhonemes( bool prepareundo );
  338. float ComputeMaxWordShift( bool forward, bool allowcrop );
  339. float ComputeMaxPhonemeShift( bool forward, bool allowcrop );
  340. int PixelsForDeltaTime( float dt );
  341. void ClearDragLimit( void );
  342. void SetDragLimit( int dragtype );
  343. void LimitDrag( int& mousex );
  344. void SelectExpression( CPhonemeTag *tag );
  345. void OnSAPI( void );
  346. void OnLipSinc( void );
  347. bool CheckSpeechAPI( void );
  348. char const *GetSpeechAPIName( void );
  349. void LoadPhonemeConverters();
  350. void UnloadPhonemeConverters();
  351. bool IsMouseOverScrubHandle( mxEvent *event );
  352. bool IsMouseOverScrubArea( mxEvent *event );
  353. void GetScrubHandleRect( RECT& rcHandle, bool clipped = false );
  354. void GetScrubAreaRect( RECT& rcArea );
  355. void DrawScrubHandle();
  356. void DrawScrubHandle( CChoreoWidgetDrawHelper& drawHelper );
  357. void ScrubThink( float dt, bool scrubbing );
  358. void SetScrubTime( float t );
  359. void SetScrubTargetTime( float t );
  360. float GetTimeForSample( int sample );
  361. void ClampTimeToSelectionInterval( float& timeval );
  362. void OnToggleVoiceDuck();
  363. // Data
  364. private:
  365. // Type of mouse movement
  366. enum
  367. {
  368. DRAGTYPE_NONE = 0,
  369. DRAGTYPE_PHONEME ,
  370. DRAGTYPE_WORD,
  371. DRAGTYPE_SELECTSAMPLES,
  372. DRAGTYPE_MOVESELECTION,
  373. DRAGTYPE_MOVESELECTIONSTART,
  374. DRAGTYPE_MOVESELECTIONEND,
  375. DRAGTYPE_MOVEWORD,
  376. DRAGTYPE_MOVEPHONEME,
  377. DRAGTYPE_EVENTTAG_MOVE,
  378. DRAGTYPE_EMPHASIS_SELECT,
  379. DRAGTYPE_EMPHASIS_MOVE,
  380. DRAGTYPE_SCRUBBER
  381. };
  382. float m_flScrub;
  383. float m_flScrubTarget;
  384. EditorMode m_CurrentMode;
  385. // Graph scale
  386. float m_flPixelsPerSecond;
  387. // Graph scale
  388. int m_nTimeZoom;
  389. int m_nTimeZoomStep;
  390. int m_nTickHeight;
  391. // Current wave file
  392. CAudioSource *m_pWaveFile;
  393. CAudioMixer *m_pMixer;
  394. CChoreoEvent *m_pEvent;
  395. int m_nClickX;
  396. struct CWorkFile
  397. {
  398. public:
  399. char m_szWaveFile[ 256 ];
  400. char m_szWorkingFile[ 256 ];
  401. char m_szBasePath[ 256 ];
  402. bool m_bDirty;
  403. };
  404. CWorkFile m_WorkFile;
  405. mxScrollbar *m_pHorzScrollBar;
  406. // Current sb value
  407. int m_nLeftOffset;
  408. CPhonemeModeTab *m_pModeTab;
  409. mxSlider *m_pPlaybackRate;
  410. float m_flPlaybackRate;
  411. mxButton *m_btnRedoPhonemeExtraction;
  412. mxButton *m_btnSave;
  413. mxButton *m_btnLoad;
  414. mxButton *m_btnPlay; // selection or full depending
  415. // Mouse dragging
  416. HCURSOR m_hPrevCursor;
  417. int m_nStartX;
  418. int m_nStartY;
  419. int m_nLastX;
  420. int m_nLastY;
  421. int m_nDragType;
  422. struct CFocusRect
  423. {
  424. RECT m_rcOrig;
  425. RECT m_rcFocus;
  426. };
  427. CUtlVector < CFocusRect > m_FocusRects;
  428. int m_nClickedPhoneme;
  429. int m_nClickedWord;
  430. // Current set of tags
  431. CSentence m_Tags;
  432. CSentence m_TagsExt;
  433. int m_nSelection[ 2 ];
  434. bool m_bSelectionActive;
  435. int m_nLastExtractionResult;
  436. int m_nSelectedPhonemeCount;
  437. int m_nSelectedWordCount;
  438. bool m_bWordsActive;
  439. struct PEUndo
  440. {
  441. CSentence *undo;
  442. CSentence *redo;
  443. };
  444. CUtlVector< PEUndo * > m_UndoStack;
  445. int m_nUndoLevel;
  446. bool m_bRedoPending;
  447. bool m_bLimitDrag;
  448. int m_nLeftLimit;
  449. int m_nRightLimit;
  450. IPhonemeExtractor *m_pPhonemeExtractor;
  451. float m_flScrubberTimeOffset;
  452. };
  453. extern PhonemeEditor *g_pPhonemeEditor;
  454. #endif // PHONEEDITOR_H