Skip to content

Instantly share code, notes, and snippets.

@hasan-hasanov
Last active October 8, 2023 07:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hasan-hasanov/affe3d32129e5e80e3705ab1f691a622 to your computer and use it in GitHub Desktop.
Save hasan-hasanov/affe3d32129e5e80e3705ab1f691a622 to your computer and use it in GitHub Desktop.
Simple code snippet that parses most of .wav files. This is not full blown parser but at least it should give you an idea. I followed the specification from here: http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html
class Program
{
static void Main(string[] args)
{
using (var file = File.Open(args[0], FileMode.Open))
{
BinaryReader reader = new BinaryReader(file);
// Contains the letters "RIFF" in ASCII form.
string riffChunkId = Encoding.ASCII.GetString(reader.ReadBytes(4));
// Size of the rest of the chunk following this number.
int riffChunkSize = reader.ReadInt32();
// Contains the letters "WAVE"
string waveFormat = Encoding.ASCII.GetString(reader.ReadBytes(4));
// Check what is the following section
string nextSection = Encoding.ASCII.GetString(reader.ReadBytes(4));
if (nextSection == "JUNK")
{
// Size of the junk section.
int junkChunkSize = reader.ReadInt32();
// JUNK section values
var disposedJunkChunk = reader.ReadBytes(28);
// Assign next section
nextSection = Encoding.ASCII.GetString(reader.ReadBytes(4));
}
if (nextSection != "fmt ")
{
throw new NotImplementedException();
}
// Contains the letters "fmt"
string fmtChunkId = nextSection;
// Size of this section
int fmtChunkSize = reader.ReadInt32();
// PCM = 1, If it is other than 1 it means that the file is compressed.
short audioFormat = reader.ReadInt16();
// Mono = 1; Stereo = 2
short numberOfChannels = reader.ReadInt16();
// 8000, 44100, etc.
int samplesPerSecond = reader.ReadInt32();
// Byte Rate = SampleRate * NumChannels * BitsPerSample/8
int avgBytePerSecond = reader.ReadInt32();
// Block Align = NumChannels * BitsPerSample / 8
short blockAlign = reader.ReadInt16();
// 8 bits = 8, 16 bits = 16, etc.
short bitsPerSample = reader.ReadInt16();
if (fmtChunkSize == 18)
{
// size of the extension: 0
short extensionSize = reader.ReadInt16();
}
else if (fmtChunkSize == 40)
{
// size of the extension: 22
short extensionSize = reader.ReadInt16();
// Should be lower or equal to bitsPerSample
short validBitsPerSample = reader.ReadInt16();
// Speaker position mask
int channelMask = reader.ReadInt32();
// GUID(first two bytes are the data format code)
byte[] subFormat = reader.ReadBytes(16);
}
else if (fmtChunkSize != 16)
{
throw new Exception("Invalid .wav format!");
}
nextSection = Encoding.ASCII.GetString(reader.ReadBytes(4));
if (nextSection == "fact")
{
// Chunk size: 4
int factChunkSize = reader.ReadInt32();
// length of the sample
int sampleLength = reader.ReadInt32();
// Check what is the following section
nextSection = Encoding.ASCII.GetString(reader.ReadBytes(4));
}
else if (nextSection != "data")
{
throw new NotImplementedException();
}
// Contains the letters "data"
string dataChunkId = nextSection;
// This is the number of bytes in the data.
int dataChunkSize = reader.ReadInt32();
// This is the raw audio data
byte[] data = reader.ReadBytes(dataChunkSize);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment