class_name AudioFactory extends RefCounted ## Factory condivisa per suoni procedurali morbidi e sensory-friendly. static func create_tone(freq: float, duration: float, amp: float = 0.3) -> AudioStreamWAV: var sample_rate := 22050 var num_samples := int(sample_rate * duration) var data := PackedByteArray() data.resize(num_samples) var attack := int(sample_rate * 0.01) for i in num_samples: var t := float(i) / sample_rate var env := 1.0 if i < attack: env = float(i) / attack env *= exp(-3.0 * t / duration) var value := int(clampf(sin(t * freq * TAU) * env * amp * 127.0, -128.0, 127.0)) data[i] = value & 0xff var stream := AudioStreamWAV.new() stream.format = AudioStreamWAV.FORMAT_8_BITS stream.mix_rate = sample_rate stream.data = data return stream static func create_arpeggio(freqs: Array[float], note_duration: float = 0.12, amp: float = 0.3) -> AudioStreamWAV: var sample_rate := 22050 var samples_per_note := int(sample_rate * note_duration) var data := PackedByteArray() data.resize(samples_per_note * freqs.size()) var index := 0 var attack := int(sample_rate * 0.01) for freq in freqs: for i in samples_per_note: var t := float(i) / sample_rate var env := 1.0 if i < attack: env = float(i) / attack env *= exp(-3.0 * t / note_duration) var value := int(clampf(sin(t * freq * TAU) * env * amp * 127.0, -128.0, 127.0)) data[index] = value & 0xff index += 1 var stream := AudioStreamWAV.new() stream.format = AudioStreamWAV.FORMAT_8_BITS stream.mix_rate = sample_rate stream.data = data return stream static func play_once(parent: Node, stream: AudioStream, volume_db: float = 0.0) -> AudioStreamPlayer: var player := AudioStreamPlayer.new() player.stream = stream player.volume_db = volume_db parent.add_child(player) player.finished.connect(player.queue_free) player.play() return player