Skip to content

Commit

Permalink
Implement arithmetically accumulative repetition
Browse files Browse the repository at this point in the history
ref #281
  • Loading branch information
frostburn committed May 3, 2024
1 parent e86e3c5 commit 456207d
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 3 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ The `sonic-weave` package is many things.

You may also be interested in the [technical overview](https://github.com/xenharmonic-devs/sonic-weave/blob/main/documentation/technical.md) of SonicWeave as a programming language.

Appendix: [tempering](https://github.com/xenharmonic-devs/sonic-weave/blob/main/documentation/tempering.md), [commas](https://github.com/xenharmonic-devs/sonic-weave/blob/main/documentation/commas.md)

## Highlights
Harmonic segment from the 8th harmonic to the 16th (repeating at the octave).
```c
Expand Down
6 changes: 6 additions & 0 deletions documentation/BUILTIN.md
Original file line number Diff line number Diff line change
Expand Up @@ -659,6 +659,12 @@ Stack the current scale on top of itself. Clears the scale if the number of repe
### repeated(*times = 2*, *scale = $$*)
Stack the current/given scale on top of itself.

### repeatedLinear(*times = 2*, *scale = $$*)
Repeat the current/given scale shifted linearly each time.

### repeatLinear(*times = 2*, *scale = $$*)
Repeat the current/given scale shifted linearly each time. Clears the scale if the number of repeats is zero.

### replace(*interval*, *replacement*, *scale = $$*)
Replace occurences of `interval` in the current/given scale by `replacement`.

Expand Down
4 changes: 3 additions & 1 deletion documentation/advanced-dsl.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ See [BUILTIN.md](https://github.com/xenharmonic-devs/sonic-weave/blob/main/docum

### Highlights

Many helper functions have an arithmetic and geometric variants.
Many helper functions have arithmetic and geometric variants.

| Action | Linear | Logarithmic | Logarithmic (accumulative) |
| ---------------- | ---------------- | -------------- | ----------------------------- |
Expand All @@ -217,6 +217,8 @@ Many helper functions have an arithmetic and geometric variants.
| Stacking | `stackLinear()` | `stack()` | *N/A* |
| Repeating | `flatRepeat()` | `flatRepeat()` | `repeat()` |

There's also the linearly accumulating `repeatLinear()` for repeating harmonic segments arithmetically.

## Issues with the decimal separator
To be backwards compatible with Scale Workshop versions 1 and 2, SonicWeave preserves the syntax for "dot cents" and "comma decimals".

Expand Down
25 changes: 25 additions & 0 deletions src/parser/__tests__/stdlib.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1417,4 +1417,29 @@ describe('SonicWeave standard library', () => {
'An interval is required.'
);
});

it('can repeat harmonics linearly (fifth to octave)', () => {
const scale = expand('6:7:9;repeatLinear()');
expect(scale).toEqual(['7/6', '9/6', '10/6', '12/6']);
});

it('can repeat harmonics linearly (octave to double octave)', () => {
const scale = expand('3:5:6;repeatLinear(3)');
expect(scale).toEqual(['5/3', '6/3', '8/3', '9/3', '11/3', '12/3']);
});

it('can repeat JI linearly (fourth to octave)', () => {
const scale = expand('10/9;7/6;4/3;repeatLinear(3)');
expect(scale).toEqual([
'10/9',
'7/6',
'4/3',
'13/9',
'9/6',
'5/3',
'16/9',
'11/6',
'6/3',
]);
});
});
22 changes: 20 additions & 2 deletions src/stdlib/prelude.ts
Original file line number Diff line number Diff line change
Expand Up @@ -772,9 +772,8 @@ riff rotated(onto = 1, scale = $$) {
riff repeated(times = 2, scale = $$) {
"Stack the current/given scale on top of itself.";
if (not times) {
if (not times)
return [];
}
scale;
const equave = scale[-1];
for (const level of equave ~^ [1..times-1])
Expand All @@ -790,6 +789,25 @@ riff repeat(times = 2, scale = $$) {
return;
}
riff repeatedLinear(times = 2, scale = $$) {
"Repeat the current/given scale shifted linearly each time.";
if (not times)
return [];
scale;
const total = (scale[-1] ~- 1);
for (const level of total ~* [1..times-1])
(scale ~- 1) ~+ level ~+ 1;
}
riff repeatLinear(times = 2, scale = $$) {
"Repeat the current/given scale shifted linearly each time. Clears the scale if the number of repeats is zero.";
$ = scale;
const segment = $[..];
clear();
repeatedLinear(times, segment);
return;
}
riff flatRepeat(times = 2, scale = $$) {
"Repeat the current/given intervals as-is without accumulating equaves. Clears the scale if the number of repeats is zero.";
$ = scale;
Expand Down

0 comments on commit 456207d

Please sign in to comment.