Spectrum Example▲
Sélectionnez
/**
**************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
***************************************************************************
*/
#ifndef ENGINE_H
#define ENGINE_H
#include
"spectrum.h"
#include
"spectrumanalyser.h"
#include
"wavfile.h"
#include <QAudioDeviceInfo>
#include <QAudioFormat>
#include <QBuffer>
#include <QByteArray>
#include <QDir>
#include <QObject>
#include <QVector>
#ifdef DUMP_CAPTURED_AUDIO
#define DUMP_DATA
#endif
#ifdef DUMP_SPECTRUM
#define DUMP_DATA
#endif
class
FrequencySpectrum;
class
QAudioInput;
class
QAudioOutput;
/**
* This class interfaces with the Qt Multimedia audio classes, and also with
* the SpectrumAnalyser class. Its role is to manage the capture and playback
* of audio data, meanwhile performing real-time analysis of the audio level
* and frequency spectrum.
*/
class
Engine : public
QObject
{
Q_OBJECT
public
:
explicit
Engine(QObject *
parent =
0
);
~
Engine();
const
QList&
lt;QAudioDeviceInfo&
gt; &
amp;availableAudioInputDevices() const
{
return
m_availableAudioInputDevices; }
const
QList&
lt;QAudioDeviceInfo&
gt; &
amp;availableAudioOutputDevices() const
{
return
m_availableAudioOutputDevices; }
QAudio::
Mode mode() const
{
return
m_mode; }
QAudio::
State state() const
{
return
m_state; }
/**
*
\return
Current audio format
*
\note
May be QAudioFormat() if engine is not initialized
*/
const
QAudioFormat&
amp; format() const
{
return
m_format; }
/**
* Stop any ongoing recording or playback, and reset to ground state.
*/
void
reset();
/**
* Load data from WAV file
*/
bool
loadFile(const
QString &
amp;fileName);
/**
* Generate tone
*/
bool
generateTone(const
Tone &
amp;tone);
/**
* Generate tone
*/
bool
generateSweptTone(qreal amplitude);
/**
* Initialize for recording
*/
bool
initializeRecord();
/**
* Position of the audio input device.
*
\return
Position in bytes.
*/
qint64 recordPosition() const
{
return
m_recordPosition; }
/**
* RMS level of the most recently processed set of audio samples.
*
\return
Level in range (0.0, 1.0)
*/
qreal rmsLevel() const
{
return
m_rmsLevel; }
/**
* Peak level of the most recently processed set of audio samples.
*
\return
Level in range (0.0, 1.0)
*/
qreal peakLevel() const
{
return
m_peakLevel; }
/**
* Position of the audio output device.
*
\return
Position in bytes.
*/
qint64 playPosition() const
{
return
m_playPosition; }
/**
* Length of the internal engine buffer.
*
\return
Buffer length in bytes.
*/
qint64 bufferLength() const
;
/**
* Amount of data held in the buffer.
*
\return
Data length in bytes.
*/
qint64 dataLength() const
{
return
m_dataLength; }
/**
* Set window function applied to audio data before spectral analysis.
*/
void
setWindowFunction(WindowFunction type);
public
slots:
void
startRecording();
void
startPlayback();
void
suspend();
void
setAudioInputDevice(const
QAudioDeviceInfo &
amp;device);
void
setAudioOutputDevice(const
QAudioDeviceInfo &
amp;device);
signals
:
void
stateChanged(QAudio::
Mode mode, QAudio::
State state);
/**
* Informational message for non-modal display
*/
void
infoMessage(const
QString &
amp;message, int
durationMs);
/**
* Error message for modal display
*/
void
errorMessage(const
QString &
amp;heading, const
QString &
amp;detail);
/**
* Format of audio data has changed
*/
void
formatChanged(const
QAudioFormat &
amp;format);
/**
* Length of buffer has changed.
*
\param
duration Duration in microseconds
*/
void
bufferLengthChanged(qint64 duration);
/**
* Amount of data in buffer has changed.
*
\param
Length of data in bytes
*/
void
dataLengthChanged(qint64 duration);
/**
* Position of the audio input device has changed.
*
\param
position Position in bytes
*/
void
recordPositionChanged(qint64 position);
/**
* Position of the audio output device has changed.
*
\param
position Position in bytes
*/
void
playPositionChanged(qint64 position);
/**
* Level changed
*
\param
rmsLevel RMS level in range 0.0 - 1.0
*
\param
peakLevel Peak level in range 0.0 - 1.0
*
\param
numSamples Number of audio samples analyzed
*/
void
levelChanged(qreal rmsLevel, qreal peakLevel, int
numSamples);
/**
* Spectrum has changed.
*
\param
position Position of start of window in bytes
*
\param
length Length of window in bytes
*
\param
spectrum Resulting frequency spectrum
*/
void
spectrumChanged(qint64 position, qint64 length, const
FrequencySpectrum &
amp;spectrum);
/**
* Buffer containing audio data has changed.
*
\param
position Position of start of buffer in bytes
*
\param
buffer Buffer
*/
void
bufferChanged(qint64 position, qint64 length, const
QByteArray &
amp;buffer);
private
slots:
void
audioNotify();
void
audioStateChanged(QAudio::
State state);
void
audioDataReady();
void
spectrumChanged(const
FrequencySpectrum &
amp;spectrum);
private
:
void
resetAudioDevices();
bool
initialize();
bool
selectFormat();
void
stopRecording();
void
stopPlayback();
void
setState(QAudio::
State state);
void
setState(QAudio::
Mode mode, QAudio::
State state);
void
setFormat(const
QAudioFormat &
amp;format);
void
setRecordPosition(qint64 position, bool
forceEmit =
false
);
void
setPlayPosition(qint64 position, bool
forceEmit =
false
);
void
calculateLevel(qint64 position, qint64 length);
void
calculateSpectrum(qint64 position);
void
setLevel(qreal rmsLevel, qreal peakLevel, int
numSamples);
#ifdef DUMP_DATA
void
createOutputDir();
QString outputPath() const
{
return
m_outputDir.path(); }
#endif
#ifdef DUMP_CAPTURED_AUDIO
void
dumpData();
#endif
private
:
QAudio::
Mode m_mode;
QAudio::
State m_state;
bool
m_generateTone;
SweptTone m_tone;
WavFile*
m_file;
// We need a second file handle via which to read data into m_buffer
// for analysis
WavFile*
m_analysisFile;
QAudioFormat m_format;
const
QList&
lt;QAudioDeviceInfo&
gt; m_availableAudioInputDevices;
QAudioDeviceInfo m_audioInputDevice;
QAudioInput*
m_audioInput;
QIODevice*
m_audioInputIODevice;
qint64 m_recordPosition;
const
QList&
lt;QAudioDeviceInfo&
gt; m_availableAudioOutputDevices;
QAudioDeviceInfo m_audioOutputDevice;
QAudioOutput*
m_audioOutput;
QString m_audioOutputCategory;
qint64 m_playPosition;
QBuffer m_audioOutputIODevice;
QByteArray m_buffer;
qint64 m_bufferPosition;
qint64 m_bufferLength;
qint64 m_dataLength;
int
m_levelBufferLength;
qreal m_rmsLevel;
qreal m_peakLevel;
int
m_spectrumBufferLength;
QByteArray m_spectrumBuffer;
SpectrumAnalyser m_spectrumAnalyser;
qint64 m_spectrumPosition;
int
m_count;
#ifdef DUMP_DATA
QDir m_outputDir;
#endif
}
;
#endif
// ENGINE_H