So far in this series, we’ve seen how we can convert an analog signal into a digital
PCM encoded stream.
We can transmit this data stream through digital transmission media or through devices, but
eventually you’d want to save the stream as a file in permanent storage.
I use the word stream here.
It’s really the perfect word to describe the underlying digital signal, as a stream
of data, a river of data, a torrent of data.
You can also think about the stream as a conveyer belt, delivering packets of data.
And what are these packets of data?
They’re simply the amplitude values of the audio samples encoded as binary numbers,if
we’ve chosen PCM encoding.
In essence, the computer interprets the PCM stream as a large collection of binary bits.
But just this data alone is not enough to do anything of value.
If you want to play the audio back, for example, all the computer has to go with is a series
of binary bits.
The computer doesn’t know at what rate the audio signal was sampled at, or the bit depth
that was used, or if the collection of bits are even audio or not.
We need some extra information that describes what this data stream is, that describes what
to do with it.
We can wrap that extra information along with the data stream in a nifty little self contained
box.
This is a container, and almost all digital media that’s stored on the computer is made
up of the data streams that contain the bulk of the media, and some additional information,
or metadata, that describes this media and both of these are wrapped into a single container.
A container is an abstract concept to what actually exists on a computer, a file format,
recognized with an extension.
There are loads of audio file formats out there.
Some are free to use and open source.
Some are proprietary and are only patented to be used within certain systems.
Some are licenced under terms and conditions of use.
The file format that you might choose to use would depend on the application that it’s
needed for, does it need to be compressed, is audio fidelity important, does the file
need be accessed across platforms or is it restricted to a certain operating system?
There are a flood of different file container formats out there, so let’s just focus a
single one.
The WAV file format, a very commonly used container for storing audio in it’s raw
uncompressed form, but not always.
The wav file format was developed by Microsoft for use within the Windows operating system.
But the specification is open to view and replicate, and currently is supported cross-platform
and can be used in any operating system.
Besides the usual information that should be provided such as sample rate, bit-depth,
number of channels and all of that, we can also embed other metadata in the container,
such as the name of the song, artist, genres, album name, copyrights, and other annotations.
Since every application reading a wav file needs to know exactly where to look for getting
information from within the container, and since every application creating a new wav
file needs to know exactly where to write information to, a specification documentation
is published and made available to the public.
Every application that supports the wav file format would need to adhere to these specifications.
Let’s take a quick peek at it.
So this is the original specification from 1991.
A whole 100 pages of it.
I’ve put links to this and whatever else I talk about in the video if you want to check
it out.
I’d wouldn’t be surprised if you didn’t.
But the internet is filled with concise, watered down versions of the original, and in a page
or 2, will describe exactly what you need to know about the wav format.
Over here, I’ll try to give you my graphical outline of it, further watered down, further
condensed.
My aim here isn’t to give you a precise overview and explanation of the specification,
but to rather give you an essence of what a file format would hold, how it would be
structured and the motivations for why they are designed the way they are.
Infact, a lot of file formats follow a similar approach, so you’d get a general overview
of other audio file formats as well.
Before you write any audio data into the wav file, you’d need to describe what the file
is even about.
You want to say hey, this is an audio file.
And hey, here’s how you read it.
So you add that basic information as a header to the file.
In the header of a wav file, the first thing that’s written is RIFF.
RIFF is Resource Interchange File Format, a generic file format template based on something
called chunks.
We’ll get to that in a bit.
RIFF tells the application that’s reading this wav file, what kind of file format template
it is.
The wave file format is basically derived from RIFF format, and both are made of units
of data called chunks.
Each chuck contains relevant data bundled together.
One chunk may contain all the audio data, another one could contain all the data that
describes the audio format, another could contain playlist and identification information.
Each chunk has an ID associated with it, and a length field which holds the size of the
entire chunk in bytes.
Right, we’re getting ahead of ourselves.
So the text string RIFF is the first item to be written.
Obviously we are writing to a binary file, so everything is written in binary 0’s and
1’s.
So the 4 characters of RIFF can be written into 4 bytes.
Each byte contains 8 bits, so each character can be represented in a unique combination
of 8 bits.
We can see this in action.
Here’s a wav file saved on my computer, let me open this on a text editor.
This is a bit silly, because obviously a text editor doesn’t know what to do with a wave
file.
All it’ll do is try to open this binary file and try to interpret it as text.
And hence you get a load of garbled nonsensical data.
But you can still see little items of text pop out, like RIFF and Wave, fmt and data.
But all the rest of it, well, you can just say it’s unparsable, these are supposed
to be audio sample values represented as binary, and not text.
After the first item, you write the size of the entire file.
Obviously, we don’t know the size of the file yet.
So we ignore this for now, and remember to come back to this after filling up everything
else.
You need one more header item, a text string called WAVE.
All of this is mandatory, the specification dictates it.
The rest of the items in this file are all different chunks, the chunks we described
earlier.
Since there is an ID and a length associated with each chunk, the application reading this
file can ignore chunks that it doesn’t need and jump to chunks that it’s interested
in.
One important chunk is the format chunk, or fmt.
The format chunk contains information about how the waveform data is stored and how it
should be played back including the type of compression used, number of channels, sample
rate, bits per sample and other relevant attributes.
Most of these are self explanatory, but the interesting attribute is compression.
As i noted earlier, a wav file is traditionally used to store uncompressed linear PCM audio
data.
In almost all cases where you may use the wav file, this is true.
Assigning 1 as a binary word to the compression field, will mean that no compression is used,
and the coding format followed is Pulse Code Modulation, or PCM.
Here’s a list of other possible compression schemes that can be used with wav files.
In this list, some of them are uncompressed, some are compressed but lossless, and some
more are compressed and lossy.
For example, the MPEG compression scheme accepts audio data encoded with a specific lossy compression
algorithm, used in MP3 for instance.
Although you can put virtually any type of encoded audio in the file, the application
reading the wav file may not choose to support it, and can reject the file if it doesn’t
know what to do with it.
You’d just end up getting an error that the file can’t be played.
The application will need to know how to decode this compressed audio into something that
it recognizes, like bitstream PCM.
If it doesn’t know how to decode the compression, it won’t be able to playback the underlying
audio.
This is completely fair.
The application reading the wav file doesn’t need to know all the compression algorithms
out there, and it just can’t.
There are hundreds, and they keep evolving over time.
So what the application would rather do in this case is have a bunch of little programs
that can be linked with it.
These programs are designed to decode a specific type of encoding algorithm, and these programs
are called codecs.
A codec is a cool made up term for a portmanteau of coder-decoder.
So if your application doesn’t know how to decode the audio, you can just download
a codec for the compression scheme used.
A little program that can be linked with the application which helps decode the compressed
audio.
In the case of MPEG compression, you’d link the LAME codec to the application.
Simple.
I hope that clearly differentiates between a codec and a container file format.
I know a common point of confusion among people is when to use what in a sentence.
And this confusion is sometimes inflamed when both have the same names.
For example, FLAC is a popular container file format for storing audio.
FLAC is also the name of the codec used for lossless audio compression which is in turn
used within the FLAC container.
You see what I mean.
It can get a bit tricky.
Simply put, a codec is a method for encoding and decoding data, in this case audio.
In comparison, a container is what holds the grouping of compressed audio as defined by
the codec.
Let’s just say that we don’t use any compression, and the audio data is uncompressed PCM.
This audio data in its entirety is stored within a chuck called data.
This will by far be the largest chunk in the file, since this will contain the bulk of
the audio data.
If it’s a mono track, meaning if the number of channels is 1, the audio samples are arranged
serially, one after another.
If it’s a stereo track with 2 channels, the audio samples are interleaved.
Left and right audio samples are alternatively written to the file.
We discussed this in the previous video where we talk about time division multiplexing.
That’s really all there is to containers.
Like I mentioned, we can have more chunks if we choose to add more metadata.
Some of the other chunks that are supported with the wav file format are shown here.
Lastly, I want to make one modification to this illustration.
Since the wav file is composed of just chunks, the header section can actually be treated
as one large overarching chunk, which internally contains a bunch of sub-chucks that we just
talked about.
Chunks are a great way for organizing data within a container.
Since each chunk has a specific purpose, and since each chunk also advertises how large
it is, applications can quickly jump to different sections of the file by reading just the size
information and calculating the position that it would need to seek to, to find the next
chunk.
I hope that provided a simple and blunt overview of containers and file formats through the
scrutiny of the wave file format.
The internet is a vast place, and so are people’s preferences.
Due to these preferences, some containers have grown in popularity to a point that they
are de-facto standards now.
Feel free to explore the different ones out there.
Just because some aren’t popular, doesn’t mean they aren’t good.