forked from rackfx/Node-WAV-File-Info
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwav-file-info.js
104 lines (89 loc) · 3.56 KB
/
wav-file-info.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
// Hi Welcome to WFI by David Jones / RackFX, LLC
var fs = require('fs');
var wfi = {}
wfi.infoByFilename = function(filename, cb){
var stats = fs.statSync(filename);
var HEADER_SIZE = 764;
var buffer = new Buffer(HEADER_SIZE); // first 40 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 = {}
// this a list of sequenced bytes in the 40 byte header. This builds the read_result object.
// Property name / Data type / Length
var reads = [
['riff_head', 'string', 4],
['chunk_size','uinteger', 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],
['data_identifier','string', 4],
//['sub_chunk2_size', 'integer', 4],
]
fs.read(fd, buffer, 0, HEADER_SIZE, 0, function(err, num) {
var i=0;
var pointer = 0;
function read_wav(){
var read = reads[i];
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]=='integer'){
read_result[read[0]] = buffer.readUInt16LE(pointer, read[2])
pointer = pointer + read[2];
}
else if(read[1]=='uinteger'){
read_result[read[0]] = buffer.readInt32LE(pointer, read[2])
pointer = pointer + read[2];
}
// hack for protools WAV files - need to seek ahead
if (read[0] === 'fmt_identifier' && read_result[read[0]] === 'JUNK') {
i--;
// hard-coding the location we need
pointer = 722;
}
if(i < reads.length) { return read_wav()}
else {
// make sure to close our file
fs.close(fd);
return post_process();
}
}
//console.log(i)
read_wav();
}); // end fs.read
function post_process(){
var error = false;
var invalid_reasons = []
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) && (read_result.audio_format != 3)) invalid_reasons.push("Unknwon 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 (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)))
});
}
});
}
module.exports = wfi;