summaryrefslogtreecommitdiffstats
path: root/src/multimedia/audio/qaudiosource.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/multimedia/audio/qaudiosource.cpp')
-rw-r--r--src/multimedia/audio/qaudiosource.cpp369
1 files changed, 369 insertions, 0 deletions
diff --git a/src/multimedia/audio/qaudiosource.cpp b/src/multimedia/audio/qaudiosource.cpp
new file mode 100644
index 000000000..1ed5e82bc
--- /dev/null
+++ b/src/multimedia/audio/qaudiosource.cpp
@@ -0,0 +1,369 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+
+#include "qaudio.h"
+#include "qaudiodevice.h"
+#include "qaudiosystem_p.h"
+#include "qaudiosource.h"
+
+#include <private/qplatformmediadevices_p.h>
+#include <private/qplatformmediaintegration_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QAudioSource
+ \brief The QAudioSource class provides an interface for receiving audio data from an audio input device.
+
+ \inmodule QtMultimedia
+ \ingroup multimedia
+ \ingroup multimedia_audio
+
+ You can construct an audio input with the system's
+ default audio input device. It is also possible to
+ create QAudioSource with a specific QAudioDevice. When
+ you create the audio input, you should also send in the
+ QAudioFormat to be used for the recording (see the QAudioFormat
+ class description for details).
+
+ To record to a file:
+
+ QAudioSource lets you record audio with an audio input device. The
+ default constructor of this class will use the systems default
+ audio device, but you can also specify a QAudioDevice for a
+ specific device. You also need to pass in the QAudioFormat in
+ which you wish to record.
+
+ Starting up the QAudioSource is simply a matter of calling start()
+ with a QIODevice opened for writing. For instance, to record to a
+ file, you can:
+
+ \snippet multimedia-snippets/audio.cpp Audio input class members
+
+ \snippet multimedia-snippets/audio.cpp Audio input setup
+
+ This will start recording if the format specified is supported by
+ the input device (you can check this with
+ QAudioDevice::isFormatSupported(). In case there are any
+ snags, use the error() function to check what went wrong. We stop
+ recording in the \c stopRecording() slot.
+
+ \snippet multimedia-snippets/audio.cpp Audio input stop recording
+
+ At any point in time, QAudioSource will be in one of four states:
+ active, suspended, stopped, or idle. These states are specified by
+ the QtAudio::State enum. You can request a state change directly through
+ suspend(), resume(), stop(), reset(), and start(). The current
+ state is reported by state(). QAudioSink will also signal you
+ when the state changes (stateChanged()).
+
+ QAudioSource provides several ways of measuring the time that has
+ passed since the start() of the recording. The \c processedUSecs()
+ function returns the length of the stream in microseconds written,
+ i.e., it leaves out the times the audio input was suspended or idle.
+ The elapsedUSecs() function returns the time elapsed since start() was called regardless of
+ which states the QAudioSource has been in.
+
+ If an error should occur, you can fetch its reason with error().
+ The possible error reasons are described by the QtAudio::Error
+ enum. The QAudioSource will enter the \l{QtAudio::}{StoppedState} when
+ an error is encountered. Connect to the stateChanged() signal to
+ handle the error:
+
+ \snippet multimedia-snippets/audio.cpp Audio input state changed
+
+ \sa QAudioSink, QAudioDevice
+*/
+
+/*!
+ Construct a new audio input and attach it to \a parent.
+ The default audio input device is used with the output
+ \a format parameters.
+*/
+
+QAudioSource::QAudioSource(const QAudioFormat &format, QObject *parent)
+ : QAudioSource({}, format, parent)
+{
+}
+
+/*!
+ Construct a new audio input and attach it to \a parent.
+ The device referenced by \a audioDevice is used with the input
+ \a format parameters.
+*/
+
+QAudioSource::QAudioSource(const QAudioDevice &audioDevice, const QAudioFormat &format, QObject *parent):
+ QObject(parent)
+{
+ d = QPlatformMediaIntegration::instance()->mediaDevices()->audioInputDevice(format, audioDevice, parent);
+ if (d) {
+ connect(d, &QPlatformAudioSource::stateChanged, this, [this](QAudio::State state) {
+ // if the signal has been emitted from another thread,
+ // the state may be already changed by main one
+ if (state == d->state())
+ emit stateChanged(state);
+ });
+ }
+ else
+ qWarning() << ("No audio device detected");
+
+}
+
+/*!
+ \fn bool QAudioSource::isNull() const
+
+ Returns \c true if the audio source is \c null, otherwise returns \c false.
+*/
+
+/*!
+ Destroy this audio input.
+*/
+
+QAudioSource::~QAudioSource()
+{
+ delete d;
+}
+
+/*!
+ Starts transferring audio data from the system's audio input to the \a device.
+ The \a device must have been opened in the \l{QIODevice::WriteOnly}{WriteOnly},
+ \l{QIODevice::Append}{Append} or \l{QIODevice::ReadWrite}{ReadWrite} modes.
+
+ If the QAudioSource is able to successfully get audio data, state() returns
+ either QtAudio::ActiveState or QtAudio::IdleState, error() returns QtAudio::NoError
+ and the stateChanged() signal is emitted.
+
+ If a problem occurs during this process, error() returns QtAudio::OpenError,
+ state() returns QtAudio::StoppedState and the stateChanged() signal is emitted.
+
+ \sa QIODevice
+*/
+
+void QAudioSource::start(QIODevice* device)
+{
+ if (!d)
+ return;
+ d->elapsedTime.start();
+ d->start(device);
+}
+
+/*!
+ Returns a pointer to the internal QIODevice being used to transfer data from
+ the system's audio input. The device will already be open and
+ \l{QIODevice::read()}{read()} can read data directly from it.
+
+ \note The pointer will become invalid after the stream is stopped or
+ if you start another stream.
+
+ If the QAudioSource is able to access the system's audio device, state() returns
+ QtAudio::IdleState, error() returns QtAudio::NoError
+ and the stateChanged() signal is emitted.
+
+ If a problem occurs during this process, error() returns QtAudio::OpenError,
+ state() returns QtAudio::StoppedState and the stateChanged() signal is emitted.
+
+ \sa QIODevice
+*/
+
+QIODevice* QAudioSource::start()
+{
+ if (!d)
+ return nullptr;
+ d->elapsedTime.start();
+ return d->start();
+}
+
+/*!
+ Returns the QAudioFormat being used.
+*/
+
+QAudioFormat QAudioSource::format() const
+{
+ return d ? d->format() : QAudioFormat();
+}
+
+/*!
+ Stops the audio input, detaching from the system resource.
+
+ Sets error() to QtAudio::NoError, state() to QtAudio::StoppedState and
+ emit stateChanged() signal.
+*/
+
+void QAudioSource::stop()
+{
+ if (d)
+ d->stop();
+}
+
+/*!
+ Drops all audio data in the buffers, resets buffers to zero.
+*/
+
+void QAudioSource::reset()
+{
+ if (d)
+ d->reset();
+}
+
+/*!
+ Stops processing audio data, preserving buffered audio data.
+
+ Sets error() to QtAudio::NoError, state() to QtAudio::SuspendedState and
+ emit stateChanged() signal.
+*/
+
+void QAudioSource::suspend()
+{
+ if (d)
+ d->suspend();
+}
+
+/*!
+ Resumes processing audio data after a suspend().
+
+ Sets error() to QtAudio::NoError.
+ Sets state() to QtAudio::ActiveState if you previously called start(QIODevice*).
+ Sets state() to QtAudio::IdleState if you previously called start().
+ emits stateChanged() signal.
+*/
+
+void QAudioSource::resume()
+{
+ if (d)
+ d->resume();
+}
+
+/*!
+ Sets the audio buffer size to \a value bytes.
+
+ Note: This function can be called anytime before start(), calls to this
+ are ignored after start(). It should not be assumed that the buffer size
+ set is the actual buffer size used, calling bufferSize() anytime after start()
+ will return the actual buffer size being used.
+
+*/
+
+void QAudioSource::setBufferSize(qsizetype value)
+{
+ if (d)
+ d->setBufferSize(value);
+}
+
+/*!
+ Returns the audio buffer size in bytes.
+
+ If called before start(), returns platform default value.
+ If called before start() but setBufferSize() was called prior, returns value set by setBufferSize().
+ If called after start(), returns the actual buffer size being used. This may not be what was set previously
+ by setBufferSize().
+
+*/
+
+qsizetype QAudioSource::bufferSize() const
+{
+ return d ? d->bufferSize() : 0;
+}
+
+/*!
+ Returns the amount of audio data available to read in bytes.
+
+ Note: returned value is only valid while in QtAudio::ActiveState or QtAudio::IdleState
+ state, otherwise returns zero.
+*/
+
+qsizetype QAudioSource::bytesAvailable() const
+{
+ /*
+ -If not ActiveState|IdleState, return 0
+ -return amount of audio data available to read
+ */
+ return d ? d->bytesReady() : 0;
+}
+
+/*!
+ Sets the input volume to \a volume.
+
+ The volume is scaled linearly from \c 0.0 (silence) to \c 1.0 (full volume). Values outside this
+ range will be clamped.
+
+ If the device does not support adjusting the input
+ volume then \a volume will be ignored and the input
+ volume will remain at 1.0.
+
+ The default volume is \c 1.0.
+
+ Note: Adjustments to the volume will change the volume of this audio stream, not the global volume.
+*/
+void QAudioSource::setVolume(qreal volume)
+{
+ if (!d)
+ return;
+ qreal v = qBound(qreal(0.0), volume, qreal(1.0));
+ d->setVolume(v);
+}
+
+/*!
+ Returns the input volume.
+
+ If the device does not support adjusting the input volume
+ the returned value will be 1.0.
+*/
+qreal QAudioSource::volume() const
+{
+ return d ? d->volume() : 1.0;
+}
+
+/*!
+ Returns the amount of audio data processed since start()
+ was called in microseconds.
+*/
+
+qint64 QAudioSource::processedUSecs() const
+{
+ return d ? d->processedUSecs() : 0;
+}
+
+/*!
+ Returns the microseconds since start() was called, including time in Idle and
+ Suspend states.
+*/
+
+#include <qdebug.h>
+
+qint64 QAudioSource::elapsedUSecs() const
+{
+ return state() == QAudio::StoppedState ? 0 : d->elapsedTime.nsecsElapsed()/1000;
+}
+
+/*!
+ Returns the error state.
+*/
+
+QtAudio::Error QAudioSource::error() const
+{
+ return d ? d->error() : QAudio::OpenError;
+}
+
+/*!
+ Returns the state of audio processing.
+*/
+
+QtAudio::State QAudioSource::state() const
+{
+ return d ? d->state() : QAudio::StoppedState;
+}
+
+/*!
+ \fn QAudioSource::stateChanged(QtAudio::State state)
+ This signal is emitted when the device \a state has changed.
+
+ \note The QtAudio namespace was named QAudio up to and including Qt 6.6.
+ String-based connections to this signal have to use \c{QAudio::State} as
+ the parameter type: \c{connect(source, SIGNAL(stateChanged(QAudio::State)), ...);}
+*/
+
+QT_END_NAMESPACE
+
+#include "moc_qaudiosource.cpp"
+