Skip to main content

AdditiveSynth

Struct AdditiveSynth 

Source
pub struct AdditiveSynth { /* private fields */ }
Expand description

Additive synthesizer - generates sound by summing sine wave partials

Build complex timbres from simple components. Perfect for:

  • Organ sounds (harmonic series)
  • Bell/metallic sounds (inharmonic partials)
  • Evolving pads (time-varying amplitudes)
  • Precise spectral control

§Example

use tunes::synthesis::additive::{AdditiveSynth, Partial};

// Create a bell-like sound with inharmonic partials
let mut bell = AdditiveSynth::new(220.0, 44100.0)
    .add_partial(Partial::inharmonic(1.0, 1.0))
    .add_partial(Partial::inharmonic(2.76, 0.6))
    .add_partial(Partial::inharmonic(5.4, 0.4))
    .add_partial(Partial::inharmonic(8.93, 0.25));

let samples = bell.generate(22050);  // 0.5 seconds

Implementations§

Source§

impl AdditiveSynth

Source

pub fn new(fundamental_freq: f32, sample_rate: f32) -> Self

Create a new additive synthesizer

§Arguments
  • fundamental_freq - Base frequency in Hz (e.g., 440.0 for A4)
  • sample_rate - Sample rate in Hz (e.g., 44100.0)
§Example
use tunes::synthesis::additive::AdditiveSynth;

let synth = AdditiveSynth::new(440.0, 44100.0);
Examples found in repository?
examples/additive_synthesis_demo.rs (line 14)
7fn main() -> anyhow::Result<()> {
8    println!("\n🎵 Example: Additive Synthesis API\n");
9
10    println!("Additive Synthesis - Building sounds from sine wave partials\n");
11
12    // 1. Pure Sine Wave (single partial)
13    println!("▶ Pure sine wave (fundamental only)");
14    let mut pure_sine = AdditiveSynth::new(440.0, 44100.0)
15        .add_partial(Partial::harmonic(1, 1.0));
16
17    let samples = pure_sine.generate(1000);
18    println!("  Generated {} samples", samples.len());
19
20    // 2. Sawtooth-like (harmonic series with 1/n amplitude)
21    println!("\n▶ Sawtooth-like sound (harmonic series)");
22    let mut sawtooth = AdditiveSynth::new(440.0, 44100.0)
23        .add_partial(Partial::harmonic(1, 1.0))
24        .add_partial(Partial::harmonic(2, 0.5))
25        .add_partial(Partial::harmonic(3, 0.33))
26        .add_partial(Partial::harmonic(4, 0.25))
27        .add_partial(Partial::harmonic(5, 0.2))
28        .add_partial(Partial::harmonic(6, 0.166));
29
30    let saw_samples = sawtooth.generate(1000);
31    println!("  Generated {} samples with 6 harmonics", saw_samples.len());
32
33    // 3. Square-like (odd harmonics only)
34    println!("\n▶ Square-like sound (odd harmonics)");
35    let mut square = AdditiveSynth::new(440.0, 44100.0)
36        .add_partial(Partial::harmonic(1, 1.0))
37        .add_partial(Partial::harmonic(3, 0.33))
38        .add_partial(Partial::harmonic(5, 0.2))
39        .add_partial(Partial::harmonic(7, 0.143))
40        .add_partial(Partial::harmonic(9, 0.111));
41
42    let square_samples = square.generate(1000);
43    println!("  Generated {} samples with odd harmonics", square_samples.len());
44
45    // 4. Organ Sound (selected harmonics for organ timbre)
46    println!("\n▶ Organ sound (organ-like harmonic recipe)");
47    let mut organ = AdditiveSynth::new(440.0, 44100.0)
48        .add_partial(Partial::harmonic(1, 1.0))    // Fundamental
49        .add_partial(Partial::harmonic(2, 0.5))    // Octave
50        .add_partial(Partial::harmonic(3, 0.8))    // Fifth
51        .add_partial(Partial::harmonic(4, 0.4))    // Double octave
52        .add_partial(Partial::harmonic(5, 0.3))    // Major third
53        .add_partial(Partial::harmonic(8, 0.2));   // Triple octave
54
55    let organ_samples = organ.generate(1000);
56    println!("  Generated {} samples with organ voicing", organ_samples.len());
57
58    // 5. Bell Sound (inharmonic partials for metallic timbre)
59    println!("\n▶ Bell sound (inharmonic partials)");
60    let mut bell = AdditiveSynth::new(440.0, 44100.0)
61        .add_partial(Partial::inharmonic(1.0, 1.0))
62        .add_partial(Partial::inharmonic(2.76, 0.6))
63        .add_partial(Partial::inharmonic(5.4, 0.4))
64        .add_partial(Partial::inharmonic(8.93, 0.25))
65        .add_partial(Partial::inharmonic(13.34, 0.15));
66
67    let bell_samples = bell.generate(1000);
68    println!("  Generated {} samples with inharmonic ratios", bell_samples.len());
69
70    // 6. Using with_partials for bulk adding
71    println!("\n▶ Using with_partials() for bulk configuration");
72    let partials = vec![
73        Partial::harmonic(1, 1.0),
74        Partial::harmonic(2, 0.5),
75        Partial::harmonic(3, 0.33),
76    ];
77
78    let mut bulk = AdditiveSynth::new(440.0, 44100.0)
79        .with_partials(partials);
80
81    let bulk_samples = bulk.generate(1000);
82    println!("  Generated {} samples from vec of partials", bulk_samples.len());
83
84    // 7. Dynamic frequency changes
85    println!("\n▶ Dynamic frequency control");
86    let mut dynamic = AdditiveSynth::new(440.0, 44100.0)
87        .add_partial(Partial::harmonic(1, 1.0));
88
89    let a440 = dynamic.generate(500);
90    dynamic.set_frequency(880.0); // Change to A5
91    let a880 = dynamic.generate(500);
92    println!("  Generated at 440Hz ({} samples), then 880Hz ({} samples)", a440.len(), a880.len());
93
94    // 8. Phase reset
95    println!("\n▶ Phase reset for synchronized playback");
96    let mut synth = AdditiveSynth::new(440.0, 44100.0)
97        .add_partial(Partial::harmonic(1, 1.0));
98
99    synth.generate(1000); // Advance phase
100    synth.reset(); // Reset to initial state
101    let reset_samples = synth.generate(1000);
102    println!("  Reset phase and generated {} samples", reset_samples.len());
103
104    println!("\n✓ Additive Synthesis Concepts:");
105    println!("  • Harmonic series: Integer frequency ratios (1, 2, 3, 4...)");
106    println!("  • Sawtooth: All harmonics with 1/n amplitude");
107    println!("  • Square: Odd harmonics only");
108    println!("  • Organ: Selected harmonics for warmth");
109    println!("  • Inharmonic: Non-integer ratios create metallic/bell timbres");
110    println!("  • Flexibility: Precise control over each frequency component");
111
112    println!("\n✓ API Usage:");
113    println!("  ```rust");
114    println!("  // Create synthesizer");
115    println!("  let mut synth = AdditiveSynth::new(440.0, 44100.0)");
116    println!("      .add_partial(Partial::harmonic(1, 1.0))");
117    println!("      .add_partial(Partial::harmonic(2, 0.5));");
118    println!();
119    println!("  // Generate samples");
120    println!("  let samples = synth.generate(44100); // 1 second");
121    println!();
122    println!("  // Change frequency");
123    println!("  synth.set_frequency(880.0);");
124    println!();
125    println!("  // Reset phase");
126    println!("  synth.reset();");
127    println!("  ```\n");
128
129    Ok(())
130}
Source

pub fn add_partial(self, partial: Partial) -> Self

Add a partial to the synthesis (builder pattern)

§Example
use tunes::synthesis::additive::{AdditiveSynth, Partial};

let synth = AdditiveSynth::new(440.0, 44100.0)
    .add_partial(Partial::harmonic(1, 1.0))
    .add_partial(Partial::harmonic(2, 0.5));
Examples found in repository?
examples/additive_synthesis_demo.rs (line 15)
7fn main() -> anyhow::Result<()> {
8    println!("\n🎵 Example: Additive Synthesis API\n");
9
10    println!("Additive Synthesis - Building sounds from sine wave partials\n");
11
12    // 1. Pure Sine Wave (single partial)
13    println!("▶ Pure sine wave (fundamental only)");
14    let mut pure_sine = AdditiveSynth::new(440.0, 44100.0)
15        .add_partial(Partial::harmonic(1, 1.0));
16
17    let samples = pure_sine.generate(1000);
18    println!("  Generated {} samples", samples.len());
19
20    // 2. Sawtooth-like (harmonic series with 1/n amplitude)
21    println!("\n▶ Sawtooth-like sound (harmonic series)");
22    let mut sawtooth = AdditiveSynth::new(440.0, 44100.0)
23        .add_partial(Partial::harmonic(1, 1.0))
24        .add_partial(Partial::harmonic(2, 0.5))
25        .add_partial(Partial::harmonic(3, 0.33))
26        .add_partial(Partial::harmonic(4, 0.25))
27        .add_partial(Partial::harmonic(5, 0.2))
28        .add_partial(Partial::harmonic(6, 0.166));
29
30    let saw_samples = sawtooth.generate(1000);
31    println!("  Generated {} samples with 6 harmonics", saw_samples.len());
32
33    // 3. Square-like (odd harmonics only)
34    println!("\n▶ Square-like sound (odd harmonics)");
35    let mut square = AdditiveSynth::new(440.0, 44100.0)
36        .add_partial(Partial::harmonic(1, 1.0))
37        .add_partial(Partial::harmonic(3, 0.33))
38        .add_partial(Partial::harmonic(5, 0.2))
39        .add_partial(Partial::harmonic(7, 0.143))
40        .add_partial(Partial::harmonic(9, 0.111));
41
42    let square_samples = square.generate(1000);
43    println!("  Generated {} samples with odd harmonics", square_samples.len());
44
45    // 4. Organ Sound (selected harmonics for organ timbre)
46    println!("\n▶ Organ sound (organ-like harmonic recipe)");
47    let mut organ = AdditiveSynth::new(440.0, 44100.0)
48        .add_partial(Partial::harmonic(1, 1.0))    // Fundamental
49        .add_partial(Partial::harmonic(2, 0.5))    // Octave
50        .add_partial(Partial::harmonic(3, 0.8))    // Fifth
51        .add_partial(Partial::harmonic(4, 0.4))    // Double octave
52        .add_partial(Partial::harmonic(5, 0.3))    // Major third
53        .add_partial(Partial::harmonic(8, 0.2));   // Triple octave
54
55    let organ_samples = organ.generate(1000);
56    println!("  Generated {} samples with organ voicing", organ_samples.len());
57
58    // 5. Bell Sound (inharmonic partials for metallic timbre)
59    println!("\n▶ Bell sound (inharmonic partials)");
60    let mut bell = AdditiveSynth::new(440.0, 44100.0)
61        .add_partial(Partial::inharmonic(1.0, 1.0))
62        .add_partial(Partial::inharmonic(2.76, 0.6))
63        .add_partial(Partial::inharmonic(5.4, 0.4))
64        .add_partial(Partial::inharmonic(8.93, 0.25))
65        .add_partial(Partial::inharmonic(13.34, 0.15));
66
67    let bell_samples = bell.generate(1000);
68    println!("  Generated {} samples with inharmonic ratios", bell_samples.len());
69
70    // 6. Using with_partials for bulk adding
71    println!("\n▶ Using with_partials() for bulk configuration");
72    let partials = vec![
73        Partial::harmonic(1, 1.0),
74        Partial::harmonic(2, 0.5),
75        Partial::harmonic(3, 0.33),
76    ];
77
78    let mut bulk = AdditiveSynth::new(440.0, 44100.0)
79        .with_partials(partials);
80
81    let bulk_samples = bulk.generate(1000);
82    println!("  Generated {} samples from vec of partials", bulk_samples.len());
83
84    // 7. Dynamic frequency changes
85    println!("\n▶ Dynamic frequency control");
86    let mut dynamic = AdditiveSynth::new(440.0, 44100.0)
87        .add_partial(Partial::harmonic(1, 1.0));
88
89    let a440 = dynamic.generate(500);
90    dynamic.set_frequency(880.0); // Change to A5
91    let a880 = dynamic.generate(500);
92    println!("  Generated at 440Hz ({} samples), then 880Hz ({} samples)", a440.len(), a880.len());
93
94    // 8. Phase reset
95    println!("\n▶ Phase reset for synchronized playback");
96    let mut synth = AdditiveSynth::new(440.0, 44100.0)
97        .add_partial(Partial::harmonic(1, 1.0));
98
99    synth.generate(1000); // Advance phase
100    synth.reset(); // Reset to initial state
101    let reset_samples = synth.generate(1000);
102    println!("  Reset phase and generated {} samples", reset_samples.len());
103
104    println!("\n✓ Additive Synthesis Concepts:");
105    println!("  • Harmonic series: Integer frequency ratios (1, 2, 3, 4...)");
106    println!("  • Sawtooth: All harmonics with 1/n amplitude");
107    println!("  • Square: Odd harmonics only");
108    println!("  • Organ: Selected harmonics for warmth");
109    println!("  • Inharmonic: Non-integer ratios create metallic/bell timbres");
110    println!("  • Flexibility: Precise control over each frequency component");
111
112    println!("\n✓ API Usage:");
113    println!("  ```rust");
114    println!("  // Create synthesizer");
115    println!("  let mut synth = AdditiveSynth::new(440.0, 44100.0)");
116    println!("      .add_partial(Partial::harmonic(1, 1.0))");
117    println!("      .add_partial(Partial::harmonic(2, 0.5));");
118    println!();
119    println!("  // Generate samples");
120    println!("  let samples = synth.generate(44100); // 1 second");
121    println!();
122    println!("  // Change frequency");
123    println!("  synth.set_frequency(880.0);");
124    println!();
125    println!("  // Reset phase");
126    println!("  synth.reset();");
127    println!("  ```\n");
128
129    Ok(())
130}
Source

pub fn with_partials(self, partials: Vec<Partial>) -> Self

Add multiple partials at once

§Example
use tunes::synthesis::additive::{AdditiveSynth, Partial};

let partials = vec![
    Partial::harmonic(1, 1.0),
    Partial::harmonic(2, 0.5),
    Partial::harmonic(3, 0.33),
];

let synth = AdditiveSynth::new(440.0, 44100.0)
    .with_partials(partials);
Examples found in repository?
examples/additive_synthesis_demo.rs (line 79)
7fn main() -> anyhow::Result<()> {
8    println!("\n🎵 Example: Additive Synthesis API\n");
9
10    println!("Additive Synthesis - Building sounds from sine wave partials\n");
11
12    // 1. Pure Sine Wave (single partial)
13    println!("▶ Pure sine wave (fundamental only)");
14    let mut pure_sine = AdditiveSynth::new(440.0, 44100.0)
15        .add_partial(Partial::harmonic(1, 1.0));
16
17    let samples = pure_sine.generate(1000);
18    println!("  Generated {} samples", samples.len());
19
20    // 2. Sawtooth-like (harmonic series with 1/n amplitude)
21    println!("\n▶ Sawtooth-like sound (harmonic series)");
22    let mut sawtooth = AdditiveSynth::new(440.0, 44100.0)
23        .add_partial(Partial::harmonic(1, 1.0))
24        .add_partial(Partial::harmonic(2, 0.5))
25        .add_partial(Partial::harmonic(3, 0.33))
26        .add_partial(Partial::harmonic(4, 0.25))
27        .add_partial(Partial::harmonic(5, 0.2))
28        .add_partial(Partial::harmonic(6, 0.166));
29
30    let saw_samples = sawtooth.generate(1000);
31    println!("  Generated {} samples with 6 harmonics", saw_samples.len());
32
33    // 3. Square-like (odd harmonics only)
34    println!("\n▶ Square-like sound (odd harmonics)");
35    let mut square = AdditiveSynth::new(440.0, 44100.0)
36        .add_partial(Partial::harmonic(1, 1.0))
37        .add_partial(Partial::harmonic(3, 0.33))
38        .add_partial(Partial::harmonic(5, 0.2))
39        .add_partial(Partial::harmonic(7, 0.143))
40        .add_partial(Partial::harmonic(9, 0.111));
41
42    let square_samples = square.generate(1000);
43    println!("  Generated {} samples with odd harmonics", square_samples.len());
44
45    // 4. Organ Sound (selected harmonics for organ timbre)
46    println!("\n▶ Organ sound (organ-like harmonic recipe)");
47    let mut organ = AdditiveSynth::new(440.0, 44100.0)
48        .add_partial(Partial::harmonic(1, 1.0))    // Fundamental
49        .add_partial(Partial::harmonic(2, 0.5))    // Octave
50        .add_partial(Partial::harmonic(3, 0.8))    // Fifth
51        .add_partial(Partial::harmonic(4, 0.4))    // Double octave
52        .add_partial(Partial::harmonic(5, 0.3))    // Major third
53        .add_partial(Partial::harmonic(8, 0.2));   // Triple octave
54
55    let organ_samples = organ.generate(1000);
56    println!("  Generated {} samples with organ voicing", organ_samples.len());
57
58    // 5. Bell Sound (inharmonic partials for metallic timbre)
59    println!("\n▶ Bell sound (inharmonic partials)");
60    let mut bell = AdditiveSynth::new(440.0, 44100.0)
61        .add_partial(Partial::inharmonic(1.0, 1.0))
62        .add_partial(Partial::inharmonic(2.76, 0.6))
63        .add_partial(Partial::inharmonic(5.4, 0.4))
64        .add_partial(Partial::inharmonic(8.93, 0.25))
65        .add_partial(Partial::inharmonic(13.34, 0.15));
66
67    let bell_samples = bell.generate(1000);
68    println!("  Generated {} samples with inharmonic ratios", bell_samples.len());
69
70    // 6. Using with_partials for bulk adding
71    println!("\n▶ Using with_partials() for bulk configuration");
72    let partials = vec![
73        Partial::harmonic(1, 1.0),
74        Partial::harmonic(2, 0.5),
75        Partial::harmonic(3, 0.33),
76    ];
77
78    let mut bulk = AdditiveSynth::new(440.0, 44100.0)
79        .with_partials(partials);
80
81    let bulk_samples = bulk.generate(1000);
82    println!("  Generated {} samples from vec of partials", bulk_samples.len());
83
84    // 7. Dynamic frequency changes
85    println!("\n▶ Dynamic frequency control");
86    let mut dynamic = AdditiveSynth::new(440.0, 44100.0)
87        .add_partial(Partial::harmonic(1, 1.0));
88
89    let a440 = dynamic.generate(500);
90    dynamic.set_frequency(880.0); // Change to A5
91    let a880 = dynamic.generate(500);
92    println!("  Generated at 440Hz ({} samples), then 880Hz ({} samples)", a440.len(), a880.len());
93
94    // 8. Phase reset
95    println!("\n▶ Phase reset for synchronized playback");
96    let mut synth = AdditiveSynth::new(440.0, 44100.0)
97        .add_partial(Partial::harmonic(1, 1.0));
98
99    synth.generate(1000); // Advance phase
100    synth.reset(); // Reset to initial state
101    let reset_samples = synth.generate(1000);
102    println!("  Reset phase and generated {} samples", reset_samples.len());
103
104    println!("\n✓ Additive Synthesis Concepts:");
105    println!("  • Harmonic series: Integer frequency ratios (1, 2, 3, 4...)");
106    println!("  • Sawtooth: All harmonics with 1/n amplitude");
107    println!("  • Square: Odd harmonics only");
108    println!("  • Organ: Selected harmonics for warmth");
109    println!("  • Inharmonic: Non-integer ratios create metallic/bell timbres");
110    println!("  • Flexibility: Precise control over each frequency component");
111
112    println!("\n✓ API Usage:");
113    println!("  ```rust");
114    println!("  // Create synthesizer");
115    println!("  let mut synth = AdditiveSynth::new(440.0, 44100.0)");
116    println!("      .add_partial(Partial::harmonic(1, 1.0))");
117    println!("      .add_partial(Partial::harmonic(2, 0.5));");
118    println!();
119    println!("  // Generate samples");
120    println!("  let samples = synth.generate(44100); // 1 second");
121    println!();
122    println!("  // Change frequency");
123    println!("  synth.set_frequency(880.0);");
124    println!();
125    println!("  // Reset phase");
126    println!("  synth.reset();");
127    println!("  ```\n");
128
129    Ok(())
130}
Source

pub fn set_frequency(&mut self, freq: f32)

Set the fundamental frequency

§Example
use tunes::synthesis::additive::AdditiveSynth;

let mut synth = AdditiveSynth::new(440.0, 44100.0);
synth.set_frequency(880.0);  // Change to A5
Examples found in repository?
examples/additive_synthesis_demo.rs (line 90)
7fn main() -> anyhow::Result<()> {
8    println!("\n🎵 Example: Additive Synthesis API\n");
9
10    println!("Additive Synthesis - Building sounds from sine wave partials\n");
11
12    // 1. Pure Sine Wave (single partial)
13    println!("▶ Pure sine wave (fundamental only)");
14    let mut pure_sine = AdditiveSynth::new(440.0, 44100.0)
15        .add_partial(Partial::harmonic(1, 1.0));
16
17    let samples = pure_sine.generate(1000);
18    println!("  Generated {} samples", samples.len());
19
20    // 2. Sawtooth-like (harmonic series with 1/n amplitude)
21    println!("\n▶ Sawtooth-like sound (harmonic series)");
22    let mut sawtooth = AdditiveSynth::new(440.0, 44100.0)
23        .add_partial(Partial::harmonic(1, 1.0))
24        .add_partial(Partial::harmonic(2, 0.5))
25        .add_partial(Partial::harmonic(3, 0.33))
26        .add_partial(Partial::harmonic(4, 0.25))
27        .add_partial(Partial::harmonic(5, 0.2))
28        .add_partial(Partial::harmonic(6, 0.166));
29
30    let saw_samples = sawtooth.generate(1000);
31    println!("  Generated {} samples with 6 harmonics", saw_samples.len());
32
33    // 3. Square-like (odd harmonics only)
34    println!("\n▶ Square-like sound (odd harmonics)");
35    let mut square = AdditiveSynth::new(440.0, 44100.0)
36        .add_partial(Partial::harmonic(1, 1.0))
37        .add_partial(Partial::harmonic(3, 0.33))
38        .add_partial(Partial::harmonic(5, 0.2))
39        .add_partial(Partial::harmonic(7, 0.143))
40        .add_partial(Partial::harmonic(9, 0.111));
41
42    let square_samples = square.generate(1000);
43    println!("  Generated {} samples with odd harmonics", square_samples.len());
44
45    // 4. Organ Sound (selected harmonics for organ timbre)
46    println!("\n▶ Organ sound (organ-like harmonic recipe)");
47    let mut organ = AdditiveSynth::new(440.0, 44100.0)
48        .add_partial(Partial::harmonic(1, 1.0))    // Fundamental
49        .add_partial(Partial::harmonic(2, 0.5))    // Octave
50        .add_partial(Partial::harmonic(3, 0.8))    // Fifth
51        .add_partial(Partial::harmonic(4, 0.4))    // Double octave
52        .add_partial(Partial::harmonic(5, 0.3))    // Major third
53        .add_partial(Partial::harmonic(8, 0.2));   // Triple octave
54
55    let organ_samples = organ.generate(1000);
56    println!("  Generated {} samples with organ voicing", organ_samples.len());
57
58    // 5. Bell Sound (inharmonic partials for metallic timbre)
59    println!("\n▶ Bell sound (inharmonic partials)");
60    let mut bell = AdditiveSynth::new(440.0, 44100.0)
61        .add_partial(Partial::inharmonic(1.0, 1.0))
62        .add_partial(Partial::inharmonic(2.76, 0.6))
63        .add_partial(Partial::inharmonic(5.4, 0.4))
64        .add_partial(Partial::inharmonic(8.93, 0.25))
65        .add_partial(Partial::inharmonic(13.34, 0.15));
66
67    let bell_samples = bell.generate(1000);
68    println!("  Generated {} samples with inharmonic ratios", bell_samples.len());
69
70    // 6. Using with_partials for bulk adding
71    println!("\n▶ Using with_partials() for bulk configuration");
72    let partials = vec![
73        Partial::harmonic(1, 1.0),
74        Partial::harmonic(2, 0.5),
75        Partial::harmonic(3, 0.33),
76    ];
77
78    let mut bulk = AdditiveSynth::new(440.0, 44100.0)
79        .with_partials(partials);
80
81    let bulk_samples = bulk.generate(1000);
82    println!("  Generated {} samples from vec of partials", bulk_samples.len());
83
84    // 7. Dynamic frequency changes
85    println!("\n▶ Dynamic frequency control");
86    let mut dynamic = AdditiveSynth::new(440.0, 44100.0)
87        .add_partial(Partial::harmonic(1, 1.0));
88
89    let a440 = dynamic.generate(500);
90    dynamic.set_frequency(880.0); // Change to A5
91    let a880 = dynamic.generate(500);
92    println!("  Generated at 440Hz ({} samples), then 880Hz ({} samples)", a440.len(), a880.len());
93
94    // 8. Phase reset
95    println!("\n▶ Phase reset for synchronized playback");
96    let mut synth = AdditiveSynth::new(440.0, 44100.0)
97        .add_partial(Partial::harmonic(1, 1.0));
98
99    synth.generate(1000); // Advance phase
100    synth.reset(); // Reset to initial state
101    let reset_samples = synth.generate(1000);
102    println!("  Reset phase and generated {} samples", reset_samples.len());
103
104    println!("\n✓ Additive Synthesis Concepts:");
105    println!("  • Harmonic series: Integer frequency ratios (1, 2, 3, 4...)");
106    println!("  • Sawtooth: All harmonics with 1/n amplitude");
107    println!("  • Square: Odd harmonics only");
108    println!("  • Organ: Selected harmonics for warmth");
109    println!("  • Inharmonic: Non-integer ratios create metallic/bell timbres");
110    println!("  • Flexibility: Precise control over each frequency component");
111
112    println!("\n✓ API Usage:");
113    println!("  ```rust");
114    println!("  // Create synthesizer");
115    println!("  let mut synth = AdditiveSynth::new(440.0, 44100.0)");
116    println!("      .add_partial(Partial::harmonic(1, 1.0))");
117    println!("      .add_partial(Partial::harmonic(2, 0.5));");
118    println!();
119    println!("  // Generate samples");
120    println!("  let samples = synth.generate(44100); // 1 second");
121    println!();
122    println!("  // Change frequency");
123    println!("  synth.set_frequency(880.0);");
124    println!();
125    println!("  // Reset phase");
126    println!("  synth.reset();");
127    println!("  ```\n");
128
129    Ok(())
130}
Source

pub fn reset(&mut self)

Reset all phase accumulators to their initial offsets

Examples found in repository?
examples/additive_synthesis_demo.rs (line 100)
7fn main() -> anyhow::Result<()> {
8    println!("\n🎵 Example: Additive Synthesis API\n");
9
10    println!("Additive Synthesis - Building sounds from sine wave partials\n");
11
12    // 1. Pure Sine Wave (single partial)
13    println!("▶ Pure sine wave (fundamental only)");
14    let mut pure_sine = AdditiveSynth::new(440.0, 44100.0)
15        .add_partial(Partial::harmonic(1, 1.0));
16
17    let samples = pure_sine.generate(1000);
18    println!("  Generated {} samples", samples.len());
19
20    // 2. Sawtooth-like (harmonic series with 1/n amplitude)
21    println!("\n▶ Sawtooth-like sound (harmonic series)");
22    let mut sawtooth = AdditiveSynth::new(440.0, 44100.0)
23        .add_partial(Partial::harmonic(1, 1.0))
24        .add_partial(Partial::harmonic(2, 0.5))
25        .add_partial(Partial::harmonic(3, 0.33))
26        .add_partial(Partial::harmonic(4, 0.25))
27        .add_partial(Partial::harmonic(5, 0.2))
28        .add_partial(Partial::harmonic(6, 0.166));
29
30    let saw_samples = sawtooth.generate(1000);
31    println!("  Generated {} samples with 6 harmonics", saw_samples.len());
32
33    // 3. Square-like (odd harmonics only)
34    println!("\n▶ Square-like sound (odd harmonics)");
35    let mut square = AdditiveSynth::new(440.0, 44100.0)
36        .add_partial(Partial::harmonic(1, 1.0))
37        .add_partial(Partial::harmonic(3, 0.33))
38        .add_partial(Partial::harmonic(5, 0.2))
39        .add_partial(Partial::harmonic(7, 0.143))
40        .add_partial(Partial::harmonic(9, 0.111));
41
42    let square_samples = square.generate(1000);
43    println!("  Generated {} samples with odd harmonics", square_samples.len());
44
45    // 4. Organ Sound (selected harmonics for organ timbre)
46    println!("\n▶ Organ sound (organ-like harmonic recipe)");
47    let mut organ = AdditiveSynth::new(440.0, 44100.0)
48        .add_partial(Partial::harmonic(1, 1.0))    // Fundamental
49        .add_partial(Partial::harmonic(2, 0.5))    // Octave
50        .add_partial(Partial::harmonic(3, 0.8))    // Fifth
51        .add_partial(Partial::harmonic(4, 0.4))    // Double octave
52        .add_partial(Partial::harmonic(5, 0.3))    // Major third
53        .add_partial(Partial::harmonic(8, 0.2));   // Triple octave
54
55    let organ_samples = organ.generate(1000);
56    println!("  Generated {} samples with organ voicing", organ_samples.len());
57
58    // 5. Bell Sound (inharmonic partials for metallic timbre)
59    println!("\n▶ Bell sound (inharmonic partials)");
60    let mut bell = AdditiveSynth::new(440.0, 44100.0)
61        .add_partial(Partial::inharmonic(1.0, 1.0))
62        .add_partial(Partial::inharmonic(2.76, 0.6))
63        .add_partial(Partial::inharmonic(5.4, 0.4))
64        .add_partial(Partial::inharmonic(8.93, 0.25))
65        .add_partial(Partial::inharmonic(13.34, 0.15));
66
67    let bell_samples = bell.generate(1000);
68    println!("  Generated {} samples with inharmonic ratios", bell_samples.len());
69
70    // 6. Using with_partials for bulk adding
71    println!("\n▶ Using with_partials() for bulk configuration");
72    let partials = vec![
73        Partial::harmonic(1, 1.0),
74        Partial::harmonic(2, 0.5),
75        Partial::harmonic(3, 0.33),
76    ];
77
78    let mut bulk = AdditiveSynth::new(440.0, 44100.0)
79        .with_partials(partials);
80
81    let bulk_samples = bulk.generate(1000);
82    println!("  Generated {} samples from vec of partials", bulk_samples.len());
83
84    // 7. Dynamic frequency changes
85    println!("\n▶ Dynamic frequency control");
86    let mut dynamic = AdditiveSynth::new(440.0, 44100.0)
87        .add_partial(Partial::harmonic(1, 1.0));
88
89    let a440 = dynamic.generate(500);
90    dynamic.set_frequency(880.0); // Change to A5
91    let a880 = dynamic.generate(500);
92    println!("  Generated at 440Hz ({} samples), then 880Hz ({} samples)", a440.len(), a880.len());
93
94    // 8. Phase reset
95    println!("\n▶ Phase reset for synchronized playback");
96    let mut synth = AdditiveSynth::new(440.0, 44100.0)
97        .add_partial(Partial::harmonic(1, 1.0));
98
99    synth.generate(1000); // Advance phase
100    synth.reset(); // Reset to initial state
101    let reset_samples = synth.generate(1000);
102    println!("  Reset phase and generated {} samples", reset_samples.len());
103
104    println!("\n✓ Additive Synthesis Concepts:");
105    println!("  • Harmonic series: Integer frequency ratios (1, 2, 3, 4...)");
106    println!("  • Sawtooth: All harmonics with 1/n amplitude");
107    println!("  • Square: Odd harmonics only");
108    println!("  • Organ: Selected harmonics for warmth");
109    println!("  • Inharmonic: Non-integer ratios create metallic/bell timbres");
110    println!("  • Flexibility: Precise control over each frequency component");
111
112    println!("\n✓ API Usage:");
113    println!("  ```rust");
114    println!("  // Create synthesizer");
115    println!("  let mut synth = AdditiveSynth::new(440.0, 44100.0)");
116    println!("      .add_partial(Partial::harmonic(1, 1.0))");
117    println!("      .add_partial(Partial::harmonic(2, 0.5));");
118    println!();
119    println!("  // Generate samples");
120    println!("  let samples = synth.generate(44100); // 1 second");
121    println!();
122    println!("  // Change frequency");
123    println!("  synth.set_frequency(880.0);");
124    println!();
125    println!("  // Reset phase");
126    println!("  synth.reset();");
127    println!("  ```\n");
128
129    Ok(())
130}
Source

pub fn sample(&mut self) -> f32

Generate a single sample

Sums all partials at their current phase positions and advances phases.

Source

pub fn generate(&mut self, length: usize) -> Vec<f32>

Generate multiple samples (SIMD-optimized)

§Arguments
  • length - Number of samples to generate
§Example
use tunes::synthesis::additive::{AdditiveSynth, Partial};

let mut synth = AdditiveSynth::new(440.0, 44100.0)
    .add_partial(Partial::harmonic(1, 1.0));

let one_second = synth.generate(44100);
Examples found in repository?
examples/additive_synthesis_demo.rs (line 17)
7fn main() -> anyhow::Result<()> {
8    println!("\n🎵 Example: Additive Synthesis API\n");
9
10    println!("Additive Synthesis - Building sounds from sine wave partials\n");
11
12    // 1. Pure Sine Wave (single partial)
13    println!("▶ Pure sine wave (fundamental only)");
14    let mut pure_sine = AdditiveSynth::new(440.0, 44100.0)
15        .add_partial(Partial::harmonic(1, 1.0));
16
17    let samples = pure_sine.generate(1000);
18    println!("  Generated {} samples", samples.len());
19
20    // 2. Sawtooth-like (harmonic series with 1/n amplitude)
21    println!("\n▶ Sawtooth-like sound (harmonic series)");
22    let mut sawtooth = AdditiveSynth::new(440.0, 44100.0)
23        .add_partial(Partial::harmonic(1, 1.0))
24        .add_partial(Partial::harmonic(2, 0.5))
25        .add_partial(Partial::harmonic(3, 0.33))
26        .add_partial(Partial::harmonic(4, 0.25))
27        .add_partial(Partial::harmonic(5, 0.2))
28        .add_partial(Partial::harmonic(6, 0.166));
29
30    let saw_samples = sawtooth.generate(1000);
31    println!("  Generated {} samples with 6 harmonics", saw_samples.len());
32
33    // 3. Square-like (odd harmonics only)
34    println!("\n▶ Square-like sound (odd harmonics)");
35    let mut square = AdditiveSynth::new(440.0, 44100.0)
36        .add_partial(Partial::harmonic(1, 1.0))
37        .add_partial(Partial::harmonic(3, 0.33))
38        .add_partial(Partial::harmonic(5, 0.2))
39        .add_partial(Partial::harmonic(7, 0.143))
40        .add_partial(Partial::harmonic(9, 0.111));
41
42    let square_samples = square.generate(1000);
43    println!("  Generated {} samples with odd harmonics", square_samples.len());
44
45    // 4. Organ Sound (selected harmonics for organ timbre)
46    println!("\n▶ Organ sound (organ-like harmonic recipe)");
47    let mut organ = AdditiveSynth::new(440.0, 44100.0)
48        .add_partial(Partial::harmonic(1, 1.0))    // Fundamental
49        .add_partial(Partial::harmonic(2, 0.5))    // Octave
50        .add_partial(Partial::harmonic(3, 0.8))    // Fifth
51        .add_partial(Partial::harmonic(4, 0.4))    // Double octave
52        .add_partial(Partial::harmonic(5, 0.3))    // Major third
53        .add_partial(Partial::harmonic(8, 0.2));   // Triple octave
54
55    let organ_samples = organ.generate(1000);
56    println!("  Generated {} samples with organ voicing", organ_samples.len());
57
58    // 5. Bell Sound (inharmonic partials for metallic timbre)
59    println!("\n▶ Bell sound (inharmonic partials)");
60    let mut bell = AdditiveSynth::new(440.0, 44100.0)
61        .add_partial(Partial::inharmonic(1.0, 1.0))
62        .add_partial(Partial::inharmonic(2.76, 0.6))
63        .add_partial(Partial::inharmonic(5.4, 0.4))
64        .add_partial(Partial::inharmonic(8.93, 0.25))
65        .add_partial(Partial::inharmonic(13.34, 0.15));
66
67    let bell_samples = bell.generate(1000);
68    println!("  Generated {} samples with inharmonic ratios", bell_samples.len());
69
70    // 6. Using with_partials for bulk adding
71    println!("\n▶ Using with_partials() for bulk configuration");
72    let partials = vec![
73        Partial::harmonic(1, 1.0),
74        Partial::harmonic(2, 0.5),
75        Partial::harmonic(3, 0.33),
76    ];
77
78    let mut bulk = AdditiveSynth::new(440.0, 44100.0)
79        .with_partials(partials);
80
81    let bulk_samples = bulk.generate(1000);
82    println!("  Generated {} samples from vec of partials", bulk_samples.len());
83
84    // 7. Dynamic frequency changes
85    println!("\n▶ Dynamic frequency control");
86    let mut dynamic = AdditiveSynth::new(440.0, 44100.0)
87        .add_partial(Partial::harmonic(1, 1.0));
88
89    let a440 = dynamic.generate(500);
90    dynamic.set_frequency(880.0); // Change to A5
91    let a880 = dynamic.generate(500);
92    println!("  Generated at 440Hz ({} samples), then 880Hz ({} samples)", a440.len(), a880.len());
93
94    // 8. Phase reset
95    println!("\n▶ Phase reset for synchronized playback");
96    let mut synth = AdditiveSynth::new(440.0, 44100.0)
97        .add_partial(Partial::harmonic(1, 1.0));
98
99    synth.generate(1000); // Advance phase
100    synth.reset(); // Reset to initial state
101    let reset_samples = synth.generate(1000);
102    println!("  Reset phase and generated {} samples", reset_samples.len());
103
104    println!("\n✓ Additive Synthesis Concepts:");
105    println!("  • Harmonic series: Integer frequency ratios (1, 2, 3, 4...)");
106    println!("  • Sawtooth: All harmonics with 1/n amplitude");
107    println!("  • Square: Odd harmonics only");
108    println!("  • Organ: Selected harmonics for warmth");
109    println!("  • Inharmonic: Non-integer ratios create metallic/bell timbres");
110    println!("  • Flexibility: Precise control over each frequency component");
111
112    println!("\n✓ API Usage:");
113    println!("  ```rust");
114    println!("  // Create synthesizer");
115    println!("  let mut synth = AdditiveSynth::new(440.0, 44100.0)");
116    println!("      .add_partial(Partial::harmonic(1, 1.0))");
117    println!("      .add_partial(Partial::harmonic(2, 0.5));");
118    println!();
119    println!("  // Generate samples");
120    println!("  let samples = synth.generate(44100); // 1 second");
121    println!();
122    println!("  // Change frequency");
123    println!("  synth.set_frequency(880.0);");
124    println!();
125    println!("  // Reset phase");
126    println!("  synth.reset();");
127    println!("  ```\n");
128
129    Ok(())
130}

Trait Implementations§

Source§

impl Clone for AdditiveSynth

Source§

fn clone(&self) -> AdditiveSynth

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for AdditiveSynth

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<S, T> Duplex<S> for T
where T: FromSample<S> + ToSample<S>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<S> FromSample<S> for S

Source§

fn from_sample_(s: S) -> S

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<F, T> IntoSample<T> for F
where T: FromSample<F>,

Source§

fn into_sample(self) -> T

Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> ToSample<U> for T
where U: FromSample<T>,

Source§

fn to_sample_(self) -> U

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V