From db2a90fa9b4f823d37e02545732ff815ca9a1726 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Mon, 11 Jan 2016 17:08:02 +0200 Subject: Remove some manual test apps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removed - Kinectsurface - Has 3rd party code. - qmlcamera - Ugly mess and kinda pointless. - qmlmultiwindow - Test is not relevant and is buggy. - spectrum - Has 3rd party code. Change-Id: Ic28ffddf9e45f51a5320d4ebd0e2b7b373452cb7 Reviewed-by: Tomi Korpipää --- tests/manual/spectrum/spectrumapp/engine.cpp | 622 --------------------- tests/manual/spectrum/spectrumapp/engine.h | 250 --------- .../spectrum/spectrumapp/frequencyspectrum.cpp | 70 --- .../spectrum/spectrumapp/frequencyspectrum.h | 79 --- tests/manual/spectrum/spectrumapp/main.cpp | 212 ------- .../spectrum/spectrumapp/soundFiles/Rockhop.wav | Bin 1059308 -> 0 bytes .../spectrumapp/soundFiles/futurebells_beat.wav | Bin 352084 -> 0 bytes ..._thuille_terzo-tempo_sestetto_small-version.wav | Bin 1055502 -> 0 bytes tests/manual/spectrum/spectrumapp/spectrum.h | 114 ---- tests/manual/spectrum/spectrumapp/spectrum.qrc | 7 - .../spectrum/spectrumapp/spectrumanalyser.cpp | 212 ------- .../manual/spectrum/spectrumapp/spectrumanalyser.h | 153 ----- tests/manual/spectrum/spectrumapp/spectrumapp.pro | 73 --- tests/manual/spectrum/spectrumapp/utils.cpp | 120 ---- tests/manual/spectrum/spectrumapp/utils.h | 93 --- tests/manual/spectrum/spectrumapp/wavfile.cpp | 132 ----- tests/manual/spectrum/spectrumapp/wavfile.h | 47 -- 17 files changed, 2184 deletions(-) delete mode 100644 tests/manual/spectrum/spectrumapp/engine.cpp delete mode 100644 tests/manual/spectrum/spectrumapp/engine.h delete mode 100644 tests/manual/spectrum/spectrumapp/frequencyspectrum.cpp delete mode 100644 tests/manual/spectrum/spectrumapp/frequencyspectrum.h delete mode 100644 tests/manual/spectrum/spectrumapp/main.cpp delete mode 100644 tests/manual/spectrum/spectrumapp/soundFiles/Rockhop.wav delete mode 100644 tests/manual/spectrum/spectrumapp/soundFiles/futurebells_beat.wav delete mode 100644 tests/manual/spectrum/spectrumapp/soundFiles/onclassical_demo_fiati-di-parma_thuille_terzo-tempo_sestetto_small-version.wav delete mode 100644 tests/manual/spectrum/spectrumapp/spectrum.h delete mode 100644 tests/manual/spectrum/spectrumapp/spectrum.qrc delete mode 100644 tests/manual/spectrum/spectrumapp/spectrumanalyser.cpp delete mode 100644 tests/manual/spectrum/spectrumapp/spectrumanalyser.h delete mode 100644 tests/manual/spectrum/spectrumapp/spectrumapp.pro delete mode 100644 tests/manual/spectrum/spectrumapp/utils.cpp delete mode 100644 tests/manual/spectrum/spectrumapp/utils.h delete mode 100644 tests/manual/spectrum/spectrumapp/wavfile.cpp delete mode 100644 tests/manual/spectrum/spectrumapp/wavfile.h (limited to 'tests/manual/spectrum/spectrumapp') diff --git a/tests/manual/spectrum/spectrumapp/engine.cpp b/tests/manual/spectrum/spectrumapp/engine.cpp deleted file mode 100644 index 349a764f..00000000 --- a/tests/manual/spectrum/spectrumapp/engine.cpp +++ /dev/null @@ -1,622 +0,0 @@ -/****************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Data Visualization module. -** -** $QT_BEGIN_LICENSE:COMM$ -** -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** $QT_END_LICENSE$ -** -******************************************************************************/ - -#include "engine.h" -#include "utils.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -//----------------------------------------------------------------------------- -// Constants -//----------------------------------------------------------------------------- - -const qint64 BufferDurationUs = 10 * 1000000; -const int NotifyIntervalMs = 100; - -// Size of the level calculation window in microseconds -const int LevelWindowUs = 0.1 * 1000000; - -//----------------------------------------------------------------------------- -// Constructor and destructor -//----------------------------------------------------------------------------- - -Engine::Engine(QObject *parent) - : QObject(parent), - m_mode(QAudio::AudioInput), - m_state(QAudio::StoppedState), - m_generateTone(false), - m_file(0), - m_analysisFile(0), - m_availableAudioInputDevices - (QAudioDeviceInfo::availableDevices(QAudio::AudioInput)), - m_audioInputDevice(QAudioDeviceInfo::defaultInputDevice()), - m_audioInput(0), - m_audioInputIODevice(0), - m_recordPosition(0), - m_availableAudioOutputDevices - (QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)), - m_audioOutputDevice(QAudioDeviceInfo::defaultOutputDevice()), - m_audioOutput(0), - m_playPosition(0), - m_bufferPosition(0), - m_bufferLength(0), - m_dataLength(0), - m_levelBufferLength(0), - m_rmsLevel(0.0), - m_peakLevel(0.0), - m_spectrumBufferLength(0), - m_spectrumAnalyser(), - m_spectrumPosition(0), - m_count(0) -{ - qRegisterMetaType("FrequencySpectrum"); - qRegisterMetaType("WindowFunction"); - CHECKED_CONNECT(&m_spectrumAnalyser, - SIGNAL(spectrumChanged(FrequencySpectrum)), - this, - SLOT(spectrumChanged(FrequencySpectrum))); - - initialize(); - qDebug() << "output devices:"; - foreach (QAudioDeviceInfo device, m_availableAudioOutputDevices) - qDebug() << device.deviceName(); - qDebug() << "input devices:"; - foreach (QAudioDeviceInfo device, m_availableAudioInputDevices) - qDebug() << device.deviceName(); -} - -Engine::~Engine() -{ - -} - -//----------------------------------------------------------------------------- -// Public functions -//----------------------------------------------------------------------------- - -bool Engine::loadFile(const QString &fileName) -{ - reset(); - bool result = false; - Q_ASSERT(!m_generateTone); - Q_ASSERT(!m_file); - Q_ASSERT(!fileName.isEmpty()); - m_file = new WavFile(this); - if (m_file->open(fileName)) { - if (isPCMS16LE(m_file->fileFormat())) { - result = initialize(); - } else { - ENGINE_DEBUG << "Audio format not supported" << formatToString(m_file->fileFormat()); - } - } else { - ENGINE_DEBUG << "Could not open file" << fileName; - } - if (result) { - m_analysisFile = new WavFile(this); - m_analysisFile->open(fileName); - } - return result; -} - -qint64 Engine::bufferLength() const -{ - return m_file ? m_file->size() : m_bufferLength; -} - -void Engine::setWindowFunction(WindowFunction type) -{ - m_spectrumAnalyser.setWindowFunction(type); -} - - -//----------------------------------------------------------------------------- -// Public slots -//----------------------------------------------------------------------------- - -void Engine::startRecording() -{ - if (m_audioInput) { - if (QAudio::AudioInput == m_mode && - QAudio::SuspendedState == m_state) { - m_audioInput->resume(); - } else { - m_spectrumAnalyser.cancelCalculation(); - changedSpectrum(0, 0, FrequencySpectrum()); - - m_buffer.fill(0); - setRecordPosition(0, true); - stopPlayback(); - m_mode = QAudio::AudioInput; - CHECKED_CONNECT(m_audioInput, SIGNAL(stateChanged(QAudio::State)), - this, SLOT(audioStateChanged(QAudio::State))); - CHECKED_CONNECT(m_audioInput, SIGNAL(notify()), - this, SLOT(audioNotify())); - m_count = 0; - m_dataLength = 0; - emit dataLengthChanged(0); - m_audioInputIODevice = m_audioInput->start(); - CHECKED_CONNECT(m_audioInputIODevice, SIGNAL(readyRead()), - this, SLOT(audioDataReady())); - } - } -} - -void Engine::startPlayback() -{ - if (m_audioOutput) { - if (QAudio::AudioOutput == m_mode && - QAudio::SuspendedState == m_state) { -#ifdef Q_OS_WIN - // The Windows backend seems to internally go back into ActiveState - // while still returning SuspendedState, so to ensure that it doesn't - // ignore the resume() call, we first re-suspend - m_audioOutput->suspend(); -#endif - m_audioOutput->resume(); - } else { - m_spectrumAnalyser.cancelCalculation(); - changedSpectrum(0, 0, FrequencySpectrum()); - setPlayPosition(0, true); - stopRecording(); - m_mode = QAudio::AudioOutput; - CHECKED_CONNECT(m_audioOutput, SIGNAL(stateChanged(QAudio::State)), - this, SLOT(audioStateChanged(QAudio::State))); - CHECKED_CONNECT(m_audioOutput, SIGNAL(notify()), - this, SLOT(audioNotify())); - m_count = 0; - if (m_file) { - m_file->seek(0); - m_bufferPosition = 0; - m_dataLength = 0; - m_audioOutput->start(m_file); - } else { - m_audioOutputIODevice.close(); - m_audioOutputIODevice.setBuffer(&m_buffer); - m_audioOutputIODevice.open(QIODevice::ReadOnly); - m_audioOutput->start(&m_audioOutputIODevice); - } - } - } -} - -void Engine::suspend() -{ - if (QAudio::ActiveState == m_state || - QAudio::IdleState == m_state) { - switch (m_mode) { - case QAudio::AudioInput: - m_audioInput->suspend(); - break; - case QAudio::AudioOutput: - m_audioOutput->suspend(); - break; - } - } -} - -void Engine::setAudioInputDevice(const QAudioDeviceInfo &device) -{ - if (device.deviceName() != m_audioInputDevice.deviceName()) { - m_audioInputDevice = device; - initialize(); - } -} - -void Engine::setAudioOutputDevice(const QAudioDeviceInfo &device) -{ - if (device.deviceName() != m_audioOutputDevice.deviceName()) { - m_audioOutputDevice = device; - initialize(); - } -} - - -//----------------------------------------------------------------------------- -// Private slots -//----------------------------------------------------------------------------- - -void Engine::audioNotify() -{ - switch (m_mode) { - case QAudio::AudioInput: { - const qint64 recordPosition = qMin(m_bufferLength, audioLength(m_format, m_audioInput->processedUSecs())); - setRecordPosition(recordPosition); - const qint64 levelPosition = m_dataLength - m_levelBufferLength; - if (levelPosition >= 0) - calculateLevel(levelPosition, m_levelBufferLength); - if (m_dataLength >= m_spectrumBufferLength) { - const qint64 spectrumPosition = m_dataLength - m_spectrumBufferLength; - calculateSpectrum(spectrumPosition); - } - emit bufferChanged(0, m_dataLength, m_buffer); - } - break; - case QAudio::AudioOutput: { - const qint64 playPosition = audioLength(m_format, m_audioOutput->processedUSecs()); - setPlayPosition(qMin(bufferLength(), playPosition)); - const qint64 levelPosition = playPosition - m_levelBufferLength; - const qint64 spectrumPosition = playPosition - m_spectrumBufferLength; - if (m_file) { - if (levelPosition > m_bufferPosition || - spectrumPosition > m_bufferPosition || - qMax(m_levelBufferLength, m_spectrumBufferLength) > m_dataLength) { - m_bufferPosition = 0; - m_dataLength = 0; - // Data needs to be read into m_buffer in order to be analysed - const qint64 readPos = qMax(qint64(0), qMin(levelPosition, spectrumPosition)); - const qint64 readEnd = qMin(m_analysisFile->size(), qMax(levelPosition + m_levelBufferLength, spectrumPosition + m_spectrumBufferLength)); - const qint64 readLen = readEnd - readPos + audioLength(m_format, WaveformWindowDuration); - ENGINE_DEBUG << "Engine::audioNotify [1]" - << "analysisFileSize" << m_analysisFile->size() - << "readPos" << readPos - << "readLen" << readLen; - if (m_analysisFile->seek(readPos + m_analysisFile->headerLength())) { - m_buffer.resize(readLen); - m_bufferPosition = readPos; - m_dataLength = m_analysisFile->read(m_buffer.data(), readLen); - ENGINE_DEBUG << "Engine::audioNotify [2]" << "bufferPosition" << m_bufferPosition << "dataLength" << m_dataLength; - } else { - ENGINE_DEBUG << "Engine::audioNotify [2]" << "file seek error"; - } - emit bufferChanged(m_bufferPosition, m_dataLength, m_buffer); - } - } else { - if (playPosition >= m_dataLength) - stopPlayback(); - } - if (levelPosition >= 0 && levelPosition + m_levelBufferLength < m_bufferPosition + m_dataLength) - calculateLevel(levelPosition, m_levelBufferLength); - if (spectrumPosition >= 0 && spectrumPosition + m_spectrumBufferLength < m_bufferPosition + m_dataLength) - calculateSpectrum(spectrumPosition); - } - break; - } -} - -void Engine::audioStateChanged(QAudio::State state) -{ - ENGINE_DEBUG << "Engine::audioStateChanged from" << m_state - << "to" << state; - - if (QAudio::IdleState == state && m_file && m_file->pos() == m_file->size()) { - stopPlayback(); - } else { - if (QAudio::StoppedState == state) { - // Check error - QAudio::Error error = QAudio::NoError; - switch (m_mode) { - case QAudio::AudioInput: - error = m_audioInput->error(); - break; - case QAudio::AudioOutput: - error = m_audioOutput->error(); - break; - } - if (QAudio::NoError != error) { - reset(); - return; - } - } - setState(state); - } -} - -void Engine::audioDataReady() -{ - Q_ASSERT(0 == m_bufferPosition); - const qint64 bytesReady = m_audioInput->bytesReady(); - const qint64 bytesSpace = m_buffer.size() - m_dataLength; - const qint64 bytesToRead = qMin(bytesReady, bytesSpace); - - const qint64 bytesRead = m_audioInputIODevice->read( - m_buffer.data() + m_dataLength, - bytesToRead); - - if (bytesRead) { - m_dataLength += bytesRead; - emit dataLengthChanged(dataLength()); - } - - if (m_buffer.size() == m_dataLength) - stopRecording(); -} - -void Engine::spectrumChanged(const FrequencySpectrum &spectrum) -{ - ENGINE_DEBUG << "Engine::spectrumChanged" << "pos" << m_spectrumPosition; - emit changedSpectrum(m_spectrumPosition, m_spectrumBufferLength, spectrum); -} - - -//----------------------------------------------------------------------------- -// Private functions -//----------------------------------------------------------------------------- - -void Engine::resetAudioDevices() -{ - delete m_audioInput; - m_audioInput = 0; - m_audioInputIODevice = 0; - setRecordPosition(0); - delete m_audioOutput; - m_audioOutput = 0; - setPlayPosition(0); - m_spectrumPosition = 0; - setLevel(0.0, 0.0, 0); -} - -void Engine::reset() -{ - stopRecording(); - stopPlayback(); - setState(QAudio::AudioInput, QAudio::StoppedState); - setFormat(QAudioFormat()); - m_generateTone = false; - delete m_file; - m_file = 0; - delete m_analysisFile; - m_analysisFile = 0; - m_buffer.clear(); - m_bufferPosition = 0; - m_bufferLength = 0; - m_dataLength = 0; - emit dataLengthChanged(0); - resetAudioDevices(); -} - -bool Engine::initialize() -{ - bool result = false; - - QAudioFormat format = m_format; - - if (selectFormat()) { - resetAudioDevices(); - if (m_file) { - emit bufferLengthChanged(bufferLength()); - emit dataLengthChanged(dataLength()); - emit bufferChanged(0, 0, m_buffer); - setRecordPosition(bufferLength()); - result = true; - } - m_audioOutput = new QAudioOutput(m_audioOutputDevice, m_format, this); - m_audioOutput->setNotifyInterval(NotifyIntervalMs); - } else { - if (m_file) - ENGINE_DEBUG << "Audio format not supported" << formatToString(m_format); - else - ENGINE_DEBUG << "No common input / output format found"; - } - - ENGINE_DEBUG << "Engine::initialize" << "m_bufferLength" << m_bufferLength; - ENGINE_DEBUG << "Engine::initialize" << "m_dataLength" << m_dataLength; - ENGINE_DEBUG << "Engine::initialize" << "format" << m_format; - - return result; -} - -bool Engine::selectFormat() -{ - bool foundSupportedFormat = false; - - if (m_file || QAudioFormat() != m_format) { - QAudioFormat format = m_format; - if (m_file) - // Header is read from the WAV file; just need to check whether - // it is supported by the audio output device - format = m_file->fileFormat(); - if (m_audioOutputDevice.isFormatSupported(format)) { - setFormat(format); - foundSupportedFormat = true; - } - } else { - - QList sampleRatesList; -#ifdef Q_OS_WIN - // The Windows audio backend does not correctly report format support - // (see QTBUG-9100). Furthermore, although the audio subsystem captures - // at 11025Hz, the resulting audio is corrupted. - sampleRatesList += 8000; -#endif - - if (!m_generateTone) - sampleRatesList += m_audioInputDevice.supportedSampleRates(); - - sampleRatesList += m_audioOutputDevice.supportedSampleRates(); - sampleRatesList = sampleRatesList.toSet().toList(); // remove duplicates - qSort(sampleRatesList); - ENGINE_DEBUG << "Engine::initialize frequenciesList" << sampleRatesList; - - QList channelsList; - channelsList += m_audioInputDevice.supportedChannelCounts(); - channelsList += m_audioOutputDevice.supportedChannelCounts(); - channelsList = channelsList.toSet().toList(); - qSort(channelsList); - ENGINE_DEBUG << "Engine::initialize channelsList" << channelsList; - - QAudioFormat format; - format.setByteOrder(QAudioFormat::LittleEndian); - format.setCodec("audio/pcm"); - format.setSampleSize(16); - format.setSampleType(QAudioFormat::SignedInt); - int sampleRate, channels; - foreach (sampleRate, sampleRatesList) { - if (foundSupportedFormat) - break; - format.setSampleRate(sampleRate); - foreach (channels, channelsList) { - format.setChannelCount(channels); - const bool inputSupport = m_generateTone || - m_audioInputDevice.isFormatSupported(format); - const bool outputSupport = m_audioOutputDevice.isFormatSupported(format); - ENGINE_DEBUG << "Engine::initialize checking " << format - << "input" << inputSupport - << "output" << outputSupport; - if (inputSupport && outputSupport) { - foundSupportedFormat = true; - break; - } - } - } - - if (!foundSupportedFormat) - format = QAudioFormat(); - - setFormat(format); - } - - return foundSupportedFormat; -} - -void Engine::stopRecording() -{ - if (m_audioInput) { - m_audioInput->stop(); - QCoreApplication::instance()->processEvents(); - m_audioInput->disconnect(); - } - m_audioInputIODevice = 0; -} - -void Engine::stopPlayback() -{ - if (m_audioOutput) { - m_audioOutput->stop(); - QCoreApplication::instance()->processEvents(); - m_audioOutput->disconnect(); - setPlayPosition(0); - } -} - -void Engine::setState(QAudio::State state) -{ - const bool changed = (m_state != state); - m_state = state; - if (changed) - emit stateChanged(m_mode, m_state); -} - -void Engine::setState(QAudio::Mode mode, QAudio::State state) -{ - const bool changed = (m_mode != mode || m_state != state); - m_mode = mode; - m_state = state; - if (changed) - emit stateChanged(m_mode, m_state); -} - -void Engine::setRecordPosition(qint64 position, bool forceEmit) -{ - const bool changed = (m_recordPosition != position); - m_recordPosition = position; - if (changed || forceEmit) - emit recordPositionChanged(m_recordPosition); -} - -void Engine::setPlayPosition(qint64 position, bool forceEmit) -{ - const bool changed = (m_playPosition != position); - m_playPosition = position; - if (changed || forceEmit) - emit playPositionChanged(m_playPosition); -} - -void Engine::calculateLevel(qint64 position, qint64 length) -{ -#ifdef DISABLE_LEVEL - Q_UNUSED(position) - Q_UNUSED(length) -#else - Q_ASSERT(position + length <= m_bufferPosition + m_dataLength); - - qreal peakLevel = 0.0; - - qreal sum = 0.0; - const char *ptr = m_buffer.constData() + position - m_bufferPosition; - const char *const end = ptr + length; - while (ptr < end) { - const qint16 value = *reinterpret_cast(ptr); - const qreal fracValue = pcmToReal(value); - peakLevel = qMax(peakLevel, fracValue); - sum += fracValue * fracValue; - ptr += 2; - } - const int numSamples = length / 2; - qreal rmsLevel = sqrt(sum / numSamples); - - rmsLevel = qMax(qreal(0.0), rmsLevel); - rmsLevel = qMin(qreal(1.0), rmsLevel); - setLevel(rmsLevel, peakLevel, numSamples); - - ENGINE_DEBUG << "Engine::calculateLevel" << "pos" << position << "len" << length - << "rms" << rmsLevel << "peak" << peakLevel; -#endif -} - -void Engine::calculateSpectrum(qint64 position) -{ -#ifdef DISABLE_SPECTRUM - Q_UNUSED(position) -#else - Q_ASSERT(position + m_spectrumBufferLength <= m_bufferPosition + m_dataLength); - Q_ASSERT(0 == m_spectrumBufferLength % 2); // constraint of FFT algorithm - - // QThread::currentThread is marked 'for internal use only', but - // we're only using it for debug output here, so it's probably OK :) - ENGINE_DEBUG << "Engine::calculateSpectrum" << QThread::currentThread() - << "count" << m_count << "pos" << position << "len" << m_spectrumBufferLength - << "spectrumAnalyser.isReady" << m_spectrumAnalyser.isReady(); - - if (m_spectrumAnalyser.isReady()) { - m_spectrumBuffer = QByteArray::fromRawData(m_buffer.constData() + position - m_bufferPosition, - m_spectrumBufferLength); - m_spectrumPosition = position; - m_spectrumAnalyser.calculate(m_spectrumBuffer, m_format); - } -#endif -} - -void Engine::setFormat(const QAudioFormat &format) -{ - const bool changed = (format != m_format); - m_format = format; - m_levelBufferLength = audioLength(m_format, LevelWindowUs); - m_spectrumBufferLength = SpectrumLengthSamples * - (m_format.sampleSize() / 8) * m_format.channelCount(); - if (changed) - emit formatChanged(m_format); -} - -void Engine::setLevel(qreal rmsLevel, qreal peakLevel, int numSamples) -{ - m_rmsLevel = rmsLevel; - m_peakLevel = peakLevel; - emit levelChanged(m_rmsLevel, m_peakLevel, numSamples); -} diff --git a/tests/manual/spectrum/spectrumapp/engine.h b/tests/manual/spectrum/spectrumapp/engine.h deleted file mode 100644 index fb8450e0..00000000 --- a/tests/manual/spectrum/spectrumapp/engine.h +++ /dev/null @@ -1,250 +0,0 @@ -/****************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Data Visualization module. -** -** $QT_BEGIN_LICENSE:COMM$ -** -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** $QT_END_LICENSE$ -** -******************************************************************************/ - -#ifndef ENGINE_H -#define ENGINE_H - -#include "spectrum.h" -#include "spectrumanalyser.h" -#include "wavfile.h" - -#include -#include -#include -#include -#include -#include -#include - -class FrequencySpectrum; -QT_BEGIN_NAMESPACE -class QAudioInput; -class QAudioOutput; -QT_END_NAMESPACE - -/** - * 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: - explicit Engine(QObject *parent = 0); - ~Engine(); - - const QList &availableAudioInputDevices() const - { return m_availableAudioInputDevices; } - - const QList &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); - - /** - * 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 Q_SLOTS: - void startRecording(); - void startPlayback(); - void suspend(); - void setAudioInputDevice(const QAudioDeviceInfo &device); - void setAudioOutputDevice(const QAudioDeviceInfo &device); - -Q_SIGNALS: - void stateChanged(QAudio::Mode mode, QAudio::State state); - - /** - * 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 changedSpectrum(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 Q_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); - -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 m_availableAudioInputDevices; - QAudioDeviceInfo m_audioInputDevice; - QAudioInput* m_audioInput; - QIODevice* m_audioInputIODevice; - qint64 m_recordPosition; - - const QList 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; - -}; - -#endif // ENGINE_H diff --git a/tests/manual/spectrum/spectrumapp/frequencyspectrum.cpp b/tests/manual/spectrum/spectrumapp/frequencyspectrum.cpp deleted file mode 100644 index 39e7e822..00000000 --- a/tests/manual/spectrum/spectrumapp/frequencyspectrum.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/****************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Data Visualization module. -** -** $QT_BEGIN_LICENSE:COMM$ -** -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** $QT_END_LICENSE$ -** -******************************************************************************/ - -#include "frequencyspectrum.h" - -FrequencySpectrum::FrequencySpectrum(int numPoints) - : m_elements(numPoints) -{ - -} - -void FrequencySpectrum::reset() -{ - iterator i = begin(); - for ( ; i != end(); ++i) - *i = Element(); -} - -int FrequencySpectrum::count() const -{ - return m_elements.count(); -} - -FrequencySpectrum::Element &FrequencySpectrum::operator[](int index) -{ - return m_elements[index]; -} - -const FrequencySpectrum::Element &FrequencySpectrum::operator[](int index) const -{ - return m_elements[index]; -} - -FrequencySpectrum::iterator FrequencySpectrum::begin() -{ - return m_elements.begin(); -} - -FrequencySpectrum::iterator FrequencySpectrum::end() -{ - return m_elements.end(); -} - -FrequencySpectrum::const_iterator FrequencySpectrum::begin() const -{ - return m_elements.begin(); -} - -FrequencySpectrum::const_iterator FrequencySpectrum::end() const -{ - return m_elements.end(); -} diff --git a/tests/manual/spectrum/spectrumapp/frequencyspectrum.h b/tests/manual/spectrum/spectrumapp/frequencyspectrum.h deleted file mode 100644 index 229f58a0..00000000 --- a/tests/manual/spectrum/spectrumapp/frequencyspectrum.h +++ /dev/null @@ -1,79 +0,0 @@ -/****************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Data Visualization module. -** -** $QT_BEGIN_LICENSE:COMM$ -** -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** $QT_END_LICENSE$ -** -******************************************************************************/ - -#ifndef FREQUENCYSPECTRUM_H -#define FREQUENCYSPECTRUM_H - -#include - -/** - * Represents a frequency spectrum as a series of elements, each of which - * consists of a frequency, an amplitude and a phase. - */ -class FrequencySpectrum { -public: - FrequencySpectrum(int numPoints = 0); - - struct Element { - Element() - : frequency(0.0), amplitude(0.0), phase(0.0), clipped(false) - { } - - /** - * Frequency in Hertz - */ - qreal frequency; - - /** - * Amplitude in range [0.0, 1.0] - */ - qreal amplitude; - - /** - * Phase in range [0.0, 2*PI] - */ - qreal phase; - - /** - * Indicates whether value has been clipped during spectrum analysis - */ - bool clipped; - }; - - typedef QVector::iterator iterator; - typedef QVector::const_iterator const_iterator; - - void reset(); - - int count() const; - Element& operator[](int index); - const Element& operator[](int index) const; - iterator begin(); - iterator end(); - const_iterator begin() const; - const_iterator end() const; - -private: - QVector m_elements; - -}; - -#endif // FREQUENCYSPECTRUM_H diff --git a/tests/manual/spectrum/spectrumapp/main.cpp b/tests/manual/spectrum/spectrumapp/main.cpp deleted file mode 100644 index e9548b4e..00000000 --- a/tests/manual/spectrum/spectrumapp/main.cpp +++ /dev/null @@ -1,212 +0,0 @@ -/****************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Data Visualization module. -** -** $QT_BEGIN_LICENSE:COMM$ -** -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** $QT_END_LICENSE$ -** -******************************************************************************/ - -#include "engine.h" -#include "utils.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -//#define USE_CONES - -using namespace QtDataVisualization; - -class MainApp : public QObject -{ -public: - MainApp(Q3DBars *window); - ~MainApp(); - - void start(QString fileName); - -public slots: - void spectrumChanged(qint64 position, qint64 length, const FrequencySpectrum &spectrum); - void stateChanged(QAudio::Mode mode, QAudio::State state); - -private slots: - void restart(); - -private: - int barIndex(qreal frequency) const; - -private: - Q3DBars *m_chart; - Engine *m_engine; - QTimer *m_restartTimer; - // Lower bound of first band in the spectrum in Hz - qreal m_lowFreq; - // Upper band of last band in the spectrum in Hz - qreal m_highFreq; -}; - -MainApp::MainApp(Q3DBars *window) - : m_chart(window), - m_engine(new Engine(this)), - m_restartTimer(new QTimer(this)), - m_lowFreq(SpectrumLowFreq), - m_highFreq(SpectrumHighFreq) -{ - m_chart->rowAxis()->setMax(SpectrumNumBands * 2); - m_chart->columnAxis()->setMax(SpectrumNumBands - 1); - // Disable grid - m_chart->activeTheme()->setGridEnabled(false); - // Disable auto-scaling of height by defining explicit range - m_chart->valueAxis()->setRange(0.0f, 1.0f); - // Disable shadows - m_chart->setShadowQuality(QAbstract3DGraph::ShadowQualityNone); -#if USE_CONES - // Set bar specifications; make them a bit wider than deep and make them be drawn 75% - // inside each other - m_chart->setBarThickness(1.25); - m_chart->setBarSpacing(QSizeF(0.2, -0.75)); - // Set bar type, smooth cones - m_chart->setBarType(QAbstract3DGraph::MeshCones, true); - // Adjust zoom manually; automatic zoom level calculation does not work well with negative - // spacings (in setBarSpacing) - m_chart->setCameraPosition(10.0f, 5.0f, 70.0f); -#else - // Set bar specifications; make them twice as wide as they're deep - m_chart->setBarThickness(2.0f); - m_chart->setBarSpacing(QSizeF(0.0, 0.0)); - // Set bar type, flat bars - // Adjust camera position - m_chart->scene()->activeCamera()->setCameraPosition(10.0f, 7.5f, 75.0f); -#endif - // Disable selection - m_chart->setSelectionMode(QAbstract3DGraph::SelectionNone); - QObject::connect(m_engine, &Engine::changedSpectrum, this, &MainApp::spectrumChanged); - QObject::connect(m_engine, &Engine::stateChanged, this, &MainApp::stateChanged); - m_restartTimer->setSingleShot(true); - QObject::connect(m_restartTimer, &QTimer::timeout, this, &MainApp::restart); - - QBar3DSeries *series = new QBar3DSeries(); - series->setBaseColor(QColor(Qt::red)); - series->setMesh(QAbstract3DSeries::MeshBar); - m_chart->addSeries(series); -} - -MainApp::~MainApp() -{ - delete m_engine; - delete m_restartTimer; -} - -void MainApp::start(QString fileName) -{ - m_engine->loadFile(fileName); - m_engine->startPlayback(); -} - -//----------------------------------------------------------------------------- -// Public slots -//----------------------------------------------------------------------------- - -void MainApp::spectrumChanged(qint64 position, qint64 length, const FrequencySpectrum &spectrum) -{ - Q_UNUSED(position); - Q_UNUSED(length); - //qDebug() << "updating bar values" << position << length; - QBarDataRow *data = new QBarDataRow(SpectrumNumBands); - for (int bar = 0; bar < SpectrumNumBands; bar++) { - // init data set - (*data)[bar].setValue(qreal(0.0)); - } - FrequencySpectrum::const_iterator i = spectrum.begin(); - const FrequencySpectrum::const_iterator end = spectrum.end(); - for ( ; i != end; ++i) { - const FrequencySpectrum::Element e = *i; - if (e.frequency >= m_lowFreq && e.frequency < m_highFreq) { - (*data)[barIndex(e.frequency)].setValue(qMax(data->at(barIndex(e.frequency)).value(), float(e.amplitude))); - } - } - m_chart->seriesList().at(0)->dataProxy()->insertRow(0, data); -} - -void MainApp::stateChanged(QAudio::Mode mode, QAudio::State state) -{ - //qDebug() << "mode:" << mode << " state: " << state; - // Restart once playback is finished - if (QAudio::AudioOutput == mode && QAudio::StoppedState == state) - m_restartTimer->start(500); -} - -//----------------------------------------------------------------------------- -// Private slots -//----------------------------------------------------------------------------- - -void MainApp::restart() -{ - // Change file each time - QString fileToLoad = QStringLiteral(":/file"); - static int fileNo = 3; - QString nrStr; - nrStr.setNum(fileNo); - fileToLoad.append(nrStr); - //qDebug() << fileToLoad; - start(fileToLoad); - fileNo++; - if (fileNo > 3) - fileNo = 1; -} - -//----------------------------------------------------------------------------- -// Private functions -//----------------------------------------------------------------------------- - -int MainApp::barIndex(qreal frequency) const -{ - Q_ASSERT(frequency >= m_lowFreq && frequency < m_highFreq); - const qreal bandWidth = (m_highFreq - m_lowFreq) / SpectrumNumBands; - const int index = (frequency - m_lowFreq) / bandWidth; - if (index < 0 || index >= SpectrumNumBands) - Q_ASSERT(false); - //qDebug() << "insert to" << index; - return index; -} - -//----------------------------------------------------------------------------- -// main -//----------------------------------------------------------------------------- -int main(int argc, char *argv[]) -{ - QGuiApplication app(argc, argv); - app.setApplicationName("QtDataVisualization spectrum analyzer"); - - Q3DBars window; - window.setFlags(window.flags() ^ Qt::FramelessWindowHint); - window.resize(1024, 768); - window.show(); - - MainApp *mainApp = new MainApp(&window); - mainApp->start(QStringLiteral(":/file2")); - - return app.exec(); -} diff --git a/tests/manual/spectrum/spectrumapp/soundFiles/Rockhop.wav b/tests/manual/spectrum/spectrumapp/soundFiles/Rockhop.wav deleted file mode 100644 index e56e1c0f..00000000 Binary files a/tests/manual/spectrum/spectrumapp/soundFiles/Rockhop.wav and /dev/null differ diff --git a/tests/manual/spectrum/spectrumapp/soundFiles/futurebells_beat.wav b/tests/manual/spectrum/spectrumapp/soundFiles/futurebells_beat.wav deleted file mode 100644 index c45cbc71..00000000 Binary files a/tests/manual/spectrum/spectrumapp/soundFiles/futurebells_beat.wav and /dev/null differ diff --git a/tests/manual/spectrum/spectrumapp/soundFiles/onclassical_demo_fiati-di-parma_thuille_terzo-tempo_sestetto_small-version.wav b/tests/manual/spectrum/spectrumapp/soundFiles/onclassical_demo_fiati-di-parma_thuille_terzo-tempo_sestetto_small-version.wav deleted file mode 100644 index 78b8dbda..00000000 Binary files a/tests/manual/spectrum/spectrumapp/soundFiles/onclassical_demo_fiati-di-parma_thuille_terzo-tempo_sestetto_small-version.wav and /dev/null differ diff --git a/tests/manual/spectrum/spectrumapp/spectrum.h b/tests/manual/spectrum/spectrumapp/spectrum.h deleted file mode 100644 index 8b072568..00000000 --- a/tests/manual/spectrum/spectrumapp/spectrum.h +++ /dev/null @@ -1,114 +0,0 @@ -/****************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Data Visualization module. -** -** $QT_BEGIN_LICENSE:COMM$ -** -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** $QT_END_LICENSE$ -** -******************************************************************************/ - -#ifndef SPECTRUM_H -#define SPECTRUM_H - -#include "utils.h" -#include "fftreal_wrapper.h" // For FFTLengthPowerOfTwo -#include - -//----------------------------------------------------------------------------- -// Constants -//----------------------------------------------------------------------------- - -// Number of audio samples used to calculate the frequency spectrum -const int SpectrumLengthSamples = PowerOfTwo::Result; - -// Number of bands in the frequency spectrum -const int SpectrumNumBands = 30; - -// Lower bound of first band in the spectrum -const qreal SpectrumLowFreq = 0.0; // Hz - -// Upper band of last band in the spectrum -const qreal SpectrumHighFreq = 1000.0; // Hz - -// Waveform window size in microseconds -const qint64 WaveformWindowDuration = 500 * 1000; - -// Fudge factor used to calculate the spectrum bar heights -const qreal SpectrumAnalyserMultiplier = 0.15; - -// Disable message timeout -const int NullMessageTimeout = -1; - - -//----------------------------------------------------------------------------- -// Types and data structures -//----------------------------------------------------------------------------- - -enum WindowFunction { - NoWindow, - HannWindow -}; - -const WindowFunction DefaultWindowFunction = HannWindow; - -struct Tone -{ - Tone(qreal freq = 0.0, qreal amp = 0.0) - : frequency(freq), amplitude(amp) - { } - - // Start and end frequencies for swept tone generation - qreal frequency; - - // Amplitude in range [0.0, 1.0] - qreal amplitude; -}; - -struct SweptTone -{ - SweptTone(qreal start = 0.0, qreal end = 0.0, qreal amp = 0.0) - : startFreq(start), endFreq(end), amplitude(amp) - { Q_ASSERT(end >= start); } - - SweptTone(const Tone &tone) - : startFreq(tone.frequency), endFreq(tone.frequency), amplitude(tone.amplitude) - { } - - // Start and end frequencies for swept tone generation - qreal startFreq; - qreal endFreq; - - // Amplitude in range [0.0, 1.0] - qreal amplitude; -}; - - -//----------------------------------------------------------------------------- -// Macros -//----------------------------------------------------------------------------- - -// Macro which connects a signal to a slot, and which causes application to -// abort if the connection fails. This is intended to catch programming errors -// such as mis-typing a signal or slot name. It is necessary to write our own -// macro to do this - the following idiom -// Q_ASSERT(connect(source, signal, receiver, slot)); -// will not work because Q_ASSERT compiles to a no-op in release builds. - -#define CHECKED_CONNECT(source, signal, receiver, slot) \ - if (!connect(source, signal, receiver, slot)) \ - qt_assert_x(Q_FUNC_INFO, "CHECKED_CONNECT failed", __FILE__, __LINE__); - -#endif // SPECTRUM_H - diff --git a/tests/manual/spectrum/spectrumapp/spectrum.qrc b/tests/manual/spectrum/spectrumapp/spectrum.qrc deleted file mode 100644 index 9368abc7..00000000 --- a/tests/manual/spectrum/spectrumapp/spectrum.qrc +++ /dev/null @@ -1,7 +0,0 @@ - - - soundFiles/onclassical_demo_fiati-di-parma_thuille_terzo-tempo_sestetto_small-version.wav - soundFiles/Rockhop.wav - soundFiles/futurebells_beat.wav - - diff --git a/tests/manual/spectrum/spectrumapp/spectrumanalyser.cpp b/tests/manual/spectrum/spectrumapp/spectrumanalyser.cpp deleted file mode 100644 index 37f2e175..00000000 --- a/tests/manual/spectrum/spectrumapp/spectrumanalyser.cpp +++ /dev/null @@ -1,212 +0,0 @@ -/****************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Data Visualization module. -** -** $QT_BEGIN_LICENSE:COMM$ -** -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** $QT_END_LICENSE$ -** -******************************************************************************/ - -#include "spectrumanalyser.h" -#include "utils.h" -#include "fftreal_wrapper.h" - -#include -#include -#include -#include - -SpectrumAnalyserThread::SpectrumAnalyserThread(QObject *parent) - : QObject(parent), - m_fft(new FFTRealWrapper), - m_numSamples(SpectrumLengthSamples), - m_windowFunction(DefaultWindowFunction), - m_window(SpectrumLengthSamples, 0.0), - m_input(SpectrumLengthSamples, 0.0), - m_output(SpectrumLengthSamples, 0.0), - m_spectrum(SpectrumLengthSamples) - #ifdef SPECTRUM_ANALYSER_SEPARATE_THREAD - , m_thread(new QThread(this)) - #endif -{ -#ifdef SPECTRUM_ANALYSER_SEPARATE_THREAD - // moveToThread() cannot be called on a QObject with a parent - setParent(0); - moveToThread(m_thread); - m_thread->start(); -#endif - calculateWindow(); -} - -SpectrumAnalyserThread::~SpectrumAnalyserThread() -{ - delete m_fft; -} - -void SpectrumAnalyserThread::setWindowFunction(WindowFunction type) -{ - m_windowFunction = type; - calculateWindow(); -} - -void SpectrumAnalyserThread::calculateWindow() -{ - for (int i=0; i(ptr); - // Scale down to range [-1.0, 1.0] - const DataType realSample = pcmToReal(pcmSample); - const DataType windowedSample = realSample * m_window[i]; - m_input[i] = windowedSample; - ptr += bytesPerSample; - } - - // Calculate the FFT - m_fft->calculateFFT(m_output.data(), m_input.data()); - - // Analyze output to obtain amplitude and phase for each frequency - for (int i=2; i<=m_numSamples/2; ++i) { - // Calculate frequency of this complex sample - m_spectrum[i].frequency = qreal(i * inputFrequency) / (m_numSamples); - - const qreal real = m_output[i]; - qreal imag = 0.0; - if (i>0 && i 1.0); - amplitude = qMax(qreal(0.0), amplitude); - amplitude = qMin(qreal(1.0), amplitude); - m_spectrum[i].amplitude = amplitude; - } - - emit calculationComplete(m_spectrum); -} - - -//============================================================================= -// SpectrumAnalyser -//============================================================================= - -SpectrumAnalyser::SpectrumAnalyser(QObject *parent) - : QObject(parent), - m_thread(new SpectrumAnalyserThread(this)), - m_state(Idle) -{ - CHECKED_CONNECT(m_thread, SIGNAL(calculationComplete(FrequencySpectrum)), - this, SLOT(calculationComplete(FrequencySpectrum))); -} - -SpectrumAnalyser::~SpectrumAnalyser() -{ - -} - -//----------------------------------------------------------------------------- -// Public functions -//----------------------------------------------------------------------------- - -void SpectrumAnalyser::setWindowFunction(WindowFunction type) -{ - const bool b = QMetaObject::invokeMethod(m_thread, "setWindowFunction", - Qt::AutoConnection, - Q_ARG(WindowFunction, type)); - Q_ASSERT(b); - Q_UNUSED(b) // suppress warnings in release builds -} - -void SpectrumAnalyser::calculate(const QByteArray &buffer, - const QAudioFormat &format) -{ - // QThread::currentThread is marked 'for internal use only', but - // we're only using it for debug output here, so it's probably OK :) - SPECTRUMANALYSER_DEBUG << "SpectrumAnalyser::calculate" - << QThread::currentThread() - << "state" << m_state; - - if (isReady()) { - Q_ASSERT(isPCMS16LE(format)); - - const int bytesPerSample = format.sampleSize() * format.channelCount() / 8; - - m_state = Busy; - - // Invoke SpectrumAnalyserThread::calculateSpectrum using QMetaObject. If - // m_thread is in a different thread from the current thread, the - // calculation will be done in the child thread. - // Once the calculation is finished, a calculationChanged signal will be - // emitted by m_thread. - const bool b = QMetaObject::invokeMethod(m_thread, "calculateSpectrum", - Qt::AutoConnection, - Q_ARG(QByteArray, buffer), - Q_ARG(int, format.sampleRate()), - Q_ARG(int, bytesPerSample)); - Q_ASSERT(b); - Q_UNUSED(b) // suppress warnings in release builds - } -} - -bool SpectrumAnalyser::isReady() const -{ - return (Idle == m_state); -} - -void SpectrumAnalyser::cancelCalculation() -{ - if (Busy == m_state) - m_state = Cancelled; -} - - -//----------------------------------------------------------------------------- -// Private slots -//----------------------------------------------------------------------------- - -void SpectrumAnalyser::calculationComplete(const FrequencySpectrum &spectrum) -{ - Q_ASSERT(Idle != m_state); - if (Busy == m_state) - emit spectrumChanged(spectrum); - m_state = Idle; -} diff --git a/tests/manual/spectrum/spectrumapp/spectrumanalyser.h b/tests/manual/spectrum/spectrumapp/spectrumanalyser.h deleted file mode 100644 index 8eb70a20..00000000 --- a/tests/manual/spectrum/spectrumapp/spectrumanalyser.h +++ /dev/null @@ -1,153 +0,0 @@ -/****************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Data Visualization module. -** -** $QT_BEGIN_LICENSE:COMM$ -** -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** $QT_END_LICENSE$ -** -******************************************************************************/ - -#ifndef SPECTRUMANALYSER_H -#define SPECTRUMANALYSER_H - -#include -#include -#include - -#include "frequencyspectrum.h" -#include "spectrum.h" - -#include "FFTRealFixLenParam.h" - -QT_FORWARD_DECLARE_CLASS(QAudioFormat) -QT_FORWARD_DECLARE_CLASS(QThread) - -class FFTRealWrapper; - -class SpectrumAnalyserThreadPrivate; - -/** - * Implementation of the spectrum analysis which can be run in a - * separate thread. - */ -class SpectrumAnalyserThread : public QObject -{ - Q_OBJECT - -public: - SpectrumAnalyserThread(QObject *parent); - ~SpectrumAnalyserThread(); - -public Q_SLOTS: - void setWindowFunction(WindowFunction type); - void calculateSpectrum(const QByteArray &buffer, - int inputFrequency, - int bytesPerSample); - -Q_SIGNALS: - void calculationComplete(const FrequencySpectrum &spectrum); - -private: - void calculateWindow(); - -private: - FFTRealWrapper* m_fft; - - const int m_numSamples; - - WindowFunction m_windowFunction; - - typedef FFTRealFixLenParam::DataType DataType; - - QVector m_window; - - QVector m_input; - QVector m_output; - - FrequencySpectrum m_spectrum; - -#ifdef SPECTRUM_ANALYSER_SEPARATE_THREAD - QThread* m_thread; -#endif -}; - -/** - * Class which performs frequency spectrum analysis on a window of - * audio samples, provided to it by the Engine. - */ -class SpectrumAnalyser : public QObject -{ - Q_OBJECT - -public: - SpectrumAnalyser(QObject *parent = 0); - ~SpectrumAnalyser(); - -public: - /* - * Set the windowing function which is applied before calculating the FFT - */ - void setWindowFunction(WindowFunction type); - - /* - * Calculate a frequency spectrum - * - * \param buffer Audio data - * \param format Format of audio data - * - * Frequency spectrum is calculated asynchronously. The result is returned - * via the spectrumChanged signal. - * - * An ongoing calculation can be cancelled by calling cancelCalculation(). - * - */ - void calculate(const QByteArray &buffer, const QAudioFormat &format); - - /* - * Check whether the object is ready to perform another calculation - */ - bool isReady() const; - - /* - * Cancel an ongoing calculation - * - * Note that cancelling is asynchronous. - */ - void cancelCalculation(); - -Q_SIGNALS: - void spectrumChanged(const FrequencySpectrum &spectrum); - -private Q_SLOTS: - void calculationComplete(const FrequencySpectrum &spectrum); - -private: - void calculateWindow(); - -private: - - SpectrumAnalyserThread* m_thread; - - enum State { - Idle, - Busy, - Cancelled - }; - - State m_state; -}; - -#endif // SPECTRUMANALYSER_H - diff --git a/tests/manual/spectrum/spectrumapp/spectrumapp.pro b/tests/manual/spectrum/spectrumapp/spectrumapp.pro deleted file mode 100644 index ab12e221..00000000 --- a/tests/manual/spectrum/spectrumapp/spectrumapp.pro +++ /dev/null @@ -1,73 +0,0 @@ -!include( ../../tests.pri ) { - error( "Couldn't find the tests.pri file!" ) -} - -!include( ../spectrum.pri ) { - error( "Couldn't find the spectrum.pri file!" ) -} - -static: error(This application cannot be statically linked to the fftreal library) - -TEMPLATE = app - -TARGET = spectrum - -QT += multimedia - -SOURCES += main.cpp \ - engine.cpp \ - frequencyspectrum.cpp \ - spectrumanalyser.cpp \ - utils.cpp \ - wavfile.cpp - -HEADERS += engine.h \ - frequencyspectrum.h \ - spectrum.h \ - spectrumanalyser.h \ - utils.h \ - wavfile.h - -fftreal_dir = ../3rdparty/fftreal - -INCLUDEPATH += $${fftreal_dir} -INCLUDEPATH += ../../../include - -RESOURCES = spectrum.qrc - -# Dynamic linkage against FFTReal DLL -!contains(DEFINES, DISABLE_FFT) { - macx { - # Link to fftreal framework - LIBS += -F$${fftreal_dir} - LIBS += -framework fftreal - } else { - LIBS += -L..$${spectrum_build_dir} - LIBS += -lfftreal - } -} - -# Deployment - -DESTDIR = ..$${spectrum_build_dir} -macx { - !contains(DEFINES, DISABLE_FFT) { - # Relocate fftreal.framework into spectrum.app bundle - framework_dir = ../spectrum.app/Contents/Frameworks - framework_name = fftreal.framework/Versions/1/fftreal - QMAKE_POST_LINK = \ - mkdir -p $${framework_dir} &&\ - rm -rf $${framework_dir}/fftreal.framework &&\ - cp -R $${fftreal_dir}/fftreal.framework $${framework_dir} &&\ - install_name_tool -id @executable_path/../Frameworks/$${framework_name} \ - $${framework_dir}/$${framework_name} &&\ - install_name_tool -change $${framework_name} \ - @executable_path/../Frameworks/$${framework_name} \ - ../spectrum.app/Contents/MacOS/spectrum - } -} else { - linux-g++*: { - # Provide relative path from application to fftreal library - QMAKE_LFLAGS += -Wl,--rpath=\\\$\$ORIGIN - } -} diff --git a/tests/manual/spectrum/spectrumapp/utils.cpp b/tests/manual/spectrum/spectrumapp/utils.cpp deleted file mode 100644 index 95a55544..00000000 --- a/tests/manual/spectrum/spectrumapp/utils.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/****************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Data Visualization module. -** -** $QT_BEGIN_LICENSE:COMM$ -** -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** $QT_END_LICENSE$ -** -******************************************************************************/ - -#include -#include "utils.h" - -qint64 audioDuration(const QAudioFormat &format, qint64 bytes) -{ - return (bytes * 1000000) / - (format.sampleRate() * format.channelCount() * (format.sampleSize() / 8)); -} - -qint64 audioLength(const QAudioFormat &format, qint64 microSeconds) -{ - qint64 result = (format.sampleRate() * format.channelCount() * (format.sampleSize() / 8)) - * microSeconds / 1000000; - result -= result % (format.channelCount() * format.sampleSize()); - return result; -} - -qreal nyquistFrequency(const QAudioFormat &format) -{ - return format.sampleRate() / 2; -} - -QString formatToString(const QAudioFormat &format) -{ - QString result; - - if (QAudioFormat() != format) { - if (format.codec() == "audio/pcm") { - Q_ASSERT(format.sampleType() == QAudioFormat::SignedInt); - - const QString formatEndian = (format.byteOrder() == QAudioFormat::LittleEndian) - ? QString("LE") : QString("BE"); - - QString formatType; - switch (format.sampleType()) { - case QAudioFormat::SignedInt: - formatType = "signed"; - break; - case QAudioFormat::UnSignedInt: - formatType = "unsigned"; - break; - case QAudioFormat::Float: - formatType = "float"; - break; - case QAudioFormat::Unknown: - formatType = "unknown"; - break; - } - - QString formatChannels = QString("%1 channels").arg(format.channelCount()); - switch (format.channelCount()) { - case 1: - formatChannels = "mono"; - break; - case 2: - formatChannels = "stereo"; - break; - } - - result = QString("%1 Hz %2 bit %3 %4 %5") - .arg(format.sampleRate()) - .arg(format.sampleSize()) - .arg(formatType) - .arg(formatEndian) - .arg(formatChannels); - } else { - result = format.codec(); - } - } - - return result; -} - -bool isPCM(const QAudioFormat &format) -{ - return (format.codec() == "audio/pcm"); -} - - -bool isPCMS16LE(const QAudioFormat &format) -{ - return isPCM(format) && - format.sampleType() == QAudioFormat::SignedInt && - format.sampleSize() == 16 && - format.byteOrder() == QAudioFormat::LittleEndian; -} - -const qint16 PCMS16MaxValue = 32767; -const quint16 PCMS16MaxAmplitude = 32768; // because minimum is -32768 - -qreal pcmToReal(qint16 pcm) -{ - return qreal(pcm) / PCMS16MaxAmplitude; -} - -qint16 realToPcm(qreal real) -{ - return real * PCMS16MaxValue; -} diff --git a/tests/manual/spectrum/spectrumapp/utils.h b/tests/manual/spectrum/spectrumapp/utils.h deleted file mode 100644 index 8c6ee151..00000000 --- a/tests/manual/spectrum/spectrumapp/utils.h +++ /dev/null @@ -1,93 +0,0 @@ -/****************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Data Visualization module. -** -** $QT_BEGIN_LICENSE:COMM$ -** -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** $QT_END_LICENSE$ -** -******************************************************************************/ - -#ifndef UTILS_H -#define UTILS_H - -#include -#include - -QT_FORWARD_DECLARE_CLASS(QAudioFormat) - -//----------------------------------------------------------------------------- -// Miscellaneous utility functions -//----------------------------------------------------------------------------- - -qint64 audioDuration(const QAudioFormat &format, qint64 bytes); -qint64 audioLength(const QAudioFormat &format, qint64 microSeconds); - -QString formatToString(const QAudioFormat &format); - -qreal nyquistFrequency(const QAudioFormat &format); - -// Scale PCM value to [-1.0, 1.0] -qreal pcmToReal(qint16 pcm); - -// Scale real value in [-1.0, 1.0] to PCM -qint16 realToPcm(qreal real); - -// Check whether the audio format is PCM -bool isPCM(const QAudioFormat &format); - -// Check whether the audio format is signed, little-endian, 16-bit PCM -bool isPCMS16LE(const QAudioFormat &format); - -// Compile-time calculation of powers of two - -template class PowerOfTwo -{ public: static const int Result = PowerOfTwo::Result * 2; }; - -template<> class PowerOfTwo<0> -{ public: static const int Result = 1; }; - - -//----------------------------------------------------------------------------- -// Debug output -//----------------------------------------------------------------------------- - -class NullDebug -{ -public: - template - NullDebug& operator<<(const T&) { return *this; } -}; - -inline NullDebug nullDebug() { return NullDebug(); } - -#ifdef LOG_ENGINE -# define ENGINE_DEBUG qDebug() -#else -# define ENGINE_DEBUG nullDebug() -#endif - -#ifdef LOG_SPECTRUMANALYSER -# define SPECTRUMANALYSER_DEBUG qDebug() -#else -# define SPECTRUMANALYSER_DEBUG nullDebug() -#endif - -#ifdef LOG_WAVEFORM -# define WAVEFORM_DEBUG qDebug() -#else -# define WAVEFORM_DEBUG nullDebug() -#endif - -#endif // UTILS_H diff --git a/tests/manual/spectrum/spectrumapp/wavfile.cpp b/tests/manual/spectrum/spectrumapp/wavfile.cpp deleted file mode 100644 index 373cdbb1..00000000 --- a/tests/manual/spectrum/spectrumapp/wavfile.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/****************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Data Visualization module. -** -** $QT_BEGIN_LICENSE:COMM$ -** -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** $QT_END_LICENSE$ -** -******************************************************************************/ - -#include -#include -#include -#include "utils.h" -#include "wavfile.h" - -struct chunk -{ - char id[4]; - quint32 size; -}; - -struct RIFFHeader -{ - chunk descriptor; // "RIFF" - char type[4]; // "WAVE" -}; - -struct WAVEHeader -{ - chunk descriptor; - quint16 audioFormat; - quint16 numChannels; - quint32 sampleRate; - quint32 byteRate; - quint16 blockAlign; - quint16 bitsPerSample; -}; - -struct DATAHeader -{ - chunk descriptor; -}; - -struct CombinedHeader -{ - RIFFHeader riff; - WAVEHeader wave; -}; - -WavFile::WavFile(QObject *parent) - : QFile(parent), - m_headerLength(0) -{ - -} - -bool WavFile::open(const QString &fileName) -{ - close(); - setFileName(fileName); - return QFile::open(QIODevice::ReadOnly) && readHeader(); -} - -const QAudioFormat &WavFile::fileFormat() const -{ - return m_fileFormat; -} - -qint64 WavFile::headerLength() const -{ - return m_headerLength; -} - -bool WavFile::readHeader() -{ - seek(0); - CombinedHeader header; - bool result = read(reinterpret_cast(&header), sizeof(CombinedHeader)) == sizeof(CombinedHeader); - if (result) { - if ((memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0 - || memcmp(&header.riff.descriptor.id, "RIFX", 4) == 0) - && memcmp(&header.riff.type, "WAVE", 4) == 0 - && memcmp(&header.wave.descriptor.id, "fmt ", 4) == 0 - && (header.wave.audioFormat == 1 || header.wave.audioFormat == 0)) { - - // Read off remaining header information - DATAHeader dataHeader; - - if (qFromLittleEndian(header.wave.descriptor.size) > sizeof(WAVEHeader)) { - // Extended data available - quint16 extraFormatBytes; - if (peek((char*)&extraFormatBytes, sizeof(quint16)) != sizeof(quint16)) - return false; - const qint64 throwAwayBytes = sizeof(quint16) + qFromLittleEndian(extraFormatBytes); - if (read(throwAwayBytes).size() != throwAwayBytes) - return false; - } - - if (read((char*)&dataHeader, sizeof(DATAHeader)) != sizeof(DATAHeader)) - return false; - - // Establish format - if (memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0) - m_fileFormat.setByteOrder(QAudioFormat::LittleEndian); - else - m_fileFormat.setByteOrder(QAudioFormat::BigEndian); - - int bps = qFromLittleEndian(header.wave.bitsPerSample); - m_fileFormat.setChannelCount(qFromLittleEndian(header.wave.numChannels)); - m_fileFormat.setCodec("audio/pcm"); - m_fileFormat.setSampleRate(qFromLittleEndian(header.wave.sampleRate)); - m_fileFormat.setSampleSize(qFromLittleEndian(header.wave.bitsPerSample)); - m_fileFormat.setSampleType(bps == 8 ? QAudioFormat::UnSignedInt : QAudioFormat::SignedInt); - } else { - result = false; - } - } - m_headerLength = pos(); - return result; -} diff --git a/tests/manual/spectrum/spectrumapp/wavfile.h b/tests/manual/spectrum/spectrumapp/wavfile.h deleted file mode 100644 index 38e81f6e..00000000 --- a/tests/manual/spectrum/spectrumapp/wavfile.h +++ /dev/null @@ -1,47 +0,0 @@ -/****************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Data Visualization module. -** -** $QT_BEGIN_LICENSE:COMM$ -** -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** $QT_END_LICENSE$ -** -******************************************************************************/ - -#ifndef WAVFILE_H -#define WAVFILE_H - -#include -#include -#include - -class WavFile : public QFile -{ -public: - WavFile(QObject *parent = 0); - - using QFile::open; - bool open(const QString &fileName); - const QAudioFormat &fileFormat() const; - qint64 headerLength() const; - -private: - bool readHeader(); - -private: - QAudioFormat m_fileFormat; - qint64 m_headerLength; -}; - -#endif // WAVFILE_H -- cgit v1.2.3