Merge branch 'main' into sync_midi_timing
This commit is contained in:
commit
a1bd905c06
9 changed files with 227 additions and 31 deletions
|
|
@ -1750,17 +1750,64 @@ export const { semitone } = registerControl('semitone');
|
||||||
// TODO: synth param
|
// TODO: synth param
|
||||||
export const { voice } = registerControl('voice');
|
export const { voice } = registerControl('voice');
|
||||||
// voicings // https://codeberg.org/uzu/strudel/issues/506
|
// voicings // https://codeberg.org/uzu/strudel/issues/506
|
||||||
// chord to voice, like C Eb Fm7 G7. the symbols can be defined via addVoicings
|
/**
|
||||||
|
* The chord to voice
|
||||||
|
* @name chord
|
||||||
|
* @param {string | Pattern} symbols chord symbols to voice e.g., C, Eb, Fm7, G7. The symbols can be defined via addVoicings
|
||||||
|
* @example
|
||||||
|
* chord("<Am C D F Am E Am E>").voicing()
|
||||||
|
**/
|
||||||
export const { chord } = registerControl('chord');
|
export const { chord } = registerControl('chord');
|
||||||
// which dictionary to use for the voicings
|
/**
|
||||||
|
* Which dictionary to use for the voicings. This falls back to the default dictionary if not provided
|
||||||
|
*
|
||||||
|
* @name dictionary
|
||||||
|
* @param {string} dictionaryName which dictionary (having been defined with `addVoicings`) to use
|
||||||
|
* @example
|
||||||
|
* addVoicings('house', {
|
||||||
|
'': ['7 12 16', '0 7 16', '4 7 12'],
|
||||||
|
'm': ['0 3 7']
|
||||||
|
})
|
||||||
|
chord("<Am C D F Am E Am E>")
|
||||||
|
.dict('house').anchor(66)
|
||||||
|
.voicing().room(.5)
|
||||||
|
**/
|
||||||
export const { dictionary, dict } = registerControl('dictionary', 'dict');
|
export const { dictionary, dict } = registerControl('dictionary', 'dict');
|
||||||
// the top note to align the voicing to, defaults to c5
|
/** The top note to align the voicing to. Defaults to c5
|
||||||
|
*
|
||||||
|
* @name anchor
|
||||||
|
* @param {string | Pattern} anchorNote the note to align the voicings to
|
||||||
|
* @example
|
||||||
|
* anchor("<c4 g4 c5 g5>").chord("C").voicing()
|
||||||
|
**/
|
||||||
export const { anchor } = registerControl('anchor');
|
export const { anchor } = registerControl('anchor');
|
||||||
// how the voicing is offset from the anchored position
|
/**
|
||||||
|
* Sets how the voicing is offset from the anchored position
|
||||||
|
*
|
||||||
|
* @name offset
|
||||||
|
* @param {number | Pattern} shift the amount to shift the voicing up or down
|
||||||
|
* @example
|
||||||
|
* chord("<Am C D F Am E Am E>").offset("<0 1 2 3 4 5>") // alter the voicing each time
|
||||||
|
**/
|
||||||
export const { offset } = registerControl('offset');
|
export const { offset } = registerControl('offset');
|
||||||
// how many octaves are voicing steps spread apart, defaults to 1
|
/**
|
||||||
|
* How many octaves are voicing steps spread apart, defaults to 1
|
||||||
|
*
|
||||||
|
* @name octaves
|
||||||
|
* @param {number | Pattern} count the number of octaves
|
||||||
|
* @example
|
||||||
|
* chord("<Am C D F Am E Am E>").octaves("<2 4>").voicing()
|
||||||
|
**/
|
||||||
export const { octaves } = registerControl('octaves');
|
export const { octaves } = registerControl('octaves');
|
||||||
// below = anchor note will be removed from the voicing, useful for melody harmonization
|
/**
|
||||||
|
* Remove anchor note from the voicing. Useful for melody harmonization
|
||||||
|
*
|
||||||
|
* @name mode
|
||||||
|
* @param {string | Pattern} modeName one of {below | above | duck | root}
|
||||||
|
* @example
|
||||||
|
* mode("<below above duck root>").chord("C").voicing()
|
||||||
|
*
|
||||||
|
**/
|
||||||
export const { mode } = registerControl(['mode', 'anchor']);
|
export const { mode } = registerControl(['mode', 'anchor']);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,12 @@ const pattern = sequence([
|
||||||
- D-Pad
|
- D-Pad
|
||||||
- `up`, `down`, `left`, `right` (or `u`, `d`, `l`, `r` or uppercase)
|
- `up`, `down`, `left`, `right` (or `u`, `d`, `l`, `r` or uppercase)
|
||||||
- Toggle versions: `tglUp`, `tglDown`, `tglLeft`, `tglRight`(or `tglU`, `tglD`, `tglL`, `tglR`)
|
- Toggle versions: `tglUp`, `tglDown`, `tglLeft`, `tglRight`(or `tglU`, `tglD`, `tglL`, `tglR`)
|
||||||
|
- Stick Buttons
|
||||||
|
- `l3`, `r3` (or `ls`, `rs`)
|
||||||
|
- Toggle versions: `tglL3`, `tglR3` (or `tglLS`, `tglRS`)
|
||||||
|
- System Buttons
|
||||||
|
- `start`, `back` (or uppercase `START`, `BACK`)
|
||||||
|
- Toggle versions: `tglStart`, `tglBack` (or `tglSTART`, `tglBACK`)
|
||||||
|
|
||||||
### Analog Sticks
|
### Analog Sticks
|
||||||
- Left Stick
|
- Left Stick
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,10 @@ The gamepad module provides access to buttons and analog sticks as normalized si
|
||||||
| | Toggle versions: `tglLB`, `tglRB`, `tglLT`, `tglRT` |
|
| | Toggle versions: `tglLB`, `tglRB`, `tglLT`, `tglRT` |
|
||||||
| D-Pad | `up`, `down`, `left`, `right` (or `u`, `d`, `l`, `r` or uppercase) |
|
| D-Pad | `up`, `down`, `left`, `right` (or `u`, `d`, `l`, `r` or uppercase) |
|
||||||
| | Toggle versions: `tglUp`, `tglDown`, `tglLeft`, `tglRight` (or `tglU`, `tglD`, `tglL`, `tglR`) |
|
| | Toggle versions: `tglUp`, `tglDown`, `tglLeft`, `tglRight` (or `tglU`, `tglD`, `tglL`, `tglR`) |
|
||||||
|
| Stick Buttons | `l3`, 'r3' (or `ls`, `rs`) |
|
||||||
|
| | Toggle versions: `tglL3`, 'tglR3' (or `tglLs`, `tglRs`) |
|
||||||
|
| System Buttons | `start`, `back` (or uppercase `START`, `BACK`) |
|
||||||
|
| | Toggle versions: `tglStart`, `tglBack` (or `tglSTART`, `tglBACK`) |
|
||||||
|
|
||||||
### Analog Sticks
|
### Analog Sticks
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,10 @@ export const buttonMap = {
|
||||||
rt: 7,
|
rt: 7,
|
||||||
back: 8,
|
back: 8,
|
||||||
start: 9,
|
start: 9,
|
||||||
|
l3: 10,
|
||||||
|
ls: 10,
|
||||||
|
r3: 11,
|
||||||
|
rs: 11,
|
||||||
u: 12,
|
u: 12,
|
||||||
up: 12,
|
up: 12,
|
||||||
d: 13,
|
d: 13,
|
||||||
|
|
|
||||||
|
|
@ -840,6 +840,31 @@ exports[`runs examples > example "amp" example index 0 1`] = `
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "anchor" example index 0 1`] = `
|
||||||
|
[
|
||||||
|
"[ 0/1 → 1/1 | note:E2 ]",
|
||||||
|
"[ 0/1 → 1/1 | note:C3 ]",
|
||||||
|
"[ 0/1 → 1/1 | note:E3 ]",
|
||||||
|
"[ 0/1 → 1/1 | note:G3 ]",
|
||||||
|
"[ 0/1 → 1/1 | note:C4 ]",
|
||||||
|
"[ 1/1 → 2/1 | note:C3 ]",
|
||||||
|
"[ 1/1 → 2/1 | note:G3 ]",
|
||||||
|
"[ 1/1 → 2/1 | note:C4 ]",
|
||||||
|
"[ 1/1 → 2/1 | note:E4 ]",
|
||||||
|
"[ 1/1 → 2/1 | note:G4 ]",
|
||||||
|
"[ 2/1 → 3/1 | note:E3 ]",
|
||||||
|
"[ 2/1 → 3/1 | note:C4 ]",
|
||||||
|
"[ 2/1 → 3/1 | note:E4 ]",
|
||||||
|
"[ 2/1 → 3/1 | note:G4 ]",
|
||||||
|
"[ 2/1 → 3/1 | note:C5 ]",
|
||||||
|
"[ 3/1 → 4/1 | note:C4 ]",
|
||||||
|
"[ 3/1 → 4/1 | note:G4 ]",
|
||||||
|
"[ 3/1 → 4/1 | note:C5 ]",
|
||||||
|
"[ 3/1 → 4/1 | note:E5 ]",
|
||||||
|
"[ 3/1 → 4/1 | note:G5 ]",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`runs examples > example "apply" example index 0 1`] = `
|
exports[`runs examples > example "apply" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/1 | note:C3 ]",
|
"[ 0/1 → 1/1 | note:C3 ]",
|
||||||
|
|
@ -1847,6 +1872,31 @@ exports[`runs examples > example "chop" example index 0 1`] = `
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "chord" example index 0 1`] = `
|
||||||
|
[
|
||||||
|
"[ 0/1 → 1/1 | note:A3 ]",
|
||||||
|
"[ 0/1 → 1/1 | note:C4 ]",
|
||||||
|
"[ 0/1 → 1/1 | note:E4 ]",
|
||||||
|
"[ 0/1 → 1/1 | note:A4 ]",
|
||||||
|
"[ 0/1 → 1/1 | note:C5 ]",
|
||||||
|
"[ 1/1 → 2/1 | note:E3 ]",
|
||||||
|
"[ 1/1 → 2/1 | note:C4 ]",
|
||||||
|
"[ 1/1 → 2/1 | note:E4 ]",
|
||||||
|
"[ 1/1 → 2/1 | note:G4 ]",
|
||||||
|
"[ 1/1 → 2/1 | note:C5 ]",
|
||||||
|
"[ 2/1 → 3/1 | note:D3 ]",
|
||||||
|
"[ 2/1 → 3/1 | note:A3 ]",
|
||||||
|
"[ 2/1 → 3/1 | note:D4 ]",
|
||||||
|
"[ 2/1 → 3/1 | note:Gb4 ]",
|
||||||
|
"[ 2/1 → 3/1 | note:A4 ]",
|
||||||
|
"[ 3/1 → 4/1 | note:F3 ]",
|
||||||
|
"[ 3/1 → 4/1 | note:C4 ]",
|
||||||
|
"[ 3/1 → 4/1 | note:F4 ]",
|
||||||
|
"[ 3/1 → 4/1 | note:A4 ]",
|
||||||
|
"[ 3/1 → 4/1 | note:C5 ]",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`runs examples > example "chorus" example index 0 1`] = `
|
exports[`runs examples > example "chorus" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/4 | note:d s:sawtooth chorus:0.5 ]",
|
"[ 0/1 → 1/4 | note:d s:sawtooth chorus:0.5 ]",
|
||||||
|
|
@ -2739,6 +2789,23 @@ exports[`runs examples > example "detune" example index 0 1`] = `
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "dictionary" example index 0 1`] = `
|
||||||
|
[
|
||||||
|
"[ 0/1 → 1/1 | note:A3 room:0.5 ]",
|
||||||
|
"[ 0/1 → 1/1 | note:C4 room:0.5 ]",
|
||||||
|
"[ 0/1 → 1/1 | note:E4 room:0.5 ]",
|
||||||
|
"[ 1/1 → 2/1 | note:G3 room:0.5 ]",
|
||||||
|
"[ 1/1 → 2/1 | note:C4 room:0.5 ]",
|
||||||
|
"[ 1/1 → 2/1 | note:E4 room:0.5 ]",
|
||||||
|
"[ 2/1 → 3/1 | note:A3 room:0.5 ]",
|
||||||
|
"[ 2/1 → 3/1 | note:D4 room:0.5 ]",
|
||||||
|
"[ 2/1 → 3/1 | note:Gb4 room:0.5 ]",
|
||||||
|
"[ 3/1 → 4/1 | note:A3 room:0.5 ]",
|
||||||
|
"[ 3/1 → 4/1 | note:C4 room:0.5 ]",
|
||||||
|
"[ 3/1 → 4/1 | note:F4 room:0.5 ]",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`runs examples > example "distort" example index 0 1`] = `
|
exports[`runs examples > example "distort" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/8 | s:hh distort:0 ]",
|
"[ 0/1 → 1/8 | s:hh distort:0 ]",
|
||||||
|
|
@ -6496,6 +6563,28 @@ exports[`runs examples > example "miditouch" example index 0 1`] = `
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "mode" example index 0 1`] = `
|
||||||
|
[
|
||||||
|
"[ 0/1 → 1/1 | note:E3 ]",
|
||||||
|
"[ 0/1 → 1/1 | note:C4 ]",
|
||||||
|
"[ 0/1 → 1/1 | note:E4 ]",
|
||||||
|
"[ 0/1 → 1/1 | note:G4 ]",
|
||||||
|
"[ 0/1 → 1/1 | note:C5 ]",
|
||||||
|
"[ 1/1 → 2/1 | note:C5 ]",
|
||||||
|
"[ 1/1 → 2/1 | note:G5 ]",
|
||||||
|
"[ 1/1 → 2/1 | note:C6 ]",
|
||||||
|
"[ 1/1 → 2/1 | note:E6 ]",
|
||||||
|
"[ 2/1 → 3/1 | note:E3 ]",
|
||||||
|
"[ 2/1 → 3/1 | note:C4 ]",
|
||||||
|
"[ 2/1 → 3/1 | note:E4 ]",
|
||||||
|
"[ 2/1 → 3/1 | note:G4 ]",
|
||||||
|
"[ 3/1 → 4/1 | note:C5 ]",
|
||||||
|
"[ 3/1 → 4/1 | note:G5 ]",
|
||||||
|
"[ 3/1 → 4/1 | note:C6 ]",
|
||||||
|
"[ 3/1 → 4/1 | note:E6 ]",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`runs examples > example "morph" example index 0 1`] = `
|
exports[`runs examples > example "morph" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/8 | s:hh ]",
|
"[ 0/1 → 1/8 | s:hh ]",
|
||||||
|
|
@ -6814,6 +6903,31 @@ exports[`runs examples > example "octave" example index 0 1`] = `
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "octaves" example index 0 1`] = `
|
||||||
|
[
|
||||||
|
"[ 0/1 → 1/1 | note:A3 ]",
|
||||||
|
"[ 0/1 → 1/1 | note:C4 ]",
|
||||||
|
"[ 0/1 → 1/1 | note:E4 ]",
|
||||||
|
"[ 0/1 → 1/1 | note:A4 ]",
|
||||||
|
"[ 0/1 → 1/1 | note:C5 ]",
|
||||||
|
"[ 1/1 → 2/1 | note:E3 ]",
|
||||||
|
"[ 1/1 → 2/1 | note:C4 ]",
|
||||||
|
"[ 1/1 → 2/1 | note:E4 ]",
|
||||||
|
"[ 1/1 → 2/1 | note:G4 ]",
|
||||||
|
"[ 1/1 → 2/1 | note:C5 ]",
|
||||||
|
"[ 2/1 → 3/1 | note:D3 ]",
|
||||||
|
"[ 2/1 → 3/1 | note:A3 ]",
|
||||||
|
"[ 2/1 → 3/1 | note:D4 ]",
|
||||||
|
"[ 2/1 → 3/1 | note:Gb4 ]",
|
||||||
|
"[ 2/1 → 3/1 | note:A4 ]",
|
||||||
|
"[ 3/1 → 4/1 | note:F3 ]",
|
||||||
|
"[ 3/1 → 4/1 | note:C4 ]",
|
||||||
|
"[ 3/1 → 4/1 | note:F4 ]",
|
||||||
|
"[ 3/1 → 4/1 | note:A4 ]",
|
||||||
|
"[ 3/1 → 4/1 | note:C5 ]",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`runs examples > example "off" example index 0 1`] = `
|
exports[`runs examples > example "off" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ -5/24 ⇜ (0/1 → 1/8) | note:62 ]",
|
"[ -5/24 ⇜ (0/1 → 1/8) | note:62 ]",
|
||||||
|
|
@ -6847,6 +6961,15 @@ exports[`runs examples > example "off" example index 0 1`] = `
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "offset" example index 0 1`] = `
|
||||||
|
[
|
||||||
|
"[ 0/1 → 1/1 | chord:Am offset:0 ]",
|
||||||
|
"[ 1/1 → 2/1 | chord:C offset:1 ]",
|
||||||
|
"[ 2/1 → 3/1 | chord:D offset:2 ]",
|
||||||
|
"[ 3/1 → 4/1 | chord:F offset:3 ]",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`runs examples > example "often" example index 0 1`] = `
|
exports[`runs examples > example "often" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/8 | s:hh speed:0.5 ]",
|
"[ 0/1 → 1/8 | s:hh speed:0.5 ]",
|
||||||
|
|
|
||||||
|
|
@ -79,13 +79,11 @@ const updateCodeWindow = (context, patternData, reset = false) => {
|
||||||
context.handleUpdate(patternData, reset);
|
context.handleUpdate(patternData, reset);
|
||||||
};
|
};
|
||||||
|
|
||||||
const autoResetPatternOnChange = !isUdels();
|
|
||||||
|
|
||||||
function UserPatterns({ context }) {
|
function UserPatterns({ context }) {
|
||||||
const activePattern = useActivePattern();
|
const activePattern = useActivePattern();
|
||||||
const viewingPatternStore = useViewingPatternData();
|
const viewingPatternStore = useViewingPatternData();
|
||||||
const viewingPatternData = parseJSON(viewingPatternStore);
|
const viewingPatternData = parseJSON(viewingPatternStore);
|
||||||
const { userPatterns, patternFilter } = useSettings();
|
const { userPatterns, patternFilter, patternAutoStart } = useSettings();
|
||||||
const viewingPatternID = viewingPatternData?.id;
|
const viewingPatternID = viewingPatternData?.id;
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-2 flex-grow overflow-hidden h-full pb-2 ">
|
<div className="flex flex-col gap-2 flex-grow overflow-hidden h-full pb-2 ">
|
||||||
|
|
@ -135,13 +133,13 @@ function UserPatterns({ context }) {
|
||||||
<div className="overflow-auto h-full bg-background p-2 rounded-md">
|
<div className="overflow-auto h-full bg-background p-2 rounded-md">
|
||||||
{/* {patternFilter === patternFilterName.user && ( */}
|
{/* {patternFilter === patternFilterName.user && ( */}
|
||||||
<PatternButtons
|
<PatternButtons
|
||||||
onClick={(id) =>
|
onClick={(id) => {
|
||||||
updateCodeWindow(
|
updateCodeWindow(context, { ...userPatterns[id], collection: userPattern.collection }, patternAutoStart);
|
||||||
context,
|
|
||||||
{ ...userPatterns[id], collection: userPattern.collection },
|
if (context.started && activePattern === id) {
|
||||||
autoResetPatternOnChange,
|
context.handleEvaluate();
|
||||||
)
|
}
|
||||||
}
|
}}
|
||||||
patterns={userPatterns}
|
patterns={userPatterns}
|
||||||
started={context.started}
|
started={context.started}
|
||||||
activePattern={activePattern}
|
activePattern={activePattern}
|
||||||
|
|
@ -188,17 +186,14 @@ function FeaturedPatterns({ context }) {
|
||||||
const examplePatterns = useExamplePatterns();
|
const examplePatterns = useExamplePatterns();
|
||||||
const collections = examplePatterns.collections;
|
const collections = examplePatterns.collections;
|
||||||
const patterns = collections.get(patternFilterName.featured);
|
const patterns = collections.get(patternFilterName.featured);
|
||||||
|
const { patternAutoStart } = useSettings();
|
||||||
return (
|
return (
|
||||||
<PatternPageWithPagination
|
<PatternPageWithPagination
|
||||||
patterns={patterns}
|
patterns={patterns}
|
||||||
context={context}
|
context={context}
|
||||||
initialPage={featuredPageNum}
|
initialPage={featuredPageNum}
|
||||||
patternOnClick={(id) => {
|
patternOnClick={(id) => {
|
||||||
updateCodeWindow(
|
updateCodeWindow(context, { ...patterns[id], collection: patternFilterName.featured }, patternAutoStart);
|
||||||
context,
|
|
||||||
{ ...patterns[id], collection: patternFilterName.featured },
|
|
||||||
autoResetPatternOnChange,
|
|
||||||
);
|
|
||||||
}}
|
}}
|
||||||
paginationOnChange={async (pageNum) => {
|
paginationOnChange={async (pageNum) => {
|
||||||
await loadAndSetFeaturedPatterns(pageNum - 1);
|
await loadAndSetFeaturedPatterns(pageNum - 1);
|
||||||
|
|
@ -213,13 +208,14 @@ function LatestPatterns({ context }) {
|
||||||
const examplePatterns = useExamplePatterns();
|
const examplePatterns = useExamplePatterns();
|
||||||
const collections = examplePatterns.collections;
|
const collections = examplePatterns.collections;
|
||||||
const patterns = collections.get(patternFilterName.public);
|
const patterns = collections.get(patternFilterName.public);
|
||||||
|
const { patternAutoStart } = useSettings();
|
||||||
return (
|
return (
|
||||||
<PatternPageWithPagination
|
<PatternPageWithPagination
|
||||||
patterns={patterns}
|
patterns={patterns}
|
||||||
context={context}
|
context={context}
|
||||||
initialPage={latestPageNum}
|
initialPage={latestPageNum}
|
||||||
patternOnClick={(id) => {
|
patternOnClick={(id) => {
|
||||||
updateCodeWindow(context, { ...patterns[id], collection: patternFilterName.public }, autoResetPatternOnChange);
|
updateCodeWindow(context, { ...patterns[id], collection: patternFilterName.public }, patternAutoStart);
|
||||||
}}
|
}}
|
||||||
paginationOnChange={async (pageNum) => {
|
paginationOnChange={async (pageNum) => {
|
||||||
await loadAndSetPublicPatterns(pageNum - 1);
|
await loadAndSetPublicPatterns(pageNum - 1);
|
||||||
|
|
|
||||||
|
|
@ -112,6 +112,7 @@ export function SettingsTab({ started }) {
|
||||||
multiChannelOrbits,
|
multiChannelOrbits,
|
||||||
isTabIndentationEnabled,
|
isTabIndentationEnabled,
|
||||||
isMultiCursorEnabled,
|
isMultiCursorEnabled,
|
||||||
|
patternAutoStart,
|
||||||
} = useSettings();
|
} = useSettings();
|
||||||
const shouldAlwaysSync = isUdels();
|
const shouldAlwaysSync = isUdels();
|
||||||
const canChangeAudioDevice = AudioContext.prototype.setSinkId != null;
|
const canChangeAudioDevice = AudioContext.prototype.setSinkId != null;
|
||||||
|
|
@ -304,6 +305,11 @@ export function SettingsTab({ started }) {
|
||||||
onChange={(cbEvent) => settingsMap.setKey('isCSSAnimationDisabled', cbEvent.target.checked)}
|
onChange={(cbEvent) => settingsMap.setKey('isCSSAnimationDisabled', cbEvent.target.checked)}
|
||||||
value={isCSSAnimationDisabled}
|
value={isCSSAnimationDisabled}
|
||||||
/>
|
/>
|
||||||
|
<Checkbox
|
||||||
|
label="Auto-start pattern on pattern change"
|
||||||
|
onChange={(cbEvent) => settingsMap.setKey('patternAutoStart', cbEvent.target.checked)}
|
||||||
|
value={patternAutoStart}
|
||||||
|
/>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem label="Zen Mode">Try clicking the logo in the top left!</FormItem>
|
<FormItem label="Zen Mode">Try clicking the logo in the top left!</FormItem>
|
||||||
<FormItem label="Reset Settings">
|
<FormItem label="Reset Settings">
|
||||||
|
|
|
||||||
|
|
@ -62,11 +62,9 @@ export function SoundsTab() {
|
||||||
|
|
||||||
// stop current sound on mouseup
|
// stop current sound on mouseup
|
||||||
useEvent('mouseup', () => {
|
useEvent('mouseup', () => {
|
||||||
const t = trigRef.current;
|
const ref = trigRef.current;
|
||||||
trigRef.current = undefined;
|
trigRef.current = undefined;
|
||||||
t?.then((ref) => {
|
ref?.stop?.(getAudioContext().currentTime + 0.01);
|
||||||
ref?.stop(getAudioContext().currentTime + 0.01);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
return (
|
return (
|
||||||
<div id="sounds-tab" className="px-4 flex gap-2 flex-col w-full h-full text-foreground">
|
<div id="sounds-tab" className="px-4 flex gap-2 flex-col w-full h-full text-foreground">
|
||||||
|
|
@ -124,12 +122,19 @@ export function SoundsTab() {
|
||||||
duration: 0.5,
|
duration: 0.5,
|
||||||
};
|
};
|
||||||
soundPreviewIdx++;
|
soundPreviewIdx++;
|
||||||
const time = ctx.currentTime + 0.05;
|
|
||||||
const onended = () => trigRef.current?.node?.disconnect();
|
const onended = () => trigRef.current?.node?.disconnect();
|
||||||
trigRef.current = Promise.resolve(onTrigger(time, params, onended));
|
try {
|
||||||
trigRef.current.then((ref) => {
|
// Pre-load the sample by calling onTrigger with a future time
|
||||||
connectToDestination(ref?.node);
|
// This triggers the loading but schedules playback for later
|
||||||
});
|
const time = ctx.currentTime + 0.5; // Give 500ms for loading
|
||||||
|
const ref = await onTrigger(time, params, onended);
|
||||||
|
trigRef.current = ref;
|
||||||
|
if (ref?.node) {
|
||||||
|
connectToDestination(ref.node);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.warn('Failed to trigger sound:', err);
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{' '}
|
{' '}
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,11 @@ export function useSettings() {
|
||||||
isPanelOpen: parseBoolean(state.isPanelOpen),
|
isPanelOpen: parseBoolean(state.isPanelOpen),
|
||||||
userPatterns: userPatterns,
|
userPatterns: userPatterns,
|
||||||
multiChannelOrbits: parseBoolean(state.multiChannelOrbits),
|
multiChannelOrbits: parseBoolean(state.multiChannelOrbits),
|
||||||
|
patternAutoStart: isUdels()
|
||||||
|
? false
|
||||||
|
: state.patternAutoStart === undefined
|
||||||
|
? true
|
||||||
|
: parseBoolean(state.patternAutoStart),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue