ElectroTechnique / TSynth-Teensy4.1

TSynth for Teensy 4.1

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Oscilloscope updating speed

ElectroTechnique opened this issue · comments

Oscilloscope function needs more work to make updates faster. It's slowed by the zero crossing code that only updates when zero is crossed from positive to negative and then there is a delay while it looks for this again.

Would be nice to get it as good as Korg 'logue synths, with x-axis scaling to show whole waveform.

Recent merge of improved code. Still not quite like Korg, but we're getting closer.

Hello tsynth :) My idee for a better scope screen, I read 4 audio blocks and scaled them to the pixel width of the display.

#ifndef Oscilloscope_h_
#define Oscilloscope_h_
#include "AudioStream.h"
#include "ST7735_t3.h"

uint8_t bufferBlock = 0;
uint8_t bufcount = 0;
int16_t prev_pixel_y = 0;
const int lineColor = 0x07B0;
boolean EnvIdelFlag = false;

class Oscilloscope : public AudioStream {
	public:
	Oscilloscope(void) : AudioStream(1, inputQueueArray) {
	}
	virtual void update(void);
	void ScreenSetup(ST7735_t3*);
	void Display(void);
	void AddtoBuffer(int16_t*);

	private:
	audio_block_t *inputQueueArray[1];
	ST7735_t3 *display;
	int16_t buffer[AUDIO_BLOCK_SAMPLES];
};
#endif

void Oscilloscope::ScreenSetup(ST7735_t3 *screen) {
	display = screen;
}

void Oscilloscope::Display() {
	uint8_t pixel_x = 0;
	prev_pixel_y = map(buffer[0], 32767, -32768, -65, 65) + 95;	// 1.Pixel to start drawing scope line
	if (prev_pixel_y < 65) prev_pixel_y = 65;
	if (prev_pixel_y > 126)prev_pixel_y = 126;
	for (uint16_t i = 0; i < AUDIO_BLOCK_SAMPLES - 1; i++) {
		int16_t pixel_y = map(buffer[i], 32767, -32768, -65, 65) + 95;
		if (pixel_y < 65) pixel_y = 65;
		if (pixel_y > 126)pixel_y = 126;
		display->drawLine(pixel_x + 17, prev_pixel_y, pixel_x + 18, pixel_y, lineColor);
		prev_pixel_y = pixel_y;
		pixel_x++;
	}
}

// Scope scale 11.6ms For a better view at low frequencies
void Oscilloscope::AddtoBuffer(int16_t *audio) {
	int16_t prev_audio = 0;
	prev_audio = *audio;
	audio++;
	if (bufferBlock == 0) {
		if (prev_audio > 0 && *audio < 512) {		// change Scope Trigger for more screen refresh
			bufferBlock = 1;
			bufcount = 0;							// ignore the first buffer block for trigger
		}
	}
	else {
		for (uint16_t i = 0; i < 32; i++) {
			buffer[bufcount++] = *audio;
			audio += 4;
		}
		bufferBlock++;
		if (bufferBlock >= 5) {
			bufferBlock = 0;
		}
	}
}

void Oscilloscope::update(void) {
	if (!display) return;
	audio_block_t *block;
	block = receiveReadOnly(0);
	if (block) {
		AddtoBuffer(block->data);
		release(block);
		if (bufferBlock == 0) {
			if (EnvIdelFlag == false) {  // is setting in the Main loop from Envelopes
				Display();
			}
		}
		
	}
}

Youtube: https://youtu.be/z1ktgjzEsYk?t=2449

Thanks for this. I've been trying slightly different adjustments to the zero crossing code. I like the larger blocks with a sample added to the buffer every fourth sample. I found this improves stability of the wave (jumping from side to side):

void Oscilloscope::AddtoBuffer(int16_t *audio) {
  audio++;
  if (bufferBlock == 0) {
    if (*(audio-1) > -16 && *(audio+3) < 16) {  //<<<<<<<<<<<<<
      bufferBlock = 1;
     bufcount = 0;
    }
  }

Still some more work to do. A lot of implementations seem to hold the righthand side to zero and allow the wave to roll backwards.

I've been following this development, hoping to use his oscilloscope code, but it appears to be in assembly or something else compiled: https://www.youtube.com/watch?v=WJGOIgaY-1s

I'm closing this issue because although it's not ideal yet, it does update faster and clearer than before.

ok. Thanks for information. I will reconsider the scope code.