arduino-libraries / ArduinoSound

66 stars 28 forks source link

ICS43432 I2S sound recording and playback #2

Closed kriswiner closed 7 years ago

kriswiner commented 7 years ago

Thank you for your Arduino Sound library. So far I can output the amplitude and spectrum measured with the ICS43432 on the serial monitor but this is not particularly useful. I would like to be able to record the time history of the spectrum, capture normal modes, plot them versus time, etc. It's hard to do this on the serial monitor. I would really like to find a way to capture the data for later analysis and playback. I am thinking I will use an SPI NOR flash for this. I have one I can attach to the MCU that has either 16 or 128 MByte of memory. This ought to be enough for small snippets of sound capture.

What I would really like to do is to record sound from the ICS43432 I2S microphone attached to my STM32L4 MCU, store the data stream on a connected SPI NOR Flash or SD card, and then play it back via PWM tone or the dual DAC, etc.

I must have a mental block or something because I just can't seem to figure out how to capture the I2S data fast enough and more particularly, how to play it back.

Do you have any example using your sound library or otherwise that demonstrates how to capture and play back the I2S sound recorded from the ICS43432 microphone?

Perhaps it would be worthwhile to add another API to the ArduinoSound library to allow capture and playback of I2S data...

sandeepmistry commented 7 years ago

Hey @kriswiner,

Do you have any example using your sound library or otherwise that demonstrates how to capture and play back the I2S sound recorded from the ICS43432 microphone?

There's nothing in the library at the moment, mainly because of SD card write performance issues.

For this, I suggest you use the I2S library directly for now.

Recording:

#include <I2S.h>

void setup() {
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  I2S.onReceive(onI2SReceive);

  // start I2S at 8 kHz with 32-bits per sample
  if (!I2S.begin(I2S_PHILIPS_MODE, 8000, 32)) {
    Serial.println("Failed to initialize I2S!");
    while (1); // do nothing
  }
}

void loop() {
}

void onI2SReceive() {
  int size = I2S.available();
  byte data[size];

  I2S.read(data, size);

  /// process the data quickly!
}

Playback:

#include <I2S.h>

void setup() {
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // start I2S at 8 kHz with 32-bits per sample
  if (!I2S.begin(I2S_PHILIPS_MODE, 8000, 32)) {
    Serial.println("Failed to initialize I2S!");
    while (1); // do nothing
  }

  // add transmit callback
  I2S.onTransmit(onI2STransmit);

  // play some silence to kick things off:
  byte silence[512];
  memset(silence, 0x00, sizeof(silence));

  I2S.write(silence, sizeof(silence));
  I2S.write(silence, sizeof(silence));
}

void loop() {
}

void onI2STransmit() {
  int size = I2S.availableForWrite();
  byte data[size];

  // load some data quickly ...

  // send it out
  I2S.write(data, size);
}

I'm closing this for now, because I think I've answered the questions, but feel free to continue the discussion.

kriswiner commented 7 years ago

Thanks Sandeep,

Where the comments of "process the data quickly" and "load the data quickly" are writte, is this where I might write the data to SPI flash and read the data from SPI flash, for example? I have a 16 MByte QSPI flash on my MCU board I plan to use to capture snippets of sound.

Does I2S.write then send I2S data to an I2S CODEC? I would like to use PWM tone or perhaps the DAC(s) to play the sound. Is this possible or does the I2S data need to be converted to PDM first?

Thank for your help here!

On Wed, Jan 11, 2017 at 11:26 AM, Sandeep Mistry notifications@github.com wrote:

Hey @kriswiner https://github.com/kriswiner,

Do you have any example using your sound library or otherwise that demonstrates how to capture and play back the I2S sound recorded from the ICS43432 microphone?

There's nothing in the library at the moment, mainly because of SD card write performance issues.

For this, I suggest you use the I2S library directly for now.

Recording:

include

void setup() { Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only }

I2S.onReceive(onI2SReceive);

// start I2S at 8 kHz with 32-bits per sample if (!I2S.begin(I2S_PHILIPS_MODE, 8000, 32)) { Serial.println("Failed to initialize I2S!"); while (1); // do nothing } } void loop() { } void onI2SReceive() { int size = I2S.available(); byte data[size];

I2S.read(data, size);

/// process the data quickly! }

Playback:

include

void setup() { Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only }

// start I2S at 8 kHz with 32-bits per sample if (!I2S.begin(I2S_PHILIPS_MODE, 8000, 32)) { Serial.println("Failed to initialize I2S!"); while (1); // do nothing }

// add transmit callback I2S.onTransmit(onI2STransmit);

// play some silence to kick things off: byte silence[512]; memset(silence, 0x00, sizeof(silence));

I2S.write(silence, sizeof(silence)); I2S.write(silence, sizeof(silence)); } void loop() { } void onI2STransmit() { int size = I2S.availableForWrite(); byte data[size];

// load some data quickly ...

// send it out I2S.write(data, size); }

I'm closing this for now, because I think I've answered the questions, but feel free to continue the discussion.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/arduino-libraries/ArduinoSound/issues/2#issuecomment-271968591, or mute the thread https://github.com/notifications/unsubscribe-auth/AGY1qnealRmyn0mkHHb7WMST8XPfcPbpks5rRSzQgaJpZM4LZR5a .

sandeepmistry commented 7 years ago

Where the comments of "process the data quickly" and "load the data quickly" are writte, is this where I might write the data to SPI flash and read the data from SPI flash, for example?

That's correct.

Does I2S.write then send I2S data to an I2S CODEC? I would like to use PWM tone or perhaps the DAC(s) to play the sound. Is this possible or does the I2S data need to be converted to PDM first?

It sends data to an I2S receiver, like the Adafruit I2S 3W Class D Amplifier Breakout - MAX98357A. I2S data is in PCM format.

anwarhahjjeffersongeorge commented 7 years ago

Hi, When I tried the Recording code example here with a MKRZero and Adafruit I2S MEMS Microphone Breakout - SPH0645LM4H I2S.onReceive, I2S.onReceive was never called. Do I need to do something special to enable the callback? Thanks.

sandeepmistry commented 7 years ago

@anwarhahjjeffersongeorge my sample code above is missing a:

  // trigger a read to kick things off
  I2S.read();

statement at the end of setup, if that doesn't work please open a new issue :)

M-Behere commented 6 years ago

Hi, I am trying to record audio from ADAFRUIT I2S MEMS MICROPHONE BREAKOUT - SPH0645LM4H and save it on onboard sdcard available on MKRZERO in .wav format. Is there any example available related to this?