PDA

View Full Version : tonesweep weirdness



1101010
08-08-2016, 01:48 AM
I am making a rudimentary sort of beat generator, and have noticed oddities whenever I include a tonesweep. The exact details vary based on the exact effects and timing i am using, but it always involves the audio dropping on one or more of the effects after a few iterations. Here is a simple piece of code to replicate. In this one the triangle wave keeps working, the drums stop, and the tonesweep is replaced by 3 pulses? Not sure where those came from actually. I added the Serial prints to make sure it wasn't an issue with my triggering timing: *1 = drum1, *2 = drum2, -> is the tonesweep, and w1+/w1- mean waveform on/off.

Any ideas what is going on?



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

// GUItool: begin automatically generated code
AudioSynthWaveform waveform1; //xy=245,438
AudioSynthSimpleDrum drum2; //xy=252,337
AudioSynthToneSweep tonesweep1; //xy=255,382
AudioSynthSimpleDrum drum1; //xy=262,281
AudioMixer4 mixer1; //xy=528,371
AudioOutputI2S i2s1; //xy=763,360
AudioConnection patchCord1(waveform1, 0, mixer1, 3);
AudioConnection patchCord2(drum2, 0, mixer1, 1);
AudioConnection patchCord3(tonesweep1, 0, mixer1, 2);
AudioConnection patchCord4(drum1, 0, mixer1, 0);
AudioConnection patchCord5(mixer1, 0, i2s1, 0);
AudioConnection patchCord6(mixer1, 0, i2s1, 1);
AudioControlSGTL5000 sgtl5000_1; //xy=242,174
// GUItool: end automatically generated code

byte beat = 0;
int beatLength = 250;
long beatTime = beatLength;
long measureTime;
long measureStart;
long loopMillis;

void setup() {
Serial.begin(115200);
sgtl5000_1.enable();
sgtl5000_1.volume(0.5);
AudioMemory(4);

AudioProcessorUsageMaxReset();
AudioMemoryUsageMaxReset();

drum1.frequency(100);
drum1.length(200);
drum2.frequency(220);
drum2.length(240);
waveform1.begin(0,220,WAVEFORM_TRIANGLE);
measureStart = millis();
}

void loop() {
loopMillis = millis();
measureTime = loopMillis - measureStart;
if (measureTime > beatTime) {
beat++;
if (beat == 16) {
beat = 0;
measureStart = loopMillis;
beatTime = 0; // will be incremented below
Serial.print("Proc = ");
Serial.print(AudioProcessorUsage());
Serial.print(" (");
Serial.print(AudioProcessorUsageMax());
Serial.print("), Mem = ");
Serial.print(AudioMemoryUsage());
Serial.print(" (");
Serial.print(AudioMemoryUsageMax());
Serial.println(")");
Serial.print("millis = ");
Serial.println(millis());
}
if (beat % 2 == 0) {
drum1.noteOn();
Serial.print("*1 ");
}
if (beat % 4 == 0) {
drum2.noteOn();
Serial.print("*2 ");
}
switch(beat) {
case 3 : waveform1.amplitude(0.5);
Serial.print("w1+ ");
break;
case 11 : waveform1.amplitude(0);
Serial.print("w1- ");
break;
case 13 : tonesweep1.play(0.5, 110, 880, 0.5);
Serial.print("-> ");
break;
}
beatTime += beatLength;
}
}

el_supremo
08-08-2016, 04:24 AM
There's definitely something wrong with tonesweep. I added these statements to the front of the loop() function:

tonesweep1.play(0.5, 110, 880, 0.5);
while(tonesweep1.isPlaying());
delay(500);
return;
and it plays the sweep three times and then stops. It doesn't matter what the duration is.
I'll dig into it tomorrow.

Pete

1101010
08-08-2016, 06:15 AM
Thanks, Pete!
If it helps, on my original program a few iterations after things started going weird, the AudioMemoryUsage and Max functions started returning 255.

And it wasn't always the tone sweep that stopped working. On one combination everything except the tonesweep stopped.

I'm kind of glad this happened because it got me to look into the audio library code, which has been educational.

el_supremo
08-08-2016, 05:59 PM
I'm not so sure it is tonesweep after all. I wrote a sketch which only uses tonesweep and it doesn't stop playing the sweep. Perhaps there's an interaction with the synth drum? I'm still looking.

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

// GUItool: begin automatically generated code
AudioSynthToneSweep tonesweep1; //xy=255,382
AudioOutputI2S i2s1; //xy=763,360
AudioConnection patchCord5(tonesweep1, 0, i2s1, 0);
AudioConnection patchCord6(tonesweep1, 0, i2s1, 1);
AudioControlSGTL5000 sgtl5000_1; //xy=242,174
// GUItool: end automatically generated code



void setup() {
Serial.begin(115200);
while(!Serial);
sgtl5000_1.enable();
sgtl5000_1.volume(0.5);
AudioMemory(4);
AudioProcessorUsageMaxReset();
AudioMemoryUsageMaxReset();
}

void loop() {
tonesweep1.play(0.5, 110, 880, 0.5);
while(tonesweep1.isPlaying());
delay(500);
}

Pete

Frank B
08-08-2016, 06:15 PM
The AudioMemory() seems to be a little too low to me...

el_supremo
08-08-2016, 06:54 PM
Oh duh! Thanks Frank. This seems to require quite a bit of memory. I changed it to (10) which made it last a bit longer but it still died. I increased it to (60) and so far, after about 5 minutes, it hasn't failed.

Pete

el_supremo
08-08-2016, 08:23 PM
I think I have found the problem. The update() function in synth_simple_drum always allocates a new buffer, even if it is not generating audio at the time. I added a "drum_busy" variable to it, similar to what I used in synth_tonesweep, so that it doesn't allocate a buffer unless it is actually generating a sound.
In the private section of synth_simple_drum.h I added this declaration:

unsigned char drum_busy;
at the end of noteOn() I added this:

drum_busy = 1;
In the update() function there are two changes. Add this as the first executable statement:

if(!drum_busy)return;
Inside " if(env_lin_current < 0x0000ffff)" add:

drum_busy = 0;

With those mods and setting AudioMemory back to 4, the code has been running here for at least 10 minutes without error.

Pete
P.S. Without this mod I would have expected that one extra buffer per drum object would have been required but it obviously needs a lot more than that.

1101010
08-09-2016, 03:13 AM
Thanks Pete! Those changes help mine too!

steven32bits
09-23-2016, 05:54 AM
Pete,

I don't understand. I have the audio shield example breadboard sent by PJRC and I have tried several example tonesweeps and none of them play any noise. Other example codes play audio for me. The most recent tonesweep I tried was this one that you uploaded. I have my i2s output soldered to a special jumper-wire XLR (standard audio balanced cable) connector which is connected to a decent speaker with volume attenuation in between.

My purpose:

I am really having trouble playing a tonesweep and pink noise (at separate times) but while playing the tones it must see a mic input to analyze with fft1024. Obviously this analysis is done in 16 bits at 44kHz sampling rate due to limitations of Teensy 3.2. I am about to start a separate forum on this because I have tried merging the example codes "do more while playing" and "fft1024" but the use different audio shield memories (which I still don't quite understand) and different audio shield controls. When I troubleshoot to have no errors it will no longer play audio and the serial monitor prints all 0's which are replaced with "-" within the fft setup loop.


"do more while playing" control function line:
AudioControlSGTL5000 sgtl5000_1;

As opposed to "fft1024" control line:
AudioControlSGTL5000 audioShield;

I figured since this tonesweep has the same control as the "fft1024" example code they may be easier to merge. Any thoughts before I start this individual thread?


Thanks in advanced,

Steven


I'm not so sure it is tonesweep after all. I wrote a sketch which only uses tonesweep and it doesn't stop playing the sweep. Perhaps there's an interaction with the synth drum? I'm still looking.

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

// GUItool: begin automatically generated code
AudioSynthToneSweep tonesweep1; //xy=255,382
AudioOutputI2S i2s1; //xy=763,360
AudioConnection patchCord5(tonesweep1, 0, i2s1, 0);
AudioConnection patchCord6(tonesweep1, 0, i2s1, 1);
AudioControlSGTL5000 sgtl5000_1; //xy=242,174
// GUItool: end automatically generated code



void setup() {
Serial.begin(115200);
while(!Serial);
sgtl5000_1.enable();
sgtl5000_1.volume(0.5);
AudioMemory(4);
AudioProcessorUsageMaxReset();
AudioMemoryUsageMaxReset();
}

void loop() {
tonesweep1.play(0.5, 110, 880, 0.5);
while(tonesweep1.isPlaying());
delay(500);
}

Pete

1101010
09-23-2016, 11:43 AM
Did you use Pete's example program as-is on your hardware and it didn't work? Or you had some modifications to it?

If the latter, can you post your failing code or at least what was changed?

The control object doesn't usually get used (from code perspective) after the setup, so the difference in control object variable names should not be a large obstacle to merging code.

steven32bits
09-23-2016, 05:35 PM
I used Pete's tonesweep code as is, no modifications. On my hardware it didn't work. The only reason I mentioned the control lines is because when merging the fft1024 example code with ''do more while playing'' example code the control lines were interfering with eachother. Arduino IDE would only compile happily when only one control was mention, one or the other.

I would like to hear the tonesweep example code because it may be easier to implement the merger of two example codes that share the control statement. In this case, Pete's tonesweep code has the same control as the fft1024 example code. If I can get them to merge without errors then it may work for my purposes. I need help trying to figure out a way to play a sine-sweep while recording the fft of the signal after the signal has passed through a speaker.

Thank you for your help,

Steven




Did you use Pete's example program as-is on your hardware and it didn't work? Or you had some modifications to it?

If the latter, can you post your failing code or at least what was changed?

The control object doesn't usually get used (from code perspective) after the setup, so the difference in control object variable names should not be a large obstacle to merging code.

el_supremo
09-23-2016, 05:58 PM
I don't know when I can look at this more deeply, maybe by tomorrow, but this one is easy:

"do more while playing" control function line:
AudioControlSGTL5000 sgtl5000_1;

As opposed to "fft1024" control line:
AudioControlSGTL5000 audioShield;

It doesn't matter what name is used when instantiating AudioControlSGTL5000 as long as there is only one instantiation and you use the same name throughout. It could have been "AudioControlSGTL5000 fred".
All you need to do is pick one name and then change all occurrences of the other to that name. e.g. when merging those two, keep "AudioControlSGTL5000 sgtl5000_1;" and remove "AudioControlSGTL5000 audioShield;". Then in the remaining code change every occurrence of "audioShield" to "sgtl5000_1".

Pete

el_supremo
09-24-2016, 12:51 AM
Did you open the serial monitor? The code won't proceed until serial is open.
Or you can comment the line:

// while(!Serial);

Pete

steven32bits
09-28-2016, 11:38 PM
Hey Pete it turned out to be a newbie mistake. I never opened the serial before, so as soon as I do now it plays over and over and everything is adjustable exactly how I want it. How ever my purpose is quite different and therefore I am still having problems. I am posting another forum about my troubles to keep the ideas separate. It will be titled PLAYING AUDIO WHILE RUNNING FFT. :D

Thanks Pete for such an excellent fix for the tone sweep!

Steven