waveform.phase() error for some waveforms

Status
Not open for further replies.

zike

Member
Trying to output quadrature test waveforms, I found that waveform.phase(90) produces the correct result for sine and square waveforms but incorrectly
renders a 45 degree phase shift for triangle and ramp waveforms. T 3.2 with audio shield, Arduino 1.8.2.

Example code to reproduce this issue is attached (look at right and left audio
outputs on a scope to see the phase error).

For the time being I will fudge a factor of two when the 'problem' waveforms are selected (i.e., ask for 180 when you want 90).

Hope this helps someone,

zike

Code:
#include <Audio.h>
#include <SPI.h>
#include <SD.h>
#include <TeensyView.h>

#define skipButton      0    // can be any free digital pin 
#define volPot          15   // hard wired to pad for pot wiper on audio adapter board 
#define ledPin          13   // built-in LED

# define freq           440


AudioControlSGTL5000     sgtl5000_1;

AudioSynthWaveform       waveform1;
AudioSynthWaveform       waveform2;

AudioMixer4              mixerLefty;      // left channel
AudioMixer4              mixerRight;      // right channel

AudioOutputI2S           audioOutput;

AudioConnection          patchCord5(waveform1, 0, mixerLefty, 2);
AudioConnection          patchCord6(waveform2, 0, mixerRight, 2);

AudioConnection          patchCord9(mixerLefty, 0, audioOutput, 0);
AudioConnection          patchCord10(mixerRight, 0, audioOutput, 1);


int wave_type[] = {
  WAVEFORM_SINE,
  WAVEFORM_TRIANGLE,
  WAVEFORM_SAWTOOTH,
  WAVEFORM_SQUARE
};
void setup() {
  Serial.begin(9600);
  Serial.println("Test phase adjust for teensy audio lib waveform generators");
  Serial.println("MEZ 12/12/2017");
  AudioMemory(20);

  sgtl5000_1.enable();
  sgtl5000_1.volume(0.1); // start at low volume
  sgtl5000_1.lineOutLevel(13); // 13 makes full 3.3Vpp DAC range available

  waveform1.amplitude(0); // waveform 1 off
  waveform2.amplitude(0); // waveform 2 off

  mixerLefty.gain(2, 1);
  mixerRight.gain(2, 1);
}

void loop() {
  playTestSignal();
}

void playTestSignal() {
  AudioNoInterrupts();
  for (int j = 0; j < sizeof(wave_type) / sizeof(wave_type[0]) ; j++) {
    Serial.print("waveform ");
    Serial.println(wave_type[j]);
    waveform1.begin(1, freq, wave_type[j]);
    waveform2.begin(1, freq, wave_type[j]);
    waveform2.phase(90);  
    AudioInterrupts();
    delay(3000);
  }
}
 
Ok, nothing strange, just a misunderstanding. you mentioned 90deg phase and a 45deg phase "shift" and I automatically assumed a phase "division" by 2.
In fact it is a bit a both.
Tested all the waveforms with a phase sweep from 0 to 180 deg and these are my findings.
desired_ is what is set in code, actual_ is output on the scope.
Code:
WAVEFORM_SINE              actual_phase = desired_phase = ok
WAVEFORM_TRIANGLE          actual_phase = desired_phase/2
WAVEFORM_SAWTOOTH          actual_phase = desired_phase = ok
WAVEFORM_SAWTOOTH_REVERSE  actual_phase = 360 - desired_phase
WAVEFORM_SQUARE            actual_phase = desired_phase = ok
WAVEFORM_PULSE             actual_phase = desired_phase/2, actual_frequency = desired_frequency/2
WAVEFORM_SAMPLE_HOLD       actual_phase = desired_phase/2, actual_frequency = desired_frequency/2
WAVEFORM_ARBITRARY         actual_phase = desired_phase = ok
Since all these waveforms belong to the same object it would be nice to have a more consistent behaviour.
Then there is the additional fact that when you set the phase, the oscillator is reset to that absolute phase position. The consequence is that when you modulate the phase while the osc is running, it will not sound good.

So there seems to be a bit more work on that object than expected.
 
Last edited:
I posted a fix in the "Suggestions & Bug Reports" forum. It would be nice If you could test it out and confirm it works.
 
Status
Not open for further replies.
Back
Top