mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 05:58:27 +02:00
Merge pull request #2640 from birarda/kill-scope
remove the audio scope
This commit is contained in:
commit
3b2b075414
8 changed files with 3 additions and 311 deletions
|
@ -150,7 +150,6 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
||||||
_viewFrustum(),
|
_viewFrustum(),
|
||||||
_lastQueriedViewFrustum(),
|
_lastQueriedViewFrustum(),
|
||||||
_lastQueriedTime(usecTimestampNow()),
|
_lastQueriedTime(usecTimestampNow()),
|
||||||
_audioScope(256, 200, true),
|
|
||||||
_mirrorViewRect(QRect(MIRROR_VIEW_LEFT_PADDING, MIRROR_VIEW_TOP_PADDING, MIRROR_VIEW_WIDTH, MIRROR_VIEW_HEIGHT)),
|
_mirrorViewRect(QRect(MIRROR_VIEW_LEFT_PADDING, MIRROR_VIEW_TOP_PADDING, MIRROR_VIEW_WIDTH, MIRROR_VIEW_HEIGHT)),
|
||||||
_mouseX(0),
|
_mouseX(0),
|
||||||
_mouseY(0),
|
_mouseY(0),
|
||||||
|
@ -161,7 +160,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
||||||
_touchAvgY(0.0f),
|
_touchAvgY(0.0f),
|
||||||
_isTouchPressed(false),
|
_isTouchPressed(false),
|
||||||
_mousePressed(false),
|
_mousePressed(false),
|
||||||
_audio(&_audioScope, STARTUP_JITTER_SAMPLES),
|
_audio(STARTUP_JITTER_SAMPLES),
|
||||||
_enableProcessVoxelsThread(true),
|
_enableProcessVoxelsThread(true),
|
||||||
_voxelProcessor(),
|
_voxelProcessor(),
|
||||||
_voxelHideShowThread(&_voxels),
|
_voxelHideShowThread(&_voxels),
|
||||||
|
@ -744,9 +743,6 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
||||||
case Qt::Key_Period:
|
case Qt::Key_Period:
|
||||||
Menu::getInstance()->handleViewFrustumOffsetKeyModifier(event->key());
|
Menu::getInstance()->handleViewFrustumOffsetKeyModifier(event->key());
|
||||||
break;
|
break;
|
||||||
case Qt::Key_Apostrophe:
|
|
||||||
_audioScope.inputPaused = !_audioScope.inputPaused;
|
|
||||||
break;
|
|
||||||
case Qt::Key_L:
|
case Qt::Key_L:
|
||||||
if (isShifted) {
|
if (isShifted) {
|
||||||
Menu::getInstance()->triggerOption(MenuOption::LodTools);
|
Menu::getInstance()->triggerOption(MenuOption::LodTools);
|
||||||
|
@ -2509,15 +2505,6 @@ void Application::displayOverlay() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Audio Scope
|
|
||||||
const int AUDIO_SCOPE_Y_OFFSET = 135;
|
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Stats)) {
|
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Oscilloscope)) {
|
|
||||||
int oscilloscopeTop = _glWidget->height() - AUDIO_SCOPE_Y_OFFSET;
|
|
||||||
_audioScope.render(MIRROR_VIEW_LEFT_PADDING, oscilloscopeTop);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Audio VU Meter and Mute Icon
|
// Audio VU Meter and Mute Icon
|
||||||
const int MUTE_ICON_SIZE = 24;
|
const int MUTE_ICON_SIZE = 24;
|
||||||
const int AUDIO_METER_INSET = 2;
|
const int AUDIO_METER_INSET = 2;
|
||||||
|
|
|
@ -407,7 +407,6 @@ private:
|
||||||
ViewFrustum _shadowViewFrustum;
|
ViewFrustum _shadowViewFrustum;
|
||||||
quint64 _lastQueriedTime;
|
quint64 _lastQueriedTime;
|
||||||
|
|
||||||
Oscilloscope _audioScope;
|
|
||||||
float _trailingAudioLoudness;
|
float _trailingAudioLoudness;
|
||||||
|
|
||||||
OctreeQuery _octreeQuery; // NodeData derived class for querying voxels from voxel server
|
OctreeQuery _octreeQuery; // NodeData derived class for querying voxels from voxel server
|
||||||
|
|
|
@ -50,7 +50,7 @@ static const int NUMBER_OF_NOISE_SAMPLE_FRAMES = 300;
|
||||||
// Mute icon configration
|
// Mute icon configration
|
||||||
static const int MUTE_ICON_SIZE = 24;
|
static const int MUTE_ICON_SIZE = 24;
|
||||||
|
|
||||||
Audio::Audio(Oscilloscope* scope, int16_t initialJitterBufferSamples, QObject* parent) :
|
Audio::Audio(int16_t initialJitterBufferSamples, QObject* parent) :
|
||||||
AbstractAudioInterface(parent),
|
AbstractAudioInterface(parent),
|
||||||
_audioInput(NULL),
|
_audioInput(NULL),
|
||||||
_desiredInputFormat(),
|
_desiredInputFormat(),
|
||||||
|
@ -67,7 +67,6 @@ Audio::Audio(Oscilloscope* scope, int16_t initialJitterBufferSamples, QObject* p
|
||||||
_proceduralOutputDevice(NULL),
|
_proceduralOutputDevice(NULL),
|
||||||
_inputRingBuffer(0),
|
_inputRingBuffer(0),
|
||||||
_ringBuffer(NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL),
|
_ringBuffer(NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL),
|
||||||
_scope(scope),
|
|
||||||
_averagedLatency(0.0),
|
_averagedLatency(0.0),
|
||||||
_measuredJitter(0),
|
_measuredJitter(0),
|
||||||
_jitterBufferSamples(initialJitterBufferSamples),
|
_jitterBufferSamples(initialJitterBufferSamples),
|
||||||
|
@ -555,12 +554,6 @@ void Audio::handleAudioInput() {
|
||||||
_lastInputLoudness = 0;
|
_lastInputLoudness = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// add input data just written to the scope
|
|
||||||
QMetaObject::invokeMethod(_scope, "addSamples", Qt::QueuedConnection,
|
|
||||||
Q_ARG(QByteArray, QByteArray((char*) monoAudioSamples,
|
|
||||||
NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL)),
|
|
||||||
Q_ARG(bool, false), Q_ARG(bool, true));
|
|
||||||
} else {
|
} else {
|
||||||
// our input loudness is 0, since we're muted
|
// our input loudness is 0, since we're muted
|
||||||
_lastInputLoudness = 0;
|
_lastInputLoudness = 0;
|
||||||
|
@ -724,11 +717,6 @@ void Audio::processReceivedAudio(const QByteArray& audioByteArray) {
|
||||||
|
|
||||||
if (_outputDevice) {
|
if (_outputDevice) {
|
||||||
_outputDevice->write(outputBuffer);
|
_outputDevice->write(outputBuffer);
|
||||||
|
|
||||||
// add output (@speakers) data just written to the scope
|
|
||||||
QMetaObject::invokeMethod(_scope, "addSamples", Qt::QueuedConnection,
|
|
||||||
Q_ARG(QByteArray, QByteArray((char*) ringBufferSamples, numNetworkOutputSamples)),
|
|
||||||
Q_ARG(bool, true), Q_ARG(bool, false));
|
|
||||||
}
|
}
|
||||||
delete[] ringBufferSamples;
|
delete[] ringBufferSamples;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,9 +34,6 @@
|
||||||
#include <AudioRingBuffer.h>
|
#include <AudioRingBuffer.h>
|
||||||
#include <StdDev.h>
|
#include <StdDev.h>
|
||||||
|
|
||||||
#include "ui/Oscilloscope.h"
|
|
||||||
|
|
||||||
|
|
||||||
static const int NUM_AUDIO_CHANNELS = 2;
|
static const int NUM_AUDIO_CHANNELS = 2;
|
||||||
|
|
||||||
class QAudioInput;
|
class QAudioInput;
|
||||||
|
@ -47,7 +44,7 @@ class Audio : public AbstractAudioInterface {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
// setup for audio I/O
|
// setup for audio I/O
|
||||||
Audio(Oscilloscope* scope, int16_t initialJitterBufferSamples, QObject* parent = 0);
|
Audio(int16_t initialJitterBufferSamples, QObject* parent = 0);
|
||||||
|
|
||||||
float getLastInputLoudness() const { return glm::max(_lastInputLoudness - _noiseGateMeasuredFloor, 0.f); }
|
float getLastInputLoudness() const { return glm::max(_lastInputLoudness - _noiseGateMeasuredFloor, 0.f); }
|
||||||
float getTimeSinceLastClip() const { return _timeSinceLastClip; }
|
float getTimeSinceLastClip() const { return _timeSinceLastClip; }
|
||||||
|
@ -126,7 +123,6 @@ private:
|
||||||
QString _inputAudioDeviceName;
|
QString _inputAudioDeviceName;
|
||||||
QString _outputAudioDeviceName;
|
QString _outputAudioDeviceName;
|
||||||
|
|
||||||
Oscilloscope* _scope;
|
|
||||||
StDev _stdev;
|
StDev _stdev;
|
||||||
timeval _lastReceiveTime;
|
timeval _lastReceiveTime;
|
||||||
float _averagedLatency;
|
float _averagedLatency;
|
||||||
|
|
|
@ -252,7 +252,6 @@ Menu::Menu() :
|
||||||
addDisabledActionAndSeparator(viewMenu, "Stats");
|
addDisabledActionAndSeparator(viewMenu, "Stats");
|
||||||
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Stats, Qt::Key_Slash);
|
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Stats, Qt::Key_Slash);
|
||||||
addActionToQMenuAndActionHash(viewMenu, MenuOption::Log, Qt::CTRL | Qt::Key_L, appInstance, SLOT(toggleLogDialog()));
|
addActionToQMenuAndActionHash(viewMenu, MenuOption::Log, Qt::CTRL | Qt::Key_L, appInstance, SLOT(toggleLogDialog()));
|
||||||
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Oscilloscope, 0, false);
|
|
||||||
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Bandwidth, 0, true);
|
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Bandwidth, 0, true);
|
||||||
addActionToQMenuAndActionHash(viewMenu, MenuOption::BandwidthDetails, 0, this, SLOT(bandwidthDetails()));
|
addActionToQMenuAndActionHash(viewMenu, MenuOption::BandwidthDetails, 0, this, SLOT(bandwidthDetails()));
|
||||||
addActionToQMenuAndActionHash(viewMenu, MenuOption::OctreeStats, 0, this, SLOT(octreeStatsDetails()));
|
addActionToQMenuAndActionHash(viewMenu, MenuOption::OctreeStats, 0, this, SLOT(octreeStatsDetails()));
|
||||||
|
|
|
@ -287,7 +287,6 @@ namespace MenuOption {
|
||||||
const QString OctreeStats = "Voxel and Particle Statistics";
|
const QString OctreeStats = "Voxel and Particle Statistics";
|
||||||
const QString OffAxisProjection = "Off-Axis Projection";
|
const QString OffAxisProjection = "Off-Axis Projection";
|
||||||
const QString OldVoxelCullingMode = "Old Voxel Culling Mode";
|
const QString OldVoxelCullingMode = "Old Voxel Culling Mode";
|
||||||
const QString Oscilloscope = "Audio Oscilloscope";
|
|
||||||
const QString Pair = "Pair";
|
const QString Pair = "Pair";
|
||||||
const QString Particles = "Particles";
|
const QString Particles = "Particles";
|
||||||
const QString PasteToVoxel = "Paste to Voxel...";
|
const QString PasteToVoxel = "Paste to Voxel...";
|
||||||
|
|
|
@ -1,192 +0,0 @@
|
||||||
//
|
|
||||||
// Oscilloscope.cpp
|
|
||||||
// interface/src/ui
|
|
||||||
//
|
|
||||||
// Created by Philip on 1/28/13.
|
|
||||||
// Copyright 2013 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <limits>
|
|
||||||
#include <cstring>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <QtCore/QDebug>
|
|
||||||
|
|
||||||
#include "InterfaceConfig.h"
|
|
||||||
|
|
||||||
#include "Oscilloscope.h"
|
|
||||||
|
|
||||||
// Reimplemented 4/26/13 (tosh) - don't blame Philip for bugs
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace { // everything in here only exists while compiling this .cpp file
|
|
||||||
|
|
||||||
// one sample buffer per channel
|
|
||||||
unsigned const MAX_SAMPLES = Oscilloscope::MAX_SAMPLES_PER_CHANNEL * Oscilloscope::MAX_CHANNELS;
|
|
||||||
|
|
||||||
// adding an x-coordinate yields twice the amount of vertices
|
|
||||||
unsigned const MAX_COORDS_PER_CHANNEL = Oscilloscope::MAX_SAMPLES_PER_CHANNEL * 2;
|
|
||||||
// allocated once for each channel
|
|
||||||
unsigned const MAX_COORDS = MAX_COORDS_PER_CHANNEL * Oscilloscope::MAX_CHANNELS;
|
|
||||||
|
|
||||||
// total amount of memory to allocate (in 16-bit integers)
|
|
||||||
unsigned const N_INT16_TO_ALLOC = MAX_SAMPLES + MAX_COORDS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Oscilloscope::Oscilloscope(int w, int h, bool isEnabled) :
|
|
||||||
enabled(isEnabled),
|
|
||||||
inputPaused(false),
|
|
||||||
_width(w),
|
|
||||||
_height(h),
|
|
||||||
_samples(0l),
|
|
||||||
_vertices(0l),
|
|
||||||
// some filtering (see details in Log.h)
|
|
||||||
_lowPassCoeff(0.4f),
|
|
||||||
// three in -> one out
|
|
||||||
_downsampleRatio(3) {
|
|
||||||
|
|
||||||
// allocate enough space for the sample data and to turn it into
|
|
||||||
// vertices and since they're all 'short', do so in one shot
|
|
||||||
_samples = new short[N_INT16_TO_ALLOC];
|
|
||||||
memset(_samples, 0, N_INT16_TO_ALLOC * sizeof(short));
|
|
||||||
_vertices = _samples + MAX_SAMPLES;
|
|
||||||
|
|
||||||
// initialize write positions to start of each channel's region
|
|
||||||
for (unsigned ch = 0; ch < MAX_CHANNELS; ++ch) {
|
|
||||||
_writePos[ch] = MAX_SAMPLES_PER_CHANNEL * ch;
|
|
||||||
}
|
|
||||||
|
|
||||||
_colors[0] = 0xffffff;
|
|
||||||
_colors[1] = 0x00ffff;
|
|
||||||
_colors[2] = 0x00ffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
Oscilloscope::~Oscilloscope() {
|
|
||||||
|
|
||||||
delete[] _samples;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Oscilloscope::addSamples(const QByteArray& audioByteArray, bool isStereo, bool isInput) {
|
|
||||||
|
|
||||||
if (! enabled || inputPaused) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned numSamplesPerChannel = audioByteArray.size() / (sizeof(int16_t) * (isStereo ? 2 : 1));
|
|
||||||
int16_t* samples = (int16_t*) audioByteArray.data();
|
|
||||||
|
|
||||||
for (int channel = 0; channel < (isStereo ? 2 : 1); channel++) {
|
|
||||||
// add samples for each of the channels
|
|
||||||
|
|
||||||
// determine start/end offset of this channel's region
|
|
||||||
unsigned baseOffs = MAX_SAMPLES_PER_CHANNEL * (channel + !isInput);
|
|
||||||
unsigned endOffs = baseOffs + MAX_SAMPLES_PER_CHANNEL;
|
|
||||||
|
|
||||||
// fetch write position for this channel
|
|
||||||
unsigned writePos = _writePos[channel + !isInput];
|
|
||||||
|
|
||||||
// determine write position after adding the samples
|
|
||||||
unsigned newWritePos = writePos + numSamplesPerChannel;
|
|
||||||
unsigned n2 = 0;
|
|
||||||
if (newWritePos >= endOffs) {
|
|
||||||
// passed boundary of the circular buffer? -> we need to copy two blocks
|
|
||||||
n2 = newWritePos - endOffs;
|
|
||||||
newWritePos = baseOffs + n2;
|
|
||||||
numSamplesPerChannel -= n2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isStereo) {
|
|
||||||
// copy data
|
|
||||||
memcpy(_samples + writePos, samples, numSamplesPerChannel * sizeof(int16_t));
|
|
||||||
if (n2 > 0) {
|
|
||||||
memcpy(_samples + baseOffs, samples + numSamplesPerChannel, n2 * sizeof(int16_t));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// we have interleaved samples we need to separate into two channels
|
|
||||||
for (unsigned i = 0; i < numSamplesPerChannel + n2; i++) {
|
|
||||||
if (i < numSamplesPerChannel - n2) {
|
|
||||||
_samples[writePos] = samples[(i * 2) + channel];
|
|
||||||
} else {
|
|
||||||
_samples[baseOffs] = samples[(i * 2) + channel];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// set new write position for this channel
|
|
||||||
_writePos[channel + !isInput] = newWritePos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Oscilloscope::render(int x, int y) {
|
|
||||||
|
|
||||||
if (! enabled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// fetch low pass factor (and convert to fix point) / downsample factor
|
|
||||||
int lowPassFixPt = -(int)(std::numeric_limits<short>::min()) * _lowPassCoeff;
|
|
||||||
unsigned downsample = _downsampleRatio;
|
|
||||||
// keep half of the buffer for writing and ensure an even vertex count
|
|
||||||
unsigned usedWidth = min(_width, MAX_SAMPLES_PER_CHANNEL / (downsample * 2)) & ~1u;
|
|
||||||
unsigned usedSamples = usedWidth * downsample;
|
|
||||||
|
|
||||||
// expand samples to vertex data
|
|
||||||
for (unsigned ch = 0; ch < MAX_CHANNELS; ++ch) {
|
|
||||||
// for each channel: determine memory regions
|
|
||||||
short const* basePtr = _samples + MAX_SAMPLES_PER_CHANNEL * ch;
|
|
||||||
short const* endPtr = basePtr + MAX_SAMPLES_PER_CHANNEL;
|
|
||||||
short const* inPtr = _samples + _writePos[ch];
|
|
||||||
short* outPtr = _vertices + MAX_COORDS_PER_CHANNEL * ch;
|
|
||||||
int sample = 0, x = usedWidth;
|
|
||||||
for (int i = (int)usedSamples; --i >= 0 ;) {
|
|
||||||
if (inPtr == basePtr) {
|
|
||||||
// handle boundary, reading the circular sample buffer
|
|
||||||
inPtr = endPtr;
|
|
||||||
}
|
|
||||||
// read and (eventually) filter sample
|
|
||||||
sample += ((*--inPtr - sample) * lowPassFixPt) >> 15;
|
|
||||||
// write every nth as y with a corresponding x-coordinate
|
|
||||||
if (i % downsample == 0) {
|
|
||||||
*outPtr++ = short(--x);
|
|
||||||
*outPtr++ = short(sample);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// set up rendering state (vertex data lives at _vertices)
|
|
||||||
glLineWidth(1.0);
|
|
||||||
glDisable(GL_LINE_SMOOTH);
|
|
||||||
glPushMatrix();
|
|
||||||
glTranslatef((float)x + 0.0f, (float)y + _height / 2.0f, 0.0f);
|
|
||||||
glScaled(1.0f, _height / 32767.0f, 1.0f);
|
|
||||||
glVertexPointer(2, GL_SHORT, 0, _vertices);
|
|
||||||
glEnableClientState(GL_VERTEX_ARRAY);
|
|
||||||
glDisableClientState(GL_COLOR_ARRAY);
|
|
||||||
glDisableClientState(GL_INDEX_ARRAY);
|
|
||||||
glDisableClientState(GL_NORMAL_ARRAY);
|
|
||||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
||||||
|
|
||||||
// render channel 0
|
|
||||||
glColor3ub(GLubyte(_colors[0] >> 16), GLubyte((_colors[0] >> 8) & 0xff), GLubyte(_colors[0] & 0xff));
|
|
||||||
glDrawArrays(GL_LINES, MAX_SAMPLES_PER_CHANNEL * 0, usedWidth);
|
|
||||||
|
|
||||||
// render channel 1
|
|
||||||
glColor3f(0.0f, 1.0f ,1.0f);
|
|
||||||
glColor3ub(GLubyte(_colors[1] >> 16), GLubyte((_colors[1] >> 8) & 0xff), GLubyte(_colors[1] & 0xff));
|
|
||||||
glDrawArrays(GL_LINES, MAX_SAMPLES_PER_CHANNEL * 1, usedWidth);
|
|
||||||
|
|
||||||
// render channel 2
|
|
||||||
glColor3ub(GLubyte(_colors[2] >> 16), GLubyte((_colors[2] >> 8) & 0xff), GLubyte(_colors[2] & 0xff));
|
|
||||||
glDrawArrays(GL_LINES, MAX_SAMPLES_PER_CHANNEL * 2, usedWidth);
|
|
||||||
|
|
||||||
// reset rendering state
|
|
||||||
glDisableClientState(GL_VERTEX_ARRAY);
|
|
||||||
glPopMatrix();
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,84 +0,0 @@
|
||||||
//
|
|
||||||
// Oscilloscope.h
|
|
||||||
// interface/src/ui
|
|
||||||
//
|
|
||||||
// Created by Philip on 1/28/13.
|
|
||||||
// Copyright 2013 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef hifi_Oscilloscope_h
|
|
||||||
#define hifi_Oscilloscope_h
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
|
|
||||||
#include <QtCore/QObject>
|
|
||||||
|
|
||||||
class Oscilloscope : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
Oscilloscope(int width, int height, bool isEnabled);
|
|
||||||
~Oscilloscope();
|
|
||||||
|
|
||||||
void render(int x, int y);
|
|
||||||
|
|
||||||
// Switches: On/Off, Stop Time
|
|
||||||
volatile bool enabled;
|
|
||||||
volatile bool inputPaused;
|
|
||||||
|
|
||||||
// Limits
|
|
||||||
static unsigned const MAX_CHANNELS = 3;
|
|
||||||
static unsigned const MAX_SAMPLES_PER_CHANNEL = 4096;
|
|
||||||
|
|
||||||
// Sets the color for a specific channel.
|
|
||||||
void setColor(unsigned ch, unsigned rgb) { assert(ch < MAX_CHANNELS); if (! inputPaused) { _colors[ch] = rgb; } }
|
|
||||||
|
|
||||||
// Controls a simple one pole IIR low pass filter that is provided to
|
|
||||||
// reduce high frequencies aliasing (to lower ones) when downsampling.
|
|
||||||
//
|
|
||||||
// The parameter sets the influence of the input in respect to the
|
|
||||||
// feed-back signal on the output.
|
|
||||||
//
|
|
||||||
// +---------+
|
|
||||||
// in O--------------|+ ideal |--o--------------O out
|
|
||||||
// .---|- op amp | |
|
|
||||||
// | +---------+ |
|
|
||||||
// | |
|
|
||||||
// o-------||-------o
|
|
||||||
// | |
|
|
||||||
// | __V__
|
|
||||||
// -------------|_____|-------+
|
|
||||||
// : : |
|
|
||||||
// 0.0 - 1.0 (GND)
|
|
||||||
//
|
|
||||||
// The values in range 0.0 - 1.0 correspond to "all closed" (input has
|
|
||||||
// no influence on the output) to "all open" (feedback has no influence
|
|
||||||
// on the output) configurations.
|
|
||||||
void setLowpassOpenness(float w) { assert(w >= 0.0f && w <= 1.0f); _lowPassCoeff = w; }
|
|
||||||
|
|
||||||
// Sets the number of input samples per output sample. Without filtering
|
|
||||||
// just uses every nTh sample.
|
|
||||||
void setDownsampleRatio(unsigned n) { assert(n > 0); _downsampleRatio = n; }
|
|
||||||
public slots:
|
|
||||||
void addSamples(const QByteArray& audioByteArray, bool isStereo, bool isInput);
|
|
||||||
private:
|
|
||||||
// don't copy/assign
|
|
||||||
Oscilloscope(Oscilloscope const&); // = delete;
|
|
||||||
Oscilloscope& operator=(Oscilloscope const&); // = delete;
|
|
||||||
|
|
||||||
// state variables
|
|
||||||
|
|
||||||
unsigned _width;
|
|
||||||
unsigned _height;
|
|
||||||
short* _samples;
|
|
||||||
short* _vertices;
|
|
||||||
unsigned _writePos[MAX_CHANNELS];
|
|
||||||
|
|
||||||
float _lowPassCoeff;
|
|
||||||
unsigned _downsampleRatio;
|
|
||||||
unsigned _colors[MAX_CHANNELS];
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // hifi_Oscilloscope_h
|
|
Loading…
Reference in a new issue