Teensy 3.5 saving data as a signed 16bit PCM .wav file, issue.

Status
Not open for further replies.

uuryuu

Member
Hello,

So I have been able to save data from both ADC's (ADC0,ADC1) using the DMA for 2 channels and then write data to SD card in a .wav file on a teensy 3.5.
My issue is that I can only open my files in audacity. Which is ok for now. And im seeing exatly what I should see,which is great.....

But I cant open them in Windows Media Player or in R. They both expect signed 16 bit PCM....but I believe I have the correct header for setting up a signed 16 bit PCM header for a .wav file. And my data is signed 16 bit.

Samplerate: 49152 Hz <-Ive tried 44100 and 48000 and neither open in windows media or R,neither does 49152. I chose the value 49152Hz so my files were 15 seconds long and didnt have any decimals after like 15.2354 seconds.
Resolution: 16bit
Number of channels : 2
And heres what the .wav fileheader is based off of:
http://soundfile.sapp.org/doc/WaveFormat/

And heres is my struct and followed by wave file header code:

STRUCT:

HTML:
struct fileheader {
  char  mainChunkId[4];                 /* "RIFF"                                                 */
  uint32_t  mainChunkSize;              /* file length in bytes                                   */
  char  mainChunkFormat[4];             /* "WAVE"                                                 */
  char  fmtChunkId[4];                  /* "fmt "                                                 */
  uint32_t  fmtChunkSize;               /* size of FMT chunk in bytes (usually 16 for PCM)        */
  uint16_t format_tag;                  /* 1=PCM, 257=Mu-Law, 258=A-Law, 259=ADPCM                */
  uint16_t num_chans;                   /* Number of channels/pins used                           */
  uint32_t  sample_rate;                /* Sampling rate in samples per second                    */
  uint32_t  byteRate;                   /* Byte rate = SampleRate * NumChannels * BitsPerSample/8 */
  uint16_t blockAlign;                  /* 2=16-bit mono, 4=16-bit stereo                         */
  uint16_t bits_per_samp;               /* Number of bits per sample                              */
  char  SubtwoChunkId[4];               /* "data"                                                 */
  uint32_t  SubtwoChunkSize;            /* data length in bytes (filelength - 44)                 */
} wavheader;

WAV FILE HEADER CODE
HTML:
void setupWAVHeader() {
  uint16_t resolution0 = adc->adc0->getResolution();
  uint32_t SubtwoChunkSizeCalc = (FILE_SIZE * 2)  * (resolution0 / 8);                                                       // =NumSamples * NumChannels * BitsPerSample/8.

  //RIFF chunk descriptor
  char riff[4] = {'R', 'I', 'F', 'F'};
  strncpy(wavheader.mainChunkId, riff, 4);
  wavheader.mainChunkSize = 36 + SubtwoChunkSizeCalc;                                                                        // Size of the entire File -8 bytes for the two fields not included in this count (ChunkID and ChunkSize)
  char wav[4] = {'W', 'A', 'V', 'E'};
  strncpy(wavheader.mainChunkFormat, wav, 4);

  //Subchunk1 --> fmt sub-chunk

  char fmt[4] = {'f', 'm', 't', ' '};
  strncpy(wavheader.fmtChunkId, fmt, 4);
  wavheader.fmtChunkSize = 16;                                                                                               //16 for PCM
  wavheader.format_tag = 1;                                                                                                  // 1 is PCM (Pulse-code modulation used for sampled analog signals)

  //Subchunk1 sound attributes

  wavheader.num_chans = numChannels;
  wavheader.sample_rate = adc_freq / ChannelPinNumber0;
  wavheader.byteRate = adc_freq / ChannelPinNumber0 * (resolution0 / 8) * numChannels;
  wavheader.blockAlign = numChannels * (resolution0 / 8);
  wavheader.bits_per_samp = resolution0;
  //ExtraParamSize = ... doesn't exist when using PCM

  //Subchunk2 contains size of data and actual sound:

  char data[4] = {'d', 'a', 't', 'a'};
  strncpy(wavheader.SubtwoChunkId, data, 4);
  wavheader.SubtwoChunkSize = SubtwoChunkSizeCalc;

}


From the looks of it,its setup for signed 16bit PCM, my data is signed 16bit btw...so I have no idea currently,why I can only open them in audacity and then have to convert them to signed 16 bit PCM and then they open in windows and R.....But if im doing everything correctly(likely not the case) is there a program that can open up a batch of .wav files and convert them,or would I be better off using say trying matlab and opening the files and converting or something?
 
Last edited:
I tried adding a .wav file using the forum attachment option in "Go Advanced" but fails.....files are 2881kB,need a smaller one? The error didn't say my file was to big so I'm not sure.
 
Last edited:
Samplerate: 49152 Hz <-Ive tried 44100 and 48000 and neither open in windows media or R,neither does 49152. I chose the value 49152Hz so my files were 15 seconds long and didnt have any decimals after like 15.2354 seconds.
Resolution: 16bit
Number of channels : 2
 
View attachment 211017-215807.zip

Got a .wav to upload,just had to change some code so files are shorter.Around 3.3 seconds long.And apologies, signal does have mains hum(60hz) so signal is "abit" noisy, but my batteries are still charging currently.
 
Last edited:
The bit resolution (bits per sample) in the WAV file is 10. This isn't valid for a WAV file. It must be 8,16, etc.
This is why I asked what bit resolution you were using. In the code which initializes the WAV header it does this:
Code:
  uint16_t resolution0 = adc->adc0->getResolution();
.
.
.
  wavheader.bits_per_samp = resolution0;

The default ADC resolution is 10 bits. You will need to either set the ADC resolution to 16 bits in setup:
Code:
  adc->adc0->setResolution(16);
or force the WAV header to 16 bits:
Code:
  wavheader.bits_per_samp = 16;

There may be other errors in the header but fix this up and try again.

Pete
 
This worked!!!, now opens in windows media w/o conversion in audacity! Thank you.

But I have originally set the ADC resolution with :
adc->adc0->setResolution(16);
adc->adc1->setResolution(16);


Code:
void setupADC() {

  adc->adc0->setResolution      (16);
  adc->adc0->setReference       (ADC_REFERENCE::REF_3V3);
  adc->adc0->enableDMA();                                                   // connect DMA and ADC
  adc->adc0->setConversionSpeed ( ADC_CONVERSION_SPEED::HIGH_SPEED);
  adc->adc0->setSamplingSpeed   ( ADC_SAMPLING_SPEED::HIGH_SPEED  );
  adc->adc0->stopPDB();                                                     // start PDB conversion trigger


  adc->adc1->setResolution      (16);
  adc->adc1->setReference       (ADC_REFERENCE::REF_3V3);
  adc->adc1->enableDMA();                                                   // connect DMA and ADC
  adc->adc1->setConversionSpeed ( ADC_CONVERSION_SPEED::HIGH_SPEED);
  adc->adc1->setSamplingSpeed   ( ADC_SAMPLING_SPEED::HIGH_SPEED  );
  adc->adc1->stopPDB();                                                     // start PDB conversion trigger

}


before hand, but....
When I manually set the .wav header resolution to 16, it worked.

Code:
wavheader.bits_per_samp = 16;

Maybe,weird error in getResolution();?
 
I tested your setupADC code. Before the resolution is set to 16, it will be 10. After that it is always 16.
Are you sure that you call setupADC() before calling setupWAVHeader() ?

Pete
 
I tested your setupADC code. Before the resolution is set to 16, it will be 10. After that it is always 16.
Are you sure that you call setupADC() before calling setupWAVHeader() ?

Pete

You are correct,I was calling setupWAVHeader() to early...thanks
 
Status
Not open for further replies.
Back
Top