📈 Beat Curve¶
Documentation¶
- Class name:
Beat Curve [Dream]
- Category:
✨ Dream/🎥 animation/📈 curves
- Output node:
False
The Beat Curve node generates animation curves based on musical beats, allowing for synchronization between visual animations and rhythmic elements of a soundtrack. It utilizes BPM (beats per minute), measure length, and optional accents to create dynamic, beat-aligned animations.
Input types¶
Required¶
frame_counter
- Provides the current frame and timing information necessary for calculating the animation curve in relation to the music's beat.
- Comfy dtype:
FRAME_COUNTER
- Python dtype:
FrameCounter
bpm
- Specifies the beats per minute of the music track, influencing the timing of the animation curve to match the rhythm.
- Comfy dtype:
FLOAT
- Python dtype:
float
time_offset
- Adjusts the start time of the animation curve, allowing for precise synchronization with the music track.
- Comfy dtype:
FLOAT
- Python dtype:
float
measure_length
- Defines the length of a musical measure in beats, used to calculate the timing of accents within the animation curve.
- Comfy dtype:
INT
- Python dtype:
int
low_value
- Sets the minimum value of the animation curve, defining the lower bound of the generated values.
- Comfy dtype:
FLOAT
- Python dtype:
float
high_value
- Sets the maximum value of the animation curve, defining the upper bound of the generated values.
- Comfy dtype:
FLOAT
- Python dtype:
float
invert
- Inverts the animation curve, flipping the generated values between the specified low and high values. This parameter accepts 'yes' or 'no' to indicate inversion.
- Comfy dtype:
COMBO[STRING]
- Python dtype:
str
power
- Applies a power function to the animation curve, adjusting the intensity and dynamics of the curve's progression.
- Comfy dtype:
FLOAT
- Python dtype:
float
accent_i
- Specifies an accent beat within a measure, enhancing the animation curve's response to musical rhythm. Accents range from 1 to the measure length, allowing for dynamic rhythm customization.
- Comfy dtype:
INT
- Python dtype:
int
Optional¶
Output types¶
FLOAT
- Comfy dtype:
FLOAT
- The floating-point value of the animation curve at the current frame, reflecting the rhythmic pattern.
- Python dtype:
float
- Comfy dtype:
INT
- Comfy dtype:
INT
- The integer-rounded value of the animation curve at the current frame, suitable for discrete animations.
- Python dtype:
int
- Comfy dtype:
Usage tips¶
- Infra type:
CPU
- Common nodes: unknown
Source code¶
class DreamBeatCurve:
NODE_NAME = "Beat Curve"
@classmethod
def INPUT_TYPES(cls):
return {
"required": SharedTypes.frame_counter | {
"bpm": ("FLOAT", {"default": 100.0, "multiline": False}),
"time_offset": ("FLOAT", {"default": 0.0, "multiline": False}),
"measure_length": ("INT", {"default": 4, "min": 1}),
"low_value": ("FLOAT", {"default": 0.0}),
"high_value": ("FLOAT", {"default": 1.0}),
"invert": (["no", "yes"],),
"power": ("FLOAT", {"default": 2.0, "min": 0.25, "max": 4}),
"accent_1": ("INT", {"default": 1, "min": 1, "max": 24}),
},
"optional": {
"accent_2": ("INT", {"default": 3, "min": 1, "max": 24}),
"accent_3": ("INT", {"default": 0}),
"accent_4": ("INT", {"default": 0}),
}
}
CATEGORY = NodeCategories.ANIMATION_CURVES
RETURN_TYPES = ("FLOAT", "INT")
RETURN_NAMES = ("FLOAT", "INT")
FUNCTION = "result"
@classmethod
def IS_CHANGED(cls, *values):
return hashed_as_strings(*values)
def _get_value_for_accent(self, accent, measure_length, bpm, frame_counter: FrameCounter, frame_offset):
current_frame = frame_counter.current_frame + frame_offset
frames_per_minute = frame_counter.frames_per_second * 60.0
frames_per_beat = frames_per_minute / bpm
frames_per_measure = frames_per_beat * measure_length
frame = (current_frame % frames_per_measure)
accent_start = (accent - 1) * frames_per_beat
accent_end = accent * frames_per_beat
if frame >= accent_start and frame < accent_end:
return 1.0 - ((frame - accent_start) / frames_per_beat)
return 0
def result(self, bpm, frame_counter: FrameCounter, measure_length, low_value, high_value, power, invert,
time_offset, **accents):
frame_offset = int(round(time_offset * frame_counter.frames_per_second))
accents_set = set(filter(lambda v: v >= 1 and v <= measure_length,
map(lambda i: accents.get("accent_" + str(i), -1), range(30))))
v = 0.0
for a in accents_set:
v += math.pow(self._get_value_for_accent(a, measure_length, bpm, frame_counter, frame_offset), power)
if invert == "yes":
v = 1.0 - v
r = low_value + v * (high_value - low_value)
return _curve_result(r)