Parsing A WAV File in C - Truelogic Blog
Parsing A WAV File in C - Truelogic Blog
TRUELOGIC BLOG
NOTES FROM THE WORLD OF SOFTWARE DEVELOPMENT, TECHNOLOGY AND STRATEGY
The WAV (or PCM) audio format is the most basic format for
storing audio. WAV �les can be of di�erent extended formats ,
but PCM is the most popular and common. The other formats
1 of 27 23/12/19, 6:21 am
Parsing a WAV file in C – Truelogic Blog http://truelogic.org/wordpress/2015/09/04/parsing...
are A-law and Mu-law. The PCM format stores raw audio data
TrueLogic India
without any compression or conversion, thus leading to the 311 likes
largest �le sizes, as compared to other formats like AIFF or
MP3 or OGG.
Like Page
While there are existing libraries in several languages which
allow you to work with WAV �les, this post is an attempt to
Be the first of your friends to like this
understand how to read the WAV �le format without any
external library. The language used here is C, and has been
compiled using GCC under Linux, but it can be easily run TrueLogic India
about a month ago
under Windows also with minimal modi�cations. Most likely
for VC++ you will have to replace #include <unistd.h> with Microsoft Japan has made it a 4 day
#include <io.h> week instead of a 5 day week. This has
resulted in increased productivity.
However if people think this can work in
WAV HEADER STRUCTURE other countries, they are wrong. The
Japanese have a very strong work
The header structure is 44 bytes long and has the following culture where people literally work
structure: themselves to death (they have a name
for it - karoshi). What they needed is to
make more time for their non-working
hours so that they dont burn out and
hence the 4 day work is a great solution.
Positions Sample Description
In other parts of the world, specially
Value
South East Asia where people are
1–4 “RIFF” Marks the �le as a ri� �le. always looking for excuses to not work,
Characters are each 1 byte long.
NEWSLETTER
5–8 File size Size of the overall �le – 8 bytes, in
(integer) bytes (32-bit integer). Typically,
First Name:
you’d �ll this in after creation.
Your first name
9 -12 “WAVE” File Type Header. For our
purposes, it always equals
Last Name:
“WAVE”.
Your last name
13-16 “fmt “ Format chunk marker. Includes
trailing null
Email address:
17-20 16 Length of format data as listed
above Your email address
2 of 27 23/12/19, 6:21 am
Parsing a WAV file in C – Truelogic Blog http://truelogic.org/wordpress/2015/09/04/parsing...
3 of 27 23/12/19, 6:21 am
Parsing a WAV file in C – Truelogic Blog http://truelogic.org/wordpress/2015/09/04/parsing...
wave.c
001 /**
002 * Read and parse a wave file
003 *
004 **/
005 #include <unistd.h>
006 #include <stdio.h>
4 of 27 23/12/19, 6:21 am
Parsing a WAV file in C – Truelogic Blog http://truelogic.org/wordpress/2015/09/04/parsing...
5 of 27 23/12/19, 6:21 am
Parsing a WAV file in C – Truelogic Blog http://truelogic.org/wordpress/2015/09/04/parsing...
061
062 read = fread(header.riff,
sizeof(header.riff), 1, ptr);
063 printf("(1-4): %s \n", header.riff);
064
065 read = fread(buffer4, sizeof(buffer4),
1, ptr);
066 printf("%u %u %u %u\n", buffer4[0],
buffer4[1], buffer4[2], buffer4[3]);
067
068 // convert little endian to big endian 4
byte int
069 header.overall_size = buffer4[0] |
070 (buffer4[1]<<8) |
071 (buffer4[2]<<16)
|
072 (buffer4[3]<<24);
073
074 printf("(5-8) Overall size: bytes:%u,
Kb:%u \n", header.overall_size,
header.overall_size/1024);
075
076 read = fread(header.wave,
sizeof(header.wave), 1, ptr);
077 printf("(9-12) Wave marker: %s\n",
header.wave);
078
079 read = fread(header.fmt_chunk_marker,
sizeof(header.fmt_chunk_marker), 1, ptr);
080 printf("(13-16) Fmt marker: %s\n",
header.fmt_chunk_marker);
081
082 read = fread(buffer4, sizeof(buffer4),
1, ptr);
083 printf("%u %u %u %u\n", buffer4[0],
buffer4[1], buffer4[2], buffer4[3]);
084
085 // convert little endian to big endian 4
byte integer
086 header.length_of_fmt = buffer4[0] |
087 (buffer4[1]
<< 8) |
088 (buffer4[2]
<< 16) |
089 (buffer4[3]
<< 24);
090 printf("(17-20) Length of Fmt header: %u
\n", header.length_of_fmt);
091
092 read = fread(buffer2, sizeof(buffer2),
1, ptr); printf("%u %u \n", buffer2[0],
buffer2[1]);
093
094 header.format_type = buffer2[0] |
(buffer2[1] << 8);
6 of 27 23/12/19, 6:21 am
Parsing a WAV file in C – Truelogic Blog http://truelogic.org/wordpress/2015/09/04/parsing...
7 of 27 23/12/19, 6:21 am
Parsing a WAV file in C – Truelogic Blog http://truelogic.org/wordpress/2015/09/04/parsing...
8 of 27 23/12/19, 6:21 am
Parsing a WAV file in C – Truelogic Blog http://truelogic.org/wordpress/2015/09/04/parsing...
9 of 27 23/12/19, 6:21 am
Parsing a WAV file in C – Truelogic Blog http://truelogic.org/wordpress/2015/09/04/parsing...
207
208 printf("\n\n.Valid range for
data values : %ld to %ld \n", low_limit,
high_limit);
209 for (i =1; i <= num_samples;
i++) {
210 printf("==========Sample
%ld / %ld=============\n", i,
num_samples);
211 read = fread(data_buffer,
sizeof(data_buffer), 1, ptr);
212 if (read == 1) {
213
214 // dump the data read
215 unsigned int
xchannels = 0;
216 int data_in_channel =
0;
217
218 for (xchannels = 0;
xchannels < header.channels; xchannels ++
) {
219 printf("Channel#%d
: ", (xchannels+1));
220 // convert data
from little endian to big endian based on
bytes in each channel sample
221 if
(bytes_in_each_channel == 4) {
222 data_in_channel
= data_buffer[0] |
223
|
224
|
225
<<24);
226 }
227 else if
(bytes_in_each_channel == 2) {
228 data_in_channel
= data_buffer[0] |
229
<< 8);
230 }
231 else if
(bytes_in_each_channel == 1) {
232 data_in_channel
= data_buffer[0];
233 }
234
235 printf("%d ",
data_in_channel);
236
237 // check if value
10 of 27 23/12/19, 6:21 am
Parsing a WAV file in C – Truelogic Blog http://truelogic.org/wordpress/2015/09/04/parsing...
was in range
238 if
(data_in_channel < low_limit ||
data_in_channel > high_limit)
239 printf("**value
out of range\n");
240
241 printf(" | ");
242 }
243
244 printf("\n");
245 }
246 else {
247 printf("Error reading
file. %d bytes\n", read);
248 break;
249 }
250
251 } // for (i =1; i <=
num_samples; i++) {
252
253 } // if (size_is_correct) {
254
255 } // if (c == 'Y' || c == 'y') {
256 } // if (header.format_type == 1) {
257
258 printf("Closing file..\n");
259 fclose(ptr);
260
261 // cleanup before quitting
262 free(filename);
263 return 0;
264
265 }
266
267 /**
268 * Convert seconds into hh:mm:ss format
269 * Params:
270 * seconds - seconds value
271 * Returns: hms - formatted string
272 **/
273 char* seconds_to_time(float raw_seconds)
{
274 char *hms;
275 int hours, hours_residue, minutes,
seconds, milliseconds;
276 hms = (char*) malloc(100);
277
278 sprintf(hms, "%f", raw_seconds);
279
280 hours = (int) raw_seconds/3600;
281 hours_residue = (int) raw_seconds %
3600;
282 minutes = hours_residue/60;
283 seconds = hours_residue % 60;
11 of 27 23/12/19, 6:21 am
Parsing a WAV file in C – Truelogic Blog http://truelogic.org/wordpress/2015/09/04/parsing...
284 milliseconds = 0;
285
286 // get the decimal part of raw_seconds
to get milliseconds
287 char *pos;
288 pos = strchr(hms, '.');
289 int ipos = (int) (pos - hms);
290 char decimalpart[15];
291 memset(decimalpart, ' ',
sizeof(decimalpart));
292 strncpy(decimalpart, &hms[ipos+1], 3);
293 milliseconds = atoi(decimalpart);
294
295
296 sprintf(hms, "%d:%d:%d.%d", hours,
minutes, seconds, milliseconds);
297 return hms;
298 }
12 of 27 23/12/19, 6:21 am
Parsing a WAV file in C – Truelogic Blog http://truelogic.org/wordpress/2015/09/04/parsing...
Related Posts
PREVIOUS NEXT
Watermark an Writing PHP
image in C# Extensions – Part
1 Overview
38 COMMENTS
13 of 27 23/12/19, 6:21 am
Parsing a WAV file in C – Truelogic Blog http://truelogic.org/wordpress/2015/09/04/parsing...
suraj
JULY 22, 2016 AT 2:58 PM
Hii Amit,
Thanks a lot for such a nice tutorial. In fact I used your code it
was working properly. I have a question if suppose the wave
header is of not 44 bytes may be 48 bytes or any other length
how the code structure would be?
REPLY
amit
SEPTEMBER 19, 2016 AT 5:30 AM
Hi Suraj,
REPLY
mel
SEPTEMBER 22, 2016 AT 6:41 PM
14 of 27 23/12/19, 6:21 am
Parsing a WAV file in C – Truelogic Blog http://truelogic.org/wordpress/2015/09/04/parsing...
REPLY
amit
SEPTEMBER 23, 2016 AT 4:49 AM
REPLY
Jay R
DECEMBER 11, 2016 AT 5:07 PM
REPLY
amit
DECEMBER 12, 2016 AT 4:18 AM
@Jay The code uses byte shifting to convert from little endian
to big endian. I am not sure if two’s complement is required
here because there are no negative values involved so we
dont need to worry about the sign bit. Correct me if I am
wrong.
15 of 27 23/12/19, 6:21 am
Parsing a WAV file in C – Truelogic Blog http://truelogic.org/wordpress/2015/09/04/parsing...
REPLY
sudha
JULY 4, 2017 AT 1:51 PM
REPLY
amit
JULY 4, 2017 AT 1:56 PM
@sudha I have never used Code Block IDE so I cant help you in
that. But this is a very simple �le – one c �le and which
includes a header �le. It should run in any IDE .
REPLY
Anamay
APRIL 16, 2018 AT 6:32 PM
REPLY
Anamay
APRIL 16, 2018 AT 6:37 PM
16 of 27 23/12/19, 6:21 am
Parsing a WAV file in C – Truelogic Blog http://truelogic.org/wordpress/2015/09/04/parsing...
REPLY
Anamay
APRIL 16, 2018 AT 6:48 PM
REPLY
Anamay
APRIL 16, 2018 AT 8:20 PM
Finally I am getting the output but could you tell me how to get
the samples as an array?
REPLY
amit
APRIL 17, 2018 AT 3:29 AM
REPLY
Anamay
17 of 27 23/12/19, 6:21 am
Parsing a WAV file in C – Truelogic Blog http://truelogic.org/wordpress/2015/09/04/parsing...
REPLY
Amit
APRIL 17, 2018 AT 5:10 AM
REPLY
Anamay
APRIL 17, 2018 AT 5:50 AM
REPLY
Anamay
APRIL 17, 2018 AT 8:34 AM
The thing is, some of the values agree with the matlab
ones, while some don’t. Is that because of endianness?
REPLY
18 of 27 23/12/19, 6:21 am
Parsing a WAV file in C – Truelogic Blog http://truelogic.org/wordpress/2015/09/04/parsing...
Amit
APRIL 18, 2018 AT 3:47 AM
REPLY
Anamay
APRIL 18, 2018 AT 3:18 PM
REPLY
Anamay
APRIL 26, 2018 AT 7:03 PM
else if (bytes_in_each_channel == 2)
{
19 of 27 23/12/19, 6:21 am
Parsing a WAV file in C – Truelogic Blog http://truelogic.org/wordpress/2015/09/04/parsing...
Amit
APRIL 27, 2018 AT 4:24 AM
@anamay,
Thanks a lot for the solution. Hope it helps others who come
across this problem.
REPLY
Shri Agnish
AUGUST 13, 2018 AT 2:05 PM
REPLY
amit
AUGUST 14, 2018 AT 3:00 AM
@shri Agnish Sorry I didnt understand. In the code you just put
the location of the wave �le in your hard disk.
20 of 27 23/12/19, 6:21 am
Parsing a WAV file in C – Truelogic Blog http://truelogic.org/wordpress/2015/09/04/parsing...
REPLY
HANEESH
SEPTEMBER 5, 2018 AT 5:11 AM
Hai…
In the command line I am giving “./a.out “, in the terminal I
have seen the sample number and channel number but
unable to listen the sound. Could you please suggest me
what’s wrong?
REPLY
HANEESH
SEPTEMBER 5, 2018 AT 5:25 AM
compiled the same code but couldn’t get any audio. Could you
suggest me any solution?
REPLY
amit
SEPTEMBER 6, 2018 AT 3:21 AM
REPLY
Mada
NOVEMBER 15, 2018 AT 9:10 AM
21 of 27 23/12/19, 6:21 am
Parsing a WAV file in C – Truelogic Blog http://truelogic.org/wordpress/2015/09/04/parsing...
REPLY
amit
NOVEMBER 17, 2018 AT 3:11 AM
@mada do you mean that you want to extract the wave �le
between seconds 2 to 4?
REPLY
OUTATIME
JANUARY 12, 2019 AT 5:06 PM
I run:
gcc wave.c
./a.out /home/path/Test1.wav
Thanks in andvance
22 of 27 23/12/19, 6:21 am
Parsing a WAV file in C – Truelogic Blog http://truelogic.org/wordpress/2015/09/04/parsing...
REPLY
amit
JANUARY 13, 2019 AT 2:29 AM
REPLY
Marcio Matos
FEBRUARY 14, 2019 AT 7:06 PM
REPLY
amit
FEBRUARY 15, 2019 AT 4:48 AM
REPLY
23 of 27 23/12/19, 6:21 am
Parsing a WAV file in C – Truelogic Blog http://truelogic.org/wordpress/2015/09/04/parsing...
Marcio Matos
FEBRUARY 15, 2019 AT 2:44 PM
REPLY
evgeny
APRIL 22, 2019 AT 4:08 AM
REPLY
Rpy Circuits
NOVEMBER 6, 2019 AT 1:36 AM
Hey there,
I have a simple but important question:
Where is the audio data stored (in which array)? I am
hesitating between data_bu�er and data_in_channel.
Could someone tell me which one it is?
Thanks in advance!
REPLY
amit
NOVEMBER 6, 2019 AT 3:27 AM
24 of 27 23/12/19, 6:21 am
Parsing a WAV file in C – Truelogic Blog http://truelogic.org/wordpress/2015/09/04/parsing...
REPLY
Rpy Circuits
NOVEMBER 6, 2019 AT 9:20 PM
REPLY
amit
NOVEMBER 7, 2019 AT 3:04 AM
@rpy Circuits, I had the same purpose when I wrote this code.
But I got busy with other projects so never got around to
actually being able play the wav data. It is de�nitely non-trivial
and requires working closely with the soundcard. From what I
can make out, playing an audio sound is a function of playing a
certain number of samples for a certain period of time on a
given frequency.
25 of 27 23/12/19, 6:21 am
Parsing a WAV file in C – Truelogic Blog http://truelogic.org/wordpress/2015/09/04/parsing...
http://digitalsoundandmusic.com/2-3-12-modeling-sound-in-
c-under-linux/ which explains how sound is modeled. Of
particular interest is the paragraph:
******
The sound wave is created by taking the sine of the
appropriate frequency (262 Hz, for example) at 44,100 evenly-
spaced intervals for one second of audio data. The value
returned from the sine function is between -1 and 1. However,
the sound card expects a value that is stored in one byte (i.e., 8
bits), ranging from -128 to 127. To put the value into this
range, we multiply by 127 and, with the �oor function, round
down.
******
REPLY
Leave a Reply
Your email address will not be published.
Comment
Name *
Email *
26 of 27 23/12/19, 6:21 am
Parsing a WAV file in C – Truelogic Blog http://truelogic.org/wordpress/2015/09/04/parsing...
Website
POST COMMENT
27 of 27 23/12/19, 6:21 am