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

Thread: Wave-File Header (recording)

  1. #1
    Junior Member
    Join Date
    Jan 2016
    Posts
    6

    Wave-File Header (recording)

    Hello

    Sorry guys, I know this has been answered a lot of times, but I am stucking with writing the wave-header to an recorded raw-file.

    As a staring point use the basic Recorder demo from the Audio-lib and add the header data after recording.
    The recording itself is ok, but at the end the file is not recognized as a wav file.

    Is there a way to check if the header was written in the correct way?

    Thanks in advance
    Marcus

    Code:
     
    #include <Bounce.h>
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <SD.h>
    #include <SerialFlash.h>
    
    
    // GUItool: begin automatically generated code
    AudioInputI2S            i2s2;           //xy=226.75,251.9999988079071
    AudioRecordQueue         queue1;         //xy=402.75,251.9999988079071
    AudioConnection          patchCord1(i2s2, 0, queue1, 0);
    AudioControlSGTL5000     sgtl5000_1;     //xy=386.75,400.9999988079071
    // GUItool: end automatically generated code
    
    // Bounce objects to easily and reliably read the buttons
    Bounce buttonRecord = Bounce(0, 8);
    Bounce buttonStop =   Bounce(1, 8);  // 8 = 8 ms debounce time
    
    const int myInput = AUDIO_INPUT_LINEIN;
    
    
    // Use these with the Teensy Audio Shield
    #define SDCARD_CS_PIN    10
    #define SDCARD_MOSI_PIN  7
    #define SDCARD_SCK_PIN   14
    
    // Remember which mode we're doing
    int mode = 0;  // 0=stopped, 1=recording
    
    // The file where data is recorded
    File frec;
    
    void setup() {
    
      Serial.begin(9600);
      // Configure the pushbutton pins
      pinMode(0, INPUT_PULLUP);
      pinMode(1, INPUT_PULLUP);
    
      AudioMemory(60);
    
      // Enable the audio shield, select input, and enable output
      sgtl5000_1.enable();
      sgtl5000_1.inputSelect(myInput);
      sgtl5000_1.volume(0.5);
    
      // 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);
        }
      }
    }
    
    
    void loop() {
      buttonRecord.update();
      buttonStop.update();
    
      if (buttonRecord.fallingEdge()) {
        Serial.println("Record Button Press");
        if (mode == 0) startRecording();
      }
      if (buttonStop.fallingEdge()) {
        Serial.println("Stop Button Press");
        if (mode == 1) stopRecording();
      }
    
      // If we're playing or recording, carry on...
      if (mode == 1) {
        continueRecording();
      }
    
      if (mode == 2) {
        Serial.println("Writing Header");
        delay(100);
        writeOutHeader();
      }
    }
    
    ///////////////////////////////////////////////////////// startRecording /////////////////////////////////////////
    void startRecording() {
      Serial.println("startRecording");
      if (SD.exists("RECORD.WAV")) {
        SD.remove("RECORD.RAW");
      }
      frec = SD.open("RECORD.WAV", FILE_WRITE);
      if (frec) {
        queue1.begin();
        mode = 1;
      }
    }
    
    ///////////////////////////////////////////////////////// continueRecording /////////////////////////////////////////
    void continueRecording() {
      if (queue1.available() >= 2) {
        byte buffer[512];
        // writes are used.
        memcpy(buffer, queue1.readBuffer(), 256);
        queue1.freeBuffer();
        memcpy(buffer + 256, queue1.readBuffer(), 256);
        queue1.freeBuffer();
        // write all 512 bytes to the SD card
        elapsedMicros usec = 0;
        frec.write(buffer, 512);
      }
    }
    
    ///////////////////////////////////////////////////////// stopRecording /////////////////////////////////////////////
    void stopRecording() {
      Serial.println("stopRecording");
      queue1.end();
      if (mode == 1) {
        while (queue1.available() > 0) {
          frec.write((byte*)queue1.readBuffer(), 256);
          queue1.freeBuffer();
        }
        frec.close();
      }
      mode = 2;
      
    }
    
    ///////////////////////////////////////////////////////// writeOutHeader ////////////////////////////////////////////
    void writeOutHeader() { // update WAV header with final filesize/datasize
      File frec = SD.open("RECORD.WAV");
    
      int dataSize = frec.size();
      int headerSize = 44;
      int dataChunkSize = dataSize + headerSize - 8;
    
      int subDataChunkSize = 16;
      byte format = 0x1; //PCM
      byte channels = 0x1; //mono
      int sampleRate = 44100;
      int bytesPerSample = 4;
      int bitsPerSample = 16;
    
      Serial.write("RIFF");  // 00 - RIFF
      for (int n = 0; n < 4; ++n) Serial.write((byte)((dataChunkSize >> (n * 8)) & 0xFF)); // 04 - how big is the rest of this file?
      Serial.write("WAVE"); // 08 - WAVE
      Serial.write("fmt "); // 12 - fmt
      for (int n = 0; n < 4; ++n) Serial.write((byte)((subDataChunkSize >> (n * 8)) & 0xFF )); // 16 - size of this chunk
      for (int n = 0; n < 2; ++n) Serial.write((byte)((format >> (n * 8)) & 0xFF)); // 20 - what is the audio format? 1 for PCM = Pulse Code Modulation
      for (int n = 0; n < 2; ++n) Serial.write((byte)((channels >> (n * 8)) & 0xFF)); // 22 - mono or stereo? 1 or 2? (or 5 or ???)
      for (int n = 0; n < 4; ++n) Serial.write((byte)((sampleRate >> (n * 8)) & 0xFF)); // 24 - samples per second (numbers per second)
      for (int n = 0; n < 4; ++n) Serial.write((byte)(((sampleRate * bytesPerSample) >> (n * 8)) & 0xFF)); // 28 - bytes per second
      for (int n = 0; n < 2; ++n) Serial.write((byte)(((bytesPerSample) >> (n * 8)) & 0xFF )); // 32 - # of bytes in one sample, for all channels
      for (int n = 0; n < 2; ++n) Serial.write((byte)((bitsPerSample >> (n * 8)) & 0xFF)); // 34 - how many bits in a sample(number)? usually 16 or 24
      Serial.write("data"); // 36 - data
      for (int n = 0; n < 4; ++n) Serial.write((byte)((dataSize >> (n * 8)) & 0xFF)); // 40 - how big is this data chunk
    
      // 44 - the actual data itself
      byte b;
      bool reading = true;
      do {
        if (frec.available()) {
          b = frec.read();
          Serial.write(b);
        }
        else reading = false;
      }
      while (reading);
    
      frec.close();
    
      mode = 0;
    }

  2. #2
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    15,716
    You can't write the header until you know the total amount of data.

    Probably the simplest way would involve seeking back to the beginning of the file and overwriting the first 44 bytes with the header, after you know exactly how much data was stored.

Posting Permissions

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