Skip to content

Commit

Permalink
fix: #49
Browse files Browse the repository at this point in the history
  • Loading branch information
dlepaux committed Apr 1, 2023
1 parent 6ad1ec3 commit 50f0a8b
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 19 deletions.
27 changes: 11 additions & 16 deletions src/realtime-bpm-analyzer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {findPeaksAtThreshold, computeBpm} from './analyzer';
import type {RealTimeBpmAnalyzerOptions, RealTimeBpmAnalyzerParameters, ValidPeaks, NextIndexPeaks, BpmCandidates, Threshold, BpmEventData} from './types';
import type {RealTimeBpmAnalyzerOptions, AnalyzerResetedEventData, RealTimeBpmAnalyzerParameters, ValidPeaks, NextIndexPeaks, BpmCandidates, Threshold, BpmEventData} from './types';
import {generateValidPeaksModel, generateNextIndexPeaksModel, descendingOverThresholds} from './utils';
import * as consts from './consts';

Expand All @@ -8,10 +8,10 @@ import * as consts from './consts';
*/
const initialValue = {
minValidThreshold: () => consts.minValidThreshold,
timeoutStabilization: () => 0,
validPeaks: () => generateValidPeaksModel(),
nextIndexPeaks: () => generateNextIndexPeaksModel(),
skipIndexes: () => 1,
effectiveBufferTime: () => 0,
};

/**
Expand All @@ -31,10 +31,6 @@ export class RealTimeBpmAnalyzer {
* Minimum valid threshold, below this level result would be irrelevant.
*/
minValidThreshold: Threshold = initialValue.minValidThreshold();
/**
* Schedule timeout triggered when the stabilizationTime is reached
*/
timeoutStabilization: number = initialValue.timeoutStabilization();
/**
* Contain all valid peaks
*/
Expand All @@ -47,6 +43,7 @@ export class RealTimeBpmAnalyzer {
* Number / Position of chunks
*/
skipIndexes: number = initialValue.skipIndexes();
effectiveBufferTime: number = initialValue.effectiveBufferTime();

/**
* @constructor
Expand Down Expand Up @@ -78,10 +75,10 @@ export class RealTimeBpmAnalyzer {
*/
reset(): void {
this.minValidThreshold = initialValue.minValidThreshold();
this.timeoutStabilization = initialValue.timeoutStabilization();
this.validPeaks = initialValue.validPeaks();
this.nextIndexPeaks = initialValue.nextIndexPeaks();
this.skipIndexes = initialValue.skipIndexes();
this.effectiveBufferTime = initialValue.effectiveBufferTime();
}

/**
Expand All @@ -90,7 +87,6 @@ export class RealTimeBpmAnalyzer {
* @returns {void}
*/
async clearValidPeaks(minThreshold: Threshold): Promise<void> {
console.log(`[clearValidPeaks] function: under ${minThreshold}, this.minValidThreshold has been setted to that threshold.`);
this.minValidThreshold = Number.parseFloat(minThreshold.toFixed(2));

await descendingOverThresholds(async threshold => {
Expand All @@ -106,12 +102,14 @@ export class RealTimeBpmAnalyzer {
/**
* Attach this function to an audioprocess event on a audio/video node to compute BPM / Tempo in realtime
* @param {Float32Array} channelData Channel data
* @param {number} audioSampleRate Audio sample rate
* @param {number} audioSampleRate Audio sample rate (44100)
* @param {number} bufferSize Buffer size
* @param {(data: any) => void} postMessage Function to post a message to the processor node
* @returns {Promise<void>}
*/
async analyzeChunck(channelData: Float32Array, audioSampleRate: number, bufferSize: number, postMessage: (data: BpmEventData) => void): Promise<void> {
async analyzeChunck(channelData: Float32Array, audioSampleRate: number, bufferSize: number, postMessage: (data: BpmEventData | AnalyzerResetedEventData) => void): Promise<void> {
this.effectiveBufferTime += bufferSize; // Ex: (1000000/44100=22s)

/**
* Compute the maximum index with all previous chunks
*/
Expand Down Expand Up @@ -144,12 +142,9 @@ export class RealTimeBpmAnalyzer {
/**
* After x milliseconds, we reinit the analyzer
*/
if (this.options.continuousAnalysis) {
clearTimeout(this.timeoutStabilization);
this.timeoutStabilization = window.setTimeout(() => {
console.log('[timeoutStabilization] setTimeout: Fired !');
this.reset();
}, this.options.stabilizationTime);
if (this.options.continuousAnalysis && this.effectiveBufferTime / audioSampleRate > this.options.stabilizationTime / 1000) {
this.reset();
postMessage({message: 'ANALYZER_RESETED'});
}
}

Expand Down
8 changes: 8 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ export type AsyncConfigurationEventData = {
parameters: RealTimeBpmAnalyzerParameters;
};

export type AnalyzerResetedEvent = {
data: AnalyzerResetedEventData;
};

export type AnalyzerResetedEventData = {
message: 'ANALYZER_RESETED';
};

export type ResetEventData = {
message: 'RESET';
};
Expand Down
6 changes: 3 additions & 3 deletions tests/lib/realtime-bpm-analyzer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { expect } from 'chai';
import { BpmEventData } from '../../src';
import { BpmEventData, AnalyzerResetedEventData } from '../../src';
import {RealTimeBpmAnalyzer} from '../../src/realtime-bpm-analyzer';
import {readChannelDataToChunk} from '../utils';

Expand All @@ -21,7 +21,7 @@ export default () => {
const channelData = readChannelDataToChunk(bufferSize);

for (const chunk of channelData) {
await realTimeBpmAnalyzer.analyzeChunck(chunk, sampleRate, bufferSize, (data: BpmEventData) => {
await realTimeBpmAnalyzer.analyzeChunck(chunk, sampleRate, bufferSize, (data: BpmEventData | AnalyzerResetedEventData) => {
// console.log('message received', data);
});
}
Expand All @@ -40,7 +40,7 @@ export default () => {
const channelData = readChannelDataToChunk(bufferSize);

for (const chunk of channelData) {
await realTimeBpmAnalyzer.analyzeChunck(chunk, sampleRate, bufferSize, (data: BpmEventData) => {
await realTimeBpmAnalyzer.analyzeChunck(chunk, sampleRate, bufferSize, (data: BpmEventData | AnalyzerResetedEventData) => {
// console.log('message received', data);
});
}
Expand Down

0 comments on commit 50f0a8b

Please sign in to comment.