Using Teensy Audio within another Library

Status
Not open for further replies.

tenkai

Well-known member
Hello!

I am trying to make a library of 'instruments' for Teensy Audio, so folks can have a wide variety of sounds without too much experimentation.

I am having a hard time accessing the Teensy Audio library and instantiating AudioConnection objects from within a library.

I have an example sketch here:
https://github.com/cosmikwolf/InstrumentLibraryTest

I am unsure if I should pass a global AudioOutputI2S or AudioControl object into the initialization of the library. I can get the sketch to compile when sending an AudioOutput object in, but it crashes my Teensy 3.1.

Any guidance would be greatly appreciated!
Thanks!
-Tenkai

here is all the code from the github sketch above:
main file:
Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <instrument.h>

AudioControlSGTL5000    audioDevice;
AudioOutputI2S i2s1;
Instrument instrument1;

void setup(){
	Serial.begin(9600);
  Serial.println("Audio Setup debug 1");

  AudioMemory(16);
  Serial.println("Audio Setup debug 2");

  audioDevice.enable();
  Serial.println("Audio Setup debug 3");

  audioDevice.volume(0.6);
  Serial.println("Audio Setup debug 4");

  instrument1.init(i2s1);

  Serial.println("Audio Setup debug 5");

}

void loop(){
	Serial.println("Audio loop start");

	instrument1.noteOn(24);
  delay(50);
  instrument1.noteOff();
  instrument1.noteOn(36);
  delay(50);
  instrument1.noteOff();
  instrument1.noteOn(48);
  delay(50);
  instrument1.noteOff();
  instrument1.noteOn(60);
  delay(50);
  instrument1.noteOff();
Serial.println("Audio loop end");

}


instrument library library header file:
Code:
#ifndef Instrument_h
#define Instrument_h

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

#define CHORUS_DELAY_LENGTH (16*AUDIO_BLOCK_SAMPLES)
// Allocate the delay lines for left and right channels


class Instrument
{

	public:
		Instrument();
		
		void init(AudioOutputI2S i2s1);
		void noteOn(uint8_t midiNote);
		void noteOff();
		
		float midiFreq[128] = { 8.17, 8.66, 9.17, 9.72, 10.30, 10.91, 11.56, 12.24, 12.97, 13.75, 14.56, 15.43, 16.35, 17.32, 18.35, 19.44, 20.60, 21.82, 23.12, 24.49, 25.95, 27.50, 29.13, 30.86, 32.70, 34.64, 36.70, 38.89, 41.20, 43.65, 46.24, 48.99, 51.91, 55.00, 58.27, 61.73, 65.40, 69.29, 73.41, 77.78, 82.40, 87.30, 92.49, 97.99, 103.82, 110.00, 116.54, 123.47, 130.81, 138.59, 146.83, 155.56, 164.81, 174.61, 184.99, 195.99, 207.65, 220.00, 233.08, 246.94, 261.62, 277.18, 293.66, 311.12, 329.62, 349.22, 369.99, 391.99, 415.30, 440.00, 466.16, 493.88, 523.25, 554.36, 587.32, 622.25, 659.25, 698.45, 739.98, 783.99, 830.60, 880.00, 932.32, 987.76, 1046.50, 1108.73, 1174.65, 1244.50, 1318.51, 1396.91, 1479.97, 1567.98, 1661.21, 1760.00, 1864.65, 1975.53, 2093.00, 2217.46, 2349.31, 2489.01, 2637.02, 2793.82, 2959.95, 3135.96, 3322.43, 3520.00, 3729.31, 3951.06, 4186.00, 4434.92, 4698.63, 4978.03, 5274.04, 5587.65, 5919.91, 6271.92, 6644.87, 7040.00, 7458.62, 7902.13, 8372.01, 8869.84, 9397.27, 9956.06, 10548.08, 11175.30, 11839.82, 12543.85 };

		AudioSynthWaveform       	waveform1;     
		AudioSynthWaveform       	waveform2;     
		AudioSynthWaveform       	waveform3;     
		AudioEffectEnvelope      	ampEnvelope;   
		AudioEffectEnvelope      	filterEnvelope;
		AudioMixer4              	mixer1;        
		AudioFilterStateVariable 	filter1;       
		AudioOutputI2S 						i2s1;

		short l_delayline[CHORUS_DELAY_LENGTH];
		short r_delayline[CHORUS_DELAY_LENGTH];

	private:
};

#endif

instrument library cpp file:
Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <instrument.h>

Instrument::Instrument() { 

}

void Instrument::init(AudioOutputI2S i2s1){
  AudioConnection patchCord1(waveform1, 0, mixer1, 0);
  AudioConnection patchCord2(waveform2, 0, mixer1, 1);
  AudioConnection patchCord3(waveform3, 0, mixer1, 2);
  AudioConnection patchCord4(mixer1, ampEnvelope);
  AudioConnection patchCord5(waveform1, filterEnvelope);
  AudioConnection patchCord6(ampEnvelope, 0, filter1, 0);
  AudioConnection patchCord7(filterEnvelope, 0, filter1, 1);
  AudioConnection patchCord8(filter1, 0, i2s1, 0);
  AudioConnection patchCord9(filter1, 0, i2s1, 1);

  Serial.println("instrument init begin");
  this -> i2s1 = i2s1;
  waveform1.begin(0.5, 220.1, WAVEFORM_SQUARE); 
  waveform2.begin(0.5, 440, WAVEFORM_SINE); 
  waveform3.begin(0.5, 440, WAVEFORM_SAWTOOTH);
  mixer1.gain(0, 0.7); 
  mixer1.gain(1, 0.7);    
  mixer1.gain(2, 0.7);    
  ampEnvelope.delay(0);
  ampEnvelope.attack(0);
  ampEnvelope.hold(50.0);		
  ampEnvelope.decay(200.0);
  ampEnvelope.sustain(1.0);
  ampEnvelope.release(0.0);
  filterEnvelope.delay(0);
  filterEnvelope.attack(0);
  filterEnvelope.hold(10.0);		
  filterEnvelope.decay(100.0);
  filterEnvelope.sustain(1.0);
  filterEnvelope.release(0.0);
  filter1.frequency(400);
  filter1.resonance(3);
  filter1.octaveControl(5);
  Serial.println("instrument init end");
}


void Instrument::noteOn(uint8_t midiNote){
  waveform1.frequency(midiFreq[midiNote]);
  waveform2.frequency(midiFreq[midiNote]);
  waveform3.frequency(midiFreq[midiNote]);
  ampEnvelope.noteOn();
  filterEnvelope.noteOn();
}

void Instrument::noteOff(){
  ampEnvelope.noteOff();
  filterEnvelope.noteOff();
}
 
Last edited:
yea, your problem looks quite similar. I am not sure whats going on... Im wondering if the chip's DSP extensions don't allow abstractions like that, but I don't know. The low level DSP stuff is beyond me.

I think the ability to build libraries on top of the audio library would allow folks to share lots of fully assembled and tested DSP instruments. This library is amazing, but there is a TON of trial and error when it comes to getting something to sound the way you think it should.
 
I agree entirely.

I'm going to be working on this again tomorrow I believe (unless I get caught up with something else). For now, I'll just be trying to find a workable solution rather than necessarily solving it though. The ability to encapsulate in another library is quite important IMO.
Will update if I find anything.
 
Paul wrote this in another thread:

This isn't how the audio library works.

The objects are the components and connections between them. It doesn't work recursively. You can't build an audio library object which is internally composed of other audio library objects & connections.

To do something like that, you'd have to copy the actual code from those other objects into your new object. That code is designed to receive and transmit audio blocks, so you'd have to redesign all that code to work as 1 integrated unit. The receiving and transmitting of audio blocks is how an object communicates to the rest of the system, not how data flows within an object.

The audio library is designed to let you very easily create audio projects, using a graphical tool to define the interconnection of the objects. But inside the objects, the code is extremely optimized. The system is NOT designed for that type of easy design inside the objects. Very low-level, high optimized programming is used inside the actual objects.


https://forum.pjrc.com/threads/24793-Audio-Library/page45

Guess we are out of luck in making an instrument library for now!
 
Good find. That's somewhat disappointing though. Can't say I'm anywhere near an expert in C++ but as far as my understanding goes, I don't really understand why this isn't possible? Anyone able to explain this?

EDIT:
Reading Pauls post through a few times, I wonder if what he means is that you can't create an Audio library object which incorporates other audio library objects into it. All we want to do is create a static wrapper for the library which stores the audio library objects within it and runs as if it were being run from the main sketch itself (we just want to wrap it all up into a nice pretty looking class).
 
Last edited:
There is at least a slim chance I could explain 'this' but I've made enough of a fool of myself for one day, I am sure; I will say the following tho

(1) You could create instruments as .ino sketches and contribute them to the library.

(2) You could at least look at the source code of the objects (eg., AudioSynthWaveForm) you are using in the library and make sure it is above your coding skills to convert your sketches into single objects you could contribute instead.

Take a look in the input and output objects source files and any others that you might decide to look at when you open the folder containing the library - if you get no confidence out of that you could take option one above but post the sketches here and ask if anyone who can make a neat enough object of it sees enough value in bother to.

I should go to bed, 2:20am here and I 'clock on' in 6 hours and 10 minutes; Good night :)
 
Status
Not open for further replies.
Back
Top