From 26b1c0e040e017ad469c264e492fec7c2efc4e03 Mon Sep 17 00:00:00 2001 From: Vladimir Mikhaylov Date: Fri, 29 Jan 2021 23:49:02 +0300 Subject: [PATCH 1/2] fix values types && added typescript --- index.d.ts | 46 ++++++++++++++++++++++++++++++++++++++++++++++ test.ts | 8 ++++++++ wav-file-info.js | 34 +++++++++++++++++----------------- 3 files changed, 71 insertions(+), 17 deletions(-) create mode 100644 index.d.ts create mode 100644 test.ts diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 0000000..bf29884 --- /dev/null +++ b/index.d.ts @@ -0,0 +1,46 @@ +export const infoByFilename: ( + fileName: string, + cb: + | ((err: IInfoByFilenameError | Error, data: null | undefined) => any) + | ((err: null | undefined, data: IInfoByFilenameData) => any) +) => void; + +export interface IInfoByFilenameHeader { + /* Marks the file as a riff file. Characters are each 1 byte long. */ + riff_head: string; + /** Size of the overall file - 8 bytes, in bytes (32-bit integer). Typically, you’d fill this in after creation. */ + chunk_size: number; + /** File Type Header. For our purposes, it always equals “WAVE”. */ + wave_identifier: string; + /** Format chunk marker. Includes trailing null */ + fmt_identifier: string; + /** Length of format data as listed above */ + sub_chunk_size: number; + /** Type of format (1 is PCM) - 2 byte integer */ + audio_format: number; + /** Number of Channels - 2 byte integer */ + num_channels: number; + /** Sample Rate - 32 byte integer. Common values are 44100 (CD), 48000 (DAT). Sample Rate = Number of Samples per second, or Hertz. */ + sample_rate: number; + /** (Sample Rate * BitsPerSample * Channels) / 8. */ + byte_rate: number; + /** (BitsPerSample * Channels) / 8.1 - 8 bit mono2 - 8 bit stereo/16 bit mono4 - 16 bit stereo */ + block_align: number; + /** Bits per sample */ + bits_per_sample: number; + /** “data” chunk header. Marks the beginning of the data section. */ + data_identifier: string; + /** Size of the data section. */ + sub_chunk2_size: number; +} +export interface IInfoByFilenameError { + error: true, + invalid_reasons: Array; + header: IInfoByFilenameHeader; + stats: any; +} +export interface IInfoByFilenameData { + header: IInfoByFilenameHeader; + stats: any; + duration: number; +} \ No newline at end of file diff --git a/test.ts b/test.ts new file mode 100644 index 0000000..a9a8e62 --- /dev/null +++ b/test.ts @@ -0,0 +1,8 @@ +import { infoByFilename } from './' + +infoByFilename('./test.wav', (err, data) => { + if (err) { + return void console.error(err.header); + } + return void console.log(data); +}); \ No newline at end of file diff --git a/wav-file-info.js b/wav-file-info.js index a4968e3..55895b2 100644 --- a/wav-file-info.js +++ b/wav-file-info.js @@ -1,10 +1,11 @@ // Hi Welcome to WFI by David Jones / RackFX, LLC var fs = require('fs'); var wfi = {} +var headerSize = 44; wfi.infoByFilename = function(filename, cb){ var stats = fs.statSync(filename) - var buffer = new Buffer(40); // first 40 bytes are RIFF header + var buffer = Buffer.alloc(headerSize); // first 44 bytes are RIFF header fs.open(filename, 'r', function(err, fd) { if(err) return cb(err); // error probably TODO:check this! @@ -13,26 +14,25 @@ wfi.infoByFilename = function(filename, cb){ var read_result = {} - // this a list of sequenced bytes in the 40 byte header. This builds the read_result object. + // this a list of sequenced bytes in the 44 byte header. This builds the read_result object. // Property name / Data type / Length var reads = [ ['riff_head', 'string', 4], - ['chunk_size','uinteger', 4], + ['chunk_size','uint32', 4], ['wave_identifier', 'string', 4], ['fmt_identifier', 'string', 4], - ['subchunk_size','integer',4], - ['audio_format','integer',2], - ['num_channels','integer',2], - ['sample_rate','uinteger',4], - ['byte_rate','integer',4], - ['block_align','integer',2], - ['bits_per_sample','integer',2], - //['uhm','integer',2], + ['sub_chunk_size','uint32', 4], + ['audio_format','uint16', 2], + ['num_channels','uint16', 2], + ['sample_rate','uint32', 4], + ['byte_rate','uint32', 4], + ['block_align','uint16', 2], + ['bits_per_sample','uint16', 2], ['data_identifier','string', 4], - //['sub_chunk2_size', 'integer', 4], + ['sub_chunk2_size', 'uint32', 4], ] - fs.read(fd, buffer, 0, 40, 0, function(err, num) { + fs.read(fd, buffer, 0, headerSize, 0, function(err, num) { var i=0; var pointer = 0; @@ -44,14 +44,14 @@ wfi.infoByFilename = function(filename, cb){ read_result[read[0]] = buffer.toString('ascii', pointer , pointer + read[2]); pointer = pointer + read[2]; // pointer = pointer plus # bytes } - else if(read[1]=='integer'){ + else if(read[1]=='uint16'){ - read_result[read[0]] = buffer.readUInt16LE(pointer, read[2]) + read_result[read[0]] = buffer.readUInt16LE(pointer) pointer = pointer + read[2]; } - else if(read[1]=='uinteger'){ + else if(read[1]=='uint32'){ - read_result[read[0]] = buffer.readInt32LE(pointer, read[2]) + read_result[read[0]] = buffer.readUInt32LE(pointer) pointer = pointer + read[2]; } if(i < reads.length) { return read_wav()} From ca064a331aaae7cbfe13921ef574fa2d4c7051e8 Mon Sep 17 00:00:00 2001 From: Vladimir Mikhaylov Date: Sat, 30 Jan 2021 00:02:24 +0300 Subject: [PATCH 2/2] some refactoring --- wav-file-info.js | 161 +++++++++++++++++++++++------------------------ 1 file changed, 78 insertions(+), 83 deletions(-) diff --git a/wav-file-info.js b/wav-file-info.js index 55895b2..0f93754 100644 --- a/wav-file-info.js +++ b/wav-file-info.js @@ -3,99 +3,94 @@ var fs = require('fs'); var wfi = {} var headerSize = 44; -wfi.infoByFilename = function(filename, cb){ - var stats = fs.statSync(filename) - var buffer = Buffer.alloc(headerSize); // first 44 bytes are RIFF header - fs.open(filename, 'r', function(err, fd) { - if(err) return cb(err); // error probably TODO:check this! +wfi.infoByFilename = function (filename, cb) { + var stats = fs.statSync(filename) + var buffer = Buffer.alloc(headerSize); // first 44 bytes are RIFF header + fs.open(filename, 'r', function (err, fd) { + if (err) return cb(err); // error probably TODO:check this! - // ex error - - // { [Error: ENOENT: no such file or directory, open './test.wav'] errno: -2, code: 'ENOENT', syscall: 'open', path: './test.wav' } - var read_result = {} + // ex error - + // { [Error: ENOENT: no such file or directory, open './test.wav'] errno: -2, code: 'ENOENT', syscall: 'open', path: './test.wav' } + var read_result = {} + // this a list of sequenced bytes in the 44 byte header. This builds the read_result object. + // Property name / Data type / Length + var props = [ + ['riff_head', 'string', 4], + ['chunk_size', 'uint32', 4], + ['wave_identifier', 'string', 4], + ['fmt_identifier', 'string', 4], + ['sub_chunk_size', 'uint32', 4], + ['audio_format', 'uint16', 2], + ['num_channels', 'uint16', 2], + ['sample_rate', 'uint32', 4], + ['byte_rate', 'uint32', 4], + ['block_align', 'uint16', 2], + ['bits_per_sample', 'uint16', 2], + ['data_identifier', 'string', 4], + ['sub_chunk2_size', 'uint32', 4], - // this a list of sequenced bytes in the 44 byte header. This builds the read_result object. - // Property name / Data type / Length - var reads = [ - ['riff_head', 'string', 4], - ['chunk_size','uint32', 4], - ['wave_identifier', 'string', 4], - ['fmt_identifier', 'string', 4], - ['sub_chunk_size','uint32', 4], - ['audio_format','uint16', 2], - ['num_channels','uint16', 2], - ['sample_rate','uint32', 4], - ['byte_rate','uint32', 4], - ['block_align','uint16', 2], - ['bits_per_sample','uint16', 2], - ['data_identifier','string', 4], - ['sub_chunk2_size', 'uint32', 4], + ]; + fs.read(fd, buffer, 0, headerSize, 0, function (err, num) { + var pointer = 0; - ] - fs.read(fd, buffer, 0, headerSize, 0, function(err, num) { + try { + for (var i = 0; i < props.length; i++) { + var prop = props[i]; + var name = prop[0]; + var type = prop[1]; + var size = prop[2]; - var i=0; - var pointer = 0; - function read_wav(){ - var read = reads[i]; + if (type === 'uint16') { + read_result[name] = buffer.readUInt16LE(pointer) + } else if (type === 'uint32') { + read_result[name] = buffer.readUInt32LE(pointer) + } else { + read_result[name] = buffer.toString('ascii', pointer, pointer + size); + } + pointer += size; + } + } catch (e) { + return void cb(e); + } - i++; - if(read[1]=='string'){ - read_result[read[0]] = buffer.toString('ascii', pointer , pointer + read[2]); - pointer = pointer + read[2]; // pointer = pointer plus # bytes - } - else if(read[1]=='uint16'){ - - read_result[read[0]] = buffer.readUInt16LE(pointer) - pointer = pointer + read[2]; - } - else if(read[1]=='uint32'){ + fs.close(fd, post_process); + }); - read_result[read[0]] = buffer.readUInt32LE(pointer) - pointer = pointer + read[2]; - } - if(i < reads.length) { return read_wav()} - else { return fs.close(fd, post_process); } + function post_process() { + var error = false; + var invalid_reasons = [] - } - //console.log(i) - read_wav(); - }); // end fs.read + if (read_result.riff_head != "RIFF") invalid_reasons.push("Expected \"RIFF\" string at 0") + if (read_result.wave_identifier != "WAVE") invalid_reasons.push("Expected \"WAVE\" string at 4") + if (read_result.fmt_identifier != "fmt ") invalid_reasons.push("Expected \"fmt \" string at 8") + if ( + (read_result.audio_format != 1) && // Wav PCM + (read_result.audio_format != 65534) && // Extensible PCM + (read_result.audio_format != 2) && // Wav + (read_result.audio_format != 6) && // Wav ALAW + (read_result.audio_format != 7) && // Wav MULAW + (read_result.audio_format != 22127) && // Vorbis ?? (issue #11) + (read_result.audio_format != 3)) // Wav + invalid_reasons.push("Unknown format: " + read_result.audio_format) + if ((read_result.chunk_size + 8) !== stats.size) invalid_reasons.push("chunk_size does not match file size") + //if ((read_result.data_identifier) != "data") invalid_reasons.push("Expected data identifier at the end of the header") - function post_process(){ - var error = false; - var invalid_reasons = [] + if (invalid_reasons.length > 0) error = true; - if (read_result.riff_head != "RIFF") invalid_reasons.push("Expected \"RIFF\" string at 0" ) - if (read_result.wave_identifier != "WAVE") invalid_reasons.push("Expected \"WAVE\" string at 4") - if (read_result.fmt_identifier != "fmt ") invalid_reasons.push("Expected \"fmt \" string at 8") - if ( - (read_result.audio_format != 1) && // Wav PCM - (read_result.audio_format != 65534) && // Extensible PCM - (read_result.audio_format != 2) && // Wav - (read_result.audio_format != 6) && // Wav ALAW - (read_result.audio_format != 7) && // Wav MULAW - (read_result.audio_format != 22127) && // Vorbis ?? (issue #11) - (read_result.audio_format != 3)) // Wav - invalid_reasons.push("Unknown format: "+read_result.audio_format) - if ((read_result.chunk_size + 8) !== stats.size) invalid_reasons.push("chunk_size does not match file size") - //if ((read_result.data_identifier) != "data") invalid_reasons.push("Expected data identifier at the end of the header") + if (error) return cb({ + error: true, + invalid_reasons: invalid_reasons, + header: read_result, + stats: stats + }); - if (invalid_reasons.length > 0) error = true; - - if (error) return cb({ - error : true, - invalid_reasons: invalid_reasons, - header: read_result, - stats: stats - }); - - cb(null, { - header: read_result, - stats: stats, - duration: ((read_result.chunk_size) / (read_result.sample_rate * read_result.num_channels * (read_result.bits_per_sample / 8))) - }); - } - }); + cb(null, { + header: read_result, + stats: stats, + duration: ((read_result.chunk_size) / (read_result.sample_rate * read_result.num_channels * (read_result.bits_per_sample / 8))) + }); + } + }); } module.exports = wfi;