Permalink
Browse files

Initial commit

  • Loading branch information...
jussi-kalliokoski committed Oct 31, 2012
0 parents commit ca2d70c36c3fd4926f5816dc20e1f0192dcce7d0
Showing with 532 additions and 0 deletions.
  1. +2 −0 .gitignore
  2. +8 −0 binding.gyp
  3. +20 −0 package.json
  4. +169 −0 src/common.h
  5. +179 −0 src/dsp.cpp
  6. +47 −0 src/dsp.h
  7. +71 −0 tests/index.js
  8. +9 −0 tests/tests/add.json
  9. +9 −0 tests/tests/div.json
  10. +9 −0 tests/tests/mul.json
  11. +9 −0 tests/tests/sub.json
@@ -0,0 +1,2 @@
+node_modules
+build
@@ -0,0 +1,8 @@
+{
+ 'targets': [{
+ 'target_name': 'node-dsp',
+ 'sources': [
+ 'src/dsp.cpp',
+ ]
+ }]
+}
@@ -0,0 +1,20 @@
+{
+ "name": "dsp",
+ "version": "0.0.0",
+ "description": "A node implementation of the DSP API.",
+ "main": "./build/Release/node-dsp",
+ "scripts": {
+ "test": "node tests",
+ "install": "node-gyp rebuild"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git@github.com:jussi-kalliokoski/node-dsp"
+ },
+ "keywords": [
+ "DSP"
+ ],
+ "author": "Jussi Kalliokoski",
+ "license": "BSD",
+ "gypfile": true
+}
@@ -0,0 +1,169 @@
+#ifndef NODE_DSP_COMMON_H
+#define NODE_DSP_COMMON_H
+
+#define sign(x) (x != x ? x : x < 0.0 || x == -0.0 ? -1.0 : 1.0)
+#define modulo(x, y) (x - floor(x / y) * y)
+#define fract(x) (modulo(x, 1))
+
+#define getFloat32Array(srcName, dstName, lengthName) float *dstName; int lengthName = 0; {\
+ Local<Object> obj = srcName;\
+ if (obj->GetIndexedPropertiesExternalArrayDataType() != kExternalFloatArray) dstName = NULL;\
+ else { lengthName = obj->GetIndexedPropertiesExternalArrayDataLength();\
+ dstName = static_cast<float*>(obj->GetIndexedPropertiesExternalArrayData());}}
+
+#define check_malloc(varname, vartype)\
+ vartype *varname;\
+ varname = (vartype*) malloc(sizeof(*varname));\
+ if (varname == NULL)
+
+#define INVALID_ARGUMENTS_ERROR ThrowException(Exception::Error(String::New("Invalid arguments.")))
+
+#define DSP_METHOD_ACCUMULATOR(name, defaultReturn, algo) Handle<Value> NodeDSP::name (const Arguments &args) {\
+ HandleScope scope;\
+\
+ getFloat32Array(args[0]->ToObject(), src, l);\
+\
+ if (src == NULL) return INVALID_ARGUMENTS_ERROR;\
+\
+ if (!l) return Number::New(defaultReturn);\
+\
+ float v = src[0];\
+\
+ for (int i=1; i<l; i++) {\
+ v = algo;\
+ }\
+\
+ return Number::New(v);\
+}
+
+#define DSP_METHOD_1(name, algo) Handle<Value> NodeDSP::name (const Arguments &args) {\
+ HandleScope scope;\
+\
+ getFloat32Array(args[0]->ToObject(), dst, ldst);\
+ getFloat32Array(args[1]->ToObject(), x, lx);\
+\
+ if (dst == NULL || x == NULL) return INVALID_ARGUMENTS_ERROR;\
+\
+ int l = min(ldst, lx);\
+\
+ for (int i=0; i<l; i++) {\
+ dst[i] = algo;\
+ }\
+\
+ return Undefined();\
+}
+
+#define DSP_METHOD_2(name, algo) Handle<Value> NodeDSP::name (const Arguments &args) {\
+ HandleScope scope;\
+\
+ getFloat32Array(args[0]->ToObject(), dst, ldst);\
+ getFloat32Array(args[1]->ToObject(), x, lx);\
+ getFloat32Array(args[2]->ToObject(), y, ly);\
+\
+ if (dst == NULL || x == NULL || y == NULL) return INVALID_ARGUMENTS_ERROR;\
+\
+ int l = min(ldst, min(lx, ly));\
+\
+ for (int i=0; i<l; i++) {\
+ dst[i] = algo;\
+ }\
+\
+ return Undefined();\
+}
+
+#define DSP_METHOD_2_OVERLOADING(name, algo1, algo2) Handle<Value> NodeDSP::name (const Arguments &args) {\
+ HandleScope scope;\
+\
+ getFloat32Array(args[0]->ToObject(), dst, ldst);\
+ getFloat32Array(args[1]->ToObject(), x, lx);\
+ getFloat32Array(args[2]->ToObject(), y, ly);\
+\
+ if (dst == NULL || x == NULL) return INVALID_ARGUMENTS_ERROR;\
+\
+ if (y == NULL) {\
+ if (!args[2]->IsNumber()) return INVALID_ARGUMENTS_ERROR;\
+\
+ float yy = args[2]->NumberValue();\
+ int l = min(ldst, lx);\
+\
+ for (int i=0; i<l; i++) {\
+ dst[i] = algo1;\
+ }\
+ } else {\
+ int l = min(ldst, min(lx, ly));\
+\
+ for (int i=0; i<l; i++) {\
+ dst[i] = algo2;\
+ }\
+ }\
+\
+ return Undefined();\
+}
+
+#define DSP_METHOD_3_OVERLOADING(name, algo1, algo2) Handle<Value> NodeDSP::name (const Arguments &args) {\
+ HandleScope scope;\
+\
+ getFloat32Array(args[0]->ToObject(), dst, ldst);\
+ getFloat32Array(args[1]->ToObject(), x, lx);\
+ getFloat32Array(args[2]->ToObject(), y, ly);\
+ getFloat32Array(args[3]->ToObject(), z, lz);\
+\
+ if (dst == NULL || x == NULL || y == NULL) return INVALID_ARGUMENTS_ERROR;\
+\
+ if (y == NULL) {\
+ if (!args[3]->IsNumber()) return INVALID_ARGUMENTS_ERROR;\
+\
+ float zz = args[3]->NumberValue();\
+ int l = min(ldst, min(lx, ly));\
+\
+ for (int i=0; i<l; i++) {\
+ dst[i] = algo1;\
+ }\
+ } else {\
+ int l = min(ldst, min(lx, min(ly, lz)));\
+\
+ for (int i=0; i<l; i++) {\
+ dst[i] = algo2;\
+ }\
+ }\
+\
+ return Undefined();\
+}
+
+#define DSP_METHOD_CPLX_2_OVERLOADING(name, algo1, algo2) Handle<Value> NodeDSP::name (const Arguments &args) {\
+ HandleScope scope;\
+\
+ getFloat32Array(args[0]->ToObject(), dstReal, ldstr);\
+ getFloat32Array(args[1]->ToObject(), dstImag, ldsti);\
+ getFloat32Array(args[2]->ToObject(), xReal, lxr);\
+ getFloat32Array(args[3]->ToObject(), xImag, lxi);\
+ getFloat32Array(args[4]->ToObject(), yReal, lyr);\
+ getFloat32Array(args[5]->ToObject(), yImag, lyi);\
+\
+ if (\
+ dstReal == NULL || dstImag == NULL\
+ xReal == NULL || xImag == NULL\
+ ) return INVALID_ARGUMENTS_ERROR;\
+\
+ if (yReal == NULL || yImag == NULL) {\
+ if (!args[4]->IsNumber()) return INVALID_ARGUMENTS_ERROR;\
+ if (!args[5]->IsNumber()) return INVALID_ARGUMENTS_ERROR;\
+\
+ float yr = args[4]->NumberValue();\
+ float yi = args[5]->NumberValue();\
+ int l = min(ldstr, min(ldsti, min(lxr, lxi)));\
+\
+ for (int i=0; i<l; i++) algo1\
+ } else {\
+ int l = min(ldstr, min(ldsti, min(lxr, min(lxi, min(lyr, lyi)))));\
+\
+ for (int i=0; i<l; i++) algo2\
+ }\
+\
+ return Undefined();\
+}
+
+#define DSP_METHOD_OP(name, op) DSP_METHOD_2_OVERLOADING(name, x[i] op yy, x[i] op y[i])
+#define DSP_METHOD_ALG(name, method) DSP_METHOD_1(name, method(x[i]))
+
+#endif
@@ -0,0 +1,179 @@
+#include <math.h>
+#include <algorithm>
+
+#include "dsp.h"
+#include "common.h"
+
+using namespace v8;
+using namespace node;
+using namespace std;
+
+extern "C" void init (v8::Handle<v8::Object> target) {
+ v8::HandleScope scope;
+
+ NodeDSP::Initialize(target);
+}
+
+
+void NodeDSP::Initialize (Handle<Object> target) {
+ HandleScope scope;
+
+ SetMethod(target, "add", Add);
+ SetMethod(target, "abs", Abs);
+// SetMethod(target, "absCplx", AbsCplx);
+ SetMethod(target, "acos", Acos);
+ SetMethod(target, "add", Add);
+ SetMethod(target, "asin", Asin);
+ SetMethod(target, "atan", Atan);
+ SetMethod(target, "atan2", Atan2);
+ SetMethod(target, "ceil", Ceil);
+// SetMethod(target, "clamp", Clamp);
+ SetMethod(target, "cos", Cos);
+ SetMethod(target, "div", Div);
+ SetMethod(target, "divCplx", DivCplx);
+ SetMethod(target, "exp", Exp);
+ SetMethod(target, "floor", Floor);
+ SetMethod(target, "fract", Fract);
+ SetMethod(target, "log", Log);
+ SetMethod(target, "madd", Madd);
+ SetMethod(target, "max", Max);
+ SetMethod(target, "min", Min);
+ SetMethod(target, "mul", Mul);
+ SetMethod(target, "mulCplx", MulCplx);
+// SetMethod(target, "pack", Pack);
+ SetMethod(target, "pow", Pow);
+// SetMethod(target, "ramp", Ramp);
+// SetMethod(target, "random", Random);
+ SetMethod(target, "round", Round);
+// SetMethod(target, "sampleCubic", SampleCubic);
+// SetMethod(target, "sampleLinear", SampleLinear);
+ SetMethod(target, "sign", Sign);
+ SetMethod(target, "sin", Sin);
+ SetMethod(target, "sqrt", Sqrt);
+ SetMethod(target, "sub", Sub);
+ SetMethod(target, "sum", Sum);
+ SetMethod(target, "tan", Tan);
+// SetMethod(target, "unpack", Unpack);
+}
+
+DSP_METHOD_OP(Add, +)
+DSP_METHOD_OP(Sub, -)
+DSP_METHOD_OP(Mul, *)
+DSP_METHOD_OP(Div, /)
+DSP_METHOD_3_OVERLOADING(Madd, x[i] + y[i] * zz, x[i] + y[i] * z[i])
+
+DSP_METHOD_ALG(Sin, sin)
+DSP_METHOD_ALG(Cos, cos)
+DSP_METHOD_ALG(Tan, tan)
+DSP_METHOD_ALG(Asin, asin)
+DSP_METHOD_ALG(Acos, acos)
+DSP_METHOD_ALG(Atan, atan)
+DSP_METHOD_2(Atan2, atan2(x[i], y[i]))
+
+DSP_METHOD_1(Sign, sign(x[i]))
+DSP_METHOD_1(Fract, fract(x[i]))
+DSP_METHOD_ALG(Abs, fabs)
+DSP_METHOD_ALG(Ceil, ceil)
+DSP_METHOD_ALG(Floor, floor)
+DSP_METHOD_ALG(Round, round)
+
+DSP_METHOD_ALG(Sqrt, sqrt)
+DSP_METHOD_2_OVERLOADING(Pow, pow(x[i], yy), pow(x[i], y[i]))
+
+DSP_METHOD_ALG(Exp, exp)
+DSP_METHOD_ALG(Log, log)
+
+DSP_METHOD_ACCUMULATOR(Sum, 0.0, src[i] + v)
+DSP_METHOD_ACCUMULATOR(Max, 1.0/0.0, max(src[i], v))
+DSP_METHOD_ACCUMULATOR(Min, 1.0/0.0, min(src[i], v))
+
+Handle<Value> NodeDSP::MulCplx (const Arguments &args) {
+ HandleScope scope;
+
+ getFloat32Array(args[0]->ToObject(), dstReal, ldstr);
+ getFloat32Array(args[1]->ToObject(), dstImag, ldsti);
+ getFloat32Array(args[2]->ToObject(), xReal, lxr);
+ getFloat32Array(args[3]->ToObject(), xImag, lxi);
+ getFloat32Array(args[4]->ToObject(), yReal, lyr);
+ getFloat32Array(args[5]->ToObject(), yImag, lyi);
+
+ if (
+ dstReal == NULL ||
+ dstImag == NULL ||
+ xReal == NULL ||
+ xImag == NULL
+ ) return INVALID_ARGUMENTS_ERROR;
+
+ if (yReal == NULL || yImag == NULL) {
+ if (!args[4]->IsNumber()) return INVALID_ARGUMENTS_ERROR;
+ if (!args[5]->IsNumber()) return INVALID_ARGUMENTS_ERROR;
+
+ float yr = args[4]->NumberValue();
+ float yi = args[5]->NumberValue();
+ int l = min(ldstr, min(ldsti, min(lxr, lxi)));
+
+ for (int i=0; i<l; i++) {
+ float x_r = xReal[i];
+ dstReal[i] = x_r * yr - xImag[i] * yi;
+ dstImag[i] = x_r * yi + xImag[i] * yr;
+ }
+ } else {
+ int l = min(ldstr, min(ldsti, min(lxr, min(lxi, min(lyr, lyi)))));
+
+ for (int i=0; i<l; i++) {
+ float x_r = xReal[i];
+ float y_r = yReal[i];
+ dstReal[i] = x_r * y_r - xImag[i] * yImag[i];
+ dstImag[i] = x_r * yImag[i] + xImag[i] * y_r;
+ }
+ }
+
+ return Undefined();
+}
+
+/* FIXME: Fix this as the spec is fixed */
+Handle<Value> NodeDSP::DivCplx (const Arguments &args) {
+ HandleScope scope;
+
+ getFloat32Array(args[0]->ToObject(), dstReal, ldstr);
+ getFloat32Array(args[1]->ToObject(), dstImag, ldsti);
+ getFloat32Array(args[2]->ToObject(), xReal, lxr);
+ getFloat32Array(args[3]->ToObject(), xImag, lxi);
+ getFloat32Array(args[4]->ToObject(), yReal, lyr);
+ getFloat32Array(args[5]->ToObject(), yImag, lyi);
+
+ if (
+ dstReal == NULL ||
+ dstImag == NULL ||
+ xReal == NULL ||
+ xImag == NULL
+ ) return INVALID_ARGUMENTS_ERROR;
+
+ if (yReal == NULL || yImag == NULL) {
+ if (!args[4]->IsNumber()) return INVALID_ARGUMENTS_ERROR;
+ if (!args[5]->IsNumber()) return INVALID_ARGUMENTS_ERROR;
+
+ float yr = args[4]->NumberValue();
+ float yi = args[5]->NumberValue();
+ int l = min(ldstr, min(ldsti, min(lxr, lxi)));
+
+ for (int i=0; i<l; i++) {
+ float denom = yr * yr + yi * yi;
+ float x_r = xReal[i];
+ dstReal[i] = (x_r * yr + xImag[i] * yi) / denom;
+ dstImag[i] = (xImag[i] * yr - x_r * yi) / denom;
+ }
+ } else {
+ int l = min(ldstr, min(ldsti, min(lxr, min(lxi, min(lyr, lyi)))));
+
+ for (int i=0; i<l; i++) {
+ float denom = yReal[i] * yReal[i] + yImag[i] * yImag[i];
+ float x_r = xReal[i];
+ float y_r = yReal[i];
+ dstReal[i] = (x_r * y_r + xImag[i] * yImag[i]) / denom;
+ dstImag[i] = (x_r * yImag[i] - xImag[i] * y_r) / denom;
+ }
+ }
+
+ return Undefined();
+}
Oops, something went wrong.

0 comments on commit ca2d70c

Please sign in to comment.