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 secondsImplementations§
Source§impl AdditiveSynth
impl AdditiveSynth
Sourcepub fn new(fundamental_freq: f32, sample_rate: f32) -> Self
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}Sourcepub fn add_partial(self, partial: Partial) -> Self
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}Sourcepub fn with_partials(self, partials: Vec<Partial>) -> Self
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}Sourcepub fn set_frequency(&mut self, freq: f32)
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 A5Examples 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}Sourcepub fn reset(&mut self)
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}Sourcepub fn sample(&mut self) -> f32
pub fn sample(&mut self) -> f32
Generate a single sample
Sums all partials at their current phase positions and advances phases.
Sourcepub fn generate(&mut self, length: usize) -> Vec<f32>
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
impl Clone for AdditiveSynth
Source§fn clone(&self) -> AdditiveSynth
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)
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from
source. Read moreAuto Trait Implementations§
impl Freeze for AdditiveSynth
impl RefUnwindSafe for AdditiveSynth
impl Send for AdditiveSynth
impl Sync for AdditiveSynth
impl Unpin for AdditiveSynth
impl UnsafeUnpin for AdditiveSynth
impl UnwindSafe for AdditiveSynth
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<S, T> Duplex<S> for Twhere
T: FromSample<S> + ToSample<S>,
Source§impl<S> FromSample<S> for S
impl<S> FromSample<S> for S
fn from_sample_(s: S) -> S
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
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