summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/tts/qtexttospeech.cpp26
-rw-r--r--src/tts/qtexttospeech.h29
-rw-r--r--tests/auto/qtexttospeech/tst_qtexttospeech.cpp11
3 files changed, 55 insertions, 11 deletions
diff --git a/src/tts/qtexttospeech.cpp b/src/tts/qtexttospeech.cpp
index 47cad9c..bcebc46 100644
--- a/src/tts/qtexttospeech.cpp
+++ b/src/tts/qtexttospeech.cpp
@@ -9,6 +9,8 @@
#include <QtCore/qdebug.h>
#include <QtCore/private/qfactoryloader_p.h>
+#include <QtMultimedia/qaudiobuffer.h>
+
QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals;
@@ -877,8 +879,9 @@ void QTextToSpeech::synthesize(const QString &text)
This function synthesizes the speech asynchronously into raw audio data.
When data is available, the \a functor will be called as
- \c {functor(const QAudioFormat &format, const QByteArray &bytes)}, with
- \c format describing the \l {QAudioFormat}{format} of the data in \c bytes.
+ \c {functor(QAudioFormat format, QByteArray bytes)}, with \c format
+ describing the \l {QAudioFormat}{format} of the data in \c bytes;
+ or as \c {functor(QAudioBuffer &buffer)}.
The \l state property is set to \l Synthesizing when the synthesis starts,
and to \l Ready once the synthesis is finished. While synthesizing, the
@@ -923,19 +926,26 @@ void QTextToSpeech::synthesize(const QString &text)
in updateState() when the state of the engine transitions back to Ready.
*/
void QTextToSpeech::synthesizeImpl(const QString &text,
- QtPrivate::QSlotObjectBase *slotObj, const QObject *context)
+ QtPrivate::QSlotObjectBase *slotObj, const QObject *context,
+ SynthesizeOverload overload)
{
Q_D(QTextToSpeech);
Q_ASSERT(slotObj);
if (d->m_slotObject)
d->m_slotObject->destroyIfLastRef();
d->m_slotObject = slotObj;
- const auto receive = [d, context](const QAudioFormat &format, const QByteArray &bytes){
+ const auto receive = [d, context, overload](const QAudioFormat &format, const QByteArray &bytes){
Q_ASSERT(d->m_slotObject);
- void *args[] = {nullptr,
- const_cast<QAudioFormat *>(&format),
- const_cast<QByteArray *>(&bytes)};
- d->m_slotObject->call(const_cast<QObject *>(context), args);
+ if (overload == SynthesizeOverload::AudioBuffer) {
+ const QAudioBuffer buffer(bytes, format);
+ void *args[] = {nullptr, const_cast<QAudioBuffer *>(&buffer)};
+ d->m_slotObject->call(const_cast<QObject *>(context), args);
+ } else {
+ void *args[] = {nullptr,
+ const_cast<QAudioFormat *>(&format),
+ const_cast<QByteArray *>(&bytes)};
+ d->m_slotObject->call(const_cast<QObject *>(context), args);
+ }
};
d->m_synthesizeConnection = connect(d->m_engine.get(), &QTextToSpeechEngine::synthesized,
context ? context : this, receive);
diff --git a/src/tts/qtexttospeech.h b/src/tts/qtexttospeech.h
index 2b3951b..6792cf6 100644
--- a/src/tts/qtexttospeech.h
+++ b/src/tts/qtexttospeech.h
@@ -17,6 +17,7 @@
QT_BEGIN_NAMESPACE
class QAudioFormat;
+class QAudioBuffer;
class QTextToSpeechPrivate;
class Q_TEXTTOSPEECH_EXPORT QTextToSpeech : public QObject
@@ -105,8 +106,19 @@ public:
# endif // Q_QDOC
Functor &&func)
{
- using Prototype = void(*)(QAudioFormat, QByteArray);
- synthesizeImpl(text, QtPrivate::makeCallableObject<Prototype>(std::forward<Functor>(func)), receiver);
+ using Prototype2 = void(*)(QAudioFormat, QByteArray);
+ using Prototype1 = void(*)(QAudioBuffer);
+ if constexpr (qxp::is_detected_v<CompatibleCallbackTest2, Functor>) {
+ synthesizeImpl(text, QtPrivate::makeCallableObject<Prototype2>(std::forward<Functor>(func)),
+ receiver, SynthesizeOverload::AudioFormatByteArray);
+ } else if constexpr (qxp::is_detected_v<CompatibleCallbackTest1, Functor>) {
+ synthesizeImpl(text, QtPrivate::makeCallableObject<Prototype1>(std::forward<Functor>(func)),
+ receiver, SynthesizeOverload::AudioBuffer);
+ } else {
+ static_assert(QtPrivate::type_dependent_false<Functor>(),
+ "Incompatible functor signature, must be either "
+ "(QAudioFormat, QByteArray) or (QAudioBuffer)!");
+ }
}
// synthesize to a functor or function pointer (without context)
@@ -167,8 +179,19 @@ protected:
QList<QVoice> allVoices(const QLocale *locale) const;
private:
+ template <typename Functor>
+ using CompatibleCallbackTest2 = decltype(QtPrivate::makeCallableObject<void(*)(QAudioFormat, QByteArray)>(std::declval<Functor>()));
+ template <typename Functor>
+ using CompatibleCallbackTest1 = decltype(QtPrivate::makeCallableObject<void(*)(QAudioBuffer)>(std::declval<Functor>()));
+
+ enum class SynthesizeOverload {
+ AudioFormatByteArray,
+ AudioBuffer
+ };
+
void synthesizeImpl(const QString &text,
- QtPrivate::QSlotObjectBase *slotObj, const QObject *context);
+ QtPrivate::QSlotObjectBase *slotObj, const QObject *context,
+ SynthesizeOverload overload);
// Helper type to find the index of a type in a tuple, which allows
// us to generate a compile-time error if there are multiple criteria
diff --git a/tests/auto/qtexttospeech/tst_qtexttospeech.cpp b/tests/auto/qtexttospeech/tst_qtexttospeech.cpp
index 701effe..317c683 100644
--- a/tests/auto/qtexttospeech/tst_qtexttospeech.cpp
+++ b/tests/auto/qtexttospeech/tst_qtexttospeech.cpp
@@ -8,6 +8,7 @@
#include <QMediaDevices>
#include <QAudioFormat>
#include <QAudioDevice>
+#include <QAudioBuffer>
#include <QOperatingSystemVersion>
#include <QRegularExpression>
#include <qttexttospeech-config.h>
@@ -1063,6 +1064,16 @@ void tst_QTextToSpeech::synthesizeCallback()
QTRY_COMPARE(tts.state(), QTextToSpeech::Ready);
QCOMPARE(processor.m_allBytes, QByteArray());
processor.reset();
+
+ // Taking QAudioBuffer
+ tts.synthesize(text, [&processor](const QAudioBuffer &buffer) {
+ processor.m_format = buffer.format();
+ processor.m_allBytes += QByteArrayView(buffer.data<uchar>(), buffer.byteCount());
+ });
+ QTRY_COMPARE(processor.m_format, expectedFormat);
+ QTRY_COMPARE(tts.state(), QTextToSpeech::Ready);
+ QCOMPARE(processor.m_allBytes, expectedBytes);
+ processor.reset();
}
QTEST_MAIN(tst_QTextToSpeech)