Skip to content

Instantly share code, notes, and snippets.

@SharpCoder
Created March 12, 2019 17:42
Show Gist options
  • Select an option

  • Save SharpCoder/a9ee4d2f6c1a1c9b18c4ce87827f4ba8 to your computer and use it in GitHub Desktop.

Select an option

Save SharpCoder/a9ee4d2f6c1a1c9b18c4ce87827f4ba8 to your computer and use it in GitHub Desktop.
nodejs Wave File parser
const fs = require('fs');
class WavHeader {
constructor() {
this.sGroupId = "";
this.dwFileLength = 0;
this.sRiffType = "";
}
}
class FormatChunk {
constructor() {
this.sGroupId = "";
this.dwChunkSize = 0;
this.wFormatTag = 0;
this.wChannels = 0;
this.dwSamplesPerSec = 0;
this.dwAvgBytesPerSec = 0;
this.wBlockAlign = 0;
this.dwBitsPerSample = 0;
}
}
class DataChunk {
constructor() {
this.sGroupId = "";
this.dwChunkSize = 0;
this.sampleData = [];
}
}
class WavReader {
constructor(buffer) {
this.header = null;
this.format = null;
this.buffer = buffer;
this.pos = 0;
}
getByte() {
return this.buffer.readInt8(this.pos++);
}
getUInt() {
const result = this.buffer.readInt32LE(this.pos);
this.pos += 4;
return result;
}
getUShort() {
const result = this.buffer.readInt16LE(this.pos);
this.pos += 2;
return result;
}
getChar() {
return String.fromCharCode(this.getByte());
}
peekChar(offset) {
return String.fromCharCode(this.buffer.readInt8(this.pos + offset));
}
peekToken() {
return `${this.peekChar(0)}${this.peekChar(1)}${this.peekChar(2)}${this.peekChar(3)}`;
}
readToData() {
while (this.pos <= this.buffer.length) {
const groupId = this.peekToken();
if (groupId == "data") break;
else this.getByte();
}
}
getBlock() {
// read the first 4 bytes to understand the type
const groupId = `${this.getChar()}${this.getChar()}${this.getChar()}${this.getChar()}`;
let chunk = null;
switch(groupId) {
case "RIFF":
chunk = new WavHeader();
chunk.sGroupId = groupId;
chunk.dwFileLength = this.getUInt();
chunk.sRiffType = `${this.getChar()}${this.getChar()}${this.getChar()}${this.getChar()}`;
this.header = chunk;
break;
case "fmt ":
chunk = new FormatChunk();
chunk.sGroupId = groupId;
chunk.dwChunkSize = this.getUInt();
chunk.wFormatTag = this.getUShort();
chunk.wChannels = this.getUShort();
chunk.dwSamplesPerSec = this.getUInt();
chunk.dwAvgBytesPerSec = this.getUInt();
chunk.wBlockAlign = this.getUShort();
chunk.dwBitsPerSample = this.getUInt();
this.format = chunk;
break;
case "data":
chunk = new DataChunk();
chunk.sGroupId = groupId;
chunk.dwChunkSize = this.getUInt();
chunk.sampleData = this.buffer.slice(this.pos);
chunk.seconds = chunk.sampleData.length / (this.format.dwSamplesPerSec * this.format.wChannels * (this.format.dwChunkSize / 8));
break;
}
return chunk;
}
process() {
console.log(this.getBlock());
console.log(this.getBlock());
// Skip other blocks
this.readToData();
// Read the data block
console.log(this.getBlock());
}
}
const filePath = "/home/sharpcoder/AmzMusic/late-in-the-evening.wav";
const bytes = fs.readFileSync(filePath);
const reader = new WavReader(bytes);
reader.process();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment