Skip to content

Commit

Permalink
Add cadence as a configurable value that can be accessed in formulas,…
Browse files Browse the repository at this point in the history
… and is_generation(f) that tells you if a given frame is a generation frame
  • Loading branch information
rewbs committed Sep 19, 2023
1 parent 2dfbc08 commit 2686283
Show file tree
Hide file tree
Showing 9 changed files with 71 additions and 8 deletions.
1 change: 1 addition & 0 deletions src/ParseqUI.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ type ParseqOptions = {
cc_window_width?: number;
cc_window_slide_rate?: number;
cc_use_input?: boolean;
cadence?: number;
};

type SimpleParseqPrompts = {
Expand Down
38 changes: 38 additions & 0 deletions src/ParseqUI.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ const ParseqUI = (props) => {
const [candidateLastFrame, setCandidateLastFrame] = useState();
const [candidateBPM, setCandidateBPM] = useState()
const [candidateFPS, setCandidateFPS] = useState()
const [candidateCadence, setCandidateCadence] = useState()
const [xaxisType, setXaxisType] = useState("frames");
const [keyframeLock, setKeyframeLock] = useState("frames");
const [gridHeight, setGridHeight] = useState(0);
Expand Down Expand Up @@ -332,6 +333,7 @@ const ParseqUI = (props) => {
setKeyframeLock(doc.keyframeLock);
setCandidateBPM(doc.options.bpm);
setCandidateFPS(doc.options.output_fps);
setCandidateCadence(doc.options.cadence);
setReverseRender(doc.reverseRender);

refreshGridFromKeyframes(doc.keyframes);
Expand Down Expand Up @@ -841,6 +843,42 @@ const ParseqUI = (props) => {
size="small"
variant="outlined" />
</Tooltip2>
<Tooltip2 title="By setting your cadence here, you can reference it in your formulas to ensure, for example, that strength dips always occur during generated frames.">
<TextField
label={"Cadence"}
value={candidateCadence}
onChange={(e)=>setCandidateCadence(e.target.value)}
onKeyDown={(e) => {
setIsDocDirty(true);
if (e.key === 'Enter') {
setTimeout(() => e.target.blur());
e.preventDefault();
} else if (e.key === 'Escape') {
setTimeout(() => e.target.blur());
setCandidateCadence(options.cadence)
e.preventDefault();
}
}}
onBlur={(e) => {
setIsDocDirty(false);
let candidate = parseInt(e.target.value);
let fallBack = options.cadence;
if (!candidate || candidate < 0 || isNaN(candidate)) {
setCandidateCadence(fallBack);
} else {
setOptions({ ...options, cadence: candidate })
}
}}
InputLabelProps={{ shrink: true, }}
InputProps={{
style: { fontSize: '0.75em' },
sx: { background: Number(candidateLastFrame) !== Number(lastFrame) ? theme.vars.palette.unsavedbg.main : '', },
endAdornment: Number(candidateLastFrame) !== Number(lastFrame) ? '🖊️' : ''
}}
sx={{ minWidth: 70, maxWidth: 100, }}
size="small"
variant="outlined" />
</Tooltip2>
<Typography fontSize={'0.6em'} style={{transform:'translate(0px, -2em)', margin:0}}>
<ul>
<li>Total duration: {lastFrame+1} frames = {frameToSec(lastFrame+1, options.output_fps).toFixed(4)} seconds = {frameToBeat(lastFrame+1, options.output_fps, options.bpm).toFixed(4)} beats </li>
Expand Down
2 changes: 1 addition & 1 deletion src/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ export default function Header() {
<li><KeyBadge>space</KeyBadge>: Play/pause</li>
<li><KeyBadge>shift</KeyBadge>+<KeyBadge>space</KeyBadge>: Play from start</li>
<li><KeyBadge>ctrl</KeyBadge>+<KeyBadge>space</KeyBadge>: Play from cursor</li>
<li><KeyBadge>ctrl</KeyBadge>+<KeyBadge>a</KeyBadge>: Add event marker at cursor position</li>
<li><KeyBadge>shift</KeyBadge>+<KeyBadge>a</KeyBadge>: Add event marker at cursor position</li>
</ul>
<h3>Graph & audio views</h3>
<ul>
Expand Down
7 changes: 7 additions & 0 deletions src/parseq-lang/parseq-lang-ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export type InvocationContext = {
}] | [],
promptType?: boolean;
rendered_frames?: ParseqRenderedFrames;
cadence: number;
}

export function getNextKeyframe(ctx: InvocationContext): number {
Expand Down Expand Up @@ -233,6 +234,12 @@ export class VariableReferenceAst extends ParseqAstNode {
return Math.floor(frameToBeat(ctx.frame, ctx.FPS, ctx.BPM));
case 's':
return frameToSec(ctx.frame, ctx.FPS);
case 'fps':
return ctx.FPS;
case 'bpm':
return ctx.BPM;
case 'cadence':
return ctx.cadence;
case 'k': // offset since last active keyframe
return ctx.frame - ctx.activeKeyframe;
case 'prev_keyframe': // deprecated, use 'active_keyframe', which is a more accurate name.
Expand Down
12 changes: 11 additions & 1 deletion src/parseq-lang/parseq-lang-functions-meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,17 @@ const functionLibrary: { [key: string]: ParseqFunction } = {
}

}
}
},
"is_generation": {
description: "Returns 1 if the supplied frame is a generation frame, and 0 if it's a cadence frame",
argDefs: [
{ description: "frame", names: ["f"], type: "number", required: false, default: (ctx) => ctx.frame, defaultDescription: "current frame number" },
],
call: (ctx, args) => {
const frame = Number(args[0]);
return frame%ctx.cadence === 0 ? 1 : 0;
}
},
}

export default functionLibrary;
9 changes: 6 additions & 3 deletions src/parseq-lang/parseq-lang-functions-prompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@ function posNegHelper(term: string, weight: number, pweight: number, nweight: nu

const weightedTerm = `${prefix}${term}:${canonicalWeight.toFixed(4)}${suffix}`;

if (moveNegToPos || movePosToNeg) {
return `__PARSEQ_MOVE__${weightedTerm}__PARSEQ_END_MOVE__`
if (weight === 0) {
// Don't include 0-weight terms.
return '';
} else if (moveNegToPos || movePosToNeg) {
return `__PARSEQ_MOVE__${weightedTerm}__PARSEQ_END_MOVE__`;
} else {
return weightedTerm
return weightedTerm;
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/parseq-lang/parseq-lang-interpreter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ const basicContext: InvocationContext = {
variableMap: new Map(),
activeKeyframe: 0,
frame: 0,
timeSeries: []
timeSeries: [],
cadence: 1
};

const runParseq = (formula: string) => {
Expand Down
4 changes: 3 additions & 1 deletion src/parseq-renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ export const parseqRender = (input: ParseqPersistableState): { renderedData: Ren
allKeyframes: keyframes,
FPS: options.output_fps,
BPM: options.bpm,
cadence: options.cadence??1,
computed_values: prev_computed_values,
variableMap: new Map([["prev_computed_value", (frame>0) ? prev_computed_values[frame-1] : 0]]),
timeSeries: timeSeries,
Expand Down Expand Up @@ -193,7 +194,8 @@ export const parseqRender = (input: ParseqPersistableState): { renderedData: Ren
allKeyframes: keyframes,
variableMap: variableMap,
timeSeries: timeSeries,
computed_values: []
computed_values: [],
cadence: options.cadence??1,
};

try {
Expand Down
3 changes: 2 additions & 1 deletion src/utils/consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ export const DEFAULT_OPTIONS = {
output_fps: 20,
cc_window_width: 0,
cc_window_slide_rate: 1,
cc_use_input: false
cc_use_input: false,
cadence: 1
}

0 comments on commit 2686283

Please sign in to comment.