Files
automixer/tests/automixer.test.js
2025-12-12 22:13:54 +01:00

149 líneas
4.3 KiB
JavaScript

/**
* AutoMixer Tests
*
* Basic test suite for the automixer library
*/
import { describe, it } from 'node:test';
import assert from 'node:assert';
import { AutoMixer, BPMDetector, AudioAnalyzer, PitchShifter } from '../src/index.js';
describe('AutoMixer', () => {
it('should create an instance with default options', () => {
const mixer = new AutoMixer();
assert.ok(mixer);
assert.strictEqual(mixer.options.crossfadeDuration, 8);
assert.strictEqual(mixer.options.preservePitch, true);
});
it('should create an instance with custom options', () => {
const mixer = new AutoMixer({
crossfadeDuration: 12,
targetBPM: 128,
preservePitch: false
});
assert.strictEqual(mixer.options.crossfadeDuration, 12);
assert.strictEqual(mixer.options.targetBPM, 128);
assert.strictEqual(mixer.options.preservePitch, false);
});
it('should add and clear tracks', () => {
const mixer = new AutoMixer();
mixer.addTracks(['track1.mp3', 'track2.mp3']);
assert.strictEqual(mixer.tracks.length, 2);
mixer.addTracks(['track3.mp3']);
assert.strictEqual(mixer.tracks.length, 3);
mixer.clearTracks();
assert.strictEqual(mixer.tracks.length, 0);
});
it('should calculate tempo ratio correctly', () => {
const mixer = new AutoMixer({ maxBPMChange: 10 });
// Simple ratio
const ratio1 = mixer.calculateTempoRatio(120, 132);
assert.strictEqual(ratio1, 1.1);
// Identity
const ratio2 = mixer.calculateTempoRatio(128, 128);
assert.strictEqual(ratio2, 1);
});
it('should throw error when analyzing without tracks', async () => {
const mixer = new AutoMixer();
await assert.rejects(
async () => mixer.createMix('output.mp3'),
{ message: 'No tracks analyzed. Call analyzeTracks() first.' }
);
});
});
describe('BPMDetector', () => {
it('should create an instance with default options', () => {
const detector = new BPMDetector();
assert.ok(detector);
assert.strictEqual(detector.options.minBPM, 60);
assert.strictEqual(detector.options.maxBPM, 200);
});
it('should normalize BPM correctly', () => {
const detector = new BPMDetector({ minBPM: 60, maxBPM: 200 });
// Normal BPM
assert.strictEqual(detector.normalizeBPM(120), 120);
// Half BPM (should double)
assert.strictEqual(detector.normalizeBPM(55), 110);
// Double BPM (should halve)
assert.strictEqual(detector.normalizeBPM(240), 120);
});
it('should extrapolate beats correctly', () => {
const detector = new BPMDetector();
// 120 BPM = 0.5s per beat
const beats = detector.extrapolateBeats([0, 0.5, 1.0], 120, 5);
assert.ok(beats.length > 0);
assert.ok(beats.every(b => b >= 0 && b < 5));
});
});
describe('AudioAnalyzer', () => {
it('should create an instance', () => {
const analyzer = new AudioAnalyzer();
assert.ok(analyzer);
});
it('should have cache management', () => {
const analyzer = new AudioAnalyzer();
analyzer.clearCache();
assert.strictEqual(analyzer.ffprobeCache.size, 0);
});
});
describe('PitchShifter', () => {
it('should create an instance with default options', () => {
const shifter = new PitchShifter();
assert.ok(shifter);
assert.strictEqual(shifter.options.outputFormat, 'mp3');
assert.strictEqual(shifter.options.outputBitrate, 320);
});
it('should build atempo chain correctly', () => {
const shifter = new PitchShifter();
// Simple ratio within range
const chain1 = shifter.buildAtempoChain(1.5);
assert.strictEqual(chain1, 'atempo=1.5');
// Ratio above 2.0 (needs chaining)
const chain2 = shifter.buildAtempoChain(3.0);
assert.ok(chain2.includes('atempo=2.0'));
assert.ok(chain2.includes('atempo=1.5'));
// Ratio below 0.5 (needs chaining)
const chain3 = shifter.buildAtempoChain(0.25);
assert.ok(chain3.includes('atempo=0.5'));
});
});
describe('Module Exports', () => {
it('should export all components', async () => {
const module = await import('../src/index.js');
assert.ok(module.AutoMixer);
assert.ok(module.BPMDetector);
assert.ok(module.AudioAnalyzer);
assert.ok(module.TrackMixer);
assert.ok(module.PitchShifter);
assert.ok(module.default);
});
});