Comparing version 0.0.2 to 0.0.3
147
index.js
/*! | ||
* Wavefile | ||
* Copyright (c) 2017 Rafael da Silva Rocha. | ||
* Read wave files with 4, 8, 16, 24, 32 PCM, 32 IEEE & 64-bit data. | ||
* Copyright (c) 2017 Rafael da Silva Rocha. MIT License. | ||
* https://github.com/rochars/wavefile | ||
* | ||
*/ | ||
const numBytes = require("byte-data"); | ||
const byteData = require("byte-data"); | ||
const unsupportedFormatError = "Not a supported format."; | ||
const noWAVEChunkError = "Could not find the 'WAVE' chunk"; | ||
const noFmtChunkError = "Could not find the 'fmt ' chunk"; | ||
const noDataChunkError = "Could not find the 'data' chunk"; | ||
/*! | ||
* A wave file with all its fields. | ||
/* | ||
* A wave file. | ||
* Objects can be created by passing a Uint8Array | ||
* of bytes representing a wave file. | ||
* | ||
* representing a wave file. | ||
*/ | ||
@@ -21,31 +24,35 @@ class Wavefile { | ||
/** | ||
* @param {Uint8Array} bytes an array representing the wave file. | ||
* | ||
* @param {Uint8Array} wavBytes an array representing the wave file. | ||
*/ | ||
constructor(wavBytes) { | ||
// "RIFF", "RF64", ... | ||
this.chunkId = ""; | ||
/** @type {string} */ | ||
this.chunkId = ""; // "RIFF" | ||
/** @type {number} */ | ||
this.chunkSize = 0; | ||
this.subChunk1Id = ""; | ||
// "fmt "" | ||
this.format = ""; | ||
/** @type {string} */ | ||
this.subChunk1Id = ""; // "WAVE" | ||
/** @type {string} */ | ||
this.format = ""; // "fmt " | ||
/** @type {number} */ | ||
this.subChunk1Size = 0; | ||
/** @type {number} */ | ||
this.audioFormat = 0; | ||
/** @type {number} */ | ||
this.numChannels = 0; | ||
/** @type {number} */ | ||
this.sampleRate = 0; | ||
/** @type {number} */ | ||
this.byteRate = 0; | ||
/** @type {number} */ | ||
this.blockAlign = 0; | ||
/** @type {number} */ | ||
this.bitsPerSample = 0; | ||
// "fact" | ||
// ... | ||
// "data" | ||
this.subChunk2Id = ""; | ||
/** @type {string} */ | ||
this.subChunk2Id = ""; // "data" | ||
/** @type {number} */ | ||
this.subChunk2Size = 0; | ||
/** @type {!Array<number>} */ | ||
this.samples = []; | ||
/** @type {string} */ | ||
this.bitDepth_ = ""; | ||
if(wavBytes) { | ||
@@ -59,14 +66,13 @@ this.readRIFFChunk_(wavBytes); | ||
/** | ||
* Read the RIFF/RF64 chunk a wave file. | ||
* Read the RIFF chunk a wave file. | ||
* @param {Uint8Array} bytes an array representing the wave file. | ||
* @throws {Error} If no "RIFF" chunk is found. | ||
*/ | ||
readRIFFChunk_(bytes) { | ||
this.chunkId = numBytes.stringFromBytes(bytes.slice(0, 4)); | ||
this.chunkId = byteData.stringFromBytes(bytes.slice(0, 4)); | ||
if (this.chunkId != "RIFF") { | ||
throw Error(unsupportedFormatError); | ||
} | ||
this.chunkSize = numBytes.intFrom4Bytes( | ||
this.chunkSize = byteData.intFrom4Bytes( | ||
bytes.slice(4, 8))[0]; | ||
@@ -77,11 +83,11 @@ } | ||
* Read the WAVE chunk of a wave file. | ||
* @param {Object} wav An object with the wav file data. | ||
* @param {Uint8Array} bytes an array representing the wave file. | ||
* @throws {Error} If no "WAVE" chunk is found. | ||
*/ | ||
readWAVEChunk_(bytes) { | ||
let start = this.findChunk_(bytes, "WAVE"); | ||
if (start == 0) { | ||
throw Error("Could not find the 'WAVE' chunk"); | ||
let start = byteData.findString(bytes, "WAVE"); | ||
if (start === -1) { | ||
throw Error(noWAVEChunkError); | ||
} | ||
this.subChunk1Id = numBytes.stringFromBytes( | ||
this.subChunk1Id = byteData.stringFromBytes( | ||
bytes.slice(start, start + 4)); | ||
@@ -93,23 +99,24 @@ } | ||
* @param {Uint8Array} bytes an array representing the wave file. | ||
* @throws {Error} If no "fmt " chunk is found. | ||
*/ | ||
readFmtChunk_(bytes) { | ||
let start = this.findChunk_(bytes, "fmt "); | ||
if (start == 0) { | ||
throw Error("Could not find the 'fmt ' chunk"); | ||
let start = byteData.findString(bytes, "fmt "); | ||
if (start === -1) { | ||
throw Error(noFmtChunkError); | ||
} | ||
this.format = numBytes.stringFromBytes( | ||
this.format = byteData.stringFromBytes( | ||
bytes.slice(start, start + 4)); | ||
this.subChunk1Size = numBytes.uIntFrom4Bytes( | ||
this.subChunk1Size = byteData.uIntFrom4Bytes( | ||
bytes.slice(start + 4, start + 8))[0]; | ||
this.audioFormat = numBytes.intFrom2Bytes( | ||
this.audioFormat = byteData.intFrom2Bytes( | ||
bytes.slice(start + 8, start + 10))[0]; | ||
this.numChannels = numBytes.uIntFrom2Bytes( | ||
this.numChannels = byteData.uIntFrom2Bytes( | ||
bytes.slice(start + 10, start + 12))[0]; | ||
this.sampleRate = numBytes.uIntFrom4Bytes( | ||
this.sampleRate = byteData.uIntFrom4Bytes( | ||
bytes.slice(start + 12, start + 16))[0]; | ||
this.byteRate = numBytes.uIntFrom4Bytes( | ||
this.byteRate = byteData.uIntFrom4Bytes( | ||
bytes.slice(start + 16, start + 20))[0]; | ||
this.blockAlign = numBytes.uIntFrom2Bytes( | ||
this.blockAlign = byteData.uIntFrom2Bytes( | ||
bytes.slice(start + 20, start + 22))[0]; | ||
this.bitsPerSample = numBytes.uIntFrom2Bytes( | ||
this.bitsPerSample = byteData.uIntFrom2Bytes( | ||
bytes.slice(start + 22, start + 24))[0]; | ||
@@ -128,20 +135,30 @@ // The bitDepth_ is used internally to determine | ||
* @param {Uint8Array} bytes an array representing the wave file. | ||
* @throws {Error} If no "data" chunk is found. | ||
*/ | ||
readDataChunk_(bytes) { | ||
let start = this.findChunk_(bytes, "data"); | ||
if (start == 0) { | ||
throw Error("Could not find the 'data' chunk"); | ||
let start = byteData.findString(bytes, "data"); | ||
if (start === -1) { | ||
throw Error(noDataChunkError); | ||
} | ||
this.subChunk2Id = numBytes.stringFromBytes( | ||
this.subChunk2Id = byteData.stringFromBytes( | ||
bytes.slice(start, start + 4)); | ||
this.subChunk2Size = numBytes.intFrom4Bytes( | ||
this.subChunk2Size = byteData.intFrom4Bytes( | ||
bytes.slice(start + 4, start + 8))[0]; | ||
this.readSamples_(bytes, start); | ||
} | ||
/** | ||
* Find and return the start offset of the data chunk on a wave file. | ||
* @param {Uint8Array} bytes Array of bytes representing the wave file. | ||
* @param {number} start The offset to start reading. | ||
*/ | ||
readSamples_(bytes, start) { | ||
let readingFunctions_ = { | ||
'4': numBytes.intFrom1Byte, | ||
'8': numBytes.uIntFrom1Byte, | ||
'16': numBytes.intFrom2Bytes, | ||
'24': numBytes.intFrom3Bytes, | ||
'32': numBytes.intFrom4Bytes, | ||
'32f': numBytes.floatFrom4Bytes, | ||
'64' : numBytes.floatFrom8Bytes | ||
'4': byteData.intFrom1Byte, | ||
'8': byteData.uIntFrom1Byte, | ||
'16': byteData.intFrom2Bytes, | ||
'24': byteData.intFrom3Bytes, | ||
'32': byteData.intFrom4Bytes, | ||
'32f': byteData.floatFrom4Bytes, | ||
'64' : byteData.floatFrom8Bytes | ||
}; | ||
@@ -155,22 +172,4 @@ this.samples = readingFunctions_[this.bitDepth_]( | ||
} | ||
/** | ||
* Find and return the start offset of the data chunk on a wave file. | ||
* @param {Uint8Array} bytes Array of bytes representing the wave file. | ||
* @return {number} The start offset of the data chunk. | ||
* @throws {Error} If no index is found. | ||
*/ | ||
findChunk_(bytes, chunkName) { | ||
let found = ""; | ||
for (let i = 0; i < bytes.length; i++) { | ||
//console.log(numBytes.stringFromBytes(bytes.slice(i, i + 4)) ) | ||
found = numBytes.stringFromBytes(bytes.slice(i, i + 4)); | ||
if (found == chunkName) { | ||
return i; | ||
} | ||
} | ||
} | ||
} | ||
module.exports.Wavefile = Wavefile; |
{ | ||
"name": "wavefile", | ||
"version": "0.0.2", | ||
"description": "Wave file.", | ||
"version": "0.0.3", | ||
"description": "Read wave files with 4, 8, 16, 24, 32 PCM, 32 IEEE & 64-bit data.", | ||
"homepage": "https://github.com/rochars/wavefile", | ||
"author": "Rafael da Silva Rocha <rocha.rafaelsilva@gmail.com>", | ||
@@ -10,12 +11,29 @@ "license": "MIT", | ||
"wave", | ||
"file" | ||
"file", | ||
"read", | ||
"browser", | ||
"4-bit", | ||
"8-bit", | ||
"16-bit", | ||
"24-bit", | ||
"32-bit", | ||
"64-bit", | ||
"PCM", | ||
"IEEE", | ||
"IMA ADPCM" | ||
], | ||
"repository": { | ||
"type": "git", | ||
"url": "git://github.com/rochars/wavefile.git" | ||
}, | ||
"scripts": { | ||
"lint": "jshint index.js", | ||
"lint": "jshint index.js && jshint test", | ||
"test": "nyc ./node_modules/mocha/bin/_mocha", | ||
"coverage": "nyc report --reporter=lcov > coverage.lcov && codecov", | ||
"bundle": "webpack", | ||
"compile": "google-closure-compiler-js dist/wavefile.js > dist/wavefile-min.js --compilationLevel ADVANCED", | ||
"compile": "google-closure-compiler-js dist/wavefile.js > dist/wavefile-min.js --useTypesForOptimization", | ||
"doc": "./node_modules/.bin/jsdoc index.js -d docs", | ||
"build": "npm run lint && npm test && npm run bundle && npm run compile && npm run doc" | ||
"qa": "npm run lint && npm test", | ||
"pack": "npm run bundle && npm run compile && npm run doc", | ||
"build": "npm run qa && npm run pack" | ||
}, | ||
@@ -34,6 +52,6 @@ "devDependencies": { | ||
}, | ||
"main": "index.js", | ||
"dependencies": { | ||
"byte-data": "^0.1.2" | ||
} | ||
"byte-data": "0.1.3" | ||
}, | ||
"main": "index.js" | ||
} |
# wavefile | ||
Wave files. | ||
Read wave files with 4, 8, 16, 24, 32 PCM, 32 IEEE & 64-bit data. | ||
Copyright (c) 2017 Rafael da Silva Rocha. | ||
## Install | ||
@@ -12,3 +13,2 @@ ``` | ||
## Use | ||
```javascript | ||
@@ -19,2 +19,3 @@ let fs = require("fs"); | ||
let wavBytes = fs.readFileSync("file.wav"); | ||
let wav = new wavefile.Wavefile(wavBytes); | ||
@@ -25,22 +26,48 @@ | ||
console.log(wav.subChunk1Id); | ||
``` | ||
### The properties | ||
```javascript | ||
console.log(wav.chunkId); | ||
console.log(wav.chunkSize); | ||
console.log(wav.subChunk1Id); | ||
// "fmt "" | ||
wav.format; | ||
wav.subChunk1Size; | ||
wav.audioFormat; | ||
wav.numChannels; | ||
wav.sampleRate; | ||
wav.byteRate; | ||
wav.blockAlign; | ||
wav.bitsPerSample; | ||
console.log(wav.format); | ||
console.log(wav.subChunk1Size); | ||
console.log(wav.audioFormat); | ||
console.log(wav.numChannels); | ||
console.log(wav.sampleRate); | ||
console.log(wav.byteRate); | ||
console.log(wav.blockAlign); | ||
console.log(wav.bitsPerSample); | ||
// "data" | ||
wav.subChunk2Id; | ||
wav.subChunk2Size; | ||
console.log(wav.subChunk2Id); | ||
console.log(wav.subChunk2Size); | ||
// array of int or float | ||
wav.samples; | ||
console.log(wav.samples.length); | ||
``` | ||
### The samples | ||
The samples range: | ||
- 0 to 255 for 8-bit | ||
- -32768 to 32767 for 16-bit | ||
- -8388608 to 8388607 for 24-bit | ||
- -2147483648 to 2147483647 for 32-bit PCM | ||
- -1.0 to 1.0 for 32-bit IEEE | ||
- -1.0 to 1.0 for 64-bit | ||
4-bit is IMA ADPCM. You must use a codec to decode the samples before working with them. | ||
## Future | ||
- Support for RF64 | ||
- Support for RIFX | ||
## LICENSE | ||
@@ -47,0 +74,0 @@ Copyright (c) 2017 Rafael da Silva Rocha. |
@@ -21,3 +21,4 @@ /*! | ||
}); | ||
it("subChunk1Id in a 32-bit IEEE 16kHz mono bwf wave file should be 'WAVE'", | ||
it("subChunk1Id in a 32-bit IEEE 16kHz mono bwf wave file should be " + | ||
"'WAVE'", | ||
function() { | ||
@@ -34,3 +35,4 @@ assert.equal(wav.subChunk1Id, "WAVE"); | ||
}); | ||
it("audioFormat in a 32-bit IEEE 16kHz mono bwf wave file should be 3 (IEEE)", | ||
it("audioFormat in a 32-bit IEEE 16kHz mono bwf wave file should be " + | ||
"3 (IEEE)", | ||
function() { | ||
@@ -59,13 +61,14 @@ assert.equal(wav.audioFormat, 3); | ||
}); | ||
it("subChunk2Id in a 32-bit IEEE 16kHz mono bwf wave file should be 'data'", | ||
it("subChunk2Id in a 32-bit IEEE 16kHz mono bwf wave file should " + | ||
"be 'data'", | ||
function() { | ||
assert.equal(wav.subChunk2Id, 'data'); | ||
}); | ||
it("subChunk2Size in a 32-bit IEEE 16kHz mono bwf wave file with contents " + | ||
"should be > 0", | ||
it("subChunk2Size in a 32-bit IEEE 16kHz mono bwf wave file with " + | ||
"contents should be > 0", | ||
function() { | ||
assert.ok(wav.subChunk2Size > 0); | ||
}); | ||
it("samples.length in a 32-bit IEEE 16kHz mono bwf wave file with contents " + | ||
"should be > 0", | ||
it("samples.length in a 32-bit IEEE 16kHz mono bwf wave file with " + | ||
"contents should be > 0", | ||
function() { | ||
@@ -72,0 +75,0 @@ assert.ok(wav.samples.length > 0); |
@@ -54,3 +54,4 @@ /*! | ||
}); | ||
it("subChunk2Size in a 4-bit 8kHz mono wave file with contents should be > 0", | ||
it("subChunk2Size in a 4-bit 8kHz mono wave file with contents " + | ||
"should be > 0", | ||
function() { | ||
@@ -57,0 +58,0 @@ assert.ok(wav.subChunk2Size > 0); |
@@ -66,3 +66,3 @@ /*! | ||
}); | ||
it("samples.length in a 64-bit 48kHz monowave file with contents " + | ||
it("samples.length in a 64-bit 48kHz mono wave file with contents " + | ||
"should be > 0", | ||
@@ -69,0 +69,0 @@ function() { |
@@ -61,3 +61,3 @@ /*! | ||
}); | ||
it("subChunk2Size in a 8-bit 16kHz mono bwf wave file with contents should" + | ||
it("subChunk2Size in a 8-bit 16kHz mono bwf wave file with contents " + | ||
"should be > 0", | ||
@@ -64,0 +64,0 @@ function() { |
@@ -6,5 +6,2 @@ const fs = require('fs'); | ||
output: { | ||
// This is the file Google Closure Compiler will use | ||
// to create dist/dist-min.js. If you change the filename | ||
// here, be sure to change in package.json under "compile" | ||
filename: './dist/wavefile.js' | ||
@@ -19,7 +16,6 @@ }, | ||
multiple: [ | ||
// to | ||
{ | ||
search: 'module.exports.Wavefile', | ||
replace: "window['Wavefile']", | ||
}, | ||
//{ | ||
// search: 'module.exports.Wavefile', | ||
// replace: "window['Wavefile']", | ||
//}, | ||
] | ||
@@ -26,0 +22,0 @@ } |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Mixed license
License(Experimental) Package contains multiple licenses.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
3317520
57
2073
1
91
1
10
+ Addedbyte-data@0.1.3(transitive)
- Removedbyte-data@0.1.9(transitive)
Updatedbyte-data@0.1.3