Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 9 of 9

Thread: 24 bit binary data to floating point number conversion?

  1. #1

    24 bit binary data to floating point number conversion?

    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?

  2. #2
    Senior Member+ MichaelMeissner's Avatar
    Join Date
    Nov 2012
    Location
    Ayer Massachussetts
    Posts
    4,075
    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.

  3. #3
    Senior Member
    Join Date
    May 2015
    Location
    USA
    Posts
    1,004
    Possibly you would want the result normalized to -1.0 to 1.0.

  4. #4
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    24,485
    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);

  5. #5
    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."

  6. #6
    I have been trying to run the following code.
    The code runs correctly, but no file is stored on the SD card?

    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;
    }

  7. #7
    Senior Member
    Join Date
    Jul 2020
    Posts
    1,118
    Quote Originally Posted by feima0011 View Post
    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?

  8. #8

    I just want to save the 24 TDM microphone signal to SD card as floating point number

    Quote Originally Posted by MarkT View Post
    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

  9. #9
    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.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •