source: trunk/demos/spectrum/app/engine.h@ 769

Last change on this file since 769 was 769, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.3 sources from branches/vendor/nokia/qt.

File size: 9.2 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the examples of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:BSD$
10** You may use this file under the terms of the BSD license as follows:
11**
12** "Redistribution and use in source and binary forms, with or without
13** modification, are permitted provided that the following conditions are
14** met:
15** * Redistributions of source code must retain the above copyright
16** notice, this list of conditions and the following disclaimer.
17** * Redistributions in binary form must reproduce the above copyright
18** notice, this list of conditions and the following disclaimer in
19** the documentation and/or other materials provided with the
20** distribution.
21** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
22** the names of its contributors may be used to endorse or promote
23** products derived from this software without specific prior written
24** permission.
25**
26** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
37** $QT_END_LICENSE$
38**
39****************************************************************************/
40
41#ifndef ENGINE_H
42#define ENGINE_H
43
44#include "spectrum.h"
45#include "spectrumanalyser.h"
46#include "wavfile.h"
47
48#include <QObject>
49#include <QByteArray>
50#include <QBuffer>
51#include <QVector>
52#include <QtMultimedia/QAudioDeviceInfo>
53#include <QtMultimedia/QAudioFormat>
54
55#ifdef DUMP_CAPTURED_AUDIO
56#define DUMP_DATA
57#endif
58
59#ifdef DUMP_SPECTRUM
60#define DUMP_DATA
61#endif
62
63#ifdef DUMP_DATA
64#include <QDir>
65#endif
66
67class FrequencySpectrum;
68
69QT_FORWARD_DECLARE_CLASS(QAudioInput)
70QT_FORWARD_DECLARE_CLASS(QAudioOutput)
71QT_FORWARD_DECLARE_CLASS(QFile)
72
73/**
74 * This class interfaces with the QtMultimedia audio classes, and also with
75 * the SpectrumAnalyser class. Its role is to manage the capture and playback
76 * of audio data, meanwhile performing real-time analysis of the audio level
77 * and frequency spectrum.
78 */
79class Engine : public QObject {
80 Q_OBJECT
81public:
82 Engine(QObject *parent = 0);
83 ~Engine();
84
85 const QList<QAudioDeviceInfo>& availableAudioInputDevices() const
86 { return m_availableAudioInputDevices; }
87
88 const QList<QAudioDeviceInfo>& availableAudioOutputDevices() const
89 { return m_availableAudioOutputDevices; }
90
91 QAudio::Mode mode() const { return m_mode; }
92 QAudio::State state() const { return m_state; }
93
94 /**
95 * \return Reference to internal audio buffer
96 * \note This reference is valid for the lifetime of the Engine
97 */
98 const QByteArray& buffer() const { return m_buffer; }
99
100 /**
101 * \return Current audio format
102 * \note May be QAudioFormat() if engine is not initialized
103 */
104 const QAudioFormat& format() const { return m_format; }
105
106 /**
107 * Stop any ongoing recording or playback, and reset to ground state.
108 */
109 void reset();
110
111 /**
112 * Load data from WAV file
113 */
114 bool loadFile(const QString &fileName);
115
116 /**
117 * Generate tone
118 */
119 bool generateTone(const Tone &tone);
120
121 /**
122 * Generate tone
123 */
124 bool generateSweptTone(qreal amplitude);
125
126 /**
127 * Initialize for recording
128 */
129 bool initializeRecord();
130
131 /**
132 * Position of the audio input device.
133 * \return Position in microseconds.
134 */
135 qint64 recordPosition() const { return m_recordPosition; }
136
137 /**
138 * RMS level of the most recently processed set of audio samples.
139 * \return Level in range (0.0, 1.0)
140 */
141 qreal rmsLevel() const { return m_rmsLevel; }
142
143 /**
144 * Peak level of the most recently processed set of audio samples.
145 * \return Level in range (0.0, 1.0)
146 */
147 qreal peakLevel() const { return m_peakLevel; }
148
149 /**
150 * Position of the audio output device.
151 * \return Position in microseconds.
152 */
153 qint64 playPosition() const { return m_playPosition; }
154
155 /**
156 * Length of the internal engine buffer.
157 * \return Buffer length in microseconds.
158 */
159 qint64 bufferDuration() const;
160
161 /**
162 * Amount of data held in the buffer.
163 * \return Data duration in microseconds.
164 */
165 qint64 dataDuration() const;
166
167 /**
168 * Returns the size of the underlying audio buffer in bytes.
169 * This should be an approximation of the capture latency.
170 */
171 qint64 audioBufferLength() const;
172
173 /**
174 * Set window function applied to audio data before spectral analysis.
175 */
176 void setWindowFunction(WindowFunction type);
177
178public slots:
179 void startRecording();
180 void startPlayback();
181 void suspend();
182 void setAudioInputDevice(const QAudioDeviceInfo &device);
183 void setAudioOutputDevice(const QAudioDeviceInfo &device);
184
185signals:
186 void stateChanged(QAudio::Mode mode, QAudio::State state);
187
188 /**
189 * Informational message for non-modal display
190 */
191 void infoMessage(const QString &message, int durationMs);
192
193 /**
194 * Error message for modal display
195 */
196 void errorMessage(const QString &heading, const QString &detail);
197
198 /**
199 * Format of audio data has changed
200 */
201 void formatChanged(const QAudioFormat &format);
202
203 /**
204 * Length of buffer has changed.
205 * \param duration Duration in microseconds
206 */
207 void bufferDurationChanged(qint64 duration);
208
209 /**
210 * Amount of data in buffer has changed.
211 * \param duration Duration of data in microseconds
212 */
213 void dataDurationChanged(qint64 duration);
214
215 /**
216 * Position of the audio input device has changed.
217 * \param position Position in microseconds
218 */
219 void recordPositionChanged(qint64 position);
220
221 /**
222 * Position of the audio output device has changed.
223 * \param position Position in microseconds
224 */
225 void playPositionChanged(qint64 position);
226
227 /**
228 * Level changed
229 * \param rmsLevel RMS level in range 0.0 - 1.0
230 * \param peakLevel Peak level in range 0.0 - 1.0
231 * \param numSamples Number of audio samples analysed
232 */
233 void levelChanged(qreal rmsLevel, qreal peakLevel, int numSamples);
234
235 /**
236 * Spectrum has changed.
237 * \param position Position of start of window in microseconds
238 * \param length Length of window in microseconds
239 * \param spectrum Resulting frequency spectrum
240 */
241 void spectrumChanged(qint64 position, qint64 length, const FrequencySpectrum &spectrum);
242
243private slots:
244 void audioNotify();
245 void audioStateChanged(QAudio::State state);
246 void audioDataReady();
247 void spectrumChanged(const FrequencySpectrum &spectrum);
248
249private:
250 bool initialize();
251 bool selectFormat();
252 void stopRecording();
253 void stopPlayback();
254 void setState(QAudio::State state);
255 void setState(QAudio::Mode mode, QAudio::State state);
256 void setFormat(const QAudioFormat &format);
257 void setRecordPosition(qint64 position, bool forceEmit = false);
258 void setPlayPosition(qint64 position, bool forceEmit = false);
259 void calculateLevel(qint64 position, qint64 length);
260 void calculateSpectrum(qint64 position);
261 void setLevel(qreal rmsLevel, qreal peakLevel, int numSamples);
262
263#ifdef DUMP_DATA
264 void createOutputDir();
265 QString outputPath() const { return m_outputDir.path(); }
266#endif
267
268#ifdef DUMP_CAPTURED_AUDIO
269 void dumpData();
270#endif
271
272private:
273 QAudio::Mode m_mode;
274 QAudio::State m_state;
275
276 bool m_generateTone;
277 SweptTone m_tone;
278
279 QFile* m_file;
280 WavFile m_wavFile;
281
282 QAudioFormat m_format;
283
284 const QList<QAudioDeviceInfo> m_availableAudioInputDevices;
285 QAudioDeviceInfo m_audioInputDevice;
286 QAudioInput* m_audioInput;
287 QIODevice* m_audioInputIODevice;
288 qint64 m_recordPosition;
289
290 const QList<QAudioDeviceInfo> m_availableAudioOutputDevices;
291 QAudioDeviceInfo m_audioOutputDevice;
292 QAudioOutput* m_audioOutput;
293 qint64 m_playPosition;
294 QBuffer m_audioOutputIODevice;
295
296 QByteArray m_buffer;
297 qint64 m_dataLength;
298
299 qreal m_rmsLevel;
300 qreal m_peakLevel;
301
302 int m_spectrumLengthBytes;
303 QByteArray m_spectrumBuffer;
304 SpectrumAnalyser m_spectrumAnalyser;
305 qint64 m_spectrumPosition;
306
307 int m_count;
308
309#ifdef DUMP_DATA
310 QDir m_outputDir;
311#endif
312
313};
314
315#endif // ENGINE_H
Note: See TracBrowser for help on using the repository browser.