24 bit binary data to floating point number conversion?

Status
Not open for further replies.

feima0011

Well-known member
Currently, we have TDM microphone connect to the teensy 4.1.

The recodings are 24 bits binary data.

Due to our limited knowledge, we do not know how to interperate the 24 bit binary data.


I am just wondering if there some function in the Teensy Audio library that can convert the
24 bit binary data to a floating point number?
 
If it is just 3 bytes written out, you would do something like:

Code:
long a = (((long)(unsigned char)byte1) << 16) | (((long)(unsigned char)byte2) << 8) | ((long)(unsigned char)byte3);
double value = a;

Now depending on the encoding the first byte in the stream might be the most significant or the least significant. If it is the least significant, then reverse byte1 and byte3.
 
If you're using the audio library, only the top 16 bits are captured. The low 8 bits are lost.

Normally people route the audio data from TDM to other audio library features. If you're not yet familiar with the audio design tool, this 31 page tutorial explains how it works. The info about using the design tool starts on page 8. While the tutorial shows use of I2S, the TDM input works the same way, only with more signals!

Extracting the raw data from the audio library is possible using the "queue" objects. But it is a fairly advanced use, not as easy as simply routing the audio within the library and allowing the library code to do the difficult work of processing so much data. The queue objects aren't covered in the tutorial. The best info available is the Recorder example (File > Examples > Audio > Recorder). That will give you 16 bit signed integer data. You can convert those numbers to 32 bit floats like this:

Code:
  float n = data[0] * (1.0f / 32768.0f);
 
I am total confused, waht do you mean

"If you're using the audio library, only the top 16 bits are captured. The low 8 bits are lost."
 
I have been trying to run the following code.
The code runs correctly, but no file is stored on the SD card? :confused:

Code:
/ Record TDM input sound as raw data (18ch, Signed 24-bit little-endian PCM, 44.1kHz, little-endian) to a SD card.
// Note: Format is modified so that mics align their 24 bit data to 32 bit slots, half of the 16 bit
// channels end up being the 8 low bits, and 8 more zeros which are discarded.

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

// GUItool: begin automatically generated code
AudioInputTDM            tdm1;           //xy=151,223
AudioRecordQueue         queue4;         //xy=416,221
AudioRecordQueue         queue5;         //xy=416,254
AudioRecordQueue         queue6;         //xy=416,287
AudioRecordQueue         queue7;         //xy=416,320
AudioRecordQueue         queue3;         //xy=417,187
AudioRecordQueue         queue8;         //xy=417,353
AudioRecordQueue         queue2;         //xy=418,154
AudioRecordQueue         queue1;         //xy=419,120


AudioConnection          patchCord1(tdm1, 0, queue1, 0);
AudioConnection          patchCord2(tdm1, 1, queue2, 0);
AudioConnection          patchCord3(tdm1, 2, queue3, 0);
AudioConnection          patchCord4(tdm1, 3, queue4, 0);
AudioConnection          patchCord5(tdm1, 4, queue5, 0);
AudioConnection          patchCord6(tdm1, 5, queue6, 0);
AudioConnection          patchCord7(tdm1, 6, queue7, 0);
AudioConnection          patchCord8(tdm1, 7, queue8, 0);


// GUItool: end automatically generated code

// GUItool: end automatically generated code

// Use these with the Teensy Audio Shield
//#define SDCARD_CS_PIN    10
//#define SDCARD_MOSI_PIN  7
//#define SDCARD_SCK_PIN   14

// Use these with the Teensy 3.5 & 3.6 SD card
#define SDCARD_CS_PIN    BUILTIN_SDCARD
#define SDCARD_MOSI_PIN  11  // not actually used
#define SDCARD_SCK_PIN   13  // not actually used

// Use these for the SD+Wiz820 or other adaptors
//#define SDCARD_CS_PIN    4
//#define SDCARD_MOSI_PIN  11
//#define SDCARD_SCK_PIN   13

// Remember which mode we're doing
int mode = 0;  // 0=stopped, 1=recording
int choice = 0;
int sample_number = 0;

unsigned int tsamplemillis = 10000;

String typeofsound;

int16_t* buffer1;
int16_t* buffer2;
int16_t* buffer3;
int16_t* buffer4;
int16_t* buffer5;
int16_t* buffer6;
int16_t* buffer7;
int16_t* buffer8;

// The file where data is recorded
File frec;

void setup() {

  Serial.begin(115200);
  // Audio connections require memory, and the record queue
  // uses this memory to buffer incoming audio.
  AudioMemory(512);

  // Initialize the SD card
  SPI.setMOSI(SDCARD_MOSI_PIN);
  SPI.setSCK(SDCARD_SCK_PIN);
  if (!(SD.begin(SDCARD_CS_PIN))) {
    // stop here if no SD card, but print a message
    while (1) {
      Serial.println("Unable to access the SD card");
      delay(500);
    }
  }
  while (!Serial);
  Serial.println("Welcome to the 4-channel TDM recording test bench");
}

void loop() {

  if (choice == 0) {
    Serial.println("\nEnter new filename for sound archive: ");
    while (!Serial.available());
    typeofsound = Serial.readString();
    sample_number = 0;
    record(typeofsound, sample_number);
  } else if (choice == 1) {
    sample_number++;
    record(typeofsound, sample_number);
  } else {
    //Do nothing
  }

  Serial.print("\nEnter 1 to take another sample in this archive or 0 to enter a new file archive: ");
  while (!Serial.available());
  choice = Serial.readString().toInt();
  Serial.println(choice);
}

void record(String type, int number)
{
  Serial.println("Recording " + type + String(number) + "...");
  String sname = type + number + ".RAW";
  String path = type + "/" + type + number + ".RAW";
  startRecording(sname, path, type);
  continueRecording();
  stopRecording();
}

void startRecording(String sname, String path, String type)
{
  int str_len = path.length() + 1;
  char charpath[str_len];
  path.toCharArray(charpath, str_len);

  if (SD.exists(charpath)) {
    // The SD library writes new data to the end of the
    // file, so to start a new recording, the old file
    // must be deleted before new data is written.
    SD.remove(charpath);
  }

  str_len = type.length() + 1;
  char chartype[str_len];
  type.toCharArray(chartype, str_len);

  if (!SD.exists(chartype)) {
    SD.mkdir(chartype);
  }

  frec = SD.open(charpath, FILE_WRITE);
  if (frec) {
    Serial.println("File Open");
  }
}

void continueRecording() {
  int data = 0, num = 0;
  elapsedMillis recordingTime = 0;
  queue1.begin();
  queue2.begin();
  queue3.begin();
  queue4.begin();
  queue5.begin();
  queue6.begin();
  queue7.begin();
  queue8.begin();
  mode = 1;
  while (recordingTime < tsamplemillis)
  {
    data = queue1.available();
    if (data > 0)
    {
      buffer1 = queue1.readBuffer();      //read all queue buffers in sets of 128 16bit num
      buffer2 = queue2.readBuffer();
      buffer3 = queue3.readBuffer();
      buffer4 = queue4.readBuffer();
      buffer5 = queue5.readBuffer();
      buffer6 = queue6.readBuffer();
      buffer7 = queue7.readBuffer();
      buffer8 = queue8.readBuffer();
      
      queue1.freeBuffer();                //free queue buffers to allow system to re issue storage
      queue2.freeBuffer();
      queue3.freeBuffer();
      queue4.freeBuffer();
      queue5.freeBuffer();
      queue6.freeBuffer();
      queue7.freeBuffer();
      queue8.freeBuffer();
      
      if (data > 48)        //test if queue buffers are getting too full, the serial write will probably cause a back log if it does happen.
      {
        Serial.write('.');    //dots in the serial monitor mean that the system isnt processing data fast enough
      }
      for (int i = 0; i < 128; i ++)                        //write data to sd card in 24bit signed pcm format (i think) (audacity seems to accept it)
      { //frames are built of 2 16 bit numbers where only 24 bits are useful, so only 3 bytes are saved to save space. Frames are little endian
        frec.write(highByte(buffer2[i])); // LSB            //<---------------------sample 1---------------------><---------------------sample n--------------------->
        frec.write(lowByte(buffer1[i])); // Middle Byte     //<----ch1----><----ch2----><----ch3----><----ch4----><----ch1----><----ch2----><----ch3----><----ch4---->    
        frec.write(highByte(buffer1[i])); // MSB            //<LSB-MID-MSB><LSB-MID-MSB><LSB-MID-MSB><LSB-MID-MSB><LSB-MID-MSB><LSB-MID-MSB><LSB-MID-MSB><LSB-MID-MSB>
   
        frec.write(highByte(buffer4[i])); // LSB
        frec.write(lowByte(buffer3[i])); // Middle Byte
        frec.write(highByte(buffer3[i])); // MSB
       
        frec.write(highByte(buffer6[i])); // LSB
        frec.write(lowByte(buffer5[i])); // Middle Byte
        frec.write(highByte(buffer5[i])); // MSB
        
        frec.write(highByte(buffer8[i])); // LSB
        frec.write(lowByte(buffer7[i])); // Middle Byte
        frec.write(highByte(buffer7[i])); // MSB
        
        num++;
      }
    }
  }
  
  
  queue1.end();     //stop the background sampling
  queue2.end();
  queue3.end();
  queue4.end();
  queue5.end();
  queue6.end();
  queue7.end();
  queue8.end();
  
  Serial.print("num of samples written per channel:");
  Serial.println(num);
}


void stopRecording() 
{
  Serial.println("Finished recording.");
  queue1.end();
  queue2.end();
  queue3.end();
  queue4.end();
  queue5.end();
  queue6.end();
  queue7.end();
  queue8.end();
  queue1.clear();
  queue2.clear();
  queue3.clear();
  queue4.clear();
  queue5.clear();
  queue6.clear();
  queue7.clear();;
  queue8.clear();
  frec.close();
  mode = 0;
}
 
Currently, we have TDM microphone connect to the teensy 4.1.

The recodings are 24 bits binary data.
How are you making these recordings? The audio library can't do 24 bit, it discards 8 LSBs with a 24 bit signal.
Due to our limited knowledge, we do not know how to interperate the 24 bit binary data.
"interperate" - that's not a word. interpolate? interpret?
I am just wondering if there some function in the Teensy Audio library that can convert the
24 bit binary data to a floating point number?
Are we talking a single 24 bit integer, 3 bytes, or a buffer full of either?
 
I just want to save the 24 TDM microphone signal to SD card as floating point number

How are you making these recordings? The audio library can't do 24 bit, it discards 8 LSBs with a 24 bit signal.

Are we talking a single 24 bit integer, 3 bytes, or a buffer full of either?


Using the audio library to process the data will discard the low 8 bit data of the orignal 24 bit microphone data.


I just want to save the 24 bit TDM microphone signal to SD card as floating point number,
but have not find a way to do it :(
 
For our project, we want to save the recording to SD card, and process the data on PC
using Matlab.

I have a hard time to covert the 24 bit PCM data to floating point number. :(
 
Status
Not open for further replies.
Back
Top