Raspberry Pi + Teensy Audio i2s

Status
Not open for further replies.

David_B

Active member
Hi, I wondered whether anyone might be able to give some guidance on using Teensy to receive audio from a RaPi over i2s.

Much of the project is fairly straightforward. I'm using an audio board with a Teensy 3.2 to play wav data from an SD card in the slot on the audio board. Sensors attached to the board will play trigger different files to be played.

However I am also playing mp3 files via a Raspberry Pi. These files will change regularly in response to user input etc. etc. which is why they can't be on the same SD card as the others.

The media player on the RaPi is controlled through serial over USB which is working well. I'm using a HiFi Berry DAC+ standard (https://www.hifiberry.com/products/dacplus/) rather than the 3.5mm output. At the moment, I'm feeding this into the line-in on the audio board. This means that I can easily control the mix of the two sounds and mute inputs when they're not in use etc. It works pretty well but I'd like to see if this could working using i2s to link the Pi and Teensy because:

1. I'm finding that there's a bit more noise (hiss) than I'd like when the audio in on the Teensy is unmuted. This is present regardless of whether it's connected to the Pi. Of course, this will be less noticeable once sound is playing but it would be great if things could be a bit quieter.

2. It seems a shame to use a RaPi HAT to take an i2s feed through a DAC over some copper, back in through an ADC and out through another DAC.

I've had a look into this, of course, but am having trouble getting my head around some things, mainly how one would go about connecting this to the Teensy. I wondered whether if I included a i2s quad input device and used pin 30 to connect to the Pi, whether this might be a good starting point. Presumably I'd have to set the RaPi up as a slave, somehow...

Thanks in advance of any pointers.

David


Code:
#include <MPR121.h>
#include <Wire.h>

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

#define SDCARD_CS_PIN    10
#define SDCARD_MOSI_PIN  7
#define SDCARD_SCK_PIN   14

#define number_of_touch_sensors 12
#define default_volume 1

AudioSynthWaveformSine   hello;
AudioEffectFade          fade_hello,
                         fade_sd;
                         
AudioPlaySdWav           sd_card_1,
                         sd_card_2,
                         sd_card_3,
                         sd_card_4;

AudioSynthToneSweep      sweep;
                         
AudioMixer4              mixer_sd,
                         mixer_in,
                         mixer_out;

AudioOutputI2S           soundcard;

AudioInputI2S            audio_in;

AudioConnection          patchcords[]={
                          AudioConnection(hello,0,fade_hello,0),
                          AudioConnection(fade_hello,0,mixer_out,0),

                          AudioConnection(sd_card_1,0,mixer_sd,0),
                          AudioConnection(sd_card_2,0,mixer_sd,1),
                          AudioConnection(sd_card_3,0,mixer_sd,2),
                          AudioConnection(sd_card_4,0,mixer_sd,3),
                          AudioConnection(mixer_sd,0,fade_sd,0),
                          AudioConnection(fade_sd,0,mixer_out,1),

                          AudioConnection(audio_in,0,mixer_in,0),
                          AudioConnection(audio_in,1,mixer_in,1),
                        //  AudioConnection(audio_in,2,mixer_in,2),
                        //  AudioConnection(audio_in,3,mixer_in,3),

                          AudioConnection(mixer_in,0,mixer_out,2),

                          AudioConnection(sweep,0,mixer_out,3),

                          AudioConnection(mixer_out,0,soundcard,0),
                          AudioConnection(mixer_out,0,soundcard,1)
                        
                        };

AudioControlSGTL5000     sgtl5000_1;
//AudioControlSGTL5000     sgtl5000_2;

int iMaxPressure=0,
    iMinPressure=0,
    iPressureDelta=0;

unsigned long ulLastMeasure;

boolean bInOnOff=true;

String aSamples[]={
  "",
  "ear.wav",
  "",
  "eye_1.wav",
  "",
  "eye_2.wav",
  "",
  "nose.wav"  
};

void fHelloSound(){
  fade_hello.fadeOut(1);
  delay(500);
  
  hello.amplitude(1);

  hello.frequency(220);
  fade_hello.fadeIn(100);
  delay(200);
  fade_hello.fadeOut(250);
  delay(250);
  hello.frequency(392);
  fade_hello.fadeIn(100);
  delay(200);
  fade_hello.fadeOut(250);
  delay(250);
  hello.amplitude(0);
}

void fChannelTest() {
  mixer_out.gain(0,default_volume);
  fHelloSound();
  mixer_out.gain(0,0);
}

void setup() {
  Serial.begin(57600);
  
  Wire.begin();
/*  
  // 0x5C is the MPR121 I2C address on the Bare Touch Board
  if(!MPR121.begin(0x5A)){ 
    Serial.println("error setting up MPR121");  
    switch(MPR121.getError()){
      case NO_ERROR:
        Serial.println("no error");
        break;  
      case ADDRESS_UNKNOWN:
        Serial.println("incorrect address");
        break;
      case READBACK_FAIL:
        Serial.println("readback failure");
        break;
      case OVERCURRENT_FLAG:
        Serial.println("overcurrent on REXT pin");
        break;      
      case OUT_OF_RANGE:
        Serial.println("electrode out of range");
        break;
      case NOT_INITED:
        Serial.println("not initialised");
        break;
      default:
        Serial.println("unknown error");
        break;      
    }
    while(1);
  }
  
  MPR121.setInterruptPin(4);
  MPR121.setTouchThreshold(40);
  MPR121.setReleaseThreshold(20);  
  MPR121.updateTouchData();
*/
  pinMode(A2, INPUT);

  SPI.setMOSI(SDCARD_MOSI_PIN);
  SPI.setSCK(SDCARD_SCK_PIN);
  if (!(SD.begin(SDCARD_CS_PIN))) Serial.println("Unable to access the SD card");
  
  AudioMemory(100);

  // Enable the first audio shield, select input, and enable output
  sgtl5000_1.setAddress(LOW);
  sgtl5000_1.enable();
  sgtl5000_1.inputSelect(AUDIO_INPUT_LINEIN);
  sgtl5000_1.volume(0.5);
  sgtl5000_1.adcHighPassFilterDisable();
  sgtl5000_1.lineInLevel(0);
/*
  // Enable the second audio shield, select input, and enable output
  sgtl5000_2.setAddress(HIGH);
  sgtl5000_2.enable();
  sgtl5000_2.inputSelect(AUDIO_INPUT_LINEIN);
  sgtl5000_2.volume(0.5);
  sgtl5000_2.adcHighPassFilterDisable();
  sgtl5000_2.lineInLevel(0);
*/
  mixer_sd.gain(0,default_volume);
  mixer_sd.gain(1,default_volume);

  mixer_in.gain(0,default_volume);
  mixer_in.gain(1,0);

  //fChannelTest();

  mixer_out.gain(1,default_volume);
  mixer_out.gain(2,default_volume);
  mixer_out.gain(3,default_volume);
}

void loop() {
  if(!sd_card_1.isPlaying()) {    
    //delay(1000);
    //sweep.play(1,220,880,0.25);
    delay(1000);
    sd_card_1.play("15s.WAV");
    delay(300);
  }
  
  if(!sweep.isPlaying()) {
    //sweep.play(1,880,220,2);
    /*float flLevel=bInOnOff?0.25:0;
    Serial.print("level=");
    Serial.print(flLevel);
    Serial.println();
    mixer_in.gain(0,flLevel);
    mixer_in.gain(1,flLevel); 
    bInOnOff=bInOnOff^1;
    */
  }
  
  if(MPR121.touchStatusChanged()){
    MPR121.updateTouchData();
    for(int iSensor=0; iSensor<number_of_touch_sensors; iSensor++){
      if(MPR121.isNewTouch(iSensor)){
        Serial.print("TOUCH ON: ");
        Serial.print(iSensor, DEC);
        Serial.println();

        sd_card_1.play(aSamples[iSensor].c_str());        
      } else if(MPR121.isNewRelease(iSensor)){
        Serial.print("TOUCH OFF: ");
        Serial.print(iSensor, DEC);
        Serial.println();  
      }
    } 
  }
}
 
Thanks for the swift reply. No, I didn't actually!

However the reason for the RaPi isn't to play mp3 specifically, but so that the files can be easily updated by the user over the internet with a trigger via a websocket.

It has occurred to me that I could connect the teensy directly to the web to do this - but I've had limited success with websockets and microcontrollers in the past...
 
... and lack of SSL is probably an issue...

Thanks for the swift reply. No, I didn't actually!

However the reason for the RaPi isn't to play mp3 specifically, but so that the files can be easily updated by the user over the internet with a trigger via a websocket.

It has occurred to me that I could connect the teensy directly to the web to do this - but I've had limited success with websockets and microcontrollers in the past...
 
I spent a lot of time and blood, sweat and tears trying to do this in spring of 2016. You can find my pleas and my solo discoveries on the RPi site forums. I was able to manually send things to the board and hear them at the wrong speed, but never got it to work right or be recognized by Raspbian. BUT there is another board made using the SGTL5000, the Fe-Pi, whose makers released a driver and configuration files and ultimately got them included in mainline Raspbian. If you download the latest Raspbian, you should theoretically be able to follow the steps for the Fe-Pi board to get the RPi to think the Teensy Audio board is a Fe-Pi board. I have not tried it and I kind of don't want to... but if you do, let me know!!

Chuckk
 
Status
Not open for further replies.
Back
Top