summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVolker Hilsheimer <volker.hilsheimer@qt.io>2023-11-10 00:39:03 +0200
committerVolker Hilsheimer <volker.hilsheimer@qt.io>2023-11-10 08:17:38 +0200
commit5e4bc89c7606bf958f3b55d09c872dcf360e9c56 (patch)
treeca01c1fc4d33d7406d975db2a49f2f27364e3c0b
parent8f9c4efb11aaaae2c3c0a456aaeec99244c26308 (diff)
WinRT: implement boundary hint support in pause
Look for the next matching boundary, which stores its starting time. Calculate the corresponding byte using QAudioFormat, then cut the delivery of data off when we reach the matching byte. In case of immediate pause, suspend the sink immediately. The default is unchanged: we search for silence in the current chunk of data. Implementing boundary support for stop() might come later. Pick-to: 6.6 Change-Id: I2b4cf06dbf8e2c55321a5364d2366c255d9e9afe Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
-rw-r--r--src/plugins/tts/winrt/qtexttospeech_winrt.cpp36
-rw-r--r--src/plugins/tts/winrt/qtexttospeech_winrt_audiosource.cpp22
-rw-r--r--src/plugins/tts/winrt/qtexttospeech_winrt_audiosource.h6
3 files changed, 59 insertions, 5 deletions
diff --git a/src/plugins/tts/winrt/qtexttospeech_winrt.cpp b/src/plugins/tts/winrt/qtexttospeech_winrt.cpp
index 61f665f..dd8e78a 100644
--- a/src/plugins/tts/winrt/qtexttospeech_winrt.cpp
+++ b/src/plugins/tts/winrt/qtexttospeech_winrt.cpp
@@ -548,11 +548,41 @@ void QTextToSpeechEngineWinRT::stop(QTextToSpeech::BoundaryHint boundaryHint)
void QTextToSpeechEngineWinRT::pause(QTextToSpeech::BoundaryHint boundaryHint)
{
- Q_UNUSED(boundaryHint);
Q_D(QTextToSpeechEngineWinRT);
- if (d->audioSource)
- d->audioSource->pause();
+ if (!d->audioSource)
+ return;
+
+ auto pauseBoundaryType = AudioSource::Boundary::Unknown;
+ switch (boundaryHint) {
+ case QTextToSpeech::BoundaryHint::Default:
+ d->audioSource->pause(0);
+ return;
+ case QTextToSpeech::BoundaryHint::Immediate:
+ d->audioSource->pause(0);
+ if (d->audioSink)
+ d->audioSink->suspend();
+ return;
+ case QTextToSpeech::BoundaryHint::Word:
+ pauseBoundaryType = AudioSource::Boundary::Word;
+ break;
+ case QTextToSpeech::BoundaryHint::Sentence:
+ pauseBoundaryType = AudioSource::Boundary::Sentence;
+ break;
+ case QTextToSpeech::BoundaryHint::Utterance:
+ // taken care off by engine-independent implementation
+ return;
+ }
+
+ // find the next boundary of the matching type
+ const auto nextBoundary = std::find_if(d->currentBoundary + 1, d->boundaries.constEnd(),
+ [pauseBoundaryType](auto &&it){
+ return it.type == pauseBoundaryType;
+ });
+ if (nextBoundary != d->boundaries.constEnd()) {
+ d->audioSource->pause(d->audioSource->format()
+ .bytesForDuration(nextBoundary->startTime));
+ }
}
void QTextToSpeechEngineWinRT::resume()
diff --git a/src/plugins/tts/winrt/qtexttospeech_winrt_audiosource.cpp b/src/plugins/tts/winrt/qtexttospeech_winrt_audiosource.cpp
index c1c198f..51d3505 100644
--- a/src/plugins/tts/winrt/qtexttospeech_winrt_audiosource.cpp
+++ b/src/plugins/tts/winrt/qtexttospeech_winrt_audiosource.cpp
@@ -136,7 +136,23 @@ qint64 AudioSource::readData(char *data, qint64 maxlen)
break;
case PauseRequested: {
Q_ASSERT(audioFormat.sampleFormat() == QAudioFormat::Int16);
- // we are dealing with artificially created sound, so we don't have
+
+ if (m_pauseRequestedAt) {
+ if (m_pauseRequestedAt <= m_bytesRead) {
+ // we missed the window, pause immediately
+ maxlen = 0;
+ } else if (m_pauseRequestedAt <= m_bytesRead + maxlen) {
+ maxlen = qMax(quint64(0), m_pauseRequestedAt - m_bytesRead) + 44;
+ } else {
+ // wait for the next chunk
+ break;
+ }
+ m_pause = Paused;
+ m_pauseRequestedAt = 0;
+ break;
+ }
+ // If no byte to pause at is specified, look for silence in the current
+ // chunk. We are dealing with artificially created sound, so we don't have
// to find a large enough window with overall low energy; we can just
// look for a series (e.g. 1/50th of a second) of samples with low
// absolute values.
@@ -165,6 +181,9 @@ qint64 AudioSource::readData(char *data, qint64 maxlen)
silenceCount = 0;
}
}
+ // no silence found - stop after this chunk
+ if (m_pause != Paused)
+ m_pause = Paused;
break;
}
case Paused:
@@ -184,6 +203,7 @@ qint64 AudioSource::readData(char *data, qint64 maxlen)
else
m_bufferOffset += maxlen;
+ m_bytesRead += maxlen;
return maxlen;
}
diff --git a/src/plugins/tts/winrt/qtexttospeech_winrt_audiosource.h b/src/plugins/tts/winrt/qtexttospeech_winrt_audiosource.h
index 79fdf16..da6e901 100644
--- a/src/plugins/tts/winrt/qtexttospeech_winrt_audiosource.h
+++ b/src/plugins/tts/winrt/qtexttospeech_winrt_audiosource.h
@@ -51,14 +51,16 @@ public:
Paused
} m_pause = NoPause;
- void pause()
+ void pause(quint64 atByte)
{
m_pause = PauseRequested;
+ m_pauseRequestedAt = atByte;
}
void resume()
{
m_pause = NoPause;
+ m_pauseRequestedAt = 0;
if (bytesAvailable())
emit readyRead();
}
@@ -126,6 +128,8 @@ private:
UINT32 m_bufferOffset = 0;
// RIFF header has been checked at the beginning of the stream
bool m_riffHeaderChecked = false;
+ quint64 m_bytesRead = 0;
+ quint64 m_pauseRequestedAt = 0;
void populateBoundaries();
QList<Boundary> boundaries;