1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4
5#include "qaudio.h"
6#include "qaudiodevice.h"
7#include "qaudiosystem_p.h"
8#include "qaudiosource.h"
9
10#include <private/qplatformaudiodevices_p.h>
11#include <private/qplatformmediaintegration_p.h>
12
13QT_BEGIN_NAMESPACE
14
15/*!
16 \class QAudioSource
17 \brief The QAudioSource class provides an interface for receiving audio data from an audio input device.
18
19 \inmodule QtMultimedia
20 \ingroup multimedia
21 \ingroup multimedia_audio
22
23 You can construct an audio input with the system's
24 default audio input device. It is also possible to
25 create QAudioSource with a specific QAudioDevice. When
26 you create the audio input, you should also send in the
27 QAudioFormat to be used for the recording (see the QAudioFormat
28 class description for details).
29
30 To record to a file:
31
32 QAudioSource lets you record audio with an audio input device. The
33 default constructor of this class will use the systems default
34 audio device, but you can also specify a QAudioDevice for a
35 specific device. You also need to pass in the QAudioFormat in
36 which you wish to record.
37
38 Starting up the QAudioSource is simply a matter of calling start()
39 with a QIODevice opened for writing. For instance, to record to a
40 file, you can:
41
42 \snippet multimedia-snippets/audio.cpp Audio input class members
43
44 \snippet multimedia-snippets/audio.cpp Audio input setup
45
46 This will start recording if the format specified is supported by
47 the input device (you can check this with
48 QAudioDevice::isFormatSupported(). In case there are any
49 snags, use the error() function to check what went wrong. We stop
50 recording in the \c stopRecording() slot.
51
52 \snippet multimedia-snippets/audio.cpp Audio input stop recording
53
54 At any point in time, QAudioSource will be in one of four states:
55 active, suspended, stopped, or idle. These states are specified by
56 the QtAudio::State enum. You can request a state change directly through
57 suspend(), resume(), stop(), reset(), and start(). The current
58 state is reported by state(). QAudioSink will also signal you
59 when the state changes (stateChanged()).
60
61 QAudioSource provides several ways of measuring the time that has
62 passed since the start() of the recording. The \c processedUSecs()
63 function returns the length of the stream in microseconds written,
64 i.e., it leaves out the times the audio input was suspended or idle.
65 The elapsedUSecs() function returns the time elapsed since start() was called regardless of
66 which states the QAudioSource has been in.
67
68 If an error should occur, you can fetch its reason with error().
69 The possible error reasons are described by the QtAudio::Error
70 enum. The QAudioSource will enter the \l{QtAudio::}{StoppedState} when
71 an error is encountered. Connect to the stateChanged() signal to
72 handle the error:
73
74 \snippet multimedia-snippets/audio.cpp Audio input state changed
75
76 \sa QAudioSink, QAudioDevice
77*/
78
79/*!
80 Construct a new audio input and attach it to \a parent.
81 The default audio input device is used with the output
82 \a format parameters.
83*/
84
85QAudioSource::QAudioSource(const QAudioFormat &format, QObject *parent)
86 : QAudioSource({}, format, parent)
87{
88}
89
90/*!
91 Construct a new audio input and attach it to \a parent.
92 The device referenced by \a audioDevice is used with the input
93 \a format parameters.
94*/
95
96QAudioSource::QAudioSource(const QAudioDevice &audioDevice, const QAudioFormat &format, QObject *parent):
97 QObject(parent)
98{
99 d = QPlatformMediaIntegration::instance()->audioDevices()->audioInputDevice(format, deviceInfo: audioDevice, parent);
100 if (d) {
101 connect(sender: d, signal: &QPlatformAudioSource::stateChanged, context: this, slot: [this](QAudio::State state) {
102 // if the signal has been emitted from another thread,
103 // the state may be already changed by main one
104 if (state == d->state())
105 emit stateChanged(state);
106 });
107 }
108 else
109 qWarning() << ("No audio device detected");
110
111}
112
113/*!
114 \fn bool QAudioSource::isNull() const
115
116 Returns \c true if the audio source is \c null, otherwise returns \c false.
117*/
118
119/*!
120 Destroy this audio input.
121*/
122
123QAudioSource::~QAudioSource()
124{
125 delete d;
126}
127
128/*!
129 Starts transferring audio data from the system's audio input to the \a device.
130 The \a device must have been opened in the \l{QIODevice::WriteOnly}{WriteOnly},
131 \l{QIODevice::Append}{Append} or \l{QIODevice::ReadWrite}{ReadWrite} modes.
132
133 If the QAudioSource is able to successfully get audio data, state() returns
134 either QtAudio::ActiveState or QtAudio::IdleState, error() returns QtAudio::NoError
135 and the stateChanged() signal is emitted.
136
137 If a problem occurs during this process, error() returns QtAudio::OpenError,
138 state() returns QtAudio::StoppedState and the stateChanged() signal is emitted.
139
140 \sa QIODevice
141*/
142
143void QAudioSource::start(QIODevice* device)
144{
145 if (!d)
146 return;
147 if (!device->isWritable()) {
148 qWarning() << "QAudioSource::start: QIODevice is not writable";
149 d->setError(QAudio::OpenError);
150 return;
151 }
152
153 d->elapsedTime.start();
154 d->start(device);
155}
156
157/*!
158 Returns a pointer to the internal QIODevice being used to transfer data from
159 the system's audio input. The device will already be open and
160 \l{QIODevice::read()}{read()} can read data directly from it.
161
162 \note The pointer will become invalid after the stream is stopped or
163 if you start another stream.
164
165 If the QAudioSource is able to access the system's audio device, state() returns
166 QtAudio::IdleState, error() returns QtAudio::NoError
167 and the stateChanged() signal is emitted.
168
169 If a problem occurs during this process, error() returns QtAudio::OpenError,
170 state() returns QtAudio::StoppedState and the stateChanged() signal is emitted.
171
172 \sa QIODevice
173*/
174
175QIODevice* QAudioSource::start()
176{
177 if (!d)
178 return nullptr;
179 d->elapsedTime.start();
180 return d->start();
181}
182
183/*!
184 Returns the QAudioFormat being used.
185*/
186
187QAudioFormat QAudioSource::format() const
188{
189 return d ? d->format() : QAudioFormat();
190}
191
192/*!
193 Stops the audio input, detaching from the system resource.
194
195 Sets error() to QtAudio::NoError, state() to QtAudio::StoppedState and
196 emit stateChanged() signal.
197*/
198
199void QAudioSource::stop()
200{
201 if (d)
202 d->stop();
203}
204
205/*!
206 Drops all audio data in the buffers, resets buffers to zero.
207*/
208
209void QAudioSource::reset()
210{
211 if (d)
212 d->reset();
213}
214
215/*!
216 Stops processing audio data, preserving buffered audio data.
217
218 Sets error() to QtAudio::NoError, state() to QtAudio::SuspendedState and
219 emit stateChanged() signal.
220*/
221
222void QAudioSource::suspend()
223{
224 if (d)
225 d->suspend();
226}
227
228/*!
229 Resumes processing audio data after a suspend().
230
231 Sets error() to QtAudio::NoError.
232 Sets state() to QtAudio::ActiveState if you previously called start(QIODevice*).
233 Sets state() to QtAudio::IdleState if you previously called start().
234 emits stateChanged() signal.
235*/
236
237void QAudioSource::resume()
238{
239 if (d)
240 d->resume();
241}
242
243/*!
244 Sets the audio buffer size to \a value bytes.
245
246 Note: This function can be called anytime before start(), calls to this
247 are ignored after start(). It should not be assumed that the buffer size
248 set is the actual buffer size used, calling bufferSize() anytime after start()
249 will return the actual buffer size being used.
250
251*/
252
253void QAudioSource::setBufferSize(qsizetype value)
254{
255 if (d)
256 d->setBufferSize(value);
257}
258
259/*!
260 Returns the audio buffer size in bytes.
261
262 If called before start(), returns platform default value.
263 If called before start() but setBufferSize() was called prior, returns value set by setBufferSize().
264 If called after start(), returns the actual buffer size being used. This may not be what was set previously
265 by setBufferSize().
266
267*/
268
269qsizetype QAudioSource::bufferSize() const
270{
271 return d ? d->bufferSize() : 0;
272}
273
274/*!
275 Returns the amount of audio data available to read in bytes.
276
277 Note: returned value is only valid while in QtAudio::ActiveState or QtAudio::IdleState
278 state, otherwise returns zero.
279*/
280
281qsizetype QAudioSource::bytesAvailable() const
282{
283 /*
284 -If not ActiveState|IdleState, return 0
285 -return amount of audio data available to read
286 */
287 return d ? d->bytesReady() : 0;
288}
289
290/*!
291 Sets the input volume to \a volume.
292
293 The volume is scaled linearly from \c 0.0 (silence) to \c 1.0 (full volume). Values outside this
294 range will be clamped.
295
296 If the device does not support adjusting the input
297 volume then \a volume will be ignored and the input
298 volume will remain at 1.0.
299
300 The default volume is \c 1.0.
301
302 Note: Adjustments to the volume will change the volume of this audio stream, not the global volume.
303*/
304void QAudioSource::setVolume(qreal volume)
305{
306 if (!d)
307 return;
308 qreal v = qBound(min: qreal(0.0), val: volume, max: qreal(1.0));
309 d->setVolume(v);
310}
311
312/*!
313 Returns the input volume.
314
315 If the device does not support adjusting the input volume
316 the returned value will be 1.0.
317*/
318qreal QAudioSource::volume() const
319{
320 return d ? d->volume() : 1.0;
321}
322
323/*!
324 Returns the amount of audio data processed since start()
325 was called in microseconds.
326*/
327
328qint64 QAudioSource::processedUSecs() const
329{
330 return d ? d->processedUSecs() : 0;
331}
332
333/*!
334 Returns the microseconds since start() was called, including time in Idle and
335 Suspend states.
336*/
337
338qint64 QAudioSource::elapsedUSecs() const
339{
340 return state() == QAudio::StoppedState ? 0 : d->elapsedTime.nsecsElapsed()/1000;
341}
342
343/*!
344 Returns the error state.
345*/
346
347QtAudio::Error QAudioSource::error() const
348{
349 return d ? d->error() : QAudio::OpenError;
350}
351
352/*!
353 Returns the state of audio processing.
354*/
355
356QtAudio::State QAudioSource::state() const
357{
358 return d ? d->state() : QAudio::StoppedState;
359}
360
361/*!
362 \fn QAudioSource::stateChanged(QtAudio::State state)
363 This signal is emitted when the device \a state has changed.
364
365 \note The QtAudio namespace was named QAudio up to and including Qt 6.6.
366 String-based connections to this signal have to use \c{QAudio::State} as
367 the parameter type: \c{connect(source, SIGNAL(stateChanged(QAudio::State)), ...);}
368*/
369
370QT_END_NAMESPACE
371
372#include "moc_qaudiosource.cpp"
373
374

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of qtmultimedia/src/multimedia/audio/qaudiosource.cpp