Using the Audio Shield alongside a Synth chip

Davidelvig

Well-known member
My Teensy 3.2-based product is a MIDI wind controller (DigiBrass)

I've been using the VS1053b chip from VLSI for several years as an internal Synth. It's a good General MIDI compliant Synth chip, and it also provides the signal to the headphone jack.

I'd like to add some new capabilities using the Audio Library and the Audio shield. (This next version will be Teensy 4.1-based)

Sound routing is the challenge.

I'd like to do the following

1) Controller MIDI messages (note on and off, pitch bend, expression, mod wheel, other) to...
2a) VS1053 synth to create standard General MIDI instrument audio to... Teensy as an audio input to morph them sound... then to the Audio Shield to a headphone jack
and/or
2b) On-Teensy MIDI interpreter/synth to audio shield to headphone jack

The VS1053 has I2S out and analog audio in/out.

What might be the best signal routing to use?
(I've not use I2S or audio in before (except as wire by the audio shield))

Thanks!
 
Does the VS1053 support being an I2S slave? With I2S only one device can be a master (generate the clocks).
 
I think it may generate the clock based on this page
VS1053-ISC Section.jpg
from the this data sheet (linked).

That makes the VS1053 an I2S Master, right, and hence I2S would not work for the yellow path below?

Signal Flow.jpg

This is the flow I want:
- Audio can get from the microphone to the Teensy Synth Code
- Audio can get from the VS1053 Synth to the Teensy Synth Code
- Synthed or modified audio can get from Teensy Synth Code to Headphones
 

Attachments

  • VS1053 - I2S Section.pdf
    239.1 KB · Views: 13
I would look at integrating this chip on I2S2 of the Teensy. Then it can run as a master (or slave), and the audio shield will work just fine on its intended I2S1 ports. Each SAI (I2S + I2S2) can run independently. I do this with the ESP32 running as a master.
 
Thanks, Jay.

So, I'd connect the VS1053's I2S out to the secondary I2S2 input of the Teensy.

T4.x
Pin Signal Direction
4 BCLK Output
33 MCLK Output
5 RX Input
3 LRCLK Output

I see I2S2 in the GUI design tool's documentation that I2S2 is in Master mode.
I don't see a SLAVE option (at least in the design tool) for I2S2.
 
Hi David,

After posting I wondered if I should have shared my examples (https://github.com/JayShoe/esp32_T4_bt_music_receiver). It looks like your suggested pins are correct. In my case, we don't use MCLK.

I guess that I2S2 slave example never made it into the library, and maybe it should be (Alex?).

I'm pretty sure the async input code also resamples it so it works with the differing clocks, too. I'm not sure that code is in the library either.

Jay
 
Got it. Were you using a different branch of the audio library that has an option to use the Teensy I2S2 pins in slave mode?
 
That would be heroic!
I'll give it a go.
Thanks, Jay!

I'm also confirming with VLSI.fl that the VS1053 operates as an I2S Master.
This is closer to the metal that I typically run.
 
Don't forget to set the USB Type: Serial + Midi + Audio when compiling it over otherwise it won't compile. Good luck!
 
I did a project sending the analog signal of the VS1053 into the audio shield... Very curious to see how this plays out!
 
Great, @blakeAlbion! How did that project work? That's an alternative I'm considering as well. Was the sound quality good?

Which pins on the VS1053 and on the Teensy did you use?
 
The VS1053 has two kinds of output I2S (as Master) and analog, which I have used for a headphone jack (and has kind of wimpy output).
If I were to instead take the analog output of the the VS1053 and pipe it into the Teensy 4x
How would I connect the three pins (Right, Left, GBUF)?
VS1053 signal flow.png

The VS1053 data sheet say GBUF is a "Common buffer for headphones, do NOT connect to ground!"
"GBUF must NOT be connected to ground under any circumstances.
If GBUF is not used, LEFT and RIGHT must be provided with coupling capacitors.
To keep GBUF stable, you should always have the resistor and capacitor even when GBUF is not used. See application notes for details."
 
The GBUF is a different ground (at DC) so I wouldn't connect it. Left and Right are floating relative to GBUF so would need to be AC-coupled. I fear this would work but would have low performance as Left and Right are not relative to ordinary ground and you cannot assume GBUF is the same AC ground as GND, if you see what I mean.

Internally GBUF is an amplified output so you must never short it to anything (at AC or DC). Its exists to avoid the need for large electrolytic capacitors when driving headphones as the chip is designed for use in small devices, just like the SGTL5000
 
That work is clear enough to test the I2S path, though on the Teensy 4.0, I'd need to use one to the back pads (33) and also find the Audio library extension that allows I2s2 to be a slave.

What would I lose in using the simpler stereo audio approach?
- how do I find out if the levels are compatible?
- do I need to use big capacitors on the right and left lines between to VS1053 and the Teensy Audio Board... or would that only be if the VS1053 was going to earphones - without the GBUF connected?

Perhaps better:
Is there an audio engineer-type Teensy person on the forum that I could hire for a little coaching?
 
In particular, connecting the VS1053's LEFT and RIGHT Stereo Earphone Driver outputs to Audio Board's LINEINL and LINEINR header as in this drawing:
VS1053 signal flow.pngTeensy Audio D2.jpg
- will this work?
- what else will I need? (I note the Audio board already has caps on these two inputs)

...and of possible significance, I'm also interested to use the MIC input as a separate signal.
- any problems there?

Thanks
 
I did a project sending the analog signal of the VS1053 into the audio shield... Very curious to see how this plays out!

I'm going to focus on analog connection between the VS1053 because I'm seeing some red flags on using I2S as an input to the Teensy (as a slave) while also wanting to use the Audio shield (with it's I2S as Master).
I'm focusing now on getting the analog output from the VS1053 synth into the Teensy, perhaps through the Audio shield.
I could really use some help for that.

blakeAlbion, you mentioned you have done this before. Can you provide assistance?

I'd be happy to hire an expert.
 
What board are you using for the VS1053.

Adafruit has an example but also hitgo?
HiLetgo VS1053 MP3 Audio Player Module Audio Decoder Board Onboard Recording Microphone SPI Interface OGG Output Port Line-in 12.288Mhz https://a.co/d/d4ZYAeE

I can buy one and test it.
 
I have the Adafruit board and I can use its example sketch to play a MIDI sequence out the LOUT and ROUT pins (along with GBUF) to a pair or headphones.
I'm trying now to connect the VS1053's ROUT and LOUT pins to the Teensy Audio Board's LINEINL and LINEINR.

My immediate plan is to use the Adafruit example code to produce the audio, and use the Teensy Audio to route it to the headphone jack on the Teensy Audio board.

I'm looking at the Audio GUI tool to try to get that's right.
Teensy GUI Tool I2S Straight Through.jpg
Is this going to do it?
 
Just got it wired up with code that should work, but no evidence of the audio from the VS1053 getting out to the Audio Shield's earphones.

Could I contact you via direct message?
 
Start with an example. Probably audio passthrough example or USB passthrough. This will probably give you examples about enabling the io on the codec...

The USB passthrough example will let you control the volume with the PC volume slider which might be helpful...

You'll need to configure the input on your sketch. https://www.pjrc.com/teensy/gui/?info=AudioControlSGTL5000#

inputSelect(input);

Select which input to use: AUDIO_INPUT_LINEIN or AUDIO_INPUT_MIC.

adcHighPassFilterEnable();

Turn the DC-blocking filter back on, if disabled, or allows it to resume tracking DC and low frequency changes, if previously frozen. This is the default setting.

But also I think the main volume needs to be turned up on the codec too....

I'm not at a PC right now to look at it in more detail.
 
Thanks!
I added the two methods inputSelect and adcHighPassFilterEnable().
Here's the code I've created from the Adafruit and the Teensy examples combined.
With this, I get VS1053 output through its earphone pins (to a speaker) and simultaneously get the sine wave output to the earphone jack on the Audio shield.

What I don't get is the VS1032 signal to run through the Teensy to the AudioShield earphone.

Code:
#include <SoftwareSerial.h>

// define the pins used
#define VS1053_RX  1 // This is the pin that connects to the RX pin on VS1053

#define VS1053_RESET 9 // This is the pin that connects to the RESET pin on VS1053

// See http://www.vlsi.fi/fileadmin/datasheets/vs1053.pdf Pg 31
#define VS1053_BANK_DEFAULT 0x00
#define VS1053_BANK_DRUMS1 0x78
#define VS1053_BANK_DRUMS2 0x7F
#define VS1053_BANK_MELODY 0x79

// See http://www.vlsi.fi/fileadmin/datasheets/vs1053.pdf Pg 32 for more!
#define VS1053_GM1_OCARINA 80

#define MIDI_NOTE_ON  0x90
#define MIDI_NOTE_OFF 0x80
#define MIDI_CHAN_MSG 0xB0
#define MIDI_CHAN_BANK 0x00
#define MIDI_CHAN_VOLUME 0x07
#define MIDI_CHAN_PROGRAM 0xC0

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

AudioInputI2S2           i2s2_1;         //xy=109,316.20000648498535
AudioSynthWaveform       waveform1;      //xy=148.1999969482422,164.1999912261963
AudioMixer4              mixerR;         //xy=421.2000274658203,266.1999912261963
AudioMixer4              mixerL;         //xy=431.2000274658203,174.19998931884766
AudioOutputI2S           i2s1;           //xy=580.0001373291016,195.39998817443848
AudioConnection          patchCord1(i2s2_1, 0, mixerL, 1);
AudioConnection          patchCord2(i2s2_1, 1, mixerR, 1);
AudioConnection          patchCord3(waveform1, 0, mixerL, 0);
AudioConnection          patchCord4(waveform1, 0, mixerR, 0);
AudioConnection          patchCord5(mixerR, 0, i2s1, 1);
AudioConnection          patchCord6(mixerL, 0, i2s1, 0);
AudioControlSGTL5000     sgtl5000_1;     //xy=219.20001220703125,368.3999881744385

SoftwareSerial VS1053_MIDI(0, VS1053_RX); // TX only, do not use the 'rx' side

void setup() {
  Serial.begin(9600);
  Serial.println("VS1053 MIDI test");
  
  AudioMemory(10);
  sgtl5000_1.enable();
  sgtl5000_1.volume(0.3);
  waveform1.begin(WAVEFORM_SINE);
  
  sgtl5000_1.inputSelect(AUDIO_INPUT_LINEIN);
  sgtl5000_1.adcHighPassFilterEnable();


  VS1053_MIDI.begin(31250); // MIDI uses a 'strange baud rate'
  
  pinMode(VS1053_RESET, OUTPUT);
  digitalWrite(VS1053_RESET, LOW);
  delay(10);
  digitalWrite(VS1053_RESET, HIGH);
  delay(10);
  
  midiSetChannelBank(0, VS1053_BANK_MELODY);
  midiSetInstrument(0, VS1053_GM1_OCARINA);
  midiSetChannelVolume(0, 127);
}

unsigned long swapTime = 0;
bool waveIsOn = false;
void loop() {  
  for (uint8_t i=60; i<69; i++) {
    midiNoteOn(0, i, 127);
    delay(100);
    midiNoteOff(0, i, 127);
  }

  if (millis() - swapTime > 1000) {
    if (waveIsOn) {
      waveform1.amplitude(0);      
    } else {
      waveform1.frequency(440);
      waveform1.amplitude(0.2);
    }
    waveIsOn = !waveIsOn;
    swapTime = millis();
  }
  delay(1000);
}

void midiSetInstrument(uint8_t chan, uint8_t inst) {
  if (chan > 15) return;
  inst --; // page 32 has instruments starting with 1 not 0 :(
  if (inst > 127) return;
  
  VS1053_MIDI.write(MIDI_CHAN_PROGRAM | chan);  
  VS1053_MIDI.write(inst);
}


void midiSetChannelVolume(uint8_t chan, uint8_t vol) {
  if (chan > 15) return;
  if (vol > 127) return;
  
  VS1053_MIDI.write(MIDI_CHAN_MSG | chan);
  VS1053_MIDI.write(MIDI_CHAN_VOLUME);
  VS1053_MIDI.write(vol);
}

void midiSetChannelBank(uint8_t chan, uint8_t bank) {
  if (chan > 15) return;
  if (bank > 127) return;
  
  VS1053_MIDI.write(MIDI_CHAN_MSG | chan);
  VS1053_MIDI.write((uint8_t)MIDI_CHAN_BANK);
  VS1053_MIDI.write(bank);
}

void midiNoteOn(uint8_t chan, uint8_t n, uint8_t vel) {
  if (chan > 15) return;
  if (n > 127) return;
  if (vel > 127) return;
  
  VS1053_MIDI.write(MIDI_NOTE_ON | chan);
  VS1053_MIDI.write(n);
  VS1053_MIDI.write(vel);
}

void midiNoteOff(uint8_t chan, uint8_t n, uint8_t vel) {
  if (chan > 15) return;
  if (n > 127) return;
  if (vel > 127) return;
  
  VS1053_MIDI.write(MIDI_NOTE_OFF | chan);
  VS1053_MIDI.write(n);
  VS1053_MIDI.write(vel);
}

And here's the hook-up:
VS1053 wiring.jpgAudio Shield Wiring.jpg

The wire color changes from Blue&Green to blue&purple between the AudioShield and the VS1053
 
Back
Top