149 líneas
4.3 KiB
JavaScript
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);
|
|
});
|
|
});
|