File size: 4,151 Bytes
f2bee8a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/* global WebAudioTestAPI */
import 'web-audio-test-api';
WebAudioTestAPI.setState({
    'OfflineAudioContext#startRendering': 'promise'
});

import AudioEffects from '../../../src/lib/audio/audio-effects';
import RobotEffect from '../../../src/lib/audio/effects/robot-effect';
import EchoEffect from '../../../src/lib/audio/effects/echo-effect';
import VolumeEffect from '../../../src/lib/audio/effects/volume-effect';

describe('Audio Effects manager', () => {
    const audioContext = new AudioContext();
    const audioBuffer = audioContext.createBuffer(1, 400, 44100);

    test('changes buffer length and playback rate for faster effect', () => {
        const audioEffects = new AudioEffects(audioBuffer, 'faster', 0, 1);
        expect(audioEffects.audioContext._.length).toBeLessThan(400);
    });

    test('changes buffer length  and playback rate for slower effect', () => {
        const audioEffects = new AudioEffects(audioBuffer, 'slower', 0, 1);
        expect(audioEffects.audioContext._.length).toBeGreaterThan(400);
    });

    test('changes buffer length for echo effect', () => {
        const audioEffects = new AudioEffects(audioBuffer, 'echo', 0, 1);
        expect(audioEffects.audioContext._.length).toBeGreaterThan(400);
    });

    test('updates the trim positions after an effect has changed the length of selection', () => {
        const slowerEffect = new AudioEffects(audioBuffer, 'slower', 0.25, 0.75);
        expect(slowerEffect.adjustedTrimStartSeconds).toEqual(slowerEffect.trimStartSeconds);
        expect(slowerEffect.adjustedTrimEndSeconds).toBeGreaterThan(slowerEffect.trimEndSeconds);

        const fasterEffect = new AudioEffects(audioBuffer, 'faster', 0.25, 0.75);
        expect(fasterEffect.adjustedTrimStartSeconds).toEqual(fasterEffect.trimStartSeconds);
        expect(fasterEffect.adjustedTrimEndSeconds).toBeLessThan(fasterEffect.trimEndSeconds);

        // Some effects do not change the length of the selection
        const fadeEffect = new AudioEffects(audioBuffer, 'fade in', 0.25, 0.75);
        expect(fadeEffect.adjustedTrimStartSeconds).toEqual(fadeEffect.trimStartSeconds);
        // Should be within one millisecond (flooring can change the duration by one sample)
        expect(fadeEffect.adjustedTrimEndSeconds).toBeCloseTo(fadeEffect.trimEndSeconds, 3);
    });

    test.skip('process starts the offline rendering context and returns a promise', () => {
        // @todo haven't been able to get web audio test api to actually run render
    });

    test('reverse effect strictly reverses the samples', () => {
        const fakeSound = [1, 2, 3, 4, 5, 6, 7, 8];

        const fakeBuffer = audioContext.createBuffer(1, 8, 44100);
        const bufferData = fakeBuffer.getChannelData(0);
        fakeSound.forEach((sample, index) => {
            bufferData[index] = sample;
        });

        // Reverse the entire sound
        const reverseAll = new AudioEffects(fakeBuffer, 'reverse', 0, 1);
        expect(Array.from(reverseAll.buffer.getChannelData(0))).toEqual(fakeSound.reverse());

        // Reverse part of the sound
        const reverseSelection = new AudioEffects(fakeBuffer, 'reverse', 0.25, 0.75);
        const selectionReversed = [1, 2, 6, 5, 4, 3, 7, 8];
        expect(Array.from(reverseSelection.buffer.getChannelData(0))).toEqual(selectionReversed);
    });
});

describe('Effects', () => {
    let audioContext;

    beforeEach(() => {
        audioContext = new AudioContext();
    });

    test('all effects provide an input and output that are connected', () => {
        const robotEffect = new RobotEffect(audioContext, 0, 1);
        expect(robotEffect.input).toBeInstanceOf(AudioNode);
        expect(robotEffect.output).toBeInstanceOf(AudioNode);

        const echoEffect = new EchoEffect(audioContext, 0, 1);
        expect(echoEffect.input).toBeInstanceOf(AudioNode);
        expect(echoEffect.output).toBeInstanceOf(AudioNode);

        const volumeEffect = new VolumeEffect(audioContext, 0.5, 0, 1);
        expect(volumeEffect.input).toBeInstanceOf(AudioNode);
        expect(volumeEffect.output).toBeInstanceOf(AudioNode);
    });
});