0% found this document useful (0 votes)
80 views

Parsing A WAV File in C - Truelogic Blog

The document discusses parsing WAV audio files in C code without external libraries. It describes the standard 44-byte WAV header structure containing metadata like file size, format, number of channels, sample rate, bits per sample. It provides sample C code that accepts a WAV file path, reads the header to get structure info like sample size and total duration, without needing external libraries.

Uploaded by

Ankesh Cdac
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
80 views

Parsing A WAV File in C - Truelogic Blog

The document discusses parsing WAV audio files in C code without external libraries. It describes the standard 44-byte WAV header structure containing metadata like file size, format, number of channels, sample rate, bits per sample. It provides sample C code that accepts a WAV file path, reads the header to get structure info like sample size and total duration, without needing external libraries.

Uploaded by

Ankesh Cdac
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 27

Parsing a WAV file in C – Truelogic Blog http://truelogic.org/wordpress/2015/09/04/parsing...

TRUELOGIC BLOG
NOTES FROM THE WORLD OF SOFTWARE DEVELOPMENT, TECHNOLOGY AND STRATEGY

HOME ABOUT THIS BLOG CONTACT ME

Parsing a WAV �le in C SEARCH …

 September 4, 2015  amit  Audio, Linux, Slideshow


 38 MY BOOK ON THE
YOUTUBE API

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

21-22 1 Type of format (1 is PCM) – 2 byte SIGN UP


integer

23-24 2 Number of Channels – 2 byte


integer CATEGORIES

25-28 44100 Sample Rate – 32 byte integer.


Apache/PHP (47)
Common values are 44100 (CD),
Programming (119)
48000 (DAT). Sample Rate =
YouTube API With PHP (31)
Number of Samples per second,
Javascript/Jquery (23)
or Hertz.
Python (22)
29-32 176400 (Sample Rate * BitsPerSample * ASP.NET (11)
Channels) / 8. C/C++ (7)
MySQL (2)
33-34 4 (BitsPerSample * Channels) / 8.1 –
VC++ (1)
8 bit mono2 – 8 bit stereo/16 bit
MongoDB (1)
mono4 – 16 bit stereo
Java (1)
35-36 16 Bits per sample FreeBSD Unix (23)
Misc (19)
37-40 “data” “data” chunk header. Marks the
Tutorials (17)
beginning of the data section.
Linux (15)
41-44 File size Size of the data section. Windows (14)
(data) Android Dev (11)
Amazing Technology (11)
Sample values are given above for a 16-bit stereo source.
WWW Stu� (10)
Useful Lists (9)
It is important to note that the WAV format uses little-endian Web Designing (5)
format to store bytes, so you need to convert the bytes to big- Xcode & Swift (5)
endian in code for the values to make sense. Uncategorized (4)
Maps (4)
CODE MS SQL Server (4)
MySQL (4)
The code consists of a header �le wave.h which is included in
Slideshow (4)
wave.c . Once you compile it and run it, it accepts the path of a
HTML (3)
wav �le from the command line and dumps the structure
Audio (3)
information including the size of each sample and the total
NginX (2)
duration of the wav audio.
Business (2)
Strategy (2)
wave.h

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

01 // WAVE file header format OpenCV (2)


02 struct HEADER {
03 unsigned char Get the right Job (1)
riff[4]; // RIFF Books (1)
string
04 unsigned int overall_size Book Downloads (1)
; // overall size of file Powershell (1)
in bytes
AWS (1)
05 unsigned char
wave[4]; // WAVE
string
06 unsigned char SOCRATES – MYSQL
fmt_chunk_marker[4]; // fmt TOOL
string with trailing null char
07 unsigned int
length_of_fmt; // length
of the format data
08 unsigned int
format_type; // format
type. 1-PCM, 3- IEEE float, 6 - 8bit A
law, 7 - 8bit mu law
09 unsigned int
channels; // no.of
channels
10 unsigned int
sample_rate; //
sampling rate (blocks per second)
11 unsigned int
byterate; //
SampleRate * NumChannels *
BitsPerSample/8
12 unsigned int Socrates – web based MySQL
block_align; //
NumChannels * BitsPerSample/8 schema diagram generator
13 unsigned int
bits_per_sample; // bits
per sample, 8- 8bits, 16- 16 bits etc
14 unsigned char data_chunk_header
[4]; // DATA string or FLLR string
15 unsigned int
data_size; //
NumSamples * NumChannels *
BitsPerSample/8 - size of the next chunk
that will be read
16 };

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

007 #include <string.h>


008 #include <stdlib.h>
009 #include "wave.h"
010 #define TRUE 1
011 #define FALSE 0
012
013 // WAVE header structure
014
015 unsigned char buffer4[4];
016 unsigned char buffer2[2];
017
018 char* seconds_to_time(float seconds);
019
020
021 FILE *ptr;
022 char *filename;
023 struct HEADER header;
024
025 int main(int argc, char **argv) {
026
027 filename = (char*) malloc(sizeof(char) *
1024);
028 if (filename == NULL) {
029 printf("Error in malloc\n");
030 exit(1);
031 }
032
033 // get file path
034 char cwd[1024];
035 if (getcwd(cwd, sizeof(cwd)) != NULL) {
036
037 strcpy(filename, cwd);
038
039 // get filename from command line
040 if (argc < 2) {
041 printf("No wave file specified\n");
042 return;
043 }
044
045 strcat(filename, "/");
046 strcat(filename, argv[1]);
047 printf("%s\n", filename);
048 }
049
050 // open file
051 printf("Opening file..\n");
052 ptr = fopen(filename, "rb");
053 if (ptr == NULL) {
054 printf("Error opening file\n");
055 exit(1);
056 }
057
058 int read = 0;
059
060 // read header parts

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

095 char format_name[10] = "";


096 if (header.format_type == 1)
097 strcpy(format_name,"PCM");
098 else if (header.format_type == 6)
099 strcpy(format_name, "A-law");
100 else if (header.format_type == 7)
101 strcpy(format_name, "Mu-law");
102
103 printf("(21-22) Format type: %u %s \n",
header.format_type, format_name);
104
105 read = fread(buffer2, sizeof(buffer2),
1, ptr);
106 printf("%u %u \n", buffer2[0],
buffer2[1]);
107
108 header.channels = buffer2[0] |
(buffer2[1] << 8);
109 printf("(23-24) Channels: %u \n",
header.channels);
110
111 read = fread(buffer4, sizeof(buffer4),
1, ptr);
112 printf("%u %u %u %u\n", buffer4[0],
buffer4[1], buffer4[2], buffer4[3]);
113
114 header.sample_rate = buffer4[0] |
115 (buffer4[1] << 8)
|
116 (buffer4[2] <<
16) |
117 (buffer4[3] <<
24);
118
119 printf("(25-28) Sample rate: %u\n",
header.sample_rate);
120
121 read = fread(buffer4, sizeof(buffer4),
1, ptr);
122 printf("%u %u %u %u\n", buffer4[0],
buffer4[1], buffer4[2], buffer4[3]);
123
124 header.byterate = buffer4[0] |
125 (buffer4[1] << 8)
|
126 (buffer4[2] <<
16) |
127 (buffer4[3] <<
24);
128 printf("(29-32) Byte Rate: %u , Bit
Rate:%u\n", header.byterate,
header.byterate*8);
129
130 read = fread(buffer2, sizeof(buffer2),
1, ptr);

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

131 printf("%u %u \n", buffer2[0],


buffer2[1]);
132
133 header.block_align = buffer2[0] |
134 (buffer2[1] << 8);
135 printf("(33-34) Block Alignment: %u \n",
header.block_align);
136
137 read = fread(buffer2, sizeof(buffer2),
1, ptr);
138 printf("%u %u \n", buffer2[0],
buffer2[1]);
139
140 header.bits_per_sample = buffer2[0] |
141 (buffer2[1] << 8);
142 printf("(35-36) Bits per sample: %u \n",
header.bits_per_sample);
143
144 read = fread(header.data_chunk_header,
sizeof(header.data_chunk_header), 1,
ptr);
145 printf("(37-40) Data Marker: %s \n",
header.data_chunk_header);
146
147 read = fread(buffer4, sizeof(buffer4),
1, ptr);
148 printf("%u %u %u %u\n", buffer4[0],
buffer4[1], buffer4[2], buffer4[3]);
149
150 header.data_size = buffer4[0] |
151 (buffer4[1] << 8) |
152 (buffer4[2] << 16) |
153 (buffer4[3] << 24 );
154 printf("(41-44) Size of data chunk: %u
\n", header.data_size);
155
156
157 // calculate no.of samples
158 long num_samples = (8 *
header.data_size) / (header.channels *
header.bits_per_sample);
159 printf("Number of samples:%lu \n",
num_samples);
160
161 long size_of_each_sample =
(header.channels *
header.bits_per_sample) / 8;
162 printf("Size of each sample:%ld
bytes\n", size_of_each_sample);
163
164 // calculate duration of file
165 float duration_in_seconds = (float)
header.overall_size / header.byterate;
166 printf("Approx.Duration in
seconds=%f\n", duration_in_seconds);

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

167 printf("Approx.Duration in h:m:s=%s\n",


seconds_to_time(duration_in_seconds));
168
169
170
171 // read each sample from data chunk if
PCM
172 if (header.format_type == 1) { // PCM
173 printf("Dump sample data? Y/N?");
174 char c = 'n';
175 scanf("%c", &c);
176 if (c == 'Y' || c == 'y') {
177 long i =0;
178 char
data_buffer[size_of_each_sample];
179 int size_is_correct = TRUE;
180
181 // make sure that the bytes-per-
sample is completely divisible by num.of
channels
182 long bytes_in_each_channel =
(size_of_each_sample / header.channels);
183 if ((bytes_in_each_channel *
header.channels) != size_of_each_sample)
{
184 printf("Error: %ld x %ud <>
%ld\n", bytes_in_each_channel,
header.channels, size_of_each_sample);
185 size_is_correct = FALSE;
186 }
187
188 if (size_is_correct) {
189 // the valid
amplitude range for values based on the
bits per sample
190 long low_limit = 0l;
191 long high_limit = 0l;
192
193 switch
(header.bits_per_sample) {
194 case 8:
195 low_limit = -128;
196 high_limit = 127;
197 break;
198 case 16:
199 low_limit = -32768;
200 high_limit = 32767;
201 break;
202 case 32:
203 low_limit =
-2147483648;
204 high_limit =
2147483647;
205 break;
206 }

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 }

A sample run is given below:

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

PHPAudio – A Speech Generate Yearly


Audio �le Translation Calendar in C++
processing in mashup in less
pure PHP than 5 hours

Python 2.7 – Writing PHP Control Multiple


Getting Started Extensions – Part Computers with
3 The Four Kinds Synergy
of Functions

 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,

There are non-standard wav �le formats which are used,


where the header size will be more than 44 bytes. Some of the
commercial audio programs and music softwares add their
own undocumented data into the header. The only way to
know if this is a not a 44 byte header is to check the location of
the “data” chunk marker. It means that a really robust
program would go on parsing the �le till it �nds a valid header
instead of assuming that it will always be at the beginning. This
is much like parsing an MP3 �le where the header can be
anywhere in the �le.

 REPLY

mel
SEPTEMBER 22, 2016 AT 6:41 PM

header.block_align and size_of_each_sample seem to be


equivalent.

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

also using header.block_align for calculating num_samples


also makes for easier to understand math i.e. num_samples =
header.data_size / header.block_align

 REPLY

amit 
SEPTEMBER 23, 2016 AT 4:49 AM

@mel Your statement is correct. The de�nition of “block align”


is “The number of bytes for one sample including all channels”
which makes you wonder why cant it be called something
more relevant.

 REPLY

Jay R
DECEMBER 11, 2016 AT 5:07 PM

To get actual amplitude on line 222, 228 or 232 wouldn’t you


need take two’s complement?

Thanks for posting the code

 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

can u please help me how to run this code on windows


through code:block IDE???
please reply me it’s very urgent.

 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

Hi Amit, I am getting an error ‘multiple de�nition of main’. Any


idea why it is so? Thanks.

 REPLY

Anamay
APRIL 16, 2018 AT 6:37 PM

Hi Amit, actually this is solved but the program is giving ‘No


wave �le speci�ed’ without giving me the chance to input it

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

at the command line.

 REPLY

Anamay
APRIL 16, 2018 AT 6:48 PM

Also in wave.c, in line no. 42, it (eclipse IDE) is giving me


an error :

“Return without value, in function returning non-void”

 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

@Anamay , there are no built in dynamic array primitives in


pure C++ . Perhaps you want to use an external library or
create a class for array handling. One alternative is to use the
vector class from STL.

 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...

APRIL 17, 2018 AT 4:56 AM

Actually I mean that which part of the program are we dealing


with the actual samples of the audio �le? Which variable are
they stored, if so?

 REPLY

Amit
APRIL 17, 2018 AT 5:10 AM

@Anamay . The actual data is found in data_in_channel

 REPLY

Anamay
APRIL 17, 2018 AT 5:50 AM

@Amit, The actual samples I obtained from matlab are all in


the range of -1 to 1 whereas the values obtained from this
program are in the ranges of 10000 also. What could be the
reason for that?

 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

@anamay I really cant say since I am not familiar with


Matlab.

 REPLY

Anamay
APRIL 18, 2018 AT 3:18 PM

Okay, no worries.. Thanks for your help.


Some feedback:
In the ‘get �lename from command line’ section,
for my program, the variable ‘argc’ was always 1.
So I manually set it to 2 to avoid getting ‘No wave
�le speci�ed’. Though my wave �le was in the same
working directory. Also argv[1] was null. Also, I
added a ‘scanf’ function there to input the �le
name from the keyboard.

 REPLY

Anamay
APRIL 26, 2018 AT 7:03 PM

Hello Amit, �nally I got my output as expected.


Thanks so much for this code. What solved the
problem was in the part where conversion
from little endian to big endian occurs, i.e. lines
220 – 232, my case being
bytes_in_each_channel == 2, lines 227 to 230,

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

data_in_channel = data_bu�er[0] & 255 |


(data_bu�er[1] << 8);
}

Just added '& 255' to it. i.e. ANDing


data_bu�er[0] with 255 (all ones). The value of
data_bu�er[0], remains the same but the
conversion of little endian to big endian occurs
correctly even when data_bu�er[0] is negative,
something which was not happening before.

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

how do i input a wav �le in windows??

 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

@haneesh . This code is just for parsing the contents of a wav


�le. It will not play the wav �le or generate any sound.

 REPLY

Mada
NOVEMBER 15, 2018 AT 9:10 AM

hello! I want help for a function that must chop a track .

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

The -chop argument clears


one audio �le from one time to another.
The result is saved in a new �le named chopped-sound1.wav,
where sound1.wav is the original audio �le name. Below is an
example of splitting a sound �le from 2nd to 4th:
$ ./wavengine-chopsound1.wav2 4

 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

Hello and thank you for the code!

i try to run your code but


1) I get an error form line 42 (return;)
2) if i comment line 42 or change in to return 0; it compiles but
i get
“Opening �le..
Error opening �le”

Any ideas why is that happening;

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

@outatime It looks like a standard �le access error. Either the


�le is not present in the path provided or perhaps the folder
does not have permissions to allow the �le to be read. A good
idea would be to use ferror() to print out the error message.

 REPLY

Marcio Matos
FEBRUARY 14, 2019 AT 7:06 PM

Hello, thanks a lot for the code.


I’m really starting out at sound programming and I’ve got the
struct (mostly) correctly �lled. But you left me wondering how i
would actually play this �le. Any tips?
I’m using windows.

 REPLY

amit 
FEBRUARY 15, 2019 AT 4:48 AM

@Marcio You are welcome. Playing a wav �le is a completely


di�erent thing than parsing it. You can always use any existing
player app for playing a wav �le. Trying to make a player of
your own can be more challenging, especially you want to do
everything from scratch.

 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

Thank you. Actually I found I can use win32 functions like


waveOutOpen to play my struct, if someone has same
problem.

 REPLY

evgeny
APRIL 22, 2019 AT 4:08 AM

In your format description it says sample rate is 32 byte


integer. Shouldn`t it be 32 bit integer, or 4 byte instead?

 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

@Rpy Circuits the actual data is in data_in_channel

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

Although I know that this program is not designed to


actually take the audio data and play it, I would like to do
just that. How would I use data_in_channel to actually play
the audio? Let’s suppose that I have a function to store the
audio data and play it that takes these parameters:
(bu�er to store data in, format of audio data, actual audio
data, size of the audio data, frequency of the audio data)
Could I simply take all of the information from the WAV
header and input it in the function? Can I actually use the
bu�er data_in_channel to play the �le?
Thanks!
The actual documentation for the function is here:
https://www.openal.org/documentation
/OpenAL_Programmers_Guide.pdf
go to function alBu�erData!

 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.

There is a great article here:

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.
******

Only sound card manufacturers deal with the actual process of


creating sound, so the info about the software logic is a little
hard to get and a lot of device manufacturers keep their code
a proprietary secret. But for people like us who want to learn
the actual process of making sound, this is the holy grail.

 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

This site uses Akismet to reduce spam. Learn how your


comment data is processed.

Copyright © 2019 | WordPress Theme by MH Themes

27 of 27 23/12/19, 6:21 am

You might also like