Issues with Placing Commands in a Loop Running a Waveform

Status
Not open for further replies.

JotyD

New member
Hey everyone,

I have a waveform sketch that runs fine when the commands are in void setup, but as soon as I place anything into void loop, the speaker no longer plays the tone. Even though it is a low frequency, the speaker physically moves which is the goal (meant to be an actuator for something cymatic-esque). When code is placed in the loop, the speaker doesn't move and instead emits a high-pitch frequency. I'm using a Teensy 3.5, outputting on DAC0.

This is the code when it works:

"
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <Bounce.h>

// GUItool: begin automatically generated code
AudioSynthWaveform waveform1; //xy=110,75
AudioOutputAnalogStereo dacs0;
AudioConnection patchCord1(waveform1, 0, dacs0, 0);
AudioConnection patchCord2(waveform1, 0, dacs0, 1);

// GUItool: end automatically generated code

void setup() {
AudioMemory(15);
waveform1.begin(WAVEFORM_SINE);
waveform1.frequency(10);
waveform1.amplitude(0.99);
}

void loop() {
}

"

This is the code when it doesn't work:

"
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <Bounce.h>

// GUItool: begin automatically generated code
AudioSynthWaveform waveform1; //xy=110,75
AudioOutputAnalogStereo dacs0;
AudioConnection patchCord1(waveform1, 0, dacs0, 0);
AudioConnection patchCord2(waveform1, 0, dacs0, 1);

// GUItool: end automatically generated code

void setup() {
AudioMemory(15);
waveform1.begin(WAVEFORM_SINE);
waveform1.frequency(10);
waveform1.amplitude(0.99);
}

void loop() {
AudioMemory(15);
waveform1.begin(WAVEFORM_SINE);
waveform1.frequency(10);
waveform1.amplitude(0.99);
}
"

Should this be happening? I'm new ish to programming, more familiar with hardware, but it seems that it shouldn't?

Ultimately, I want this tone to be triggered by an IR sensor and to last for 2 minutes with a fade in and a fade out. I would like it to concurrently send an ON signal to a computer running TouchDesigner, this will trigger a network in Touch. This can be done either over Serial or OSC, I'm planning to use a router that creates a network just for this signal switching, not planning to have it on wifi.

Below is my stab at what I would ultimately like to get at, does anyone have any advice if this will work or if I should change something?

Thank you so much!

CODE FOR OSC:

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

#include <Ethernet.h>
#include <EthernetUdp.h>
#include <SPI.h>
#include <OSCMessage.h>

#define IR_Pin 18

// GUItool: begin automatically generated code
AudioSynthWaveform waveform1; //xy=184.00000381469727,355.0000042915344
AudioEffectFade fade1; //xy=355.00000381469727,359.0000057220459
AudioOutputAnalog dac1; //xy=522.0000114440918,361.00000286102295
AudioConnection patchCord1(waveform1, fade1);
AudioConnection patchCord2(fade1, dac1);
// GUItool: end automatically generated code

EthernetUDP Udp;

//the Arduino's IP
IPAddress ip(128, 32, 122, 252);
//destination IP
IPAddress outIp(128, 32, 122, 125);
const unsigned int outPort = 9999;

byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // you can find this written on the board of some Arduino Ethernets or shields
void setup() {
Ethernet.begin(mac,ip);
Udp.begin(8888);
}


void setup() {
pinMode(IR_Pin, INPUT);
Serial.begin(9600);
AudioMemory(15);
waveform1.begin(WAVEFORM_SINE);
fade1.fadeIn(100);
waveform1.frequency(10);
waveform1.amplitude(0.99);
fade1.fadeOut(100);
}

void loop() {
//the message wants an OSC address as first argument
OSCMessage msg("/analog/0");
msg.add((int32_t)analogRead(0));

int senseMotion = digitalRead(IR_Pin);

if (senseMotion = HIGH) {
waveform1.begin(WAVEFORM_SINE);
fade1.fadeIn(100);
waveform1.frequency(10);
waveform1.amplitude(0.99);
fade1.fadeOut(100);

Udp.beginPacket(outIp, outPort);
msg.send(Udp); // send the bytes to the SLIP stream
Udp.endPacket(); // mark the end of the OSC Packet
msg.empty(); // free space occupied by message
delay(20);
}
}
 
I'm pretty sure AudioMemory(15); should not be in the main loop, because you are then repeatedly setting the audio memory up.
By reinitialising the audio memory every loop, you are preventing the waveform from playing.

Try:

void setup() {
AudioMemory(15);
}

void loop() {
waveform1.begin(WAVEFORM_SINE);
waveform1.frequency(10);
waveform1.amplitude(0.99);
}

actually I just realised, you only want to run waveform begin once too, each time you call that command you are reinitialising the waveform too.

So really it should be:

void setup() {
AudioMemory(15);
waveform1.begin(WAVEFORM_SINE);
}

void loop() {
waveform1.frequency(10);
waveform1.amplitude(0.99);
}

the only time you would call waveform.begin is when you want to change the waveform to something different like a sawtooth
 
Last edited:
if you are not changing the waveform frequency and amplitude, there is no reason for any of the commands to be in your loop, just the fade in and fade out commands.
in which case you could combine them all together in a single begin command within the setup loop ie:

void setup() {
AudioMemory(15);
waveform1.begin(0.99,10,WAVEFORM_SINE)
}

void loop() {

fade1.fadeIn(100);
delay(1800);
fade1.fadeOut(100);

}

once the oscillator is running it continues running with those settings in the background, regardless of what your other code is doing.
the delay command halts the program for 1.8 seconds, allowing your sound to play for 2 seconds withn the fade in / fade out
 
A much better method though would be to use an envelope module instead of a fader
You can have the envelope running at the same time as your background code then.
To do this, replace your fader object with an envelope object.
then the code would be something like:

void setup() {
AudioMemory(15);
waveform1.begin(0.99,10,WAVEFORM_SINE)
envelope1.attack(100);
envelope1.hold(1800);
envelope1.decay(100);
envelope1.sustain(0.0);
envelope1.release(0.0);
}

elapsedMillis onTime = 0;

void loop() {
if (senseMotion = HIGH) {
onTime = 0;
envelope1.noteOn();
}
if (onTime > 200)
{
envelope1.noteOff();
}
}

the elapsed milliseconds variable allows you to test whether the envelope has been on for more than 200 milliseconds.
the hold part of the envelope settings decides how long the envelope is on once it has faded in.
 
Status
Not open for further replies.
Back
Top