Go Down

Topic: WAV decoding method (Read 4799 times) previous topic - next topic

Aadarsh

Hi

I learnt about the WAV format and how it's arranged in the memory.While coming to the point of arduino,How can I able to decode the data present in the wav file to sound?.Since I am using ATmega8 ,I have only less memory space for the program.I used petit FAT library for reading data from the SD card.Still I have 3Kb left in the memory.How can I program to decode the data of the wave file in the 3kb space.


robtillaart

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Aadarsh

Hi Robtillaart

I want to decode that hex data present in the wav file to a audible sound.For that what can I do?

robtillaart

As far as I know wave you need to apply the values in the wav file to analogWrite(pin, value);
where value - o..255. then use some delay(250) or so

Apply a low pass filter to the PWM pin and you should get some soundlike thingie.

a low pass filter is a resistor and a capacitor -> google images isyour friend
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

DVDdoug

#4
Aug 30, 2015, 08:03 pm Last Edit: Aug 30, 2015, 08:09 pm by DVDdoug
If you are using a DAC, Just send the samples to DAC at the correct sample rate (per the WAV file header), and the DAC converts the WAV/PCM data to "sound" in real-time.   (Actually to an analog signal  which needs to be amplified before the speaker converts it to sound).    If the bit-depth of the WAV file doesn't match the DAC, scale it up or down (multiply or divide) as required.

...The audio doesn't need to be decoded.   The header has to be "decoded" (or parsed) to get the bit depth, sample rate, and number of channels on order to get the bytes to the DAC with the correct speed/sequence/structure.

If you are "faking it" with Arduino PWM, scale-down the samples to 8-bits (if they are not 8-bits already) before writing the data to PWM at the correct sample rate.  (i.e. Divide 16-bit samples by 256 or bit-shift right by 8-bits.)  Note that 8-bit WAV files are unsigned, so that data can be sent directly to PWM.   But, 16 bit or more WAV files are signed so you'll have to bias the 8-bit data for the PWM output which doesn't go negative.

Note that the 8-bits (and the low default PWM frequency) make for poor-quality sound.   You need a DAC to get anything close to the quality from a soundcard or iPod, etc.   (You can get an audio shield with a built-in DAC and a sample rate clock and that takes a big load off your Arduino and your software.)

Quote
Still I have 3Kb left in the memory.How can I program to decode the data of the wave file in the 3kb space.
What????

Aadarsh

Hi robtillaart

Thanks for your suggestions.... :)

Hi DVDdoug

Is it good to use the resistor ladder DAC as DAC? OR I need other ic chip for DAC?. If I use DAC how can I spilt that hex value(0-255) to 1's and 0's and then send the corresponding 1 and 0's to the correct pins present in the arduino. Can I use any one port for this process?. I mean how can I convert that single hex value to 8 pin output?. How can I able to implement in the program?... Is DAC method support for 44,100 hz music play ?

DVDdoug

#6
Aug 31, 2015, 10:22 pm Last Edit: Aug 31, 2015, 10:31 pm by DVDdoug
You can use bitRead() to get the individual bits from your byte, then write them out to the appropriate pins.   You'll get a little glitch, since you are not writing all of the bits at the same time but I assume that may be fast-enough so you don't hear it, and if you have a filter it should (hopefully) get filtered-out.    (A real DAC doesn't get clocked until the data has had time to settle, so the analog output doesn't change until it "knows" what the next analog value will be.)

There are port commands that allow you to write a byte at once, but I've never used them so I can't help you with that.    And, the "bits" would have to be wired to the correct I/O pins in the correct order.   And although the timing should be better,  real-world physics mean that all of the bits won't be written at exactly  the same time, and you'll still get undefined in-between values/states.

Quote
Is DAC method support for 44,100 hz music play ?
I think  the Arduino is fast-enough for that (as long as you're not trying to do to many other things at the same time), but I don't really know how fast it can write-out a bit in a "fast loop".     You'll need to use the micros() function to time the samples.       Please double-check my math, but at 4.1Khz I get about 23uS between samples.

Aadarsh

hi DVDdoug

I gone through the concepts of I/O ports of Atmel in the book.It's a good idea to send the data of wav to the port pin by making DDRx as 0xFF.I also saw the link which you send.In that a point is highlighted that if we accidentally set the Rx as output(set the 1'st bit of the port ) may cause broblem during the next code uploading time.Is it safer to make the MOSI as input and MISO as output.Is it cause any problem during debugging using ISP headers?.

I think you need 243 uS delay for 4.1KHz sampling rate( since 1/4.1e+3 =243.9e-6).For what I asked ie. 44100 Hz sampling rate,I found that my atmega8 runs @ 16MHz clock speed.So it can execute 1 instruction in 6.25e-8 seconds. the sampling rate what I got for 44100 Hz is (1/44100=22.6758e-6) approximately 22 us.By the above calculation it seems that possiblity of playing 44100 Hz music.What do you think so about this :)

knut_ny

You can play bytes already in RAM.  Fetching data from SD-card is slow - with an extra 'wait' for page change.
U need a ringbuffer and code that keeps fetching data to the buffer. An interrupt routine does the playback.
@ 16kB/s the CPU is almost at full load.   You can not get "HiFi" without additional sound-chip
Ny

Aadarsh

Hi Knut_ny

Adding a sound chip will require more program space,so it's not possible in my case to add IC1100 playback chip.I can understand that the CPU usage will be maximum if I try to play at full resolution (44100Hz).It's just fine to play at 16Khz sampling rate.I'll also convert the song to 8Kbps so that it's easy for a microcontroller to have enough time to buffer.I mean it's relatively less data fetch compared to 16Kbps. Shall I use a 0808 DAC for the output audio or will go by resistor ladder DAC?

Can I play the stereo(2 channel with two speakers) music using arduino? Should I need to add another port for output or can I multiplex from this one port?Is it feasible to do so?

If I want to play a 2 channel sound how the data is arranged in the audio file(wav file).Can you please send me a sample picture to show the left and right channel separation in the audio file(wav file in HEX editor)? :)

DVDdoug

Quote
Can I play the stereo(2 channel with two speakers) music using arduino? Should I need to add another port for output
You need two ports and 2 DACs (or a stereo DAC).  

Quote
or can I multiplex from this one port?Is it feasible to do so?
If you buy a stereo DAC, it might accept a multiplexed signal.    You'd have to check the datasheet.  Most stereo or multi-channel DACs are only going to have one digital input (serial or parallel).

Quote
If I want to play a 2 channel sound how the data is arranged in the audio file(wav file).Can you please send me a sample picture to show the left and right channel separation in the audio file(wav file in HEX editor)?
The channels alternate with the left channel first.    With 8-bits it's easy because the bytes simply alternate and the worst that can happen is the left & right get reversed.

With 16-bits you have to get the byte-order correct.   If the high & low bytes get mixed-up you'll get what sounds like pure noise.   With 16-bit stereo there are more ways to screw-up by getting one byte from the left and one from the right.

Quote
Shall I use a 0808 DAC for the output audio or will go by resistor ladder DAC?
You're the engineer!    ;)   ...If it was me, I'd use an audio shield or the Raspberry Pi.  :D    I'm not familiar with that chip, but it appears not to be "clocked" so (like with a resistor ladder) you'll probably get undefined output (glitches) when it's switching.    But again, those glitches may be above the audio frequency range and may not be audible.

Aadarsh

Hi DVDdoug

I attached some pictures which I converted from mp3 to wav and made some costume changes(using online converter offers more options)(pic name RIFF1.jpg).Is the thinks what I gave is correct?please tell me is it correct for playing in arduino level.

I also attached a hex file of wav file(I changed the resolution as 8 bit),can you please download(RIFF.jpg) and edit in the same picture as which is left and which data is right speaker and then attach in your reply. :D

pjrc

#12
Sep 03, 2015, 03:42 am Last Edit: Sep 03, 2015, 03:42 am by Paul Stoffregen
All WAV files have at least a 44 byte header.  Many others have extra non-sound sections, so some extra work is needed to parse the file until you find the one that begins with 0x61746164.

Here's some code I wrote that plays WAV files as part of a larger audio library.  It parses the header and ignore non-sound sections.  The playback section converts mono to 2 identical output stereo, but it doesn't (yet) do anything to convert/resample non-44 kHz files.

https://github.com/PaulStoffregen/Audio/blob/master/play_sd_wav.cpp

This code is well tested and definitely plays most WAV files very nicely!

Aadarsh

Hi Paul Stoffregen

Actually I want to deal with some small level wav player.You mentioned 0x61746164 which is a 32 bit data .Arduino Uno (in my case ATmega8) is just a 8 bit processor.So only I mentioned in the picture that it is a unsigned 8 bit wav format(RIFF1.jpg),showing that it's just a 8 bit data.And also arduino has 3 ports only.On that 1 port is completely used for SD card interface and one port I planned to use for playing audio.I can't use the port containing Tx and Rx for UART.

The program what you done is nice.I'll try to get the points from your program and I'll try to reconstruct for 8 bit level.

Grumpy_Mike

Quote
Arduino Uno (in my case ATmega8) is just a 8 bit processor.
That does not stop it from being able to manipulate as many byte quantities as you want.
In normal Aruino code an int is two bytes long ( 16 bits ) a long is four bytes ( 32 bits ) and a long long is eight bytes or 64 bits.

Go Up