Text to speech engine - finishing

This commit is contained in:
Jakub Melka
2020-02-20 19:25:32 +01:00
parent 44889cfcb8
commit 5823df0443
4 changed files with 93 additions and 43 deletions

View File

@ -108,7 +108,9 @@ PDFSidebarWidget::PDFSidebarWidget(pdf::PDFDrawWidgetProxy* proxy, PDFTextToSpee
m_textToSpeech->initializeUI(ui->speechLocaleComboBox, ui->speechVoiceComboBox, m_textToSpeech->initializeUI(ui->speechLocaleComboBox, ui->speechVoiceComboBox,
ui->speechRateEdit, ui->speechPitchEdit, ui->speechVolumeEdit, ui->speechRateEdit, ui->speechPitchEdit, ui->speechVolumeEdit,
ui->speechPlayButton, ui->speechPauseButton, ui->speechStopButton, ui->speechSynchronizeButton); ui->speechPlayButton, ui->speechPauseButton, ui->speechStopButton, ui->speechSynchronizeButton,
ui->speechRateValueLabel, ui->speechPitchValueLabel, ui->speechVolumeValueLabel,
ui->speechActualTextEdit);
selectPage(Invalid); selectPage(Invalid);
updateButtons(); updateButtons();

View File

@ -274,16 +274,10 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="2" column="0">
<widget class="QSlider" name="speechVolumeEdit"> <widget class="QLabel" name="speechVolumeLabel">
<property name="maximum"> <property name="text">
<number>100</number> <string>Volume</string>
</property>
<property name="value">
<number>100</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property> </property>
</widget> </widget>
</item> </item>
@ -300,13 +294,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="0">
<widget class="QLabel" name="speechRateLabel">
<property name="text">
<string>Rate</string>
</property>
</widget>
</item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QLabel" name="speechPitchLabel"> <widget class="QLabel" name="speechPitchLabel">
<property name="text"> <property name="text">
@ -314,13 +301,35 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0"> <item row="2" column="1">
<widget class="QLabel" name="speechVolumeLabel"> <widget class="QSlider" name="speechVolumeEdit">
<property name="text"> <property name="maximum">
<string>Volume</string> <number>100</number>
</property>
<property name="value">
<number>100</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="0">
<widget class="QLabel" name="speechRateLabel">
<property name="text">
<string>Rate</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="speechRateValueLabel"/>
</item>
<item row="1" column="2">
<widget class="QLabel" name="speechPitchValueLabel"/>
</item>
<item row="2" column="2">
<widget class="QLabel" name="speechVolumeValueLabel"/>
</item>
</layout> </layout>
</item> </item>
<item> <item>
@ -368,22 +377,18 @@
<iconset resource="pdfforqtviewer.qrc"> <iconset resource="pdfforqtviewer.qrc">
<normaloff>:/resources/synchronize.svg</normaloff>:/resources/synchronize.svg</iconset> <normaloff>:/resources/synchronize.svg</normaloff>:/resources/synchronize.svg</iconset>
</property> </property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget> </widget>
</item> </item>
</layout> </layout>
</item> </item>
<item> <item>
<spacer name="verticalSpacer"> <widget class="QTextBrowser" name="speechActualTextEdit"/>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>393</height>
</size>
</property>
</spacer>
</item> </item>
</layout> </layout>
</widget> </widget>

View File

@ -21,10 +21,12 @@
#include "pdfcompiler.h" #include "pdfcompiler.h"
#include "pdfdrawwidget.h" #include "pdfdrawwidget.h"
#include <QLabel>
#include <QAction> #include <QAction>
#include <QSlider> #include <QSlider>
#include <QComboBox> #include <QComboBox>
#include <QToolButton> #include <QToolButton>
#include <QTextBrowser>
#include <QTextToSpeech> #include <QTextToSpeech>
namespace pdfviewer namespace pdfviewer
@ -45,7 +47,11 @@ PDFTextToSpeech::PDFTextToSpeech(QObject* parent) :
m_speechPlayButton(nullptr), m_speechPlayButton(nullptr),
m_speechPauseButton(nullptr), m_speechPauseButton(nullptr),
m_speechStopButton(nullptr), m_speechStopButton(nullptr),
m_speechSynchronizeButton(nullptr) m_speechSynchronizeButton(nullptr),
m_speechRateValueLabel(nullptr),
m_speechPitchValueLabel(nullptr),
m_speechVolumeValueLabel(nullptr),
m_speechActualTextBrowser(nullptr)
{ {
} }
@ -138,7 +144,7 @@ void PDFTextToSpeech::setSettings(const PDFViewerSettings* viewerSettings)
updateUI(); updateUI();
} }
void PDFTextToSpeech::setProxy(const pdf::PDFDrawWidgetProxy* proxy) void PDFTextToSpeech::setProxy(pdf::PDFDrawWidgetProxy* proxy)
{ {
m_proxy = proxy; m_proxy = proxy;
pdf::PDFAsynchronousTextLayoutCompiler* compiler = m_proxy->getTextLayoutCompiler(); pdf::PDFAsynchronousTextLayoutCompiler* compiler = m_proxy->getTextLayoutCompiler();
@ -153,7 +159,11 @@ void PDFTextToSpeech::initializeUI(QComboBox* speechLocaleComboBox,
QToolButton* speechPlayButton, QToolButton* speechPlayButton,
QToolButton* speechPauseButton, QToolButton* speechPauseButton,
QToolButton* speechStopButton, QToolButton* speechStopButton,
QToolButton* speechSynchronizeButton) QToolButton* speechSynchronizeButton,
QLabel* speechRateValueLabel,
QLabel* speechPitchValueLabel,
QLabel* speechVolumeValueLabel,
QTextBrowser* speechActualTextBrowser)
{ {
Q_ASSERT(speechLocaleComboBox); Q_ASSERT(speechLocaleComboBox);
Q_ASSERT(speechVoiceComboBox); Q_ASSERT(speechVoiceComboBox);
@ -174,6 +184,10 @@ void PDFTextToSpeech::initializeUI(QComboBox* speechLocaleComboBox,
m_speechPauseButton = speechPauseButton; m_speechPauseButton = speechPauseButton;
m_speechStopButton = speechStopButton; m_speechStopButton = speechStopButton;
m_speechSynchronizeButton = speechSynchronizeButton; m_speechSynchronizeButton = speechSynchronizeButton;
m_speechRateValueLabel = speechRateValueLabel;
m_speechPitchValueLabel = speechPitchValueLabel;
m_speechVolumeValueLabel = speechVolumeValueLabel;
m_speechActualTextBrowser = speechActualTextBrowser;
connect(m_speechLocaleComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &PDFTextToSpeech::onLocaleChanged); connect(m_speechLocaleComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &PDFTextToSpeech::onLocaleChanged);
connect(m_speechVoiceComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &PDFTextToSpeech::onVoiceChanged); connect(m_speechVoiceComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &PDFTextToSpeech::onVoiceChanged);
@ -303,18 +317,21 @@ void PDFTextToSpeech::setRate(const double rate)
{ {
pdf::PDFLinearInterpolation<double> interpolation(-1.0, 1.0, m_speechRateEdit->minimum(), m_speechRateEdit->maximum()); pdf::PDFLinearInterpolation<double> interpolation(-1.0, 1.0, m_speechRateEdit->minimum(), m_speechRateEdit->maximum());
m_speechRateEdit->setValue(qRound(interpolation(rate))); m_speechRateEdit->setValue(qRound(interpolation(rate)));
onRateChanged(m_speechRateEdit->value());
} }
void PDFTextToSpeech::setPitch(const double pitch) void PDFTextToSpeech::setPitch(const double pitch)
{ {
pdf::PDFLinearInterpolation<double> interpolation(-1.0, 1.0, m_speechPitchEdit->minimum(), m_speechPitchEdit->maximum()); pdf::PDFLinearInterpolation<double> interpolation(-1.0, 1.0, m_speechPitchEdit->minimum(), m_speechPitchEdit->maximum());
m_speechPitchEdit->setValue(qRound(interpolation(pitch))); m_speechPitchEdit->setValue(qRound(interpolation(pitch)));
onPitchChanged(m_speechPitchEdit->value());
} }
void PDFTextToSpeech::setVolume(const double volume) void PDFTextToSpeech::setVolume(const double volume)
{ {
pdf::PDFLinearInterpolation<double> interpolation(0.0, 1.0, m_speechVolumeEdit->minimum(), m_speechVolumeEdit->maximum()); pdf::PDFLinearInterpolation<double> interpolation(0.0, 1.0, m_speechVolumeEdit->minimum(), m_speechVolumeEdit->maximum());
m_speechVolumeEdit->setValue(qRound(interpolation(volume))); m_speechVolumeEdit->setValue(qRound(interpolation(volume)));
onVolumeChanged(m_speechVolumeEdit->value());
} }
void PDFTextToSpeech::onLocaleChanged() void PDFTextToSpeech::onLocaleChanged()
@ -345,7 +362,9 @@ void PDFTextToSpeech::onRateChanged(int rate)
if (m_textToSpeech) if (m_textToSpeech)
{ {
pdf::PDFLinearInterpolation<double> interpolation(m_speechRateEdit->minimum(), m_speechRateEdit->maximum(), -1.0, 1.0); pdf::PDFLinearInterpolation<double> interpolation(m_speechRateEdit->minimum(), m_speechRateEdit->maximum(), -1.0, 1.0);
m_textToSpeech->setRate(interpolation(rate)); double value = interpolation(rate);
m_textToSpeech->setRate(value);
m_speechRateValueLabel->setText(QString::number(value, 'f', 2));
} }
} }
@ -354,7 +373,9 @@ void PDFTextToSpeech::onPitchChanged(int pitch)
if (m_textToSpeech) if (m_textToSpeech)
{ {
pdf::PDFLinearInterpolation<double> interpolation(m_speechPitchEdit->minimum(), m_speechPitchEdit->maximum(), -1.0, 1.0); pdf::PDFLinearInterpolation<double> interpolation(m_speechPitchEdit->minimum(), m_speechPitchEdit->maximum(), -1.0, 1.0);
m_textToSpeech->setPitch(interpolation(pitch)); double value = interpolation(pitch);
m_textToSpeech->setPitch(pitch);
m_speechPitchValueLabel->setText(QString::number(value, 'f', 2));
} }
} }
@ -363,7 +384,9 @@ void PDFTextToSpeech::onVolumeChanged(int volume)
if (m_textToSpeech) if (m_textToSpeech)
{ {
pdf::PDFLinearInterpolation<double> interpolation(m_speechVolumeEdit->minimum(), m_speechVolumeEdit->maximum(), 0.0, 1.0); pdf::PDFLinearInterpolation<double> interpolation(m_speechVolumeEdit->minimum(), m_speechVolumeEdit->maximum(), 0.0, 1.0);
m_textToSpeech->setVolume(interpolation(volume)); double value = interpolation(volume);
m_textToSpeech->setVolume(value);
m_speechVolumeValueLabel->setText(QString::number(value, 'f', 2));
} }
} }
@ -375,7 +398,10 @@ void PDFTextToSpeech::onPlayClicked()
{ {
m_textToSpeech->resume(); m_textToSpeech->resume();
m_state = Playing; m_state = Playing;
updatePlay(); if (m_textToSpeech->state() == QTextToSpeech::Ready)
{
updatePlay();
}
break; break;
} }
@ -452,6 +478,7 @@ void PDFTextToSpeech::updatePlay()
const pdf::PDFTextFlow& textFlow = m_textFlows[m_currentTextFlowIndex]; const pdf::PDFTextFlow& textFlow = m_textFlows[m_currentTextFlowIndex];
QString text = textFlow.getText(); QString text = textFlow.getText();
m_textToSpeech->say(text); m_textToSpeech->say(text);
m_speechActualTextBrowser->setText(text);
} }
else else
{ {
@ -480,6 +507,7 @@ void PDFTextToSpeech::updateToNextPage(pdf::PDFInteger pageIndex)
m_currentTextLayout = pdf::PDFTextLayout(); m_currentTextLayout = pdf::PDFTextLayout();
m_textFlows.clear(); m_textFlows.clear();
m_speechActualTextBrowser->clear();
// Find first nonempty page // Find first nonempty page
while (m_currentPage < pageCount) while (m_currentPage < pageCount)
@ -495,6 +523,11 @@ void PDFTextToSpeech::updateToNextPage(pdf::PDFInteger pageIndex)
++m_currentPage; ++m_currentPage;
} }
if (m_currentPage < pageCount && m_speechSynchronizeButton->isChecked())
{
m_proxy->goToPage(m_currentPage);
}
m_currentTextFlowIndex = 0; m_currentTextFlowIndex = 0;
} }

View File

@ -23,9 +23,11 @@
#include <QObject> #include <QObject>
class QLabel;
class QSlider; class QSlider;
class QComboBox; class QComboBox;
class QToolButton; class QToolButton;
class QTextBrowser;
class QTextToSpeech; class QTextToSpeech;
namespace pdf namespace pdf
@ -70,7 +72,7 @@ public:
void setSettings(const PDFViewerSettings* viewerSettings); void setSettings(const PDFViewerSettings* viewerSettings);
/// Set draw proxy /// Set draw proxy
void setProxy(const pdf::PDFDrawWidgetProxy* proxy); void setProxy(pdf::PDFDrawWidgetProxy* proxy);
/// Initialize the ui, which is used /// Initialize the ui, which is used
void initializeUI(QComboBox* speechLocaleComboBox, void initializeUI(QComboBox* speechLocaleComboBox,
@ -81,7 +83,11 @@ public:
QToolButton* speechPlayButton, QToolButton* speechPlayButton,
QToolButton* speechPauseButton, QToolButton* speechPauseButton,
QToolButton* speechStopButton, QToolButton* speechStopButton,
QToolButton* speechSynchronizeButton); QToolButton* speechSynchronizeButton,
QLabel* speechRateValueLabel,
QLabel* speechPitchValueLabel,
QLabel* speechVolumeValueLabel,
QTextBrowser* speechActualTextBrowser);
private: private:
/// Updates UI controls depending on the state /// Updates UI controls depending on the state
@ -111,7 +117,7 @@ private:
QTextToSpeech* m_textToSpeech; QTextToSpeech* m_textToSpeech;
const pdf::PDFDocument* m_document; const pdf::PDFDocument* m_document;
const pdf::PDFDrawWidgetProxy* m_proxy; pdf::PDFDrawWidgetProxy* m_proxy;
State m_state; State m_state;
bool m_initialized; bool m_initialized;
@ -124,6 +130,10 @@ private:
QToolButton* m_speechPauseButton; QToolButton* m_speechPauseButton;
QToolButton* m_speechStopButton; QToolButton* m_speechStopButton;
QToolButton* m_speechSynchronizeButton; QToolButton* m_speechSynchronizeButton;
QLabel* m_speechRateValueLabel;
QLabel* m_speechPitchValueLabel;
QLabel* m_speechVolumeValueLabel;
QTextBrowser* m_speechActualTextBrowser;
pdf::PDFTextLayout m_currentTextLayout; ///< Text layout for actual page pdf::PDFTextLayout m_currentTextLayout; ///< Text layout for actual page
pdf::PDFTextFlows m_textFlows; ///< Text flows for actual page pdf::PDFTextFlows m_textFlows; ///< Text flows for actual page