97 lines
2.4 KiB
GDScript
97 lines
2.4 KiB
GDScript
extends AudioStreamPlayer
|
|
|
|
"""
|
|
AudioStreamPlayer with ADSR
|
|
"""
|
|
|
|
var releasing = false
|
|
var instrument = null
|
|
var velocity = 0
|
|
var pitch_bend = 0
|
|
var mix_rate = 0
|
|
var using_timer = 0.0
|
|
var timer = 0.0
|
|
var current_volume = 0
|
|
var maximum_volume_db = -8.0
|
|
var minimum_volume_db = -108.0
|
|
var pan = 0.5
|
|
var ads_state = [
|
|
{ "time": 0, "volume": 1.0 },
|
|
{ "time": 0.2, "volume": 0.95 },
|
|
# { "time": 0.2, "jump_to": 0.0 }, # not implemented
|
|
]
|
|
var release_state = [
|
|
{ "time": 0, "volume": 0.8 },
|
|
{ "time": 0.01, "volume": 0.0 },
|
|
# { "time": 0.2, "jump_to": 0.0 }, # not implemented
|
|
]
|
|
|
|
func _ready( ):
|
|
self.stop( )
|
|
|
|
func set_instrument( instrument ):
|
|
self.instrument = instrument
|
|
self.mix_rate = instrument.mix_rate
|
|
self.stream = instrument.stream.duplicate( )
|
|
self.ads_state = instrument.ads_state
|
|
self.release_state = instrument.release_state
|
|
|
|
func play( from_position=0.0 ):
|
|
self.releasing = false
|
|
self.timer = 0.0
|
|
self.using_timer = 0.0
|
|
self.current_volume = self.ads_state[0].volume
|
|
self.stream.mix_rate = round( self.mix_rate * ( 1.0 + self.pitch_bend * 0.5 ) )
|
|
.play( from_position )
|
|
self._update_volume( )
|
|
|
|
func start_release( ):
|
|
self.releasing = true
|
|
self.current_volume = self.release_state[0].volume
|
|
self.timer = 0.0
|
|
self._update_volume( )
|
|
|
|
func set_pitch_bend( pb ):
|
|
self.pitch_bend = pb
|
|
var pos = self.get_playback_position( )
|
|
self.stream.mix_rate = round( self.mix_rate * ( 1.0 + self.pitch_bend * 0.5 ) )
|
|
.play( pos )
|
|
|
|
func _process( delta ):
|
|
if not self.playing:
|
|
return
|
|
|
|
self.timer += delta
|
|
self.using_timer += delta
|
|
# self.transform.origin.x = self.pan * self.get_viewport( ).size.x
|
|
|
|
# ADSR
|
|
var use_state = null
|
|
if self.releasing:
|
|
use_state = self.release_state
|
|
else:
|
|
use_state = self.ads_state
|
|
|
|
var all_states = use_state.size( )
|
|
var last_state = all_states - 1
|
|
if use_state[last_state].time <= self.timer:
|
|
self.current_volume = use_state[last_state].volume
|
|
if self.releasing:
|
|
self.stop( )
|
|
else:
|
|
for state_number in range( 1, all_states ):
|
|
var state = use_state[state_number]
|
|
if self.timer < state.time:
|
|
var pre_state = use_state[state_number-1]
|
|
var s = ( state.time - self.timer ) / ( state.time - pre_state.time )
|
|
var t = 1.0 - s
|
|
self.current_volume = pre_state.volume * s + state.volume * t
|
|
break
|
|
|
|
self._update_volume( )
|
|
|
|
func _update_volume( ):
|
|
var s = self.current_volume
|
|
var t = 1.0 - s
|
|
self.volume_db = s * self.maximum_volume_db + t * self.minimum_volume_db
|