1/* 2signal.test.mjs - <short description TODO> 3Copyright (C) 2022 Strudel contributors - see <https://codeberg.org/uzu/strudel/src/branch/main/packages/core/test/pattern.test.mjs> 4This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>. 5*/ 6 7import Fraction from 'fraction.js'; 8 9import { describe, it, expect, vi } from 'vitest'; 10 11import { 12 saw, 13 saw2, 14 isaw, 15 isaw2, 16 tri, 17 tri2, 18 itri, 19 itri2, 20 square, 21 square2, 22 isquare, 23 isquare2, 24 per, 25 perx, 26 cyclesPer, 27} from '../signal.mjs'; 28import { fastcat, sequence, State, TimeSpan, Hap, note } from '../index.mjs'; 29 30const st = (begin, end) => new State(ts(begin, end)); 31const ts = (begin, end) => new TimeSpan(Fraction(begin), Fraction(end)); 32const hap = (whole, part, value, context = {}) => new Hap(whole, part, value, context); 33 34const third = Fraction(1, 3); 35const twothirds = Fraction(2, 3); 36 37const sameFirst = (a, b) => { 38 return expect(a.sortHapsByPart().firstCycle()).toStrictEqual(b.sortHapsByPart().firstCycle()); 39}; 40 41describe('signal()', () => { 42 it('Can make saw/saw2', () => { 43 expect(saw.struct(true, true, true, true).firstCycle()).toStrictEqual(sequence(0, 0.25, 0.5, 0.75).firstCycle()); 44 expect(saw2.struct(true, true, true, true).firstCycle()).toStrictEqual(sequence(-1, -0.5, 0, 0.5).firstCycle()); 45 }); 46 it('Can make isaw/isaw2', () => { 47 expect(isaw.struct(true, true, true, true).firstCycle()).toStrictEqual(sequence(1, 0.75, 0.5, 0.25).firstCycle()); 48 expect(isaw2.struct(true, true, true, true).firstCycle()).toStrictEqual(sequence(1, 0.5, 0, -0.5).firstCycle()); 49 }); 50 it('Can make tri/tri2', () => { 51 expect(tri.struct(true, true, true, true).firstCycle()).toStrictEqual(sequence(0, 0.5, 1, 0.5).firstCycle()); 52 expect(tri2.struct(true, true, true, true).firstCycle()).toStrictEqual(sequence(-1, 0, 1, 0).firstCycle()); 53 }); 54 it('Can make itri/itri2', () => { 55 expect(itri.struct(true, true, true, true).firstCycle()).toStrictEqual(sequence(1, 0.5, 0, 0.5).firstCycle()); 56 expect(itri2.struct(true, true, true, true).firstCycle()).toStrictEqual(sequence(1, 0, -1, 0).firstCycle()); 57 }); 58 it('Can make square/square2', () => { 59 expect(square.struct(true, true, true, true).firstCycle()).toStrictEqual(sequence(0, 0, 1, 1).firstCycle()); 60 expect(square2.struct(true, true, true, true).firstCycle()).toStrictEqual(sequence(-1, -1, 1, 1).firstCycle()); 61 }); 62 it('Can make isquare/isquare2', () => { 63 expect(isquare.struct(true, true, true, true).firstCycle()).toStrictEqual(sequence(1, 1, 0, 0).firstCycle()); 64 expect(isquare2.struct(true, true, true, true).firstCycle()).toStrictEqual(sequence(1, 1, -1, -1).firstCycle()); 65 }); 66 it('Can go into negative time', () => { 67 expect(saw.late(1).struct(true, true, true, true).firstCycle()).toStrictEqual( 68 sequence(0, 0.25, 0.5, 0.75).firstCycle(), 69 ); 70 expect(saw2.late(1).struct(true, true, true, true).firstCycle()).toStrictEqual( 71 sequence(-1, -0.5, 0, 0.5).firstCycle(), 72 ); 73 expect(isaw.late(1).struct(true, true, true, true).firstCycle()).toStrictEqual( 74 sequence(1, 0.75, 0.5, 0.25).firstCycle(), 75 ); 76 expect(isaw2.late(1).struct(true, true, true, true).firstCycle()).toStrictEqual( 77 sequence(1, 0.5, 0, -0.5).firstCycle(), 78 ); 79 expect(tri.late(1).struct(true, true, true, true).firstCycle()).toStrictEqual( 80 sequence(0, 0.5, 1, 0.5).firstCycle(), 81 ); 82 expect(tri2.late(1).struct(true, true, true, true).firstCycle()).toStrictEqual(sequence(-1, 0, 1, 0).firstCycle()); 83 expect(itri.late(1).struct(true, true, true, true).firstCycle()).toStrictEqual( 84 sequence(1, 0.5, 0, 0.5).firstCycle(), 85 ); 86 expect(itri2.late(1).struct(true, true, true, true).firstCycle()).toStrictEqual(sequence(1, 0, -1, 0).firstCycle()); 87 expect(square.late(1).struct(true, true, true, true).firstCycle()).toStrictEqual(sequence(0, 0, 1, 1).firstCycle()); 88 expect(square2.late(1).struct(true, true, true, true).firstCycle()).toStrictEqual( 89 sequence(-1, -1, 1, 1).firstCycle(), 90 ); 91 expect(isquare.late(1).struct(true, true, true, true).firstCycle()).toStrictEqual( 92 sequence(1, 1, 0, 0).firstCycle(), 93 ); 94 expect(isquare2.late(1).struct(true, true, true, true).firstCycle()).toStrictEqual( 95 sequence(1, 1, -1, -1).firstCycle(), 96 ); 97 }); 98}); 99 100describe('cyclesPer', () => { 101 it('gives cycles per hap', () => { 102 sameFirst( 103 cyclesPer.struct(true, true, true, fastcat(true, true)), 104 sequence(0.25, 0.25, 0.25, fastcat(0.125, 0.125)).fmap(Fraction), 105 ); 106 }); 107}); 108describe('per', () => { 109 it('gives haps per cycle', () => { 110 sameFirst(per.struct(true, true, true, fastcat(true, true)), sequence(4, 4, 4, fastcat(8, 8)).fmap(Fraction)); 111 }); 112}); 113 114describe('perx', () => { 115 it('gives exponential haps per cycle', () => { 116 sameFirst( 117 perx.struct(true, true, true, fastcat(true, fastcat(true, true))), 118 sequence(3, 3, 3, fastcat(4, fastcat(5, 5))), 119 ); 120 }); 121}); 122 123describe('shuffle', () => { 124 it('returns original pattern if input is 1', () => { 125 expect(note('c d e f').sound('piano').shuffle(1).firstCycle()).toEqual(note('c d e f').sound('piano').firstCycle()); 126 }); 127});