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
|
//! # Rust audio oscillator for the Godot game engine
//!
//! This crate contains logic for generating samples for audio wave forms which are then
//! used to fill Godot's `AudioStreamPlayback` buffers. Scripts using this code as a dynamic
//! library will be able to request a certain number of frames (represented as a `Vector2`)
//! at a specific frequency. Because of how the Godot bindings work, the wave structs will
//! have a default sample rate at 48kHz. You'll want to set it in your script's `_ready`
//! function to match the sample rate in Godot.
use gdnative::prelude::*;
use gdnative::core_types::TypedArray;
use std::f32::consts::TAU;
#[derive(NativeClass)]
#[inherit(Node)]
pub struct SineWave {
pub sample_rate: f32,
pub phase: f32
}
/// # Examples
///
/// ```
/// use klangfarbrs::SineWave;
/// let mut wave = SineWave { sample_rate: 24000.0, phase: 0.0 };
/// assert_eq!(wave.sample_rate, 24000.0);
/// ```
#[methods]
impl SineWave {
pub fn new(_owner: &Node) -> Self {
Self { sample_rate: 48000.0, phase: 0.0 }
}
#[export]
fn _ready(&self, _owner: &Node) {
godot_print!("DAS IST KLANGFARBRS.")
}
#[export]
pub fn set_sample_rate(&mut self, _owner: &Node, sample_rate: f32) {
self.sample_rate = sample_rate;
}
#[export]
pub fn frames(&mut self, _owner: &Node, frequency: f32, duration: i32) -> TypedArray<Vector2> {
let mut frames = TypedArray::new();
for _i in 0..duration {
let sample = (TAU * self.phase).sin().clamp(-1.0, 1.0);
frames.push(Vector2::new(sample, sample));
self.phase = (self.phase + (frequency / self.sample_rate)) % 1.0;
}
return frames
}
}
// Function that registers all exposed classes to Godot
fn init(handle: InitHandle) {
// Register the `Sine` type we declared.
handle.add_class::<SineWave>();
}
// Macro that creates the entry-points of the dynamic library.
godot_init!(init);
|