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

Last change on this file since 858 was 846, checked in by Dmitry A. Kuminov, 14 years ago

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

File size: 9.3 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
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;
68QT_FORWARD_DECLARE_CLASS(QAudioInput)
69QT_FORWARD_DECLARE_CLASS(QAudioOutput)
70QT_FORWARD_DECLARE_CLASS(QFile)
71
72/**
73 * This class interfaces with the QtMultimedia audio classes, and also with
74 * the SpectrumAnalyser class. Its role is to manage the capture and playback
75 * of audio data, meanwhile performing real-time analysis of the audio level
76 * and frequency spectrum.
77 */
78class Engine : public QObject {
79 Q_OBJECT
80public:
81 Engine(QObject *parent = 0);
82 ~Engine();
83
84 const QList<QAudioDeviceInfo>& availableAudioInputDevices() const
85 { return m_availableAudioInputDevices; }
86
87 const QList<QAudioDeviceInfo>& availableAudioOutputDevices() const
88 { return m_availableAudioOutputDevices; }
89
90 QAudio::Mode mode() const { return m_mode; }
91 QAudio::State state() const { return m_state; }
92
93 /**
94 * \return Current audio format
95 * \note May be QAudioFormat() if engine is not initialized
96 */
97 const QAudioFormat& format() const { return m_format; }
98
99 /**
100 * Stop any ongoing recording or playback, and reset to ground state.
101 */
102 void reset();
103
104 /**
105 * Load data from WAV file
106 */
107 bool loadFile(const QString &fileName);
108
109 /**
110 * Generate tone
111 */
112 bool generateTone(const Tone &tone);
113
114 /**
115 * Generate tone
116 */
117 bool generateSweptTone(qreal amplitude);
118
119 /**
120 * Initialize for recording
121 */
122 bool initializeRecord();
123
124 /**
125 * Position of the audio input device.
126 * \return Position in bytes.
127 */
128 qint64 recordPosition() const { return m_recordPosition; }
129
130 /**
131 * RMS level of the most recently processed set of audio samples.
132 * \return Level in range (0.0, 1.0)
133 */
134 qreal rmsLevel() const { return m_rmsLevel; }
135
136 /**
137 * Peak level of the most recently processed set of audio samples.
138 * \return Level in range (0.0, 1.0)
139 */
140 qreal peakLevel() const { return m_peakLevel; }
141
142 /**
143 * Position of the audio output device.
144 * \return Position in bytes.
145 */
146 qint64 playPosition() const { return m_playPosition; }
147
148 /**
149 * Length of the internal engine buffer.
150 * \return Buffer length in bytes.
151 */
152 qint64 bufferLength() const;
153
154 /**
155 * Amount of data held in the buffer.
156 * \return Data length in bytes.
157 */
158 qint64 dataLength() const { return m_dataLength; }
159
160 /**
161 * Set window function applied to audio data before spectral analysis.
162 */
163 void setWindowFunction(WindowFunction type);
164
165public slots:
166 void startRecording();
167 void startPlayback();
168 void suspend();
169 void setAudioInputDevice(const QAudioDeviceInfo &device);
170 void setAudioOutputDevice(const QAudioDeviceInfo &device);
171
172signals:
173 void stateChanged(QAudio::Mode mode, QAudio::State state);
174
175 /**
176 * Informational message for non-modal display
177 */
178 void infoMessage(const QString &message, int durationMs);
179
180 /**
181 * Error message for modal display
182 */
183 void errorMessage(const QString &heading, const QString &detail);
184
185 /**
186 * Format of audio data has changed
187 */
188 void formatChanged(const QAudioFormat &format);
189
190 /**
191 * Length of buffer has changed.
192 * \param duration Duration in microseconds
193 */
194 void bufferLengthChanged(qint64 duration);
195
196 /**
197 * Amount of data in buffer has changed.
198 * \param Length of data in bytes
199 */
200 void dataLengthChanged(qint64 duration);
201
202 /**
203 * Position of the audio input device has changed.
204 * \param position Position in bytes
205 */
206 void recordPositionChanged(qint64 position);
207
208 /**
209 * Position of the audio output device has changed.
210 * \param position Position in bytes
211 */
212 void playPositionChanged(qint64 position);
213
214 /**
215 * Level changed
216 * \param rmsLevel RMS level in range 0.0 - 1.0
217 * \param peakLevel Peak level in range 0.0 - 1.0
218 * \param numSamples Number of audio samples analyzed
219 */
220 void levelChanged(qreal rmsLevel, qreal peakLevel, int numSamples);
221
222 /**
223 * Spectrum has changed.
224 * \param position Position of start of window in bytes
225 * \param length Length of window in bytes
226 * \param spectrum Resulting frequency spectrum
227 */
228 void spectrumChanged(qint64 position, qint64 length, const FrequencySpectrum &spectrum);
229
230 /**
231 * Buffer containing audio data has changed.
232 * \param position Position of start of buffer in bytes
233 * \param buffer Buffer
234 */
235 void bufferChanged(qint64 position, qint64 length, const QByteArray &buffer);
236
237private slots:
238 void audioNotify();
239 void audioStateChanged(QAudio::State state);
240 void audioDataReady();
241 void spectrumChanged(const FrequencySpectrum &spectrum);
242
243private:
244 void resetAudioDevices();
245 bool initialize();
246 bool selectFormat();
247 void stopRecording();
248 void stopPlayback();
249 void setState(QAudio::State state);
250 void setState(QAudio::Mode mode, QAudio::State state);
251 void setFormat(const QAudioFormat &format);
252 void setRecordPosition(qint64 position, bool forceEmit = false);
253 void setPlayPosition(qint64 position, bool forceEmit = false);
254 void calculateLevel(qint64 position, qint64 length);
255 void calculateSpectrum(qint64 position);
256 void setLevel(qreal rmsLevel, qreal peakLevel, int numSamples);
257
258#ifdef DUMP_DATA
259 void createOutputDir();
260 QString outputPath() const { return m_outputDir.path(); }
261#endif
262
263#ifdef DUMP_CAPTURED_AUDIO
264 void dumpData();
265#endif
266
267private:
268 QAudio::Mode m_mode;
269 QAudio::State m_state;
270
271 bool m_generateTone;
272 SweptTone m_tone;
273
274 WavFile* m_file;
275 // We need a second file handle via which to read data into m_buffer
276 // for analysis
277 WavFile* m_analysisFile;
278
279 QAudioFormat m_format;
280
281 const QList<QAudioDeviceInfo> m_availableAudioInputDevices;
282 QAudioDeviceInfo m_audioInputDevice;
283 QAudioInput* m_audioInput;
284 QIODevice* m_audioInputIODevice;
285 qint64 m_recordPosition;
286
287 const QList<QAudioDeviceInfo> m_availableAudioOutputDevices;
288 QAudioDeviceInfo m_audioOutputDevice;
289 QAudioOutput* m_audioOutput;
290 qint64 m_playPosition;
291 QBuffer m_audioOutputIODevice;
292
293 QByteArray m_buffer;
294 qint64 m_bufferPosition;
295 qint64 m_bufferLength;
296 qint64 m_dataLength;
297
298 int m_levelBufferLength;
299 qreal m_rmsLevel;
300 qreal m_peakLevel;
301
302 int m_spectrumBufferLength;
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.