-
Notifications
You must be signed in to change notification settings - Fork 0
/
synth.jl
102 lines (95 loc) · 3.36 KB
/
synth.jl
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
using Random
const frequencies = Dict("c"=>16.3516,"c#"=>17.32391, "d"=>18.35405, "d#"=>19.44544, "e"=>20.60172,
"f"=>21.82676, "f#"=>23.12465, "g"=>24.49971, "g#" => 25.95654, "a"=>27.5, "a#"=>29.13524,
"b"=>30.86771
)
#check input string to see if it matches convention
function checkInput(input::AbstractString)
if (length(input) >3 || length(input) < 2 ) return false end
return !isnothing(match(r"([a-g]#?[\d])"i, input))
end
#returns the correct frequency for the given note and octave
function getFreq(input::AbstractString)
if !checkInput(input) return false end
if length(input)==2
noteName = lowercase(string(input[1]))
octave = parse(Int, input[2])
else
noteName = lowercase(input[1:2])
octave = parse(Int, input[3])
end
return frequencies[noteName] * 2^octave
end
function getFreq(input::Real)
return input
end
#returns a vector where fs is sampling rate, from 0 to seconds in increments of 1/fs
function getTimeVector(seconds,fs)
return 0.0 : inv(fs) : seconds
end
#returns a sin wave at give frequency for givin time
function getSine(seconds, hz, fs = 41000.0)
t = 0.0 : inv(fs) : seconds
sin.(2π * hz * t )
end
#returns a sin wave at given note name and time
function getSine(seconds, freq::AbstractString, fs = 41000.0)
hz = getFreq(freq)
t = 0.0 : inv(fs) : seconds
sin.(2π * hz * t )
end
#=
get a sin wave with vibrato code adapted from:
https://www.audiolabs-erlangen.de/resources/MIR/FMP/C1/C1S3_Timbre.html
#Meinard Müller and Frank Zalkow: FMP Notebooks: Educational Material for Teaching and Learning Fundamentals of Music Processing. Proceedings of the International Conference on Music Information Retrieval (ISMIR), Delft, The Netherlands, 2019.
=#
function getSine(seconds, hz, fs, vib_amp=1, vib_rate=5)
t = 0.0 : inv(fs) : seconds
freq_vib = hz .+ vib_amp .* sin.(t * 2π * vib_rate)
phase_vib = zeros(length(t))
for i in 2:length(t)
phase_vib[i] = phase_vib[i-1] + 2π* freq_vib[i-1] / fs
end
sin.(phase_vib)
end
function getSine(seconds, freq::AbstractString, fs, vib_amp=1, vib_rate=5)
hz = getFreq(freq)
t = 0.0 : inv(fs) : seconds
freq_vib = hz .+ vib_amp .* sin.(t * 2π * vib_rate)
phase_vib = zeros(length(t))
for i in 2:length(t)
phase_vib[i] = phase_vib[i-1] + 2π* freq_vib[i-1] / fs
end
sin.(phase_vib)
end
#=returns a saw wave at give frequency for givin time
#note to self:change to the series formation of saw wave
to remove aliasing
=#
function getSaw(seconds, hz, fs = 41000.0)
timeVector = getTimeVector(seconds, fs)
2 .* mod.(timeVector * hz, 1).-1
end
#returns a sin wave at given note name and time
function getSaw(seconds, freq::AbstractString, fs = 41000.0)
hz = getFreq(freq)
timeVector = getTimeVector(seconds, fs)
2 .* mod.(timeVector * hz, 1).-1
end
function lfo(signal::AbstractVector{T},hz,fun::Function, i::Tuple = (1,40),fs=41000)where
{T<:Real}
inc = Float64(0)
newSignal = T[]
f(x) = (i[2]-i[1])*sin(2π * x * hz)/2 + (i[2]+i[1])/2
for i in signal
push!(newSignal, fun(i,f(inc)))
inc+=inv(fs)
end
return newSignal
end
#returns a vector containing random noise for seconds
function getRand(seconds,fs= 41000)
rng = MersenneTwister(1234)
count = length(0.0 : inv(fs) : seconds)
return rand!(rng, zeros(count)).*2 .-1
end