mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 22:36:57 +02:00
Merge branch '19165' of git://github.com/tschw/hifi
This commit is contained in:
commit
2cc5f732ce
2 changed files with 67 additions and 51 deletions
|
@ -20,13 +20,15 @@ using namespace std;
|
||||||
namespace { // everything in here only exists while compiling this .cpp file
|
namespace { // everything in here only exists while compiling this .cpp file
|
||||||
|
|
||||||
// one sample buffer per channel
|
// one sample buffer per channel
|
||||||
unsigned const N_SAMPLES_ALLOC = Oscilloscope::MAX_SAMPLES * Oscilloscope::MAX_CHANNELS;
|
unsigned const MAX_SAMPLES = Oscilloscope::MAX_SAMPLES_PER_CHANNEL * Oscilloscope::MAX_CHANNELS;
|
||||||
|
|
||||||
// adding an x-coordinate yields twice the amount of vertices
|
// adding an x-coordinate yields twice the amount of vertices
|
||||||
unsigned const MAX_COORDS = Oscilloscope::MAX_SAMPLES * 2;
|
unsigned const MAX_COORDS_PER_CHANNEL = Oscilloscope::MAX_SAMPLES_PER_CHANNEL * 2;
|
||||||
unsigned const N_COORDS_ALLOC = MAX_COORDS * Oscilloscope::MAX_CHANNELS;
|
// allocated once for each channel
|
||||||
|
unsigned const MAX_COORDS = MAX_COORDS_PER_CHANNEL * Oscilloscope::MAX_CHANNELS;
|
||||||
unsigned const N_ALLOC_TOTAL = N_SAMPLES_ALLOC + N_COORDS_ALLOC;
|
|
||||||
|
// total amount of memory to allocate (in 16-bit integers)
|
||||||
|
unsigned const N_INT16_TO_ALLOC = MAX_SAMPLES + MAX_COORDS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,13 +40,13 @@ Oscilloscope::Oscilloscope(int w, int h, bool isEnabled) :
|
||||||
|
|
||||||
// allocate enough space for the sample data and to turn it into
|
// allocate enough space for the sample data and to turn it into
|
||||||
// vertices and since they're all 'short', do so in one shot
|
// vertices and since they're all 'short', do so in one shot
|
||||||
_arrSamples = new short[N_ALLOC_TOTAL];
|
_arrSamples = new short[N_INT16_TO_ALLOC];
|
||||||
memset(_arrSamples, 0, N_ALLOC_TOTAL * sizeof(short));
|
memset(_arrSamples, 0, N_INT16_TO_ALLOC * sizeof(short));
|
||||||
_arrVertices = _arrSamples + N_SAMPLES_ALLOC;
|
_arrVertices = _arrSamples + MAX_SAMPLES;
|
||||||
|
|
||||||
// initialize write positions
|
// initialize write positions to start of each channel's region
|
||||||
for (unsigned ch = 0; ch < MAX_CHANNELS; ++ch) {
|
for (unsigned ch = 0; ch < MAX_CHANNELS; ++ch) {
|
||||||
_arrWritePos[ch] = MAX_SAMPLES * ch;
|
_arrWritePos[ch] = MAX_SAMPLES_PER_CHANNEL * ch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,25 +60,31 @@ void Oscilloscope::addSamples(unsigned ch, short const* data, unsigned n) {
|
||||||
if (! enabled || inputPaused) {
|
if (! enabled || inputPaused) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned baseOffs = MAX_SAMPLES * ch;
|
|
||||||
unsigned endOffs = baseOffs + MAX_SAMPLES;
|
|
||||||
|
|
||||||
unsigned writePos = _arrWritePos[ch];
|
|
||||||
unsigned newWritePos = writePos + n;
|
|
||||||
|
|
||||||
|
// determine start/end offset of this channel's region
|
||||||
|
unsigned baseOffs = MAX_SAMPLES_PER_CHANNEL * ch;
|
||||||
|
unsigned endOffs = baseOffs + MAX_SAMPLES_PER_CHANNEL;
|
||||||
|
|
||||||
|
// fetch write position for this channel
|
||||||
|
unsigned writePos = _arrWritePos[ch];
|
||||||
|
|
||||||
|
// determine write position after adding the samples
|
||||||
|
unsigned newWritePos = writePos + n;
|
||||||
unsigned n2 = 0;
|
unsigned n2 = 0;
|
||||||
if (newWritePos >= endOffs) {
|
if (newWritePos >= endOffs) {
|
||||||
|
// passed boundary of the circular buffer? -> we need to copy two blocks
|
||||||
n2 = newWritePos - endOffs;
|
n2 = newWritePos - endOffs;
|
||||||
newWritePos = baseOffs + n2;
|
newWritePos = baseOffs + n2;
|
||||||
n -= n2;
|
n -= n2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// copy data
|
||||||
memcpy(_arrSamples + writePos, data, n * sizeof(short));
|
memcpy(_arrSamples + writePos, data, n * sizeof(short));
|
||||||
if (n2 > 0) {
|
if (n2 > 0) {
|
||||||
memcpy(_arrSamples + baseOffs, data + n, n2 * sizeof(short));
|
memcpy(_arrSamples + baseOffs, data + n, n2 * sizeof(short));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set new write position for this channel
|
||||||
_arrWritePos[ch] = newWritePos;
|
_arrWritePos[ch] = newWritePos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,34 +93,38 @@ void Oscilloscope::render(int x, int y) {
|
||||||
if (! enabled) {
|
if (! enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// expand data to vertex data, now
|
// determine lowpass / downsample factors
|
||||||
int lowpass = -int(std::numeric_limits<short>::min()) * _valLowpass;
|
int lowpass = -int(std::numeric_limits<short>::min()) * _valLowpass;
|
||||||
unsigned downsample = _valDownsample;
|
unsigned downsample = _valDownsample;
|
||||||
// keep half of the buffer for writing and ensure an even vertex count
|
// keep half of the buffer for writing and ensure an even vertex count
|
||||||
unsigned usedWidth = min(_valWidth, MAX_SAMPLES / (downsample * 2)) & ~1u;
|
unsigned usedWidth = min(_valWidth, MAX_SAMPLES_PER_CHANNEL / (downsample * 2)) & ~1u;
|
||||||
unsigned usedSamples = usedWidth * downsample;
|
unsigned usedSamples = usedWidth * downsample;
|
||||||
|
|
||||||
|
// expand samples to vertex data
|
||||||
for (unsigned ch = 0; ch < MAX_CHANNELS; ++ch) {
|
for (unsigned ch = 0; ch < MAX_CHANNELS; ++ch) {
|
||||||
|
// for each channel: determine memory regions
|
||||||
short const* basePtr = _arrSamples + MAX_SAMPLES * ch;
|
short const* basePtr = _arrSamples + MAX_SAMPLES_PER_CHANNEL * ch;
|
||||||
short const* endPtr = basePtr + MAX_SAMPLES;
|
short const* endPtr = basePtr + MAX_SAMPLES_PER_CHANNEL;
|
||||||
short const* inPtr = _arrSamples + _arrWritePos[ch];
|
short const* inPtr = _arrSamples + _arrWritePos[ch];
|
||||||
short* outPtr = _arrVertices + MAX_COORDS * ch;
|
short* outPtr = _arrVertices + MAX_COORDS_PER_CHANNEL * ch;
|
||||||
int sample = 0, x = usedWidth;
|
int sample = 0, x = usedWidth;
|
||||||
for (int i = int(usedSamples); --i >= 0 ;) {
|
for (int i = int(usedSamples); --i >= 0 ;) {
|
||||||
|
|
||||||
if (inPtr == basePtr) {
|
if (inPtr == basePtr) {
|
||||||
|
// handle boundary, reading the circular sample buffer
|
||||||
inPtr = endPtr;
|
inPtr = endPtr;
|
||||||
}
|
}
|
||||||
sample += ((*--inPtr - sample) * lowpass) >> 15;
|
// read and (eventually) filter sample
|
||||||
|
sample += ((*--inPtr - sample) * lowpass) >> 15;
|
||||||
|
// write every nth as y with a corresponding x-coordinate
|
||||||
if (i % downsample == 0) {
|
if (i % downsample == 0) {
|
||||||
*outPtr++ = short(--x);
|
*outPtr++ = short(--x);
|
||||||
*outPtr++ = short(sample);
|
*outPtr++ = short(sample);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set up rendering state (vertex data lives at _arrVertices)
|
||||||
glLineWidth(1.0);
|
glLineWidth(1.0);
|
||||||
glDisable(GL_LINE_SMOOTH);
|
glDisable(GL_LINE_SMOOTH);
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
|
@ -120,12 +132,20 @@ void Oscilloscope::render(int x, int y) {
|
||||||
glScaled(1.0f, _valHeight / 32767.0f, 1.0f);
|
glScaled(1.0f, _valHeight / 32767.0f, 1.0f);
|
||||||
glVertexPointer(2, GL_SHORT, 0, _arrVertices);
|
glVertexPointer(2, GL_SHORT, 0, _arrVertices);
|
||||||
glEnableClientState(GL_VERTEX_ARRAY);
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
|
|
||||||
|
// render channel 0
|
||||||
glColor3f(1.0f, 1.0f, 1.0f);
|
glColor3f(1.0f, 1.0f, 1.0f);
|
||||||
glDrawArrays(GL_LINE_STRIP, MAX_SAMPLES * 0, usedWidth);
|
glDrawArrays(GL_LINES, MAX_SAMPLES_PER_CHANNEL * 0, usedWidth);
|
||||||
|
|
||||||
|
// render channel 1
|
||||||
glColor3f(0.0f, 1.0f ,1.0f);
|
glColor3f(0.0f, 1.0f ,1.0f);
|
||||||
glDrawArrays(GL_LINE_STRIP, MAX_SAMPLES * 1, usedWidth);
|
glDrawArrays(GL_LINES, MAX_SAMPLES_PER_CHANNEL * 1, usedWidth);
|
||||||
|
|
||||||
|
// render channel 2
|
||||||
glColor3f(0.0f, 1.0f ,1.0f);
|
glColor3f(0.0f, 1.0f ,1.0f);
|
||||||
glDrawArrays(GL_LINE_STRIP, MAX_SAMPLES * 2, usedWidth);
|
glDrawArrays(GL_LINES, MAX_SAMPLES_PER_CHANNEL * 2, usedWidth);
|
||||||
|
|
||||||
|
// reset rendering state
|
||||||
glDisableClientState(GL_VERTEX_ARRAY);
|
glDisableClientState(GL_VERTEX_ARRAY);
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,31 +13,19 @@
|
||||||
|
|
||||||
class Oscilloscope {
|
class Oscilloscope {
|
||||||
public:
|
public:
|
||||||
static unsigned const MAX_CHANNELS = 3;
|
|
||||||
static unsigned const MAX_SAMPLES = 4096; // per channel
|
|
||||||
private:
|
|
||||||
unsigned _valWidth;
|
|
||||||
unsigned _valHeight;
|
|
||||||
short* _arrSamples;
|
|
||||||
short* _arrVertices;
|
|
||||||
unsigned _arrWritePos[MAX_CHANNELS];
|
|
||||||
|
|
||||||
float _valLowpass;
|
|
||||||
unsigned _valDownsample;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
Oscilloscope(int width, int height, bool isEnabled);
|
Oscilloscope(int width, int height, bool isEnabled);
|
||||||
~Oscilloscope();
|
~Oscilloscope();
|
||||||
|
|
||||||
volatile bool enabled;
|
|
||||||
volatile bool inputPaused;
|
|
||||||
|
|
||||||
|
|
||||||
void addSamples(unsigned ch, short const* data, unsigned n);
|
void addSamples(unsigned ch, short const* data, unsigned n);
|
||||||
|
|
||||||
void render(int x, int y);
|
void render(int x, int y);
|
||||||
|
|
||||||
|
static unsigned const MAX_CHANNELS = 3;
|
||||||
|
static unsigned const MAX_SAMPLES_PER_CHANNEL = 4096;
|
||||||
|
|
||||||
|
volatile bool enabled;
|
||||||
|
volatile bool inputPaused;
|
||||||
|
|
||||||
void setLowpass(float w) { assert(w > 0.0f && w <= 1.0f); _valLowpass = w; }
|
void setLowpass(float w) { assert(w > 0.0f && w <= 1.0f); _valLowpass = w; }
|
||||||
void setDownsampling(unsigned f) { assert(f > 0); _valDownsample = f; }
|
void setDownsampling(unsigned f) { assert(f > 0); _valDownsample = f; }
|
||||||
|
|
||||||
|
@ -46,8 +34,16 @@ private:
|
||||||
Oscilloscope(Oscilloscope const&); // = delete;
|
Oscilloscope(Oscilloscope const&); // = delete;
|
||||||
Oscilloscope& operator=(Oscilloscope const&); // = delete;
|
Oscilloscope& operator=(Oscilloscope const&); // = delete;
|
||||||
|
|
||||||
// implementation
|
// state variables
|
||||||
inline short* bufferBase(int i, int channel);
|
|
||||||
|
unsigned _valWidth;
|
||||||
|
unsigned _valHeight;
|
||||||
|
short* _arrSamples;
|
||||||
|
short* _arrVertices;
|
||||||
|
unsigned _arrWritePos[MAX_CHANNELS];
|
||||||
|
|
||||||
|
float _valLowpass;
|
||||||
|
unsigned _valDownsample;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* defined(__interface__oscilloscope__) */
|
#endif /* defined(__interface__oscilloscope__) */
|
||||||
|
|
Loading…
Reference in a new issue