Hi guys

Recently got a teensy 3.2 and a audio adaptor along with it, thinking that i could program Mozzi and have a basic inputs and outputs bundled on the adaptor for easy access.

well, turns out I didn't do my research and the ports are NOT simply redirecting signals to A14 and whatnot, but they're digial inputs that works with SGTL5000. you know what, i'm still not sure. correct me if I'm talking unicorns.

I could just get a headphone jack connected to A14 but i want to actually use the adaptor.

so i did muh research and managed to have Mozzi's output streamed into I2S's AudioPlayQueue

References from

https://forum.pjrc.com/threads/28254...1-audio-Shield

https://forum.pjrc.com/threads/27736...g%29-frequency

So what I'm doing is :

- have a typical Mozzi project. Code below is a modification of a Mozzi example Control Echo Theremin. I modded it so a sine wave's pitch alters according to input pin 2.

- in each updateAudio(), I collected the samples before its returned, into a buffer(just a simple list of 128 int16_t)

- when the buffer hits the end, I'd put them in a memory from where the queue resides,

- playQueue() and restart the buffer

- also got the hint from the above thread to change the STGL5000's sample rate to 16384.

- tada

Took me long to fiddle with buffer size and where to put any functions.. but this is the best I could do.

Now where I need you guys help is the consistent clicks in the output. First guess is that this is caused by sample rate not 100% in sync with Mozzi by decimals. Meh... I think this is the limit of mixing two independant audio system... But i'd really like to use mozzi and the teensy audio shield, though.

I'd really appreciate it if anyone could help with this!

Thanks in advance guys

Code:#include <MozziGuts.h> #include <Oscil.h> // oscillator template #include <tables/sin2048_int8.h> // sine table for oscillator #include <RollingAverage.h> #include <ControlDelay.h> #include <Audio.h> #include <Wire.h> #include <SPI.h> #include <SD.h> #include <SerialFlash.h> AudioPlayQueue queue1; //xy=92,334 AudioOutputI2S i2s1; //xy=342,313 AudioConnection patchCord1(queue1, 0, i2s1, 0); AudioConnection patchCord2(queue1, 0, i2s1, 1); AudioControlSGTL5000 sgtl5000_1; //xy=298,544 #define FSAMPLE 16384 int16_t buffer[128]; int bufferIndex = 0; // function prototype bool setI2SmasterClock(uint32_t freq, uint32_t mult = 256); float getI2SmasterClock(uint32_t mult = 256); #define INPUT_PIN 2 // analog control input unsigned int echo_cells_1 = 32; unsigned int echo_cells_2 = 60; unsigned int echo_cells_3 = 127; #define CONTROL_RATE 64 ControlDelay <128, int> kDelay; // 2seconds // oscils to compare bumpy to averaged control input Oscil <SIN2048_NUM_CELLS, AUDIO_RATE> aSin0(SIN2048_DATA); Oscil <SIN2048_NUM_CELLS, AUDIO_RATE> aSin1(SIN2048_DATA); Oscil <SIN2048_NUM_CELLS, AUDIO_RATE> aSin2(SIN2048_DATA); Oscil <SIN2048_NUM_CELLS, AUDIO_RATE> aSin3(SIN2048_DATA); // use: RollingAverage <number_type, how_many_to_average> myThing RollingAverage <int, 32> kAverage; // how_many_to_average has to be power of 2 int averaged; void setup(){ kDelay.set(echo_cells_1); startMozzi(); AudioMemory(60); setI2SmasterClock(FSAMPLE); sgtl5000_1.enable(); sgtl5000_1.volume(0.6); Serial.begin(9600); } void updateControl(){ int bumpy_input = mozziAnalogRead(INPUT_PIN); averaged = kAverage.next(bumpy_input); aSin0.setFreq(averaged); aSin1.setFreq(kDelay.next(averaged)); aSin2.setFreq(kDelay.read(echo_cells_2)); aSin3.setFreq(kDelay.read(echo_cells_3)); } int updateAudio(){ int16_t currentSample = 3*((int)aSin0.next()+aSin1.next()+(aSin2.next()>>1)+(aSin3.next()>>2)) << 3; if(bufferIndex < 128){ buffer[bufferIndex] = currentSample; bufferIndex++; }else{ int16_t *bufferPointer = queue1.getBuffer(); memcpy(bufferPointer, buffer, 256); queue1.playBuffer(); bufferIndex = 0; } return currentSample; } void loop(){ audioHook(); } /* Generate I2S master clock The MCLK output frequencies should be in the range from F_pll/4096 to 12.5 MHz. For convenience the frequency has been split into a sample frequency and a sample clock multiplication factor. For direct control of the master clock frequency, set the multiplier to 1. For almost all combinations of sample clocks (8, 11.025, 12, 16, 22.05, 24, 32, 44.1 and 48 kHz) and cpu clock frequencies it will find a ratio, that generates the exact frequency. For the other few, the output frequency lies within 0.5 Hz distance from the desired frequency. freq: sample frequency in Hz mult: sample clock multiplication factor, (default 256) return value: true if the frequency is within the valid range */ bool setI2SmasterClock(uint32_t freq, uint32_t mult) { // determine fractional ratio for: p / q = freq * mult / f_pll // f_pll = 16 MHz * ((MCG_C6 & 0x1f) + 24) / ((MCG_C5 & 0x1f) + 1) uint32_t p = freq * mult * ((MCG_C5 & 0x1f) + 1); uint32_t q = 16000000ul * ((MCG_C6 & 0x1f) + 24); uint32_t fract = 0, divide = 1; // I2Sx_MDR register values uint32_t fract1, fract2 = 1; // values of iterations n-1 and n-2. uint32_t divide1, divide2 = 0; // idem. uint8_t src = 3; // clock source selection: 3 = pll // Master clock should be slower than reference clock if (p > q) return false; else if (p == q) fract = divide = 1; else { // Approximate p/q by a continued fraction expansion. // (typically takes only 4 to 8 iterations) while (p) { // find next element of continued fraction uint32_t a = q / p; uint32_t oldp = p; p = q - a * p; q = oldp; // update fract/divide by Wallis method fract1 = fract; divide1 = divide; fract = fract1 * a + fract2; divide = divide1 * a + divide2; fract2 = fract1; divide2 = divide1; // Exit loop if fraction gets too big for the registers if (fract > 256 || divide > 4096) { // Revert back to last approximation that still fitted fract = fract2; divide = divide2; break; } } // Check if frequency too low or too high if (!fract) return false; } // Actually set registers and enable MCLK. SIM_SCGC6 |= SIM_SCGC6_I2S; I2S0_MDR = I2S_MDR_FRACT((fract - 1)) | I2S_MDR_DIVIDE((divide - 1)); I2S0_MCR = I2S_MCR_MICS(src) | I2S_MCR_MOE; // 'Connect' MCLK output to an actual output pin CORE_PIN11_CONFIG = PORT_PCR_MUX(6); //CORE_PIN28_CONFIG = PORT_PCR_MUX(4); // Pin on bottom return true; } float getI2SmasterClock(uint32_t mult) { float fpll = 16.0e6f * ((MCG_C6 & 0x1f) + 24) / ((MCG_C5 & 0x1f) + 1); uint32_t fract = ((I2S0_MDR >> 12) & 0xff) + 1; uint32_t divide = (I2S0_MDR & 0xfff) + 1; return fpll * fract / (divide * mult); }