mirror of
https://github.com/SleepingInsomniac/pixelfaucet
synced 2025-02-02 20:45:54 +01:00
Improve piano, add harmonica
This commit is contained in:
parent
55f9ce35f4
commit
2c22abf2ea
4 changed files with 49 additions and 9 deletions
|
@ -18,7 +18,7 @@ module PF
|
|||
@white_keys = [] of Tuple(Vector2(Int32), Vector2(Int32), String)
|
||||
@black_keys = [] of Tuple(Vector2(Int32), Vector2(Int32), String)
|
||||
|
||||
@instruments : Array(Instrument) = [RetroVoice.new, PianoVoice.new, Flute.new, KickDrum.new, SnareDrum.new]
|
||||
@instruments : Array(Instrument) = [RetroVoice.new, PianoVoice.new, Flute.new, KickDrum.new, SnareDrum.new, Harmonica.new]
|
||||
|
||||
def initialize(*args, **kwargs)
|
||||
super
|
||||
|
|
|
@ -6,7 +6,7 @@ module PF
|
|||
@device_id : LibSDL::AudioDeviceID
|
||||
property volume = 0.5
|
||||
# https://dsp.stackexchange.com/questions/3581/algorithms-to-mix-audio-signals-without-clipping
|
||||
property headroom = 0.4
|
||||
property headroom = 0.3
|
||||
delegate :freq, to: @spec
|
||||
@playing : Bool = false
|
||||
getter time : Float64 = 0.0
|
||||
|
|
|
@ -3,6 +3,7 @@ module PF
|
|||
property name : String = "Unnamed Instrument"
|
||||
property envelope : Envelope
|
||||
property wave : Sound::Wave
|
||||
property volume : Float64 = 1.0
|
||||
|
||||
getter sounds : Array(Sound) = [] of Sound
|
||||
@notes : Hash(UInt32, Sound) = {} of UInt32 => Sound
|
||||
|
@ -13,7 +14,7 @@ module PF
|
|||
|
||||
def on(hertz : Float64, time : Float64)
|
||||
@note_id += 1_u32
|
||||
sound = Sound.new(hertz, @envelope, time, @wave)
|
||||
sound = Sound.new(hertz, @envelope, time, @volume, @wave)
|
||||
@notes[@note_id] = sound
|
||||
@sounds << sound
|
||||
@note_id
|
||||
|
@ -47,13 +48,32 @@ module PF
|
|||
class PianoVoice < Instrument
|
||||
def initialize
|
||||
@name = "Piano"
|
||||
|
||||
exp_interpolation = ->(time : Float64, duration : Float64, initial : Float64, level : Float64) do
|
||||
# https://www.desmos.com/calculator/r2jn9wurwv
|
||||
curve = 1000
|
||||
(initial - level) * ((curve ** -(time / duration)) * (1 + (1 / curve)) - (1 / curve)) + level
|
||||
end
|
||||
|
||||
@envelope = Envelope.new(
|
||||
attack: Envelope::Stage.new(0.001, 0.0, 1.0),
|
||||
decay: Envelope::Stage.new(0.7, 1.0, 0.0),
|
||||
attack: Envelope::Stage.new(0.001, 0.0, 1.0, exp_interpolation),
|
||||
decay: Envelope::Stage.new(3.0, 1.0, 0.0, exp_interpolation),
|
||||
sustain: Envelope::Stage.new(0.0, 0.0, 0.0),
|
||||
release: Envelope::Stage.new(0.5, 1.0, 0.0)
|
||||
release: Envelope::Stage.new(0.3, 1.0, 0.0)
|
||||
)
|
||||
@wave = Sound.triangle_wave(6.0, 0.0005)
|
||||
|
||||
@wave = ->(time : Float64, hertz : Float64) do
|
||||
# https://www.desmos.com/calculator/mnxargxllk
|
||||
av = 2 * Math::PI * hertz * time
|
||||
y = (Math.sin(Math::PI * (av / Math::PI)) ** 3) + Math.sin(Math::PI * ((av / Math::PI) + (2 / 3)))
|
||||
y = (Math.sin(av) ** 3) + Math.sin(av + 0.6666)
|
||||
y += y / 2
|
||||
y += y / 4
|
||||
y += y / 8
|
||||
y += y / 16
|
||||
y += y / 32
|
||||
y /= 5
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -106,4 +126,23 @@ module PF
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Harmonica < Instrument
|
||||
def initialize
|
||||
@name = "Harmonica"
|
||||
@envelope = Envelope.new(
|
||||
attack: Envelope::Stage.new(0.1, 0.0, 1.0),
|
||||
decay: Envelope::Stage.new(0.3, 1.0, 0.8),
|
||||
sustain: Envelope::Stage.new(Float64::INFINITY, 0.8, 0.8),
|
||||
release: Envelope::Stage.new(0.3, 1.0, 0.0)
|
||||
)
|
||||
@volume = 0.5
|
||||
wave = Sound.square_wave
|
||||
@wave = ->(time : Float64, hertz : Float64) do
|
||||
0.5 * wave.call(time + 0.1, hertz * 2) +
|
||||
wave.call(time, hertz) +
|
||||
rand(-0.05..0.05)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
module PF
|
||||
struct Note
|
||||
NAMES = %w[C C#/Db D D#/Eb E F F#/Gb G G#/Ab A A#/Bb B]
|
||||
ACCIDENTALS = StaticArray[1u8, 3u8, 6u8, 8u8, 10u8]
|
||||
TWELFTH_ROOT = 2 ** (1 / 12)
|
||||
NAMES = %w[C C#/Db D D#/Eb E F F#/Gb G G#/Ab A A#/Bb B]
|
||||
ACCIDENTALS = StaticArray[1u8, 3u8, 6u8, 8u8, 10u8]
|
||||
|
||||
getter tuning : Float64 = 440.0
|
||||
getter number : Float64
|
||||
|
|
Loading…
Add table
Reference in a new issue