Files
soundgen/SoundGen/Synth.fs
2022-11-01 09:20:22 +04:00

81 lines
1.7 KiB
Forth

module SoundGen.Synth
open Settings
open Oscillator
open SoundGen.Oscillator
let getHzBySemitones semi =
pitchStandard * (2. ** (1. / 12.)) ** semi
let getSemitonesByNote (str: string) =
let defaultOctave = 4
let notes =
[ "A"
"A#"
"B"
"C"
"C#"
"D"
"D#"
"E"
"F"
"F#"
"G"
"G#" ]
|> List.toArray
let octave =
str.Substring(str.Length - 1) |> int
let noteShift =
Array.findIndex (fun e -> e = str.Substring(0, str.Length - 1)) notes
(octave - defaultOctave - 1) * 12 + noteShift
let freq hz duration (osc: OscillatorParameter list) =
let samples =
seq { 0.0 .. (duration * sampleRate) }
let attack =
let samplesToRise =
(sampleRate * (0.001 * attackMs))
let risingDelta = 1. / samplesToRise
let mutable i = 0.
seq {
while true do
i <- i + risingDelta
yield min i 1.
}
let output =
Seq.map
(fun x ->
multiosc { Oscillators = osc; Sample = x }
|> (*) volume)
samples
let adsrLength = Seq.length output
let attackArray =
attack |> Seq.take adsrLength
let release = Seq.rev attackArray
Seq.zip3 release attackArray output
|> Seq.map (fun (x, y, z) -> (x * y * z))
let note semitone beats =
let hz = getHzBySemitones (semitone - 12.)
freq
hz
(beats * beatDuration)
[ { Osc = Sine; Freq = hz / 4. }
{ Osc = Saw; Freq = (hz + 1.) }
{ Osc = Saw; Freq = (hz - 1.3) } ]