summaryrefslogtreecommitdiff
path: root/src/audio/spectral_brush.h
blob: 3125f35aab3108b53436b3b4c2204eacb8b44f40 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
// This file is part of the 64k demo project.
// It implements the "Spectral Brush" primitive for procedural audio generation.
// Spectral brushes trace Bezier curves through spectrograms with vertical profiles.

#pragma once

#include <cstdint>

// Profile types for vertical distribution around central Bezier curve
enum ProfileType {
  PROFILE_GAUSSIAN = 0,            // Smooth harmonic falloff
  PROFILE_DECAYING_SINUSOID = 1,   // Resonant/metallic texture
  PROFILE_NOISE = 2                // Random texture/grit
};

// Evaluate linear Bezier interpolation at given frame
// control_frames: Array of frame positions for control points
// control_values: Array of values at control points (freq_hz or amplitude)
// n_points: Number of control points
// frame: Frame number to evaluate at
// Returns: Interpolated value at frame (linearly interpolated between control points)
float evaluate_bezier_linear(const float* control_frames,
                              const float* control_values,
                              int n_points,
                              float frame);

// Draw a spectral brush stroke onto a spectrogram
// Traces a Bezier curve through time-frequency space with a vertical profile
// spectrogram: Output buffer (dct_size × num_frames), modified in-place
// dct_size: Number of frequency bins (e.g., 512)
// num_frames: Number of time frames
// control_frames: Frame positions of Bezier control points
// control_freqs_hz: Frequency values (Hz) at control points
// control_amps: Amplitude values at control points (0.0-1.0 typical)
// n_control_points: Number of control points (minimum 2 for a curve)
// profile_type: Type of vertical profile to apply
// profile_param1: First parameter (sigma for Gaussian, decay for sinusoid, amplitude for noise)
// profile_param2: Second parameter (unused for Gaussian, frequency for sinusoid, seed for noise)
void draw_bezier_curve(float* spectrogram,
                       int dct_size,
                       int num_frames,
                       const float* control_frames,
                       const float* control_freqs_hz,
                       const float* control_amps,
                       int n_control_points,
                       ProfileType profile_type,
                       float profile_param1,
                       float profile_param2 = 0.0f);

// Additive variant of draw_bezier_curve (adds to existing spectrogram content)
// Use for compositing multiple profiles (e.g., Gaussian + Noise)
// Parameters same as draw_bezier_curve()
void draw_bezier_curve_add(float* spectrogram,
                            int dct_size,
                            int num_frames,
                            const float* control_frames,
                            const float* control_freqs_hz,
                            const float* control_amps,
                            int n_control_points,
                            ProfileType profile_type,
                            float profile_param1,
                            float profile_param2 = 0.0f);

// Evaluate vertical profile at given distance from central curve
// type: Profile type (Gaussian, Decaying Sinusoid, Noise)
// distance: Distance in frequency bins from curve center
// param1: First profile parameter
// param2: Second profile parameter
// Returns: Profile amplitude at given distance (0.0-1.0 range typically)
float evaluate_profile(ProfileType type,
                       float distance,
                       float param1,
                       float param2);

// Home-brew deterministic RNG for noise profile
// Simple linear congruential generator (LCG) for small code size
// seed: Input seed value
// Returns: Pseudo-random uint32_t value
uint32_t spectral_brush_rand(uint32_t seed);