Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 7 of 7

Thread: Quad I2S using 1 audio board, switching between synth/mic

  1. #1
    Member propa's Avatar
    Join Date
    Apr 2018
    Location
    UK
    Posts
    93

    Quad I2S using 1 audio board, switching between synth/mic

    I'm trying to put a couple of pieces of code together, one mode outputs a synth sound, one mode outputs the mic in.

    I've read you can only use 1 I2S object, and can't use a mixer to send multiple signals to it. The code attached is a work around after finding the quad i2s object.

    I'm aware it's been made to use with multiple audio boards; however can it be used to with 1 audio board if you're not simultaneously processing two streams?

    There's a great deal of ambiguity in the statement:

    "Normally, this object is used with two Audio Shields, which are controlled separately by a pair of "sgtl5000" objects"

    Is there any wiggle room with normality? Can the quad I2S object be used like this with only one shield?

    Code:
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <SD.h>
    #include <SerialFlash.h>
    
    // GUItool: begin automatically generated code
    AudioSynthWaveformSine   sine1;          //xy=63,154
    AudioSynthWaveformSineModulated sine_fm1;       //xy=190,252
    AudioInputI2S            i2s2;           //xy=226,65
    AudioEffectEnvelope      envelope1;      //xy=340,257
    AudioMixer4              mixer2;         //xy=403,79
    AudioEffectDelay         delay1;         //xy=501,339
    AudioEffectGranular      granular1;      //xy=556,71
    AudioMixer4              mixer1;         //xy=681,270
    AudioOutputI2SQuad       i2s_quad1;      //xy=784,109
    AudioConnection          patchCord1(sine1, sine_fm1);
    AudioConnection          patchCord2(sine_fm1, envelope1);
    AudioConnection          patchCord3(i2s2, 0, mixer2, 0);
    AudioConnection          patchCord4(i2s2, 1, mixer2, 1);
    AudioConnection          patchCord5(envelope1, delay1);
    AudioConnection          patchCord6(envelope1, 0, i2s_quad1, 2);
    AudioConnection          patchCord7(mixer2, granular1);
    AudioConnection          patchCord8(delay1, 0, mixer1, 0);
    AudioConnection          patchCord9(delay1, 1, mixer1, 1);
    AudioConnection          patchCord10(delay1, 2, mixer1, 2);
    AudioConnection          patchCord11(delay1, 3, mixer1, 3);
    AudioConnection          patchCord12(granular1, 0, i2s_quad1, 0);
    AudioConnection          patchCord13(granular1, 0, i2s_quad1, 1);
    AudioConnection          patchCord14(mixer1, 0, i2s_quad1, 3);
    AudioControlSGTL5000     sgtl5000_1;     //xy=303,373
    // GUItool: end automatically generated code

  2. #2
    Senior Member+ Theremingenieur's Avatar
    Join Date
    Feb 2014
    Location
    Colmar, France
    Posts
    2,385
    Reading the documentation and looking at the schematics of the audio board should tell you that the I2S data stream for the 3rd and 4th channel (I2S0_TXD1) is of no use when using only one audio board. Each SGTL5000 can accept one single stream, either I2S0_TXD0 containing channels 1 and 2 or I2S0_TXD1 containing channels 3 and 4, but never both.
    Only when using 2 audio boards, you might connect one data line to the one and the other line to the other, while connecting the master clock, bit clock, and frame sync signals in parallel.

  3. #3
    Member propa's Avatar
    Join Date
    Apr 2018
    Location
    UK
    Posts
    93
    Quote Originally Posted by Theremingenieur View Post
    Reading the documentation and looking at the schematics of the audio board should tell you that the I2S data stream for the 3rd and 4th channel (I2S0_TXD1) is of no use when using only one audio board. Each SGTL5000 can accept one single stream, either I2S0_TXD0 containing channels 1 and 2 or I2S0_TXD1 containing channels 3 and 4, but never both.
    Only when using 2 audio boards, you might connect one data line to the one and the other line to the other, while connecting the master clock, bit clock, and frame sync signals in parallel.
    Thank you for making that clear.

    Is it still possible to switch between audio input and synthesiser without using two shields then? I've tried using a mixer and switching two of the four channels on and off in code but can't get any synth sound out.

    Does the code from the audio tool seem ok? Should it theoretically produce a synth and a mic signal at the same time?

    Code:
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <SD.h>
    #include <SerialFlash.h>
    
    // GUItool: begin automatically generated code
    AudioSynthWaveformSine   sine1;          //xy=111,35
    AudioSynthWaveformSine   sine2;          //xy=111,70
    AudioInputI2S            i2s2;           //xy=210,124
    AudioMixer4              mixer3;         //xy=347,137
    AudioSynthWaveformModulated waveformMod1;   //xy=439,46
    AudioEffectGranular      granular1;      //xy=489,137
    AudioMixer4              mixer2;         //xy=646,124
    AudioOutputI2S           i2s1;           //xy=797,122
    AudioConnection          patchCord1(sine1, 0, waveformMod1, 0);
    AudioConnection          patchCord2(sine1, 0, mixer2, 1);
    AudioConnection          patchCord3(sine2, 0, waveformMod1, 1);
    AudioConnection          patchCord4(i2s2, 0, mixer3, 0);
    AudioConnection          patchCord5(i2s2, 1, mixer3, 1);
    AudioConnection          patchCord6(mixer3, granular1);
    AudioConnection          patchCord7(waveformMod1, 0, mixer2, 0);
    AudioConnection          patchCord8(granular1, 0, mixer2, 2);
    AudioConnection          patchCord9(granular1, 0, mixer2, 3);
    AudioConnection          patchCord10(mixer2, 0, i2s1, 0);
    AudioConnection          patchCord11(mixer2, 0, i2s1, 1);
    AudioControlSGTL5000     sgtl5000_1;     //xy=122,212
    // GUItool: end automatically generated code

  4. #4
    Senior Member+ Theremingenieur's Avatar
    Join Date
    Feb 2014
    Location
    Colmar, France
    Posts
    2,385
    Take off the second I2S output, you don't have any.

    Use a mixer to dispatch your different signals on the left and right channels of the remaining single i2s output. Don't make things more complicated than they are.

  5. #5
    Member propa's Avatar
    Join Date
    Apr 2018
    Location
    UK
    Posts
    93
    Quote Originally Posted by Theremingenieur View Post
    Take off the second I2S output, you don't have any.

    Use a mixer to dispatch your different signals on the left and right channels of the remaining single i2s output. Don't make things more complicated than they are.
    I'm not sure I understand, I don't have a second i2s output there. The signals are being mixed by a mixer before going into a single i2s output (same code as 2nd message):

    Code:
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <SD.h>
    #include <SerialFlash.h>
    
    // GUItool: begin automatically generated code
    AudioSynthWaveformSine   sine1;          //xy=152,180
    AudioSynthWaveformSine   sine2;          //xy=152,215
    AudioInputI2S            i2s2;           //xy=251,269
    AudioMixer4              mixer3;         //xy=388,282
    AudioSynthWaveformModulated waveformMod1;   //xy=480,191
    AudioEffectGranular      granular1;      //xy=530,282
    AudioMixer4              mixer2;         //xy=687,269
    AudioOutputI2S           i2s1;           //xy=834,276
    AudioConnection          patchCord1(sine1, 0, waveformMod1, 0);
    AudioConnection          patchCord2(sine1, 0, mixer2, 1);
    AudioConnection          patchCord3(sine2, 0, waveformMod1, 1);
    AudioConnection          patchCord4(i2s2, 0, mixer3, 0);
    AudioConnection          patchCord5(i2s2, 1, mixer3, 1);
    AudioConnection          patchCord6(mixer3, granular1);
    AudioConnection          patchCord7(waveformMod1, 0, mixer2, 0);
    AudioConnection          patchCord8(granular1, 0, mixer2, 2);
    AudioConnection          patchCord9(granular1, 0, mixer2, 3);
    AudioConnection          patchCord10(mixer2, 0, i2s1, 0);
    AudioConnection          patchCord11(mixer2, 0, i2s1, 1);
    AudioControlSGTL5000     sgtl5000_1;     //xy=163,357
    // GUItool: end automatically generated code
    I don't understand whether these objects are all being processed at the same time, seems like unnecessary processing if that is the case.

  6. #6
    Senior Member+ Theremingenieur's Avatar
    Join Date
    Feb 2014
    Location
    Colmar, France
    Posts
    2,385
    Sorry, my fault. I misread i2s2 for an output.

    Why not start simpler and let most of the synth stuff away for a moment. Keep just a sine waveform and on mixer and try to alternate between the mic signal and the sine wave. When you got that working, add the second sine wave, and so on. proceed step by step. Much easier to debug.

  7. #7
    Member propa's Avatar
    Join Date
    Apr 2018
    Location
    UK
    Posts
    93
    Quote Originally Posted by Theremingenieur View Post
    Sorry, my fault. I misread i2s2 for an output.

    Why not start simpler and let most of the synth stuff away for a moment. Keep just a sine waveform and on mixer and try to alternate between the mic signal and the sine wave. When you got that working, add the second sine wave, and so on. proceed step by step. Much easier to debug.
    Indeed, good idea; that's what I've ended up doing for the last few hours.

    Got it working now, mic and synth can be heard at the same time! You can use the mic and create a synth sound at the same time without any problems!

    Tried putting together with the granulator and seems to have broken the freeze function sadly:

    Code:
    // Waveform Modulation Example - Create waveforms with 
    // modulated frequency
    //
    // This example is meant to be used with 3 buttons (pin 0,
    // 1, 2) and 2 knobs (pins 16/A2, 17/A3), which are present
    // on the audio tutorial kit.
    //   https://www.pjrc.com/store/audio_tutorial_kit.html
    //
    // Use an oscilloscope to view the 2 waveforms.
    //
    // Button0 changes the waveform shape
    //
    // Knob A2 changes the amount of frequency modulation
    //
    // Knob A3 varies the shape (only for Pulse & Variable Triangle)
    //
    // This example code is in the public domain.
    
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <SerialFlash.h>
    #include <Bounce.h>
    
    #define GRANULAR_MEMORY_SIZE 12800  // enough for 290 ms at 44.1 kHz
    int16_t granularMemory[GRANULAR_MEMORY_SIZE];
    
    
    // GUItool: begin automatically generated code
    AudioSynthWaveformSine   sine1;          //xy=152,180
    AudioSynthWaveformSine   sine2;          //xy=152,215
    AudioInputI2S            i2s2;           //xy=251,269
    AudioMixer4              mixer3;         //xy=388,282
    AudioSynthWaveformModulated waveformMod1;   //xy=480,191
    AudioEffectGranular      granular1;      //xy=530,282
    AudioMixer4              mixer2;         //xy=687,269
    AudioOutputI2S           i2s1;           //xy=834,276
    AudioConnection          patchCord1(sine1, 0, waveformMod1, 0);
    AudioConnection          patchCord2(sine1, 0, mixer2, 1);
    AudioConnection          patchCord3(sine2, 0, waveformMod1, 1);
    AudioConnection          patchCord4(i2s2, 0, mixer3, 0);
    AudioConnection          patchCord5(i2s2, 1, mixer3, 1);
    AudioConnection          patchCord6(mixer3, granular1);
    AudioConnection          patchCord7(waveformMod1, 0, mixer2, 0);
    AudioConnection          patchCord8(granular1, 0, mixer2, 2);
    AudioConnection          patchCord9(granular1, 0, mixer2, 3);
    AudioConnection          patchCord10(mixer2, 0, i2s1, 0);
    AudioConnection          patchCord11(mixer2, 0, i2s1, 1);
    AudioControlSGTL5000     sgtl5000_1;     //xy=163,357
    // GUItool: end automatically generated code
    
    Bounce button0 = Bounce(0, 15);
    Bounce button1 = Bounce(6, 15);
    Bounce button2 = Bounce(7, 15);
    
    int current_waveform=0;
    int16_t current_mode = 1;
    
    //extern const int16_t myWaveform[256];  // defined in myWaveform.ino
    
    void setup() {
      Serial.begin(9600);
      pinMode(0, INPUT_PULLUP);
      pinMode(1, INPUT_PULLUP);// spdt switch
      pinMode(2, INPUT_PULLUP);// spdt
      pinMode(6, INPUT_PULLUP);
      pinMode(7, INPUT_PULLUP);
      pinMode(8, INPUT_PULLUP);
      //pinMode(led1, OUTPUT); 
      //pinMode(led2, OUTPUT); 
    
      delay(300);
      Serial.println("Waveform Modulation Test");
      // Audio connections require memory to work.  For more
      // detailed information, see the MemoryAndCpuUsage example
      AudioMemory(100);
    
      // Comment these out if not using the audio adaptor board.
      sgtl5000_1.enable();
      sgtl5000_1.volume(0.8); // caution: very loud - use oscilloscope only!
      sgtl5000_1.inputSelect(AUDIO_INPUT_MIC);
      sgtl5000_1.micGain(36);
      
      mixer2.gain(0,0.5);
      mixer2.gain(1,0.5);
    
      mixer2.gain(2,0.5);
      mixer2.gain(3,0.5);
    
      mixer3.gain(0,0.5);
      mixer3.gain(1,0.5);
      
      granular1.begin(granularMemory, GRANULAR_MEMORY_SIZE);
      // Confirgure both to use "myWaveform" for WAVEFORM_ARBITRARY
      //waveformMod1.arbitraryWaveform(myWaveform, 172.0);
    
      // Configure for middle C note without modulation
      waveformMod1.frequency(261.63);
      waveformMod1.amplitude(1.0);
      sine1.frequency(20.3); // Sine waves are low frequency oscillators (LFO)
      sine2.frequency(1.2);
    
      current_waveform = WAVEFORM_TRIANGLE_VARIABLE;
      waveformMod1.begin(current_waveform);
      // uncomment to try modulating phase instead of frequency
      //waveformMod1.phaseModulation(720.0);
    }
    
    void loop() {
      // Read the buttons and knobs, scale knobs to 0-1.0
      button0.update();
      button1.update();
      button2.update();
      float knob_A2 = (float)analogRead(A7) / 1023.0;
      float knob_A3 = (float)analogRead(A6) / 1023.0;
      // use Knobsto adjust the amount of modulation
      sine1.amplitude(knob_A2);
      sine2.amplitude(knob_A3);
    
      if (button1.fallingEdge()) 
      {
        Serial.println("Current Mode");
        Serial.println(current_mode);
          //switch(current_mode) 
    //    {
    //      case 1: 
    //      synthTime();
    //      Serial.println("Current Mode Synth");
    //      break;
    //      case 2:
    //      vocalTime();
    //      Serial.println("Current Mode MicIN");
    //      break;
    //     }
        current_mode += 1;
        if (current_mode > 2) current_mode = 0;
      }
      if (current_mode == 0) 
        {
          synthTime();
          mixer2.gain(0,0.5);
          mixer2.gain(1,0.5);
    
          mixer2.gain(2,0.0);
          mixer2.gain(3,0.0);
        }
    
        if (current_mode == 1) 
        {
          mixer2.gain(0,0.0);
          mixer2.gain(1,0.0);
          
          mixer2.gain(2,0.5);
          mixer2.gain(3,0.5);
          vocalTime();
        }
    
        if (current_mode == 2) 
        {
          vocalTime();
          mixer2.gain(0,0.5); // 
          mixer2.gain(1,0.5); // both together
          
          mixer2.gain(2,0.5);
          mixer2.gain(3,0.5);
        }
        
    }
    
    void vocalTime()
    {
      float knobA2 = (float)analogRead(A6) / 1023.0;
      float knobA3 = (float)analogRead(A7) / 1023.0;
      
      // Button 0 starts Freeze effect
      if (button0.fallingEdge()) 
      {
        float msec = 100.0 + (knobA3 * 150.0);
        granular1.beginFreeze(msec);
        Serial.print("Begin granular freeze using ");
        Serial.print(msec);
        Serial.println(" grains");
      }
      
      if (button0.risingEdge()) 
      {
        granular1.stop();
      }
      // Button 1 starts Pitch Shift effect
      if (button2.fallingEdge()) {
        float msec = 25.0 + (knobA3 * 75.0);
        granular1.beginPitchShift(msec);
        Serial.print("Begin granular pitch phift using ");
        Serial.print(msec);
        Serial.println(" grains");
      }
      if (button2.risingEdge()) 
      {
        granular1.stop();
      }
      // Continuously adjust the speed, based on the A3 pot
      float ratio;
      ratio = powf(2.0, knobA2 * 2.0 - 1.0); // 0.5 to 2.0
      //ratio = powf(2.0, knobA2 * 6.0 - 3.0); // 0.125 to 8.0 -- uncomment for far too much range!
      granular1.setSpeed(ratio);
    }
    
    void synthTime()
    {
       // Button 0 changes the waveform type
      if (button0.fallingEdge()) 
      {
        switch (current_waveform) {
          case WAVEFORM_SINE:
            current_waveform = WAVEFORM_SAWTOOTH;
            Serial.println("Sawtooth");
            break;
          case WAVEFORM_SAWTOOTH:
            current_waveform = WAVEFORM_SAWTOOTH_REVERSE;
            Serial.println("Reverse Sawtooth");
            break;
          case WAVEFORM_SAWTOOTH_REVERSE:
            current_waveform = WAVEFORM_SQUARE;
            Serial.println("Square");
            break;
          case WAVEFORM_SQUARE:
            current_waveform = WAVEFORM_TRIANGLE;
            Serial.println("Triangle");
            break;
          case WAVEFORM_TRIANGLE:
            current_waveform = WAVEFORM_TRIANGLE_VARIABLE;
            Serial.println("Variable Triangle");
            break;
          case WAVEFORM_TRIANGLE_VARIABLE:
    //        current_waveform = WAVEFORM_ARBITRARY;
    //        Serial.println("Arbitary Waveform");
    //        break;
    //      case WAVEFORM_ARBITRARY:
            current_waveform = WAVEFORM_PULSE;
            Serial.println("Pulse");
            break;
          case WAVEFORM_PULSE:
    //        current_waveform = WAVEFORM_SAMPLE_HOLD;
    //        Serial.println("Sample & Hold");
    //        break;
    //      case WAVEFORM_SAMPLE_HOLD:
            current_waveform = WAVEFORM_SINE;
            Serial.println("Sine");
            break;
        }
        waveformMod1.begin(current_waveform);
      }
    }
    Works but I must be doing something wrong for the freeze function to have stopped working.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •