File size: 4,064 Bytes
6bcb42f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
93
94
95
96
97
98
99
100
101
102
103
import {
    computeRMS,
    computeChunkedRMS,
    downsampleIfNeeded,
    dropEveryOtherSample
} from '../../../src/lib/audio/audio-util';

describe('computeRMS', () => {
    test('returns 0 when given no samples', () => {
        expect(computeRMS([])).toEqual(0);
    });
    test('returns the RMS scaled by the given unity value and square rooted', () => {
        const unity = 0.5;
        const samples = [3, 2, 1];
        expect(computeRMS(samples, unity)).toEqual(
            Math.sqrt(Math.sqrt(((3 * 3) + (2 * 2) + (1 * 1)) / 3) / 0.5)
        );
    });
    test('uses a default unity value of 0.55', () => {
        const samples = [1, 1, 1];
        // raw rms is 1, scaled to (1 / 0.55) and square rooted
        expect(computeRMS(samples)).toEqual(Math.sqrt(1 / 0.55));
    });
});


describe('computeChunkedRMS', () => {
    test('computes the rms for each chunk based on chunk size', () => {
        const samples = [2, 1, 3, 2, 5];
        const chunkedLevels = computeChunkedRMS(samples, 2);
        // chunked to [2, 0], [3, 0], [5]
        // rms scaled with default unity of 0.55
        expect(chunkedLevels.length).toEqual(3);
        expect(chunkedLevels).toEqual([
            Math.sqrt(Math.sqrt(((2 * 2) + (1 * 1)) / 2) / 0.55),
            Math.sqrt(Math.sqrt(((3 * 3) + (2 * 2)) / 2) / 0.55),
            Math.sqrt(Math.sqrt((5 * 5) / 1) / 0.55)
        ]);
    });
    test('chunk size larger than sample size creates single chunk', () => {
        const samples = [1, 1, 1];
        const chunkedLevels = computeChunkedRMS(samples, 7);
        // chunked to [1, 1, 1]
        // rms scaled with default unity of 0.55
        expect(chunkedLevels.length).toEqual(1);
        expect(chunkedLevels).toEqual([Math.sqrt(1 / 0.55)]);
    });
    test('chunk size as multiple is handled correctly', () => {
        const samples = [1, 1, 1, 1, 1, 1];
        const chunkedLevels = computeChunkedRMS(samples, 3);
        // chunked to [1, 1, 1], [1, 1, 1]
        // rms scaled with default unity of 0.55
        expect(chunkedLevels.length).toEqual(2);
        expect(chunkedLevels).toEqual([Math.sqrt(1 / 0.55), Math.sqrt(1 / 0.55)]);
    });
});

describe('downsampleIfNeeded', () => {
    const samples = {length: 1};
    const sampleRate = 44100;
    test('returns given data when no downsampling needed', async () => {
        samples.length = 1;
        const res = await downsampleIfNeeded({samples, sampleRate}, null);
        expect(res.samples).toEqual(samples);
        expect(res.sampleRate).toEqual(sampleRate);
    });
    test('downsamples to 22050 if that puts it under the limit', async () => {
        samples.length = 44100 * 3 * 60;
        const resampler = jest.fn(() => 'TEST');
        const res = await downsampleIfNeeded({samples, sampleRate}, resampler);
        expect(resampler).toHaveBeenCalledWith({samples, sampleRate}, 22050);
        expect(res).toEqual('TEST');
    });
    // TW: We allow resampling even if it would exceed the limit because our GUI handles this better.
    test.skip('fails if resampling would not put it under the limit', async () => {
        samples.length = 44100 * 4 * 60;
        try {
            await downsampleIfNeeded({samples, sampleRate}, null);
        } catch (e) {
            expect(e.message).toEqual('Sound too large to save, refusing to edit');
        }
    });
});

describe('dropEveryOtherSample', () => {
    const buffer = {
        samples: [1, 0, 2, 0, 3, 0],
        sampleRate: 2
    };
    test('result is half the length', () => {
        const {samples} = dropEveryOtherSample(buffer);
        expect(samples.length).toEqual(Math.floor(buffer.samples.length / 2));
    });
    test('result contains only even-index items', () => {
        const {samples} = dropEveryOtherSample(buffer);
        expect(samples).toEqual(new Float32Array([1, 2, 3]));
    });
    test('result sampleRate is given sampleRate / 2', () => {
        const {sampleRate} = dropEveryOtherSample(buffer);
        expect(sampleRate).toEqual(buffer.sampleRate / 2);
    });
});