Recording .wav files using I2S MEMS microphone SPH0645 and Arduino MKR1010

Respected All,
I want to record 10-20 seconds audio files in .wav format. The audio source is coming from the earpieces of a stethoscope to convert a conventional stethoscope into a digital stethoscope.
I have connected the SPH0645LM4H-B Adafruit I2S digital microphone with Arduino MKR1010.
With the help of ICS43432 I2S sound recording and playback · Issue #2 · arduino-libraries/ArduinoSound · GitHub by @sandeepmistry
I am able to see visually the audio data in serial plotter.
I want to store this audio recordings in .wav format in (say my computer drive) for further signal processing in Matlab.
Requesting help in this regard,
Thanking You,
Ajiket

I don't know anything about the MKR1010, but the 1st issue is - Are you getting data into RAM or an SD card and then can you get that data or file transferred to the computer?

A [u]WAV file[/u] is pretty simple. It's just a 44-byte header followed by the audio samples. Of course, you have to get the byte sequence right - little endian and left channel first for stereo data, and 8-bit WAVs use unsigned integers.

You probably don't actually need the header with MATLAB. Or if you don't want to write the code to create the header, You can use Audacity to open a raw (headerless) audio file and export it as WAV.

If you have Matlab available, the most straightforward way might be to read the serial output with Matlab into a vector and write that to a .wav file using the Matlab function.

Respected Mr. Mark,
Thank You for your idea,
but i am not able to record the .wav format files.
For Serial plotter i am using the following code and connections (ICS43432 and SPH0645 are similar microphones)

/*
 This example reads audio data from an Invensense's ICS43432 I2S microphone
 breakout board, and prints out the samples to the Serial console. The
 Serial Plotter built into the Arduino IDE can be used to plot the audio
 data (Tools -> Serial Plotter)

 Circuit:
 * Arduino/Genuino Zero, MKR family and Nano 33 IoT
 * ICS43432:
   * GND connected GND
   * 3.3V connected to 3.3V (Zero, Nano) or VCC (MKR)
   * WS connected to pin 0 (Zero) or 3 (MKR) or A2 (Nano)
   * CLK connected to pin 1 (Zero) or 2 (MKR) or A3 (Nano)
   * SD connected to pin 9 (Zero) or A6 (MKR) or 4 (Nano)

 created 17 November 2016
 by Sandeep Mistry
 */

#include <I2S.h>

void setup() {
  // Open serial communications and wait for port to open:
  // A baud rate of 115200 is used instead of 9600 for a faster data rate
  // on non-native USB ports
  Serial.begin(115200);
  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
  }
}

void loop() {
  // read a sample
// read a sample
int sample = I2S.read();
if ((sample == 0) || (sample == -1) ) {
return;
}
// convert to 18 bit signed
sample >>= 14;
// if it's non-zero print value to serial
Serial.println(sample);
  delay(1);
}

For connecting to the serial port, reading serial output in Matlab i am using

s = serialport("COM4",115200,"Timeout",5); % My COM 4 is MKR1010
data = read(s,1e5,"uint32");

I am playing music during the read command execution for recording
For converting to .wav format and playback,

filename = 'tr3.wav';
audiowrite(filename,data,44100);
[y,Fs] = audioread(filename);
sound(y,Fs);

Matlab snip attached for reference. The tr3.wav file generated does not contain the music to be recorded.

Thanking You for your help,

You're sending ASCII data from the Arduino and reading it as binary (UINT32) into MATLAB. You should be using readline() on the MATLAB side to receive the ASCII serial data stream.

An easy way to see if you're receiving data correctly would be to plot the receive data vector. When I'm doing this sort of thing, it's easier to look at a sine wave rather than something more complex. I like to use this Android Waveform Generator as a sound source.

Respected Sir,
I am able to read the serial plotter amplitude data into Matlab.

Amplitude Serial plotter in Arduino

/*
 This example reads audio data from an Invensense's ICS43432 I2S microphone
 breakout board, and prints out the amplitude to the Serial console. The
 Serial Plotter built into the Arduino IDE can be used to plot the audio
 amplitude data (Tools -> Serial Plotter)

 Circuit:
 * Arduino/Genuino Zero, MKRZero or MKR1000 board
 * ICS43432:
   * GND connected GND
   * 3.3V connected 3.3V (Zero) or VCC (MKR1000, MKRZero)
   * WS connected to pin 0 (Zero) or pin 3 (MKR1000, MKRZero)
   * CLK connected to pin 1 (Zero) or pin 2 (MKR1000, MKRZero)
   * SD connected to pin 9 (Zero) or pin A6 (MKR1000, MKRZero)

 created 23 November 2016
 by Sandeep Mistry
 */

#include <ArduinoSound.h>

// create an amplitude analyzer to be used with the I2S input
AmplitudeAnalyzer amplitudeAnalyzer;

void setup() {
  // Open serial communications and wait for port to open:
  // A baud rate of 115200 is used instead of 9600 for a faster data rate
  // on non-native USB ports
  Serial.begin(115200);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // setup the I2S audio input for 44.1 kHz with 32-bits per sample
  if (!AudioInI2S.begin(44100, 32)) {
    Serial.println("Failed to initialize I2S input!");
    while (1); // do nothing
  }

  // configure the I2S input as the input for the amplitude analyzer
  if (!amplitudeAnalyzer.input(AudioInI2S)) {
    Serial.println("Failed to set amplitude analyzer input!");
    while (1); // do nothing
  }
}

void loop() {
  // check if a new analysis is available
  if (amplitudeAnalyzer.available()) {
    // read the new amplitude
    int amplitude = amplitudeAnalyzer.read();

    // print out the amplititude to the serial monitor
    Serial.println(amplitude);
  }
}

The same Serial plotter data is imported into Matlab by

% find the serial port connected to the Arduino 
serialportlist("available")';

% connect to the arduino using serial port and baud rate specified 
% in arduino code 
arduinoObj = serialport("COM4",115200);

% prepare the serial port to start streaming data
% Set the terminator property to match terminator specified
% in arduino code

configureTerminator(arduinoObj,"CR/LF");

% flush the serial port to remove old data
flush(arduinoObj);

% Prepare the UserData property to store arduino data
% The Data field of the struct saves the sine wave value and 
% the count field saves the x-axis value of the sine wave
arduinoObj.UserData = struct("Data",[],"Count",1);

% create a callback function that reads the first 1000 ASCII 
% terminated sine wave data points and plots the results

% Set the BytesAvailableFcnMode property to "terminator"
% and the BytesAvailableFcnMode property to @readSineWaveData
% the callback function readSineWaveData is triggered when a
% new sine wave data (with the terminator) is available to be read
% from the arduino

configureCallback(arduinoObj,"terminator",@readSineWaveData);

function readSineWaveData(src, ~)

% Read the ASCII data from the serialport object.
data = readline(src);

% Convert the string data to numeric type and save it in the UserData
% property of the serialport object.
src.UserData.Data(end+1) = str2double(data);

% Update the Count value of the serialport object.
src.UserData.Count = src.UserData.Count + 1;

% If 1001 data points have been collected from the Arduino, switch off the
% callbacks and plot the data.
if src.UserData.Count > 5001
    configureCallback(src, "off");
    plot(src.UserData.Data(2:end));
end
end

The configure callback uses readline to read serial port data, Now I have the exact serial plotter data into Matlab. The task is to convert this data into some audio format (.wav file)
To convert to .wav format i am using

filename = 'test1.wav';
y = arduinoObj.UserData.Data;
Fs = 44100;
audiowrite(filename,y,Fs,'BitsPerSample',32);

As per me my problem is
The serial plotter data is of the order of 1E8, whereas for audiowrite the data should be in the range of -1<=data<=1, type.
I want to know how to convert the higher magnitude data in the range -1 to 1 i.e audio format data.

I also tried

s = serialport("COM4",115200); 
data = read(s,1e5,"double");

to read the serial port data into -1 to +1. however the data is now getting extreme negative values
order in 1E-50. range.

Thanking You

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.