-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathspectrum.rb
59 lines (52 loc) · 1.22 KB
/
spectrum.rb
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
#!/usr/bin/ruby
DESC = 'Computes the spectrum of a waveform. No scaling is done.
Usage: ./spectrum.rb [<option>...] <values>...
Options:
- `db`: Output values in decibels'
#def ft(a, b, f, k)
# return k * (b - a) if f == 0
# w = 2.0 * Math::PI * f
# k / w * (Math.sin(w * b) - Math.sin(w * a) +
# 1i * (Math.cos(w * b) - Math.cos(w * a)))
#end
def ft_step(a, s, f, k)
return k / s.to_f if f == 0
pi_f = Math::PI * f
Math.sin(pi_f / s) * k / pi_f *
Math::E ** (-(2.0 * a + 1.0 / s) * pi_f * 1i)
end
def spectrum(f, *t)
(0..f).map do |f|
t.map.with_index do |x, k|
ft_step(k.to_f / t.size, t.size, f, x)
end.reduce(0, &:+)
end
end
samples = []
db = false
if ARGV.empty?
puts DESC
exit
end
ARGV.each do |x|
case x
when 'db'
db = true
else
begin
samples << Float(x)
rescue
STDERR.puts 'Error while parsing arguments.'
exit 1
end
end
end
if samples.size < 2
STDERR.puts 'At least two samples are required.'
exit 1
end
s = spectrum(25, *samples).map &:magnitude
dc = s.shift
s.map! {|x| 20.0 * Math.log(x < 1e-12 ? 0 : x, 10)} if db
print s.map.with_index {|x, k| '% 8.4f%s' % [x, k % 5 == 4 ? "\n" : ' ']}.join
print '%sDC: %.4f' % [s.size % 5 == 0 ? '' : "\n", dc]