Last active
August 3, 2024 16:49
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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