ruby-mext 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Rakefile +3 -0
- data/lib/mext/math/expon.rb +88 -0
- data/lib/mext/math.rb +9 -0
- data/lib/mext/numeric/cpspch.rb +18 -0
- data/lib/mext/numeric/mtopch.rb +20 -0
- data/lib/mext/numeric/pchcps.rb +16 -0
- data/lib/mext/numeric/pchtom.rb +26 -0
- data/lib/mext/numeric/rrand.rb +32 -0
- data/lib/mext/numeric.rb +5 -0
- data/lib/mext.rb +1 -0
- data/lib/tasks/clean.rake +5 -0
- data/lib/tasks/gruff/expon.rake +20 -0
- data/lib/tasks/gruff/gruff.rake +3 -0
- data/lib/tasks/gruff/gruff_plot.rb +39 -0
- data/lib/version.rb +1 -1
- data/ruby-mext.gemspec +1 -0
- metadata +27 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f9b816eb8358ac2720a30375f4d7c5c85a8d99b61781efd8eea22ba931e54b5e
|
4
|
+
data.tar.gz: fe9a1ad5339a33fc710319bcd9c512538aec99902ebd3ac5bee8e0b617bef013
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 77455bc326bfe523232abca1f8985ea6ded5a7368c06ca41f2b10f551b541b656c4d402b0e10fcf7946895169ad4e2c6c2ee7c7c9260319602081c71900e2f9c
|
7
|
+
data.tar.gz: c02ba1e2882ad0760cb7c217980c92c7d65896f6cb7e42c086f7f428efa57852c0a5f30f2400a181d364fe4ff84ee00f416f876d863dfa90d7a743934dc70340
|
data/Rakefile
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
2
|
require "rspec/core/rake_task"
|
3
3
|
require 'rdoc/task'
|
4
|
+
require 'ruby-mext'
|
4
5
|
|
5
6
|
RDoc::Task.new do |rdoc|
|
6
7
|
rdoc.main = "README.md"
|
@@ -10,3 +11,5 @@ end
|
|
10
11
|
RSpec::Core::RakeTask.new(:spec)
|
11
12
|
|
12
13
|
task :default => :spec
|
14
|
+
|
15
|
+
Dir.glob(File.expand_path(File.join('..', 'lib', 'tasks', '**', '*.rake'), __FILE__)).each { |f| load f }
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'cmath'
|
2
|
+
|
3
|
+
module Math
|
4
|
+
|
5
|
+
class Expon
|
6
|
+
|
7
|
+
attr_reader :y_start, :y_end, :x_start, :x_end, :tau
|
8
|
+
attr_reader :a, :b, :c
|
9
|
+
|
10
|
+
#
|
11
|
+
# +DEFAULT_TAU+: default exponential curvature factor for +expon()+
|
12
|
+
#
|
13
|
+
DEFAULT_TAU = 0.01
|
14
|
+
|
15
|
+
#
|
16
|
+
# +Math::Expon.new(ystart, yend, xstart, xend, tau = DEFAULT_TAU)+:
|
17
|
+
#
|
18
|
+
# exponential curve `y = e^(a*x + b) + c` where:
|
19
|
+
#
|
20
|
+
# `c = yend + tau`
|
21
|
+
#
|
22
|
+
# Arguments are:
|
23
|
+
#
|
24
|
+
# +ystart+, +yend+: start/end y values required
|
25
|
+
# +xstart+, +xend+: start/end x values
|
26
|
+
# +tau+: the curvature factor
|
27
|
+
#
|
28
|
+
#:nodoc:
|
29
|
+
def initialize(ys, ye, xs, xe, tau = DEFAULT_TAU)
|
30
|
+
@y_start = ys
|
31
|
+
@y_end = ye
|
32
|
+
@x_start = xs
|
33
|
+
@x_end = xe
|
34
|
+
@tau = tau
|
35
|
+
setup
|
36
|
+
end
|
37
|
+
|
38
|
+
#:doc:
|
39
|
+
#
|
40
|
+
# +y(x)+:
|
41
|
+
#
|
42
|
+
# Returns a real value (forcing any complex result to its modulus) for any
|
43
|
+
# given x
|
44
|
+
#
|
45
|
+
#:nodoc:
|
46
|
+
def y(x)
|
47
|
+
(CMath::exp(self.a*x + self.b) + self.c).abs # we want a real number result, no complex please
|
48
|
+
end
|
49
|
+
|
50
|
+
#:doc:
|
51
|
+
#
|
52
|
+
# +xy(step)+
|
53
|
+
#
|
54
|
+
# Returns a full deployment of the function evaluated with a step of
|
55
|
+
# +step+. It is returned in two arrays - one for the +x+ values and the
|
56
|
+
# other for the +y+ values.
|
57
|
+
#
|
58
|
+
# This method is mainly for testing purposes with the dataxy method of +gruff+
|
59
|
+
#
|
60
|
+
#:nodoc:
|
61
|
+
def xy(s)
|
62
|
+
resx = []
|
63
|
+
resy = []
|
64
|
+
self.x_start.step(x_end, s) do
|
65
|
+
|x|
|
66
|
+
resx << x
|
67
|
+
resy << self.y(x)
|
68
|
+
end
|
69
|
+
[resx, resy]
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def setup
|
75
|
+
@c = self.y_end + self.tau
|
76
|
+
|
77
|
+
exp_sv = self.y_start - self.c # start value of the exponential
|
78
|
+
exp_ev = self.y_end - self.c # end value of the exponential
|
79
|
+
x_length = self.x_end - self.x_start
|
80
|
+
|
81
|
+
@a = (CMath::log(exp_ev) - CMath::log(exp_sv)) / x_length;
|
82
|
+
@b= CMath::log(exp_sv) - (self.a * x_start);
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
data/lib/mext/math.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
class Numeric
|
2
|
+
|
3
|
+
#
|
4
|
+
# +cpspch+: frequency to pitch class converter
|
5
|
+
#
|
6
|
+
# interprets its receiver as frequency and returns its corresponing pitch class
|
7
|
+
#
|
8
|
+
#:nodoc:
|
9
|
+
|
10
|
+
def cpspch
|
11
|
+
raise NegativeNumeric if self <= 0.0
|
12
|
+
|
13
|
+
midi_note = self.ftom
|
14
|
+
|
15
|
+
midi_note.mtopch
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class Numeric
|
2
|
+
|
3
|
+
#
|
4
|
+
# +mtopch+: MIDI note to pitch class converter
|
5
|
+
#
|
6
|
+
# interprets its receiver as a MIDI note and returns its corresponing pitch class
|
7
|
+
#
|
8
|
+
#:nodoc:
|
9
|
+
|
10
|
+
def mtopch
|
11
|
+
|
12
|
+
intv = (self - MIDI_MIDDLE_C) / CHROMATIC_NOTES_PER_OCTAVE
|
13
|
+
|
14
|
+
intv_octave = intv.to_i
|
15
|
+
intv_semi = (intv - intv_octave) * CHROMATIC_NOTES_PER_OCTAVE;
|
16
|
+
|
17
|
+
PITCH_MIDDLE_C + intv_octave + (intv_semi/100.0);
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class Numeric
|
2
|
+
|
3
|
+
#
|
4
|
+
# +pchtom+: pitch class to MIDI note converter
|
5
|
+
#
|
6
|
+
# interprets its receiver as a pitch class and returns its corresponing MIDI note
|
7
|
+
#
|
8
|
+
#:nodoc:
|
9
|
+
MIDI_MIDDLE_C = 60
|
10
|
+
PITCH_MIDDLE_C = 8.0
|
11
|
+
CHROMATIC_NOTES_PER_OCTAVE = 12.0
|
12
|
+
|
13
|
+
def pchtom
|
14
|
+
p_octave = self.to_i
|
15
|
+
p_note = (self - p_octave) * 100
|
16
|
+
ref = self < 0.0 ? -CHROMATIC_NOTES_PER_OCTAVE : CHROMATIC_NOTES_PER_OCTAVE
|
17
|
+
|
18
|
+
p_octave += (p_note / CHROMATIC_NOTES_PER_OCTAVE).to_i # cater for octave wrapping
|
19
|
+
p_note = (p_note % ref); # reduce note in a 0-11 space (keeping track of sign)
|
20
|
+
|
21
|
+
m_octave = ((p_octave - PITCH_MIDDLE_C)*CHROMATIC_NOTES_PER_OCTAVE) + MIDI_MIDDLE_C; # find the appropriate midi octave
|
22
|
+
|
23
|
+
m_octave + p_note
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class Numeric
|
2
|
+
|
3
|
+
#
|
4
|
+
# +rrand(upper)+: random number generator
|
5
|
+
#
|
6
|
+
# returns a random number in the range receiver-upper bound
|
7
|
+
#
|
8
|
+
# If any of the numbers (the receiver +or+ the argument) are +Float+s
|
9
|
+
# the method will return a +Float+. If both arguments are integers then an
|
10
|
+
# +Integer+ will be returned.
|
11
|
+
#
|
12
|
+
# (this method is present in the SuperCollider sclang interpreter)
|
13
|
+
#
|
14
|
+
#:nodoc:
|
15
|
+
|
16
|
+
def rrand(upper)
|
17
|
+
lobound = self.to_f
|
18
|
+
rng = upper.to_f - lobound
|
19
|
+
|
20
|
+
(rand()*rng) + lobound
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
class Integer
|
26
|
+
|
27
|
+
def rrand(upper)
|
28
|
+
res = super(upper)
|
29
|
+
upper.is_a?(Integer) ? res.round : res
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
data/lib/mext/numeric.rb
CHANGED
data/lib/mext.rb
CHANGED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require File.expand_path(File.join(['..'] * 4, 'spec', 'fixtures', 'expon_dataset'), __FILE__)
|
3
|
+
require File.expand_path(File.join('..', 'gruff_plot'), __FILE__)
|
4
|
+
|
5
|
+
namespace :plot do
|
6
|
+
|
7
|
+
task :create_output_dir do
|
8
|
+
unless Dir.exists?(Mext::Gruff::Plotter::OUTPUT_PATH)
|
9
|
+
mkdir_p Mext::Gruff::Plotter::OUTPUT_PATH
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
desc 'plot the Expon dataset'
|
14
|
+
task :expon => :create_output_dir do
|
15
|
+
ranges = [ Range.new(0, 2), Range.new(3,3) ]
|
16
|
+
p = Mext::Gruff::Plotter.new('expon_dataset', 800, Mext::Spec::Fixtures::Math::EXPON_DATASETS, ranges)
|
17
|
+
p.plot
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'gruff'
|
2
|
+
|
3
|
+
module Mext
|
4
|
+
module Gruff
|
5
|
+
|
6
|
+
class Plotter
|
7
|
+
attr_reader :title, :size, :datasets, :ranges
|
8
|
+
|
9
|
+
OUTPUT_PATH = File.expand_path(File.join(['..'] * 4, 'tmp', 'output'), __FILE__)
|
10
|
+
|
11
|
+
def initialize(t, s, ds, r = nil)
|
12
|
+
@title = t
|
13
|
+
@size = s
|
14
|
+
@datasets = ds
|
15
|
+
@ranges = r
|
16
|
+
end
|
17
|
+
|
18
|
+
def plot
|
19
|
+
@ranges = [Range.new(0, self.datasets-1)] unless self.ranges
|
20
|
+
idx = 0
|
21
|
+
self.ranges.each do
|
22
|
+
|range|
|
23
|
+
g = ::Gruff::Line.new(self.size)
|
24
|
+
g.title = self.title + " (#{idx})"
|
25
|
+
self.datasets[range].each do
|
26
|
+
|args|
|
27
|
+
(ys, ye, xs, xe, tau, xmid, ymid) = args
|
28
|
+
f = Math::Expon.new(ys, ye, xs, xe, tau)
|
29
|
+
(xdata, ydata) = f.xy(0.1)
|
30
|
+
g.dataxy("tau: #{f.tau}", xdata, ydata)
|
31
|
+
end
|
32
|
+
g.write(File.join(Mext::Gruff::Plotter::OUTPUT_PATH, self.title.gsub(/\s+/, '_') + "_#{idx}.png"))
|
33
|
+
idx += 1
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/version.rb
CHANGED
data/ruby-mext.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-mext
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nicola Bernardini
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-04-
|
11
|
+
date: 2019-04-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: gruff
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
83
97
|
description: 'ruby-mext: musical extensions for the Ruby language.'
|
84
98
|
email:
|
85
99
|
- nicb@sme-ccppd.org
|
@@ -100,14 +114,25 @@ files:
|
|
100
114
|
- bin/console
|
101
115
|
- bin/setup
|
102
116
|
- lib/mext.rb
|
117
|
+
- lib/mext/math.rb
|
118
|
+
- lib/mext/math/expon.rb
|
103
119
|
- lib/mext/numeric.rb
|
104
120
|
- lib/mext/numeric/ampdb.rb
|
121
|
+
- lib/mext/numeric/cpspch.rb
|
105
122
|
- lib/mext/numeric/dbamp.rb
|
106
123
|
- lib/mext/numeric/exceptions.rb
|
107
124
|
- lib/mext/numeric/ftom.rb
|
108
125
|
- lib/mext/numeric/mtof.rb
|
126
|
+
- lib/mext/numeric/mtopch.rb
|
127
|
+
- lib/mext/numeric/pchcps.rb
|
128
|
+
- lib/mext/numeric/pchtom.rb
|
109
129
|
- lib/mext/numeric/pitch_fork.rb
|
130
|
+
- lib/mext/numeric/rrand.rb
|
110
131
|
- lib/ruby-mext.rb
|
132
|
+
- lib/tasks/clean.rake
|
133
|
+
- lib/tasks/gruff/expon.rake
|
134
|
+
- lib/tasks/gruff/gruff.rake
|
135
|
+
- lib/tasks/gruff/gruff_plot.rb
|
111
136
|
- lib/version.rb
|
112
137
|
- ruby-mext.gemspec
|
113
138
|
homepage: https://github.com/nicb/ruby-mext
|