Initial commit with tests.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Joshua Jung
|
||||
Copyright (c) 2015 Vail Systems
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -1,2 +1,45 @@
|
||||
# node-dct
|
||||
Node.js implementation of the Discrete Cosine Transform (version 2 for now).
|
||||
|
||||
# Introduction
|
||||
|
||||
The discrete cosine transform (DCT) is used widely for signal compression due to its power compaction properties as opposed to the discrete fourier transform.
|
||||
|
||||
For a signal of length `N` the DCT function returns a vector of coefficients of length `N`, each coefficient representing how closely the signal maps to that cosine function.
|
||||
|
||||
The first coefficient represents a flat function. As a result, if the input is all the same value the first coefficient is going to be a non-zero value while all other coefficients should be close to zero.
|
||||
|
||||
Various versions of the DCT exist, each one having special properties. For its widespread use this implementation uses the DCT-II with a scaling factor of 2.
|
||||
|
||||
# Example
|
||||
|
||||
var dct = require('dct'),
|
||||
signal = [1,1,1,1,1];
|
||||
|
||||
var coef = dct(signal);
|
||||
|
||||
console.log(coef); // [12, 0, 0, 0, 0]
|
||||
|
||||
# License
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Vail Systems
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
var DCT= require('./');
|
||||
|
||||
process.stdin.on('data', function (data) {
|
||||
console.log(data.toString());
|
||||
var coef = (new DCT()).run(data.toString().split(','));
|
||||
console.log(coef);
|
||||
});
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "dct",
|
||||
"version": "0.0.1",
|
||||
"description": "Node.js implementation of the Discrete Cosine Transform (version 2 for now).",
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/vail-systems/node-dct",
|
||||
"repository": "vail-systems/node-dct",
|
||||
"contributors": [
|
||||
"Joshua Jung <joshua.p.jung@gmail.com> (http://www.joshjung.com)",
|
||||
"Ben Bryan <bbryan@vailsys.com>"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=0.12.0"
|
||||
},
|
||||
"main": "index.js",
|
||||
"files": [
|
||||
"dct.js",
|
||||
"src",
|
||||
"test"
|
||||
],
|
||||
"keywords": [
|
||||
"dct",
|
||||
"discrete cosine transform"
|
||||
]
|
||||
}
|
||||
Binary file not shown.
+48
@@ -0,0 +1,48 @@
|
||||
/*===========================================================================*\
|
||||
* Discrete Cosine Transform
|
||||
*
|
||||
* (c) Vail Systems. Joshua Jung and Ben Bryan. 2015
|
||||
*
|
||||
* This code is not designed to be highly optimized but as an educational
|
||||
* tool to understand the Mel-scale and its related coefficients used in
|
||||
* human speech analysis.
|
||||
\*===========================================================================*/
|
||||
cosMap = null;
|
||||
|
||||
// Builds a cosine map for the given block size. This allows multiple block sizes to be
|
||||
// memoized automagically.
|
||||
var memoizeCosines = function(N) {
|
||||
cosMap = cosMap || {};
|
||||
cosMap[N] = new Array(N*N);
|
||||
|
||||
var PI_N = Math.PI / N;
|
||||
|
||||
for (var k = 0; k < N; k++) {
|
||||
for (var n = 0; n < N; n++) {
|
||||
cosMap[N][n + (k * N)] = Math.cos(PI_N * (n + 0.5) * k);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function run(signal, scale) {
|
||||
var L = signal.length,
|
||||
self = this;
|
||||
|
||||
scale = scale || 2;
|
||||
|
||||
if (!cosMap || !cosMap[L]) memoizeCosines(L);
|
||||
|
||||
// Discrete Cosine Transform is O(n*m) where:
|
||||
// n: number of MFCC bins
|
||||
// m: number of Spectrum bins
|
||||
// Usually n == 12 and 20 <= m <= 40
|
||||
var coefficients = signal.map(function () {return 0;});
|
||||
|
||||
return coefficients.map(function (__, ix) {
|
||||
return scale * signal.reduce(function (prev, cur, ix_, arr) {
|
||||
return prev + (cur * cosMap[L][ix_ + (ix * L)]);
|
||||
}, 0);
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = run;
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
1,0,1,0
|
||||
@@ -0,0 +1 @@
|
||||
1,1,1,1,1
|
||||
@@ -0,0 +1,45 @@
|
||||
var assert = require('assert'),
|
||||
dct = require('../');
|
||||
|
||||
describe('DCT-2', function () {
|
||||
describe('1,0,1,0', function () {
|
||||
it('Should properly compute [1,0,1,0]', function () {
|
||||
var coef = dct([1,0,1,0]);
|
||||
|
||||
assert(equalWithThresh(coef[0], 4, 0.01));
|
||||
assert(equalWithThresh(coef[1], 1.082392, 0.01));
|
||||
assert(equalWithThresh(coef[2], 0, 0.01));
|
||||
assert(equalWithThresh(coef[3], 2.613126, 0.01));
|
||||
});
|
||||
});
|
||||
|
||||
describe('1,1,1,1,1,1', function () {
|
||||
it('Should properly compute [1,1,1,1,1,1]', function () {
|
||||
var coef = dct([1,1,1,1,1,1]);
|
||||
|
||||
assert(equalWithThresh(coef[0], 12, 0.01));
|
||||
assert(equalWithThresh(coef[1], 0, 0.01));
|
||||
assert(equalWithThresh(coef[2], 0, 0.01));
|
||||
assert(equalWithThresh(coef[3], 0, 0.01));
|
||||
assert(equalWithThresh(coef[4], 0, 0.01));
|
||||
assert(equalWithThresh(coef[5], 0, 0.01));
|
||||
});
|
||||
});
|
||||
|
||||
describe('2,0.5,0.1,5', function () {
|
||||
it('Should properly compute [2,0.5,0.1,5]', function () {
|
||||
var coef = dct([2,0.5,0.1,5]);
|
||||
|
||||
assert(equalWithThresh(coef[0], 15.2, 0.01));
|
||||
assert(equalWithThresh(coef[1], -5.24, 0.01));
|
||||
assert(equalWithThresh(coef[2], 9.05, 0.01));
|
||||
assert(equalWithThresh(coef[3], -3.04, 0.01));
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function equalWithThresh(val1, val2, threshold) {
|
||||
return (val1 > val2 - threshold) &&
|
||||
(val1 < val2 + threshold);
|
||||
};
|
||||
Reference in New Issue
Block a user