Well, I got it working (I didn't use the audio shield. Just a Teensy 3.2 and the MEMS mic). For those who're trying to accomplish the same thing, here's what I did:
Wiring (SPH0645 -> Teensy3.2):
SEL -> GND
LRCL -> 12
DOUT -> 13
BCLK -> 11
GND -> GND
3V -> 3.3V
Teensy I2S library:
https://github.com/nodae/teensy_i2s_experimental
(Place the decompressed 'teensy_i2s_experimental-master' folder in your 'Documents\Arduino\libraries' folder)
Teensy 3.2 code:
Code:
#include <Wire.h>
#include <i2s.h>
#define CLOCK_TYPE (I2S_CLOCK_48K_INTERNAL) // 8, 32, 44, 48
uint32_t nRX = 0;
uint8_t bytes[64];
void i2s_rx_callback(int32_t *pBuf)
{
bytes[nRX++] = pBuf[0] & 0xFF;
bytes[nRX++] = (pBuf[0] >> 8) & 0xFF;
bytes[nRX++] = (pBuf[0] >> 16) & 0xFF;
bytes[nRX++] = (pBuf[0] >> 24) & 0xFF;
if (nRX >= 64)
{
Serial.write(bytes, 64);
nRX = 0;
}
}
void setup()
{
Serial.begin(9600);
I2SRx0.begin(CLOCK_TYPE, i2s_rx_callback);
I2SRx0.start();
}
void loop()
{
}
Visual Studio C# code:
Code:
using System.IO.Ports; // place at the beginning of your class file
private void SerialPortMain_DataReceived(object sender, SerialDataReceivedEventArgs e) // Event associated with the SerialPort control
{
rC = serialPortMain.BytesToRead; // rC is an int
serialPortMain.Read(myBuffer, pos, rC); // myBuffer is an array of bytes
pos += rC; // pos is an int
}
In visual studio, create a SerialPort object either through the designer or in code. Set the PortName property to that of the Teensy serial port (eg. "COM5" or something - you can obtain a list of all the ports found on your machine via SerialPort.GetPortNames()). Normally I would say set the BaudRate property of the control to match that of the Teensy, however it seems that the Teensy simulates the serial port connection and that the baud rate is actually irrelevant. You might want to increase the ReadBufferSize property from 4096 (mine was set to 65536), but I don't know if it makes a difference. With BaudRate set to the default 9600, I was transferring data from the Teensy at a rate of 192 KBps (equivalent of 1536000 baud - and it'll probably go higher).
Create a handler either through the designer or in code for the DataReceived event for your serial port (in the code above, my serial port is called SerialPortMain). This is where all of the transfers from the Teensy to your PC occur. As you can see, I simply made myself an array of bytes and copied the data into it each time the serial port received a transmission. To start recording, simply open the port with the .Open() method. The only other thing you'll want to do is decide what to do with the data as you go. For example you can make that byte array very large and then when you've finished, save all the bytes to a file (using System.IO, File.WriteAllBytes(string path, byte[] bytes)). You can then import the audio via an audio editor like Audacity. To do so, load the program and go to File -> Import -> Raw Data... Select the file and use these settings:
Encoding: Signed 32-bit PCM
Byte order: Little-endian
Channels: 1 Channel (Mono)
Start offset: 0
Amount to import: 100%
Sample rate: 48000
On a side note, you might want to normalise the audio and adjust for the DC offset if you have one. You can also do this in code on either the Teensy or the PC. It's a matter of subtracting the average sample value from each sample (removes DC offset - do this first) and then multiplying each sample by [the upper limit / the absolute maximum sample value] (normalises, in other words, increases the amplitude). This is fine if you do it after you've finished recording. However to do it live via code, both of these processes are dependant on monitoring a time window and can be a bit tricky due to changes that occur as you go.
Alternatively, you could periodically save or utilise the data in the buffer (for example for live playback). Just read (or save) the contents of the buffer up to 'pos' and then set 'pos' back to 0. However if you're periodically saving to a file, keeping a file stream open and writing to that might be a better idea. Also, don't forget to close your ports (or check whether they're already open) in your C# program.