From 849fb817d18b4759dada016a55cf2a40b6bd64c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Rypu=C5=82a?= Date: Sun, 15 Apr 2018 22:11:14 +0200 Subject: [PATCH] Adds staticImplements check, FFT class update --- src/common/simple-math/simple-math.ts | 5 +- src/dsp/complex/complex-factory.ts | 5 +- src/dsp/complex/complex.ts | 5 +- src/dsp/fft/fft.interface.ts | 1 + src/dsp/fft/fft.spec.ts | 66 +++++++++++++++++++++++++++ src/dsp/fft/fft.ts | 46 +++++++++---------- 6 files changed, 100 insertions(+), 28 deletions(-) create mode 100644 src/dsp/fft/fft.spec.ts diff --git a/src/common/simple-math/simple-math.ts b/src/common/simple-math/simple-math.ts index ac56a86..4590c67 100644 --- a/src/common/simple-math/simple-math.ts +++ b/src/common/simple-math/simple-math.ts @@ -1,7 +1,10 @@ // Copyright (c) 2015-2018 Robert Rypuła - https://audio-network.rypula.pl -import { ISimpleMath } from './simple-math.interface'; +import { staticImplements } from 'rr-tsdi'; +import { ISimpleMath, ISimpleMathStatic } from './simple-math.interface'; + +@staticImplements() class SimpleMath implements ISimpleMath { public getPi(): number { return Math.PI; diff --git a/src/dsp/complex/complex-factory.ts b/src/dsp/complex/complex-factory.ts index 3dfdf63..4802ef3 100644 --- a/src/dsp/complex/complex-factory.ts +++ b/src/dsp/complex/complex-factory.ts @@ -1,10 +1,13 @@ // Copyright (c) 2015-2018 Robert Rypuła - https://audio-network.rypula.pl +import { staticImplements } from 'rr-tsdi'; + import { SIMPLE_MATH } from '../../common/simple-math/di-token'; import { ISimpleMath } from './../../common/simple-math/simple-math.interface'; import Complex from './complex'; -import { IComplexFactory } from './complex-factory.interface'; +import { IComplexFactory, IComplexFactoryStatic } from './complex-factory.interface'; +@staticImplements() class ComplexFactory implements IComplexFactory { public static $inject: string[] = [ SIMPLE_MATH diff --git a/src/dsp/complex/complex.ts b/src/dsp/complex/complex.ts index a393209..2a39300 100644 --- a/src/dsp/complex/complex.ts +++ b/src/dsp/complex/complex.ts @@ -1,8 +1,11 @@ // Copyright (c) 2015-2018 Robert Rypuła - https://audio-network.rypula.pl +import { staticImplements } from 'rr-tsdi'; + import { ISimpleMath } from './../../common/simple-math/simple-math.interface'; -import { IComplex } from './complex.interface'; +import { IComplex, IComplexStatic } from './complex.interface'; +@staticImplements() class Complex implements IComplex { // TODO probably it's bad to have reference to 'simpleMath' // in each Complex object but it's how DI works... diff --git a/src/dsp/fft/fft.interface.ts b/src/dsp/fft/fft.interface.ts index 679fb46..a19c420 100644 --- a/src/dsp/fft/fft.interface.ts +++ b/src/dsp/fft/fft.interface.ts @@ -5,6 +5,7 @@ import { IComplex } from '../complex/complex.interface'; interface IFft { forward(input: IComplex[]): IComplex[]; + inverse(input: IComplex[]): IComplex[]; } interface IFftStatic { diff --git a/src/dsp/fft/fft.spec.ts b/src/dsp/fft/fft.spec.ts new file mode 100644 index 0000000..00cfd72 --- /dev/null +++ b/src/dsp/fft/fft.spec.ts @@ -0,0 +1,66 @@ +// Copyright (c) 2015-2018 Robert Rypuła - https://audio-network.rypula.pl + +import { Injector } from 'rr-tsdi'; + +import { SIMPLE_MATH } from '../../common/simple-math/di-token'; +import SimpleMath from '../../common/simple-math/simple-math'; +import ComplexFactory from '../complex/complex-factory'; +import { IComplexFactory } from '../complex/complex-factory.interface'; +import { IComplex } from '../complex/complex.interface'; +import { COMPLEX_FACTORY } from '../complex/di-token'; +import { FFT } from './di-token'; +import Fft from './fft'; +import { IFft } from './fft.interface'; + +describe('Complex', () => { + let fft: IFft; + let complexFactory: IComplexFactory; + + beforeEach(() => { + const injector = new Injector(); + + injector.registerService(SIMPLE_MATH, SimpleMath); + injector.registerService(COMPLEX_FACTORY, ComplexFactory); + injector.registerService(FFT, Fft); + fft = injector.get(FFT); + complexFactory = injector.get(COMPLEX_FACTORY); + }); + + // TODO refactor it + xit('should', () => { + const input = [ + complexFactory.createPolar(0.00, 1), + complexFactory.createPolar(0.25, 1), + complexFactory.createPolar(0.50, 1), + complexFactory.createPolar(0.75, 1) + ]; + const output = fft + .forward(input) + .map((item: IComplex) => { + return { + imaginary: item.getImaginary(), + real: item.getReal() + }; + }); + + expect(output).toEqual([ + { + imaginary: 0, + real: 0 + }, + { + imaginary: 0, + real: 0 + }, + { + imaginary: 0, + real: 0 + }, + { + imaginary: 0, + real: 0 + } + ]); + }); + +}); diff --git a/src/dsp/fft/fft.ts b/src/dsp/fft/fft.ts index 2c63e74..a9fdcd3 100644 --- a/src/dsp/fft/fft.ts +++ b/src/dsp/fft/fft.ts @@ -1,10 +1,13 @@ // Copyright (c) 2015-2018 Robert Rypuła - https://audio-network.rypula.pl +import { staticImplements } from 'rr-tsdi'; + import { IComplexFactory } from '../complex/complex-factory.interface'; import { IComplex } from '../complex/complex.interface'; import { COMPLEX_FACTORY } from '../complex/di-token'; -import { IFft } from './fft.interface'; +import { IFft, IFftStatic } from './fft.interface'; +@staticImplements() class Fft implements IFft { public static $inject: string[] = [ COMPLEX_FACTORY @@ -16,59 +19,52 @@ class Fft implements IFft { } public forward(input: IComplex[]): IComplex[] { - return input; - /* - var - n = input.length, - nHalf, - even, - odd, - output = [], - wnkMultiplied, - wnk, - k, - unitAngle; + const n = input.length; + let nHalf: number; + let even: IComplex[]; + let odd: IComplex[]; + const output: IComplex[] = []; + let wnkMultiplied: IComplex; + let wnk: IComplex; + let k: number; + let unitAngle: number; if (n === 1) { return input; } // even and odd parts - even = Fft.forward(Fft.$$getHalf(input, 0)); - odd = Fft.forward(Fft.$$getHalf(input, 1)); + even = this.forward(this.getHalf(input, 0)); + odd = this.forward(this.getHalf(input, 1)); // combine output.length = n; nHalf = n / 2; for (k = 0; k < nHalf; k++) { unitAngle = -k / n; - wnk = Complex.polar(unitAngle); + wnk = this.complexFactory.createPolar(unitAngle); wnkMultiplied = wnk.clone().multiply(odd[k]); output[k] = even[k].clone().add(wnkMultiplied); output[nHalf + k] = even[k].clone().subtract(wnkMultiplied); } return output; - */ } - /* - Fft.inverse = function (input) { - var - output = [], - i; + public inverse(input: IComplex[]): IComplex[] { + let output: IComplex[] = []; + let i: number; for (i = 0; i < input.length; i++) { output.push(input[i].clone().swap()); } - output = Fft.forward(output); + output = this.forward(output); for (i = 0; i < output.length; i++) { output[i].swap().divideScalar(output.length); } return output; - }; - */ + } private getHalf(list: IComplex[], offset: number): IComplex[] { const listHalf: IComplex[] = [];