Files correlati : cg0.exe cg0700a.msk cg0700b.msk cg3.exe cg4.exe Bug : Commento: Merge 1.0 libraries
316 lines
9.2 KiB
C++
316 lines
9.2 KiB
C++
/****************************************************************************
|
|
**
|
|
** Copyright (C) 2015 The Qt Company Ltd.
|
|
** Contact: http://www.qt.io/licensing/
|
|
**
|
|
** This file is part of the examples of the Qt Toolkit.
|
|
**
|
|
** $QT_BEGIN_LICENSE:BSD$
|
|
** 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 <QObject>
|
|
#include <QByteArray>
|
|
#include <QBuffer>
|
|
#include <QVector>
|
|
#include <QtMultimedia/QAudioDeviceInfo>
|
|
#include <QtMultimedia/QAudioFormat>
|
|
|
|
#ifdef DUMP_CAPTURED_AUDIO
|
|
#define DUMP_DATA
|
|
#endif
|
|
|
|
#ifdef DUMP_SPECTRUM
|
|
#define DUMP_DATA
|
|
#endif
|
|
|
|
#ifdef DUMP_DATA
|
|
#include <QDir>
|
|
#endif
|
|
|
|
class FrequencySpectrum;
|
|
QT_FORWARD_DECLARE_CLASS(QAudioInput)
|
|
QT_FORWARD_DECLARE_CLASS(QAudioOutput)
|
|
QT_FORWARD_DECLARE_CLASS(QFile)
|
|
|
|
/**
|
|
* This class interfaces with the QtMultimedia 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:
|
|
Engine(QObject *parent = 0);
|
|
~Engine();
|
|
|
|
const QList<QAudioDeviceInfo>& availableAudioInputDevices() const
|
|
{ return m_availableAudioInputDevices; }
|
|
|
|
const QList<QAudioDeviceInfo>& 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& 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 &fileName);
|
|
|
|
/**
|
|
* Generate tone
|
|
*/
|
|
bool generateTone(const Tone &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 &device);
|
|
void setAudioOutputDevice(const QAudioDeviceInfo &device);
|
|
|
|
signals:
|
|
void stateChanged(QAudio::Mode mode, QAudio::State state);
|
|
|
|
/**
|
|
* Informational message for non-modal display
|
|
*/
|
|
void infoMessage(const QString &message, int durationMs);
|
|
|
|
/**
|
|
* Error message for modal display
|
|
*/
|
|
void errorMessage(const QString &heading, const QString &detail);
|
|
|
|
/**
|
|
* Format of audio data has changed
|
|
*/
|
|
void formatChanged(const QAudioFormat &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 &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 &buffer);
|
|
|
|
private slots:
|
|
void audioNotify();
|
|
void audioStateChanged(QAudio::State state);
|
|
void audioDataReady();
|
|
void spectrumChanged(const FrequencySpectrum &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 &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<QAudioDeviceInfo> m_availableAudioInputDevices;
|
|
QAudioDeviceInfo m_audioInputDevice;
|
|
QAudioInput* m_audioInput;
|
|
QIODevice* m_audioInputIODevice;
|
|
qint64 m_recordPosition;
|
|
|
|
const QList<QAudioDeviceInfo> m_availableAudioOutputDevices;
|
|
QAudioDeviceInfo m_audioOutputDevice;
|
|
QAudioOutput* m_audioOutput;
|
|
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
|