Teensy Audio Library create melody

Status
Not open for further replies.

jcfrgmn

Member
All,

This is just killing me. I really like the Audio Library and the very cool GUI. With it I can make incredible sounds and the tool set is very rich so I can add reverb, SV filtering, etc.

I am super embarrassed, but I do not know how to produce a melody of say 3 notes. Using 'delay()' causes artifacts, and the interrupt driven tool set runs right over it. I am not talking about delays at the sample level. What I would like to do is produce three notes, over say, 3 seconds... and I just can not figure out how to do it.

I have searched, and searched... but using delay in the search pulls up sample delay, but not say 1000 delay so I can produce a sequence of notes. The Monolith code must contain the code, but it is hard to tease it out.

And I have tried stop and start audio interrupt (or what ever it is called).

The protocol is to add code so it is included below, but it does not include the multiple note function, but it would be after the main loop detecting a button push where I would play three notes, not one. The place I would like the short sequence is:

if (buttonDrum1.fallingEdge()) {
drum1.noteOn();
}

- I want to trigger three notes, not one.

Thanks for any quick references to the forum or other examples.

I am really stuck.

Thanks for your kindness,

John

----------------------------------------------------------------------------------------------------------------------


// sDX_tAD_912 Program for Teensy 3.6 (4.16.17) board to play drums
// Sept. 12, 2017, stored in db>jcarter>projects>arduino
// modified from program for Teensy 3.2 (3.6.17) board
// A2, A3 controls level, depth of drum harmonics
// flange help from audio>effects>flange
// chorus help from audio>effects>chorus
// optimizing with one note, different channels


#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <synth_simple_drum.h>
#include <Bounce.h> // Pushbutton Debouncer

// =========================CHORUS===============================
// Number of samples in each delay line
#define CHORUS_DELAY_LENGTH (16*AUDIO_BLOCK_SAMPLES)
// Allocate the delay lines for left and right channels
short l_CH_delayline[CHORUS_DELAY_LENGTH];
short r_CH_delayline[CHORUS_DELAY_LENGTH];
// number of "voices" in the chorus which INCLUDES the original voice
int n_chorus = 2;
// =========================CHORUS===============================

// ###########################FLANGE##############################
#define FLANGE_DELAY_LENGTH (2*AUDIO_BLOCK_SAMPLES) // Was 2
// Allocate the delay lines for left and right channels
short l_delayline[FLANGE_DELAY_LENGTH];
short r_delayline[FLANGE_DELAY_LENGTH];
int s_idx = 2*FLANGE_DELAY_LENGTH/4;
int s_depth = FLANGE_DELAY_LENGTH/4;
double s_freq = 4;
float fkey = 134.0;
// ###########################FLANGE##############################

// +++++++++++++++++++++++++REVERB+++++++++++++++++++++++++++++++
float rt60 = 1.0;
// +++++++++++++++++++++++++REVERB+++++++++++++++++++++++++++++++

static uint32_t next;
int led = 13;



float f1 = fkey; float f2 = fkey; float f3 = fkey ; float f4 = fkey;

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

// GUItool: begin automatically generated code
AudioSynthSimpleDrum drum1; //xy=172,207
AudioSynthSimpleDrum drum4; //xy=171,482
AudioSynthSimpleDrum drum3; //xy=173,263
AudioSynthSimpleDrum drum2; //xy=178,319
AudioSynthWaveform waveform1; //xy=183,401
AudioFilterStateVariable filter1; //xy=324,352
AudioMixer4 mixer2; //xy=476,289
AudioEffectFlange flange1; //xy=610,208
AudioEffectReverb reverb1; //xy=613,289
AudioEffectChorus chorus1; //xy=616,481
AudioMixer4 mixer1; //xy=856,336
AudioOutputI2S i2s1; //xy=1001,331
AudioConnection patchCord1(drum1, flange1);
AudioConnection patchCord2(drum4, chorus1);
AudioConnection patchCord3(drum3, 0, mixer2, 0);
AudioConnection patchCord4(drum2, 0, filter1, 0);
AudioConnection patchCord5(waveform1, 0, filter1, 1);
AudioConnection patchCord6(filter1, 0, mixer2, 1);
AudioConnection patchCord7(filter1, 0, mixer1, 2);
AudioConnection patchCord8(mixer2, reverb1);
AudioConnection patchCord9(flange1, 0, mixer1, 0);
AudioConnection patchCord10(reverb1, 0, mixer1, 1);
AudioConnection patchCord11(chorus1, 0, mixer1, 3);
AudioConnection patchCord12(mixer1, 0, i2s1, 0);
AudioConnection patchCord13(mixer1, 0, i2s1, 1);
AudioControlSGTL5000 sgtl5000_1; //xy=843,437
// GUItool: end automatically generated code

AudioControlSGTL5000 audioShield;

Bounce buttonDrum1 = Bounce(0, 16); // 16 = 16 ms debounce time
Bounce buttonDrum2 = Bounce(1, 16);
Bounce buttonDrum3 = Bounce(2, 16);
Bounce buttonDrum4 = Bounce(3, 16);

void setup() {

pinMode(led, OUTPUT);
blink (9);
blink (2);
//blink (4);

// ###########################FLANGE##############################

// Set up the flange effect:
// address of delayline
// total number of samples in the delay line
// Index (in samples) into the delay line for the added voice
// Depth of the flange effect
// frequency of the flange effect
flange1.begin(l_delayline,FLANGE_DELAY_LENGTH,s_idx,s_depth,s_freq);

// Initially the effect is off. It is switched on when the
// PASSTHRU button is pushed.
flange1.voices(FLANGE_DELAY_PASSTHRU,0,0);
// ###########################FLANGE##############################

// =========================CHORUS===============================
chorus1.begin(l_CH_delayline,CHORUS_DELAY_LENGTH,n_chorus);
// =========================CHORUS===============================

// +++++++++++++++++++++++++REVERB+++++++++++++++++++++++++++++++
reverb1.reverbTime(rt60);
// +++++++++++++++++++++++++REVERB+++++++++++++++++++++++++++++++

//*************************SVFilter*******************************
filter1.frequency(fkey*2.0);
filter1.resonance(2);
filter1.octaveControl(2);
//*************************SVFilter*******************************

//++++++++++++++++++++++++WAVEFORM++++++++++++++++++++++++++++++++
waveform1.begin(0.5, 10.0, WAVEFORM_SINE); // Frequency rate at 10 hz
//++++++++++++++++++++++++WAVEFORM++++++++++++++++++++++++++++++++



drum1.frequency(f1); //
drum2.frequency(f2); //
drum3.frequency(f3); //
drum4.frequency(f4); //


// Configure the pushbutton pins
pinMode(0, INPUT_PULLUP);
pinMode(1, INPUT_PULLUP);
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);

Serial.begin(115200);

// audio library init
AudioMemory(15);


audioShield.enable();
audioShield.volume(0.5);

next = millis() + 1000;

AudioNoInterrupts();

drum1.length(300);
drum1.secondMix(0.5);
drum1.pitchMod(0.45);


drum2.length(300);
drum2.secondMix(0.5);
drum2.pitchMod(.50);


drum3.length(300);
drum3.secondMix(.5);
drum3.pitchMod(0.5);

drum4.length(300);
drum4.secondMix(0.5);
drum4.pitchMod(0.55);

sgtl5000_1.enable();
sgtl5000_1.volume(0.5);

mixer1.gain(0,2.);
mixer1.gain(1,2.);
mixer1.gain(2,4.0);
mixer1.gain(3,2.0);
mixer2.gain(0,1.5);
mixer2.gain(1, 0.25);

AudioInterrupts();
}

void loop() {
digitalWrite(led, LOW);
// ###########################FLANGE##############################

flange1.voices(s_idx,s_depth,s_freq);

// ###########################FLANGE##############################

// =========================CHORUS===============================

chorus1.voices(n_chorus);

// =========================CHORUS===============================

float freqMult = (map(analogRead(A2),0,1023,1000,8000))/1000.0; // 0 - 4.0
drum1.frequency(fkey*freqMult); //
drum2.frequency(fkey*freqMult); //
drum3.frequency(fkey*freqMult); //
drum4.frequency(fkey*freqMult); //

rt60 = 5*((map(analogRead(A3),0,1023,0,1000))/1000.0); // 0 - 5.0 seconds
reverb1.reverbTime(rt60);

float level = 0.75;
drum1.secondMix(level);
drum2.secondMix(level);
drum3.secondMix(level);
drum4.secondMix(level);

float depth = 0.33;
drum1.pitchMod(depth);
drum2.pitchMod(depth);
drum3.pitchMod(depth);
drum4.pitchMod(depth);

float length_ms = 2000.0; // length = 500 ms
length_ms = length_ms/4.0;
drum1.length(length_ms);
drum2.length(length_ms);
drum3.length(length_ms);
drum4.length(length_ms);

buttonDrum1.update(); buttonDrum2.update(); buttonDrum3.update(); buttonDrum4.update();
if (buttonDrum1.fallingEdge()) {
drum1.noteOn();
}
if (buttonDrum2.fallingEdge()) {
drum2.noteOn();
}
if (buttonDrum3.fallingEdge()) {
freqMult = 4.0;
drum3.frequency(f2*freqMult); //
drum3.noteOn();

}
if (buttonDrum4.fallingEdge()) {
drum4.noteOn();
}
digitalWrite(led, HIGH);
}


// ###########################FLANGE##############################

void blink(int number){
for (int i = 0; i<(number); i++){
digitalWrite(led, HIGH);
delay(100);
digitalWrite(led, LOW);
delay(100);
}
delay(100);
}
 
Last edited:
I solved my own problem. The solution appears to be to either use delay() or a while loop with millis() as can be seen from the code below. I do think there may be some interaction between the delay() and reverb or flanging, but we shall see. The millis() test should be a good backup. Here is the working code for a 3 note drum melody.

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <synth_simple_drum.h>
#include <Bounce.h> // Pushbutton Debouncer

static uint32_t next; // long unsigned int to hold time value
int led = 13;
float fkey = 134.0;

// GUItool: begin automatically generated code
AudioSynthSimpleDrum drum1; //xy=172,207
AudioOutputI2S i2s1; //xy=1001,331
AudioConnection patchCord1(drum1, 0, i2s1, 0);
AudioConnection patchCord2(drum1, 0, i2s1, 1);
AudioControlSGTL5000 sgtl5000_1; //xy=737,488
// GUItool: end automatically generated code

AudioControlSGTL5000 audioShield;

Bounce buttonDrum1 = Bounce(0, 16); // 16 = 16 ms debounce time

void setup() {
pinMode(led, OUTPUT);
// Configure the pushbutton pins
pinMode(0, INPUT_PULLUP);

// audio library init
AudioMemory(15);
audioShield.enable();
audioShield.volume(0.5);
AudioNoInterrupts();
sgtl5000_1.enable();
sgtl5000_1.volume(0.5);
AudioInterrupts();
}

void loop() {
digitalWrite(led, LOW);
float freqMult = (map(analogRead(A2),0,1023,1000,8000))/1000.0; // 0 - 4.0
float level = 0.75;
drum1.secondMix(level);
float depth = 0.33;
drum1.pitchMod(depth);
float length_ms = 500.0; // length = 500 ms
drum1.length(length_ms);

buttonDrum1.update();
if (buttonDrum1.fallingEdge()) {
drum1.noteOn();
drum1.frequency(fkey*freqMult);
delay(700);
digitalWrite(led, HIGH);
drum1.noteOn();
drum1.frequency(fkey*freqMult*1.41);
next = millis() + 600;
while (next > millis()){}
digitalWrite(led, LOW);
drum1.noteOn();
drum1.frequency(fkey*freqMult*0.707);
}
digitalWrite(led, HIGH);
 
I do think there may be some interaction between the delay() and reverb or flanging, but we shall see.

Please let me know if you come up with any test programs that clearly expose problems.

Both of these were contributed code, and both seem to have quite a few issues. The reverb has a known problem where its output doesn't continue if it stops getting input data. It might also have noise or signal level problems, but so far no clear tests to reproduce those issues.

Lately I haven't been able to put much dev time into the audio library, but I am collecting a long list of stuff to fix and improve when I get back to really putting time into audio.
 
Paul, you rock! Thanks, I will probe a bit and let you know. Yes, I think the code might be as robust as yours.
 
I solved my own problem. The solution appears to be to either use delay() or a while loop with millis() as can be seen from the code below. I do think there may be some interaction between the delay() and reverb or flanging, but we shall see. The millis() test should be a good backup. Here is the working code for a 3 note drum melody.

I had similar glitches using the flanger object and updating its values without a delay. The glitches become noticeable when the delay is below 100ms circa. In your previous code I see that you updated the flanger values at every loop; you might want to add a function that stores the values of the potentiometers that control the flanger values and have it update them only if there's been a change on the pots; this might still lead to glitches (as per what I just said before) but you won't constantly hear them.
 
Status
Not open for further replies.
Back
Top