Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v6 breaking changes #886

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from
18 changes: 1 addition & 17 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,7 @@ jobs:

strategy:
matrix:
node-version: [
# Disabled because with typescript, the 10.x build fails by running out
# of heap space. I can't figure out how to increase heap size on the build
# but since we're dropping support for 10.x soon, I think this is fine.
# Tests still run on all the other versions, and we publish from 16.x now,
# so we I think we're fine to disable it for the next few releases.
# See you in 2035.
#
# https://github.com/meyda/meyda/pull/908/checks?check_run_id=3090204396
# 10.x,
12.x,
13.x,
14.x,
15.x,
16.x,
17.x,
]
node-version: [16.x, 18.x, 19.x, 20.x]

steps:
- uses: actions/checkout@v1
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/merge-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ on:
push:
branches:
- main
- v6

jobs:
build:
Expand Down
47 changes: 47 additions & 0 deletions __tests__/extractors/positiveFlux.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import TestData from "../TestData";
import { fft } from "fftjs";

// Setup
var positiveFlux = require("../../dist/node/extractors/positiveFlux");

var COMPLEX_SPECTRUM = fft(TestData.VALID_SIGNAL);

describe("positiveFlux", () => {
test("should return correct Positive Flux value", (done) => {
var en = positiveFlux({
complexSpectrum: COMPLEX_SPECTRUM,
previousComplexSpectrum: {
real: COMPLEX_SPECTRUM.real.map((e) => e * 0.8),
},
bufferSize: TestData.VALID_SIGNAL.length,
});

expect(en).toEqual(2.1288412531209104e-8);

done();
});

test.skip("should throw an error when passed an empty object", (done) => {
try {
var en = positiveFlux({});
} catch (e) {
done();
}
});

test.skip("should throw an error when not passed anything", (done) => {
try {
var en = positiveFlux();
} catch (e) {
done();
}
});

test.skip("should throw an error when passed something invalid", (done) => {
try {
var en = positiveFlux({ signal: "not a signal" });
} catch (e) {
done();
}
});
});
47 changes: 47 additions & 0 deletions __tests__/extractors/spectralFlux.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import TestData from "../TestData";
import { fft } from "fftjs";

// Setup
var spectralFlux = require("../../dist/node/extractors/spectralFlux");

var COMPLEX_SPECTRUM = fft(TestData.VALID_SIGNAL);

describe("spectralFlux", () => {
test("should return correct Spectral Flux value", (done) => {
var en = spectralFlux({
complexSpectrum: COMPLEX_SPECTRUM,
previousComplexSpectrum: {
real: COMPLEX_SPECTRUM.real.map((e) => e * 0.8),
},
bufferSize: TestData.VALID_SIGNAL.length,
});

expect(en).toEqual(1.03425562865083e-7);

done();
});

test.skip("should throw an error when passed an empty object", (done) => {
try {
var en = spectralFlux({});
} catch (e) {
done();
}
});

test.skip("should throw an error when not passed anything", (done) => {
try {
var en = spectralFlux();
} catch (e) {
done();
}
});

test.skip("should throw an error when passed something invalid", (done) => {
try {
var en = spectralFlux({ signal: "not a signal" });
} catch (e) {
done();
}
});
});
4 changes: 2 additions & 2 deletions docs/audio-features.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ To use RMS in applications where you expect a ceiling on each audio feature, we
`spectralFlux`

- _Description_: A measure of how quickly the spectrum of a signal is changing. It is calculated by computing the difference between the current spectrum and that of the previous frame.
- _What Is It Used For_: Often corresponds to perceptual "roughness" of a sound. Can be used for example, to determine the timbre of a sound.
- _Range_: Starts at `0.0`. This has no upper range as it depends on the input signal.
- _What Is It Used For_: Often corresponds to perceptual "roughness" of a sound. Can be used for example, to determine the timbre of a sound, and onset detection.
- _Range_: Starts at `0.0`. The upper bound is equal to the square root of the buffer size.

### Spectral Slope

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
"wav": "^1.0.2"
},
"engines": {
"node": "^10 || ^12 || ^13 || ^14 || ^15 || ^16 || ^17"
"node": "^16 || ^18 || ^19 || ^20"
},
"jest": {
"preset": "ts-jest",
Expand Down
28 changes: 28 additions & 0 deletions src/extractors/positiveFlux.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { normalizeToOne } from "../utilities";

export default function ({
complexSpectrum,
previousComplexSpectrum,
}: {
complexSpectrum: { real: number[]; imag: number[] };
previousComplexSpectrum: { real: number[]; imag: number[] };
}): number {
if (!previousComplexSpectrum) {
return 0;
}

const normalizedRealComponent = normalizeToOne(complexSpectrum.real);
const previousNormalizedRealComponent = normalizeToOne(
previousComplexSpectrum.real
);

let sf = 0;
for (let i = 0; i < normalizedRealComponent.length; i++) {
let x =
Math.abs(previousNormalizedRealComponent[i]) -
Math.abs(normalizedRealComponent[i]);
sf += Math.pow(Math.max(x, 0), 2);
}

return Math.sqrt(sf);
}
34 changes: 19 additions & 15 deletions src/extractors/spectralFlux.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
// This file isn't being typechecked at all because there are major issues with it.
// See #852 for details. Once that's merged, this file should be typechecked.
// @ts-nocheck
import { normalizeToOne } from "../utilities";

export default function ({
signal,
previousSignal,
bufferSize,
complexSpectrum,
previousComplexSpectrum,
}: {
signal: Float32Array;
previousSignal: Float32Array;
bufferSize: number;
complexSpectrum: { real: number[]; imag: number[] };
previousComplexSpectrum: { real: number[]; imag: number[] };
}): number {
if (typeof signal !== "object" || typeof previousSignal != "object") {
throw new TypeError();
if (!previousComplexSpectrum) {
return 0;
}

const normalizedRealComponent = normalizeToOne(complexSpectrum.real);
const previousNormalizedRealComponent = normalizeToOne(
previousComplexSpectrum.real
);

let sf = 0;
for (let i = -(bufferSize / 2); i < signal.length / 2 - 1; i++) {
x = Math.abs(signal[i]) - Math.abs(previousSignal[i]);
sf += (x + Math.abs(x)) / 2;
for (let i = 0; i < normalizedRealComponent.length; i++) {
let x =
Math.abs(normalizedRealComponent[i]) -
Math.abs(previousNormalizedRealComponent[i]);
sf += Math.pow(x, 2);
}

return sf;
return Math.sqrt(sf);
}
2 changes: 2 additions & 0 deletions src/featureExtractors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import mfcc from "./extractors/mfcc";
import chroma from "./extractors/chroma";
import powerSpectrum from "./extractors/powerSpectrum";
import spectralFlux from "./extractors/spectralFlux";
import positiveFlux from "./extractors/positiveFlux";

let buffer = function (args) {
return args.signal;
Expand Down Expand Up @@ -49,4 +50,5 @@ export {
mfcc,
chroma,
spectralFlux,
positiveFlux,
};
5 changes: 4 additions & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,14 @@ export interface MeydaFeaturesObject {
rms: number;
spectralCentroid: number;
spectralFlatness: number;
spectralFlux: number;
spectralKurtosis: number;
spectralRolloff: number;
spectralSkewness: number;
spectralSlope: number;
spectralSpread: number;
zcr: number;
positiveFlux: number;
}

export type MeydaWindowingFunction =
Expand Down Expand Up @@ -63,7 +65,8 @@ export type MeydaAudioFeature =
| "spectralSlope"
| "spectralSpread"
| "zcr"
| "buffer";
| "buffer"
| "positiveFlux";

/**
* A type representing an audio signal. In general it should be an array of
Expand Down
6 changes: 4 additions & 2 deletions src/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,15 @@ export function mean(a) {
);
}

const MEL_CONSTANT = 1127;

function _melToFreq(melValue) {
var freqValue = 700 * (Math.exp(melValue / 1125) - 1);
var freqValue = 700 * (Math.exp(melValue / MEL_CONSTANT) - 1);
return freqValue;
}

function _freqToMel(freqValue) {
var melValue = 1125 * Math.log(1 + freqValue / 700);
var melValue = MEL_CONSTANT * Math.log(1 + freqValue / 700);
return melValue;
}

Expand Down