void WaveformView::playSegment(LipsyncPhrase *fPhrase, LipsyncWord *fWord, LipsyncPhoneme *fPhoneme, int32 fScrubFrame) { bool playSegment = false; QMediaPlayer *audioPlayer = fDoc->GetAudioPlayer(); int32 startFrame; fAudioStopFrame = -1; if (audioPlayer) { if (fPhrase) { playSegment = true; startFrame = fPhrase->fStartFrame; fAudioStopFrame = fPhrase->fEndFrame + 1; } else if (fWord) { playSegment = true; startFrame = fWord->fStartFrame; fAudioStopFrame = fWord->fEndFrame + 1; } else if (fPhoneme) { playSegment = true; startFrame = fPhoneme->fFrame; fAudioStopFrame = startFrame + 1; } if (playSegment) { float f = ((real)startFrame / (real)fDoc->Fps()) * 1000.0f; audioPlayer->setPosition(PG_ROUND(f)); audioPlayer->play(); emit(frameChanged(fScrubFrame)); } } }
void MainWindow::onBreakdown() { if (!fDoc || !fDoc->fCurrentVoice) return; LipsyncDoc::LoadDictionaries(); fDoc->fDirty = true; int32 duration = fDoc->Fps() * 10; if (fDoc->GetAudioExtractor()) { real f = fDoc->GetAudioExtractor()->Duration(); f *= fDoc->Fps(); duration = PG_ROUND(f); } fDoc->fCurrentVoice->RunBreakdown("EN", duration); ui->waveformView->update(); }
uint32 AudioExtractor::TimeToSample(real time, bool clamped) const { if (fSamples == NULL) return 0; uint32 sample; time = time * (real)(fSndInfo.samplerate * fSndInfo.channels); sample = PG_ROUND(time); if (fSndInfo.channels) { while (sample % fSndInfo.channels) sample--; } if (clamped) return PG_CLAMP(sample, 0, fNumSamples - 1); else return sample; }
void WaveformView::paintEvent(QPaintEvent *event) { PG_UNUSED(event); QPainter dc(this); int32 clientWidth = width(); int32 clientHeight = height(); if (fDoc == NULL) { dc.drawText(QRect(0, 0, clientWidth, clientHeight), Qt::AlignHCenter | Qt::AlignVCenter, tr("Drop WAV audio file here")); return; } int32 topBorder = 16; // should be the height of frame label text int32 halfClientHeight; int32 sampleHeight, halfSampleHeight, textHeight; int32 fps = fDoc->Fps(); int32 x = 0; int32 frameX; int32 sample = 0; int32 frame = 0; bool drawPlayMarker = false; QRect r; QColor textCol(64, 64, 64); QColor sampleFillCol(162, 205, 242); QColor sampleOutlineCol(30, 121, 198); QColor playBackCol(255, 127, 127); QColor playForeCol(209, 102, 121, 128); QColor playOutlineCol(128, 0, 0); QColor frameCol(192, 192, 192); QColor phraseFillCol(205, 242, 162); QColor phraseOutlineCol(121, 198, 30); QColor wordFillCol(242, 205, 162); QColor wordOutlineCol(198, 121, 30); QColor wordMissingFillCol(255, 127, 127); QColor wordMissingOutlineCol(255, 0, 0); QColor phonemeFillCol(231, 185, 210); QColor phonemeOutlineCol(173, 114, 146); QMediaPlayer *audioPlayer = fDoc->GetAudioPlayer(); textHeight = dc.fontMetrics().height() + 4; topBorder = textHeight; halfClientHeight = (clientHeight - textHeight) / 2; if (audioPlayer && audioPlayer->state() == QMediaPlayer::PlayingState) { drawPlayMarker = true; x = fCurFrame * fFrameWidth; dc.fillRect(QRect(x, 0, fFrameWidth, clientHeight), playBackCol); } x = 0; for (int32 i = 0; i < fNumSamples; i++) { if (((sample + 1) % fSamplesPerFrame) == 0) { dc.setPen(frameCol); // draw frame marker frameX = (frame + 1) * fFrameWidth; if (fSampleWidth >= 2 && ((fFrameWidth > 2) || ((frame + 2) % fps == 0))) { dc.drawLine(frameX, topBorder, frameX, clientHeight); } // draw frame label if ((fFrameWidth > 30) || ((frame + 2) % fps == 0)) { dc.drawLine(frameX, 0, frameX, topBorder); dc.drawText(frameX + 2, textHeight - 4, QString::number(frame + 2)); } } sampleHeight = PG_ROUND(fAmp[i] * (real)(clientHeight - topBorder)); halfSampleHeight = sampleHeight / 2; r.setRect(x, topBorder + halfClientHeight - halfSampleHeight, fSampleWidth + 1, sampleHeight); dc.fillRect(r, sampleFillCol); dc.setPen(sampleOutlineCol); dc.drawLine(r.topLeft(), r.topRight()); dc.drawLine(r.bottomLeft(), r.bottomRight()); dc.drawLine(r.topRight(), r.bottomRight()); if (i == 0) { dc.drawLine(r.topLeft(), r.bottomLeft()); } else if (fAmp[i] > fAmp[i - 1]) { sampleHeight = PG_ROUND(fAmp[i - 1] * (real)(clientHeight - topBorder)); halfSampleHeight = sampleHeight / 2; dc.drawLine(r.topLeft(), QPoint(r.left(), topBorder + halfClientHeight - halfSampleHeight)); dc.drawLine(r.bottomLeft(), QPoint(r.left(), topBorder + halfClientHeight - halfSampleHeight + sampleHeight - 1)); } x += fSampleWidth; sample++; if ((sample % fSamplesPerFrame) == 0) frame++; } if (fDoc->fCurrentVoice) { topBorder += 4; for (int32 p = 0; p < fDoc->fCurrentVoice->fPhrases.size(); p++) { LipsyncPhrase *phrase = fDoc->fCurrentVoice->fPhrases[p]; r = QRect(phrase->fStartFrame * fFrameWidth, topBorder, (phrase->fEndFrame - phrase->fStartFrame + 1) * fFrameWidth, textHeight); phrase->fTop = r.top(); phrase->fBottom = r.bottom(); dc.fillRect(r, phraseFillCol); dc.setPen(phraseOutlineCol); dc.drawRect(r); dc.setClipRect(r); dc.setPen(textCol); r = r.marginsRemoved(QMargins(2, 2, 2, 2)); dc.drawText(QPoint(r.left(), r.bottom() - 2), phrase->fText); dc.setClipping(false); for (int32 w = 0; w < phrase->fWords.size(); w++) { LipsyncWord *word = phrase->fWords[w]; r = QRect(word->fStartFrame * fFrameWidth, topBorder + 4 + textHeight, (word->fEndFrame - word->fStartFrame + 1) * fFrameWidth, textHeight); if (w & 1) r.translate(0, textHeight - textHeight / 4); word->fTop = r.top(); word->fBottom = r.bottom(); if (word->fPhonemes.size() == 0) { dc.fillRect(r, wordMissingFillCol); dc.setPen(wordMissingOutlineCol); } else { dc.fillRect(r, wordFillCol); dc.setPen(wordOutlineCol); } dc.drawRect(r); dc.setClipRect(r); dc.setPen(textCol); r = r.marginsRemoved(QMargins(2, 2, 2, 2)); dc.drawText(QPoint(r.left(), r.bottom() - 2), word->fText); dc.setClipping(false); for (int32 i = 0; i < word->fPhonemes.size(); i++) { LipsyncPhoneme *phoneme = word->fPhonemes[i]; r = QRect(phoneme->fFrame * fFrameWidth, clientHeight - 4 - textHeight, fFrameWidth, textHeight); if (i & 1) r.translate(0, -(textHeight - textHeight / 4)); phoneme->fTop = r.top(); phoneme->fBottom = r.bottom(); dc.fillRect(r, phonemeFillCol); dc.setPen(phonemeOutlineCol); dc.drawRect(r); dc.setPen(textCol); r = r.marginsRemoved(QMargins(2, 2, 2, 2)); dc.drawText(QPoint(r.left(), r.bottom() - 2), phoneme->fText); } // for i } // for w } // for p } if (drawPlayMarker) { x = fCurFrame * fFrameWidth; dc.fillRect(QRect(x, 0, fFrameWidth, clientHeight), playForeCol); dc.setPen(playOutlineCol); dc.drawRect(QRect(x, 0, fFrameWidth, clientHeight)); } }