Audacity 3.2.0
Lyrics.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 Lyrics.cpp
6
7 Dominic Mazzoni
8 Vaughan Johnson
9
10**********************************************************************/
11
12#include "Lyrics.h"
13
14#include <math.h>
15
16#include <wx/dcclient.h>
17#include <wx/defs.h>
18#include <wx/dcmemory.h>
19#include <wx/frame.h>
20#include <wx/mimetype.h>
21
22#include "AudioIO.h"
23#include "Project.h"
24#include "ProjectWindowBase.h"
25#include "LabelTrack.h"
26#include "MenuCreator.h"
27#include "UndoManager.h"
28#include "ViewInfo.h"
29
30
31BEGIN_EVENT_TABLE(HighlightTextCtrl, wxTextCtrl)
32 EVT_MOUSE_EVENTS(HighlightTextCtrl::OnMouseEvent)
34
36 wxWindowID id,
37 const wxString& value /* = {} */,
38 const wxPoint& pos /*= wxDefaultPosition*/,
39 const wxSize& size /*= wxDefaultSize*/)
40: wxTextCtrl(parent, id, // wxWindow* parent, wxWindowID id,
41 value, // const wxString& value = {},
42 pos, // const wxPoint& pos = wxDefaultPosition,
43 size, // const wxSize& size = wxDefaultSize,
44 wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH | wxTE_RICH2 | wxTE_AUTO_URL | wxTE_NOHIDESEL), //v | wxHSCROLL)
45 mLyricsPanel(parent)
46{
47}
48
49void HighlightTextCtrl::OnMouseEvent(wxMouseEvent& event)
50{
51 if (event.ButtonUp())
52 {
53 long from, to;
54 this->GetSelection(&from, &to);
55
57 int nNewSyl = mLyricsPanel->FindSyllable(from);
58 if (nNewSyl != nCurSyl)
59 {
60 Syllable* pCurSyl = mLyricsPanel->GetSyllable(nNewSyl);
61 auto pProj = FindProjectFromWindow( this );
62 auto &selectedRegion = ViewInfo::Get( *pProj ).selectedRegion;
63 selectedRegion.setT0( pCurSyl->t );
64
65 //v Should probably select to end as in
66 // SelectUtilities::Handler::OnSelectCursorEnd,
67 // but better to generalize that in AudacityProject methods.
68 selectedRegion.setT1( pCurSyl->t );
69 }
70 }
71
72 event.Skip();
73}
74
75
76//v static const kHighlightTextCtrlID = 7654;
77
78BEGIN_EVENT_TABLE(LyricsPanel, wxPanelWrapper)
79 EVT_KEY_DOWN(LyricsPanel::OnKeyEvent)
80 EVT_PAINT(LyricsPanel::OnPaint)
81 EVT_SIZE(LyricsPanel::OnSize)
82
83 //v Doesn't seem to be a way to capture a selection event in a read-only wxTextCtrl.
84 // EVT_COMMAND_LEFT_CLICK(kHighlightTextCtrlID, LyricsPanel::OnHighlightTextCtrl)
86
88
89LyricsPanel::LyricsPanel(wxWindow* parent, wxWindowID id,
91 const wxPoint& pos /*= wxDefaultPosition*/,
92 const wxSize& size /*= wxDefaultSize*/) :
93 wxPanelWrapper(parent, id, pos, size, wxWANTS_CHARS),
94 mWidth(size.x), mHeight(size.y)
95 , mProject(project)
96{
97 mKaraokeHeight = mHeight;
98 mLyricsStyle = kBouncingBallLyrics; // default
99 mKaraokeFontSize = this->GetDefaultFontSize(); // Call only after mLyricsPanelStyle is set.
100
101 this->SetBackgroundColour(*wxWHITE);
102
103 mHighlightTextCtrl =
104 safenew HighlightTextCtrl(this, -1, // wxWindow* parent, wxWindowID id,
105 wxT(""), // const wxString& value = {},
106 wxPoint(0, 0), // const wxPoint& pos = wxDefaultPosition,
107 size); // const wxSize& size = wxDefaultSize
108 this->SetHighlightFont();
109 mHighlightTextCtrl->Show(mLyricsStyle == kHighlightLyrics); // test, in case we conditionalize the default, above
110
111
112 mT = 0.0;
113
114 Clear();
115 Finish(0.0);
116
117 #ifdef __WXMAC__
118 wxSizeEvent dummyEvent;
119 OnSize(dummyEvent);
120 #endif
121
122 parent->Bind(wxEVT_SHOW, &LyricsPanel::OnShow, this);
123
124 if (project)
125 mUndoSubscription = UndoManager::Get(*project)
127
128 mAudioIOSubscription =
130}
131
133{
134}
135
136#define I_FIRST_REAL_SYLLABLE 2
137
139{
140 mSyllables.clear();
141 mText = wxT("");
142
143 // Add two dummy syllables at the beginning
144 mSyllables.push_back(Syllable());
145 mSyllables[0].t = -2.0;
146 mSyllables.push_back(Syllable());
147 mSyllables[1].t = -1.0;
148
149 mHighlightTextCtrl->Clear();
150}
151
153{
154 const size_t numLabels = pLT->GetNumLabels();
155 wxString highlightText;
156 for (size_t ii = 0; ii < numLabels; ++ii) {
157 const LabelStruct *const pLabel = pLT->GetLabel(ii);
158 Add(pLabel->getT0(), pLabel->title, highlightText);
159 }
160 mHighlightTextCtrl->AppendText(highlightText);
161}
162
163void LyricsPanel::Add(double t, const wxString &syllable, wxString &highlightText)
164{
165 int i = mSyllables.size();
166
167 {
168 Syllable &prevSyllable = mSyllables[i - 1];
169
170 if (prevSyllable.t == t) {
171 // We can't have two syllables with the same time, so append
172 // this to the end of the previous one if they're at the
173 // same time.
174 prevSyllable.text += syllable;
175 prevSyllable.textWithSpace += syllable;
176 prevSyllable.char1 += syllable.length();
177 return;
178 }
179 }
180
181 mSyllables.push_back(Syllable());
182 Syllable &thisSyllable = mSyllables[i];
183 thisSyllable.t = t;
184 thisSyllable.text = syllable;
185
186 thisSyllable.char0 = mText.length();
187
188 // Put a space between syllables unless the previous one
189 // ended in a hyphen
190 if (i > 0 &&
191 // mSyllables[i-1].text.length() > 0 &&
192 mSyllables[i - 1].text.Right(1) != wxT("-"))
193 thisSyllable.textWithSpace = wxT(" ") + syllable;
194 else
195 thisSyllable.textWithSpace = syllable;
196
197 mText += thisSyllable.textWithSpace;
198 thisSyllable.char1 = mText.length();
199
200 int nTextLen = thisSyllable.textWithSpace.length();
201 if ((nTextLen > 0) && (thisSyllable.textWithSpace.Right(1) == wxT("_")))
202 highlightText += (thisSyllable.textWithSpace.Left(nTextLen - 1) + wxT("\n"));
203 else
204 highlightText += thisSyllable.textWithSpace;
205}
206
207void LyricsPanel::Finish(double finalT)
208{
209 // Add 3 dummy syllables at the end
210 int i = mSyllables.size();
211 mSyllables.push_back(Syllable());
212 mSyllables[i].t = finalT + 1.0;
213 mSyllables.push_back(Syllable());
214 mSyllables[i+1].t = finalT + 2.0;
215 mSyllables.push_back(Syllable());
216 mSyllables[i+2].t = finalT + 3.0;
217
218 // Mark measurements as invalid
219 mMeasurementsDone = false; // only for drawn text
221 mHighlightTextCtrl->ShowPosition(0);
222}
223
224// Binary-search for the syllable whose char0 <= startChar <= char1.
225int LyricsPanel::FindSyllable(long startChar)
226{
227 int i1, i2;
228
229 i1 = 0;
230 i2 = mSyllables.size();
231 while (i2 > i1+1) {
232 int pmid = (i1+i2)/2;
233 if (mSyllables[pmid].char0 > startChar)
234 i2 = pmid;
235 else
236 i1 = pmid;
237 }
238
239 if (i1 < 2)
240 i1 = 2;
241 if (i1 > (int)(mSyllables.size()) - 3)
242 i1 = mSyllables.size() - 3;
243
244 return i1;
245}
246
247void LyricsPanel::SetLyricsStyle(const LyricsStyle newLyricsStyle)
248{
249 if (mLyricsStyle == newLyricsStyle)
250 return;
251
252 mLyricsStyle = newLyricsStyle;
254
255 wxSizeEvent ignore;
256 this->OnSize(ignore);
257}
258
259
261{
262 return (mLyricsStyle == kBouncingBallLyrics) ? 48 : 10;
263}
264
266{
267 dc->SetFont(wxFont(mKaraokeFontSize, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL));
268}
269
270void LyricsPanel::SetHighlightFont() // for kHighlightLyrics
271{
272 wxFont newFont(mKaraokeFontSize, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
273 mHighlightTextCtrl->SetDefaultStyle(wxTextAttr(wxNullColour, wxNullColour, newFont));
274 mHighlightTextCtrl->SetStyle(0, mHighlightTextCtrl->GetLastPosition(),
275 wxTextAttr(wxNullColour, wxNullColour, newFont));
276}
277
278void LyricsPanel::Measure(wxDC *dc) // only for drawn text
279{
280 this->SetDrawnFont(dc);
281 int width = 0, height = 0;
282
283 const int kIndent = 4;
284 int x = 2*kIndent;
285
286 unsigned int i;
287 for(i = 0; i < mSyllables.size(); i++) {
288 if ((i < I_FIRST_REAL_SYLLABLE) || // Clear() starts the list with I_FIRST_REAL_SYLLABLE dummies.
289 (i >= mSyllables.size() - 3)) // Finish() ends with 3 dummies.
290 {
291 dc->GetTextExtent(wxT("DUMMY"), &width, &height); // Get the correct height even if we're at i=0.
292 width = 0;
293 }
294 else {
295 dc->GetTextExtent(mSyllables[i].textWithSpace, &width, &height);
296 }
297
298 // Add some space between words; the space is normally small but
299 // when there's a long pause relative to the previous word, insert
300 // extra space.
301 int extraWidth;
302 if (i >= I_FIRST_REAL_SYLLABLE && i < mSyllables.size() - 2)
303 {
304 double deltaThis = mSyllables[i+1].t - mSyllables[i].t;
305 double deltaPrev = mSyllables[i].t - mSyllables[i-1].t;
306
307 double ratio;
308 if (deltaPrev > 0.0)
309 ratio = deltaThis / deltaPrev;
310 else
311 ratio = deltaThis;
312
313 if (ratio > 2.0)
314 extraWidth = 15 + (int)(15.0 * ratio);
315 else
316 extraWidth = 15;
317 }
318 else
319 extraWidth = 20;
320
321 mSyllables[i].width = width + extraWidth;
322 mSyllables[i].leftX = x;
323 mSyllables[i].x = x + width/2;
324 x += mSyllables[i].width;
325 }
326
327 mTextHeight = height;
328
329 mMeasurementsDone = true;
330}
331
332// Binary-search for the syllable with the largest time not greater than t
334{
335 int i1, i2;
336
337 i1 = 0;
338 i2 = mSyllables.size();
339 while (i2 > i1+1) {
340 int pmid = (i1+i2)/2;
341 if (mSyllables[pmid].t > t)
342 i2 = pmid;
343 else
344 i1 = pmid;
345 }
346
347 if (i1 < 2)
348 i1 = 2;
349 if (i1 > (int)(mSyllables.size()) - 3)
350 i1 = mSyllables.size() - 3;
351
352 return i1;
353}
354
355// Bouncing Ball:
356// Given the current time t, returns the x/y position of the scrolling
357// karaoke display. For some syllable i, when t==mSyllables[i].t,
358// it will return mSyllables[i].x for outX and 0 for outY.
359// In-between words, outX is interpolated using smooth acceleration
360// between the two neighboring words, and y is a positive number indicating
361// the bouncing ball height
363 int *outX, double *outY)
364{
365 *outX = 0;
366 *outY = 0;
367
368 if (t < mSyllables[I_FIRST_REAL_SYLLABLE].t || t > mSyllables[mSyllables.size() - 3].t)
369 return;
370
371 int i0, i1, i2, i3;
372 int x0, x1, x2, x3;
373 double t0, t1, t2, t3;
374 i1 = FindSyllable(t);
375 i2 = i1 + 1;
376
377 // Because we've padded the syllables with two dummies at the beginning
378 // and end, we know that i0...i3 will always exist. Also, we've made
379 // sure that we don't ever have two of the same time, so t2>t1 strictly.
380 //
381 // t
382 // \/
383 // time: t0 t1 t2 t3
384 // pos: x0 x1 x2 x3
385 // index: i0 i1 i2 i3
386 // vel: vel1 vel2
387
388 i0 = i1 - 1;
389 i3 = i2 + 1;
390
391 x0 = mSyllables[i0].x;
392 x1 = mSyllables[i1].x;
393 x2 = mSyllables[i2].x;
394 x3 = mSyllables[i3].x;
395
396 t0 = mSyllables[i0].t;
397 t1 = mSyllables[i1].t;
398 t2 = mSyllables[i2].t;
399 t3 = mSyllables[i3].t;
400
401 double linear_vel0 = (x1 - x0) / (t1 - t0);
402 double linear_vel1 = (x2 - x1) / (t2 - t1);
403 double linear_vel2 = (x3 - x2) / (t3 - t2);
404
405 // average velocities
406 double v1 = (linear_vel0 + linear_vel1) / 2;
407 double v2 = (linear_vel1 + linear_vel2) / 2;
408
409 // Solve a cubic equation f(t) = at^3 + bt^2 + ct + d
410 // which gives the position x as a function of
411 // (t - t1), by constraining f(0), f'(0), f(t2-t1), f'(t2-t1)
412 double delta_t = t2 - t1;
413 double delta_x = x2 - x1;
414 v1 *= delta_t;
415 v2 *= delta_t;
416 double a = v1 + v2 - 2*delta_x;
417 double b = 3*delta_x - 2*v1 - v2;
418 double c = v1;
419 double d = x1;
420
421 t = (t - t1) / (t2 - t1);
422 double xx = a*t*t*t + b*t*t + c*t + d;
423
424 // Unfortunately sometimes our cubic goes backwards. This is a quick
425 // hack to stop that from happening.
426 if (xx < x1)
427 xx = x1;
428
429 *outX = (int)xx;
430
431 // The y position is a simple cosine curve; the max height is a
432 // function of the time.
433 double height = t2 - t1 > 4.0? 1.0: sqrt((t2-t1)/4.0);
434 *outY = height * sin(M_PI * t);
435}
436
438{
439 if (t < 0.0)
440 {
441 // TrackPanel::OnTimer passes gAudioIO->GetStreamTime(), which is -DBL_MAX if !IsStreamActive().
442 // In that case, use the selection start time.
443 auto pProj = FindProjectFromWindow( this );
444 const auto &selectedRegion = ViewInfo::Get( *pProj ).selectedRegion;
445 mT = selectedRegion.t0();
446 }
447 else
448 mT = t;
449
451 {
452 wxRect karaokeRect(0, 0, mWidth, mKaraokeHeight);
453 this->Refresh(false, &karaokeRect);
454 }
455
456 int i = FindSyllable(mT);
457 if (i == mCurrentSyllable)
458 return;
459
461
463 {
464 mHighlightTextCtrl->SetSelection(mSyllables[i].char0, mSyllables[i].char1);
465
466 //v No trail for now.
468 //if (i == I_FIRST_REAL_SYLLABLE)
469 // // Reset the trail to zero.
470 // mHighlightTextCtrl->SetStyle(0, mHighlightTextCtrl->GetLastPosition(), wxTextAttr(wxNullColour, *wxWHITE));
472 //mHighlightTextCtrl->SetStyle(mSyllables[i].char0, mSyllables[i].char1, wxTextAttr(wxNullColour, *wxLIGHT_GREY));
473
474 //v Too much flicker: mHighlightTextCtrl->ShowPosition(mSyllables[i].char0);
475 }
476}
477
479{
480 switch (message.type) {
485 break;
486 default:
487 return;
488 }
490}
491
493{
494 // It's crucial to not do that repopulating during playback.
495 auto gAudioIO = AudioIOBase::Get();
496 if (gAudioIO->IsStreamActive()) {
497 mDelayedUpdate = true;
498 return;
499 }
500
501 Clear();
502
503 if (!mProject)
504 return;
505
506 // Lyrics come from only the first label track.
507 auto pLabelTrack =
508 *TrackList::Get(*mProject).Any<const LabelTrack>().begin();
509 if (!pLabelTrack)
510 return;
511
512 // The code that updates the lyrics is rather expensive when there
513 // are a lot of labels.
514 // So - bail out early if the lyrics window is not visible.
515 // We will later force an update when the lyrics window is made visible.
516 auto parent = dynamic_cast<wxFrame*>(GetParent());
517 if( !(parent && parent->IsVisible()) )
518 return;
519
520 AddLabels(pLabelTrack);
521 Finish(pLabelTrack->GetEndTime());
522 const auto &selectedRegion = ViewInfo::Get( *mProject ).selectedRegion;
523 Update(selectedRegion.t0());
524}
525
527{
529 return;
530 if ( !e.on && mDelayedUpdate ) {
531 mDelayedUpdate = false;
533 }
534}
535
536void LyricsPanel::OnShow(wxShowEvent &e)
537{
538 e.Skip();
539 if (e.IsShown())
541}
542
543void LyricsPanel::OnKeyEvent(wxKeyEvent & event)
544{
545 if (auto project = FindProjectFromWindow(this))
547 event.Skip();
548}
549
550void LyricsPanel::OnPaint(wxPaintEvent & WXUNUSED(event))
551{
552 wxPaintDC dc(this);
553 DoPaint(dc);
554}
555
557{
558 if (!this->GetParent()->IsShown())
559 return;
560
562 {
564 Measure(&dc);
565
566 #ifdef __WXMAC__
567 // Mac OS X automatically double-buffers the screen for you,
568 // so our bitmap is unnecessary
569 HandlePaint(dc);
570 #else
571 wxBitmap bitmap(mWidth, mKaraokeHeight);
572 wxMemoryDC memDC;
573 memDC.SelectObject(bitmap);
574 HandlePaint(memDC);
575 dc.Blit(0, 0, mWidth, mKaraokeHeight, &memDC, 0, 0, wxCOPY, FALSE);
576 #endif
577 }
578 else // (mLyricsStyle == kHighlightLyrics)
579 {
580 //v causes flicker in ported version
581 // this->SetHighlightFont();
582 }
583}
584
585void LyricsPanel::OnSize(wxSizeEvent & WXUNUSED(event))
586{
587 GetClientSize(&mWidth, &mHeight);
588
590
592 (int)((float)(this->GetDefaultFontSize() * mHeight) / (float)LYRICS_DEFAULT_HEIGHT);
593 // Usually don't get the size window we want, usually less than
594 // LYRICS_DEFAULT_HEIGHT, so bump it a little.
595 mKaraokeFontSize += 2;
596
598 {
599 mMeasurementsDone = false;
600 wxClientDC dc(this);
601 this->DoPaint(dc);
602 }
603 else // (mLyricsStyle == kHighlightLyrics)
604 {
606 this->SetHighlightFont();
607 }
608
609 this->Refresh(false);
610}
611
612//v Doesn't seem to be a way to capture a selection event in a read-only wxTextCtrl.
613//void LyricsPanel::OnHighlightTextCtrl(wxCommandEvent & event)
614//{
615// long from, to;
616//
617// mHighlightTextCtrl->GetSelection(&from, &to);
618// // TODO: Find the start time of the corresponding syllable and set playback to start there.
619//}
620
622{
624 dc.SetBrush(*wxWHITE_BRUSH);
625 dc.DrawRectangle(0, 0, mWidth, mKaraokeHeight);
626
627 this->HandlePaint_BouncingBall(dc);
628}
629
631{
632 int ctr = mWidth / 2;
633 int x;
634 double y;
635 GetKaraokePosition(mT, &x, &y);
636
637 dc.SetTextForeground(wxColour(238, 0, 102));
638 bool changedColor = false;
639
640 SetDrawnFont(&dc);
641 unsigned int i;
642 wxCoord yTextTop = mKaraokeHeight - mTextHeight - 4;
643 for(i = 0; i < mSyllables.size(); i++) {
644 if (mSyllables[i].x + mSyllables[i].width < (x - ctr))
645 continue;
646 if (mSyllables[i].x > x + ctr)
647 continue;
648
649 if (!changedColor && mSyllables[i].x >= x) {
650 dc.SetTextForeground(*wxBLACK);
651 changedColor = true;
652 }
653
654 wxString text = mSyllables[i].text;
655 if (text.length() > 0 && text.Right(1) == wxT("_")) {
656 text = text.Left(text.length() - 1);
657 }
658
659 dc.DrawText(text,
660 mSyllables[i].leftX + ctr - x,
661 yTextTop);
662 }
663
664 int ballRadius = (int)(mTextHeight / 8.0);
665 int bounceTop = ballRadius * 2;
666 int bounceHeight = yTextTop - bounceTop;
667 int yi = (int)(yTextTop - 4 - (y * bounceHeight));
668
669 if (mT >= 0.0) {
670 wxRect ball(ctr - ballRadius, yi - ballRadius, 2 * ballRadius, 2 * ballRadius);
671 dc.SetBrush(wxBrush(wxColour(238, 0, 102), wxBRUSHSTYLE_SOLID));
672 dc.DrawEllipse(ball);
673 }
674}
675
wxT("CloseDown"))
END_EVENT_TABLE()
#define M_PI
Definition: Distortion.cpp:30
#define I_FIRST_REAL_SYLLABLE
Definition: Lyrics.cpp:136
#define LYRICS_DEFAULT_HEIGHT
Definition: Lyrics.h:28
#define safenew
Definition: MemoryX.h:10
AudacityProject * FindProjectFromWindow(wxWindow *pWindow)
IMPLEMENT_CLASS(cloud::ShareAudioToolbar, ToolBar)
const auto project
static void OnSize(wxSizeEvent &evt)
Definition: VSTEditor.cpp:224
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
static AudioIOBase * Get()
Definition: AudioIOBase.cpp:93
static AudioIO * Get()
Definition: AudioIO.cpp:126
void OnMouseEvent(wxMouseEvent &evt)
Definition: Lyrics.cpp:49
LyricsPanel * mLyricsPanel
Definition: Lyrics.h:65
A LabelStruct holds information for ONE label in a LabelTrack.
Definition: LabelTrack.h:29
double getT0() const
Definition: LabelTrack.h:39
wxString title
Definition: LabelTrack.h:70
A LabelTrack is a Track that holds labels (LabelStruct).
Definition: LabelTrack.h:87
int GetNumLabels() const
Definition: LabelTrack.cpp:961
const LabelStruct * GetLabel(int index) const
Definition: LabelTrack.cpp:966
LyricsPanel is a panel that paints the bouncing ball and the lyrics text.
Definition: Lyrics.h:79
void OnStartStop(AudioIOEvent)
Definition: Lyrics.cpp:526
void SetLyricsStyle(const LyricsStyle newLyricsStyle)
Definition: Lyrics.cpp:247
virtual ~LyricsPanel()
Definition: Lyrics.cpp:132
int FindSyllable(long startChar)
Definition: Lyrics.cpp:225
void HandlePaint(wxDC &dc)
Definition: Lyrics.cpp:621
void Update(double t)
Definition: Lyrics.cpp:437
LyricsStyle mLyricsStyle
Definition: Lyrics.h:153
wxString mText
Definition: Lyrics.h:160
void SetHighlightFont()
Definition: Lyrics.cpp:270
double mT
Definition: Lyrics.h:156
void OnKeyEvent(wxKeyEvent &event)
Definition: Lyrics.cpp:543
int GetCurrentSyllableIndex()
Definition: Lyrics.h:96
@ kBouncingBallLyrics
Definition: Lyrics.h:83
@ kHighlightLyrics
Definition: Lyrics.h:85
void GetKaraokePosition(double t, int *outX, double *outY)
Definition: Lyrics.cpp:362
int mKaraokeHeight
Definition: Lyrics.h:150
int mCurrentSyllable
Definition: Lyrics.h:158
void Measure(wxDC *dc)
Definition: Lyrics.cpp:278
void DoPaint(wxDC &dc)
Definition: Lyrics.cpp:556
int mHeight
Definition: Lyrics.h:148
void Finish(double finalT)
Definition: Lyrics.cpp:207
int mWidth
Definition: Lyrics.h:147
void Clear()
Definition: Lyrics.cpp:138
HighlightTextCtrl * mHighlightTextCtrl
Definition: Lyrics.h:154
wxWeakRef< AudacityProject > mProject
Definition: Lyrics.h:165
unsigned int mKaraokeFontSize
Definition: Lyrics.h:151
void OnShow(wxShowEvent &e)
Definition: Lyrics.cpp:536
Syllable * GetSyllable(int nSyl)
Definition: Lyrics.h:97
unsigned int GetDefaultFontSize() const
Definition: Lyrics.cpp:260
bool mDelayedUpdate
Definition: Lyrics.h:166
void Add(double t, const wxString &syllable, wxString &highlightText)
Definition: Lyrics.cpp:163
void AddLabels(const LabelTrack *pLT)
Definition: Lyrics.cpp:152
void OnSize(wxSizeEvent &evt)
Definition: Lyrics.cpp:585
void HandlePaint_BouncingBall(wxDC &dc)
Definition: Lyrics.cpp:630
void DoUpdateLyrics()
Definition: Lyrics.cpp:492
void OnPaint(wxPaintEvent &evt)
Definition: Lyrics.cpp:550
std::vector< Syllable > mSyllables
Definition: Lyrics.h:159
void UpdateLyrics(struct UndoRedoMessage)
Definition: Lyrics.cpp:478
int mTextHeight
Definition: Lyrics.h:162
bool mMeasurementsDone
Definition: Lyrics.h:163
void SetDrawnFont(wxDC *dc)
Definition: Lyrics.cpp:265
static bool FilterKeyEvent(AudacityProject &project, const wxKeyEvent &evt, bool permit=false)
bool setT0(double t, bool maySwap=true)
Definition: ViewInfo.cpp:61
Subscription Subscribe(Callback callback)
Connect a callback to the Publisher; later-connected are called earlier.
Definition: Observer.h:199
auto Any() -> TrackIterRange< TrackType >
Definition: Track.h:1079
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:347
static UndoManager & Get(AudacityProject &project)
Definition: UndoManager.cpp:71
NotifyingSelectedRegion selectedRegion
Definition: ViewInfo.h:215
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:235
__finl float_x4 __vecc sqrt(const float_x4 &a)
bool on
Definition: AudioIO.h:66
enum AudioIOEvent::Type type
used in LyricsPanel, a Syllable gives positional information to be used with the bouncing ball effect...
Definition: Lyrics.h:32
wxString text
Definition: Lyrics.h:40
wxString textWithSpace
Definition: Lyrics.h:41
double t
Definition: Lyrics.h:39
int char1
Definition: Lyrics.h:43
int char0
Definition: Lyrics.h:42
Type of message published by UndoManager.
Definition: UndoManager.h:55
enum UndoRedoMessage::Type type