ruby-mext 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 773f3e12f73de66842d7642971dcea4b2867739ef6b4cc31cd5817e0ffe4ffe6
4
- data.tar.gz: 15072b30760291f0018672562ab5f3a7b3a72a3e943b63822b2ef334c4a4cbb5
3
+ metadata.gz: f9b816eb8358ac2720a30375f4d7c5c85a8d99b61781efd8eea22ba931e54b5e
4
+ data.tar.gz: fe9a1ad5339a33fc710319bcd9c512538aec99902ebd3ac5bee8e0b617bef013
5
5
  SHA512:
6
- metadata.gz: d90bc088598500d36d74bfecc0dcf56cbc7be5f1e4f9febbbbd954ce2d49da1c3bc6b949729363da5ffe0d8476361ddc10ac66fb4da040efcc7fd6babe44bc3d
7
- data.tar.gz: 66a518a399b40aadaf5e9e318489951859eed2c8412f655336c802f0195bb8713b68aeb25873f91388f8daa960669a91f6f154f01c1c86bca5c384abad75d46b
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,9 @@
1
+ module Mext
2
+
3
+ MATH_PATH = File.join(Mext::PATH, 'math')
4
+
5
+ end
6
+
7
+ %w(
8
+ expon
9
+ ).each { |f| require File.join(Mext::MATH_PATH, f) }
@@ -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,16 @@
1
+ class Numeric
2
+
3
+ #
4
+ # +pchcps+: pitch class converter to frequency
5
+ #
6
+ # interprets its receiver as pitch class and returns its corresponing frequency
7
+ #
8
+ #:nodoc:
9
+
10
+ def pchcps
11
+ m_note = self.pchtom
12
+
13
+ m_note.mtof
14
+ end
15
+
16
+ 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
@@ -11,4 +11,9 @@ end
11
11
  ftom
12
12
  ampdb
13
13
  dbamp
14
+ pchtom
15
+ mtopch
16
+ cpspch
17
+ pchcps
18
+ rrand
14
19
  ).each { |f| require File.join(Mext::NUMERIC_PATH, f) }
data/lib/mext.rb CHANGED
@@ -6,4 +6,5 @@ end
6
6
 
7
7
  %w(
8
8
  numeric
9
+ math
9
10
  ).each { |f| require File.join(Mext::PATH, f) }
@@ -0,0 +1,5 @@
1
+ require 'rake/clean'
2
+
3
+ CLEAN.include('tmp')
4
+ CLEAN.include('html')
5
+ CLEAN.include('pkg')
@@ -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,3 @@
1
+
2
+ desc 'plot all plots'
3
+ task :plot => ['plot:expon']
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Mext
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
data/ruby-mext.gemspec CHANGED
@@ -34,5 +34,6 @@ Gem::Specification.new do |spec|
34
34
  spec.add_development_dependency 'rspec', '~> 3.0'
35
35
  spec.add_development_dependency 'rdoc'
36
36
  spec.add_development_dependency 'byebug'
37
+ spec.add_development_dependency 'gruff'
37
38
 
38
39
  end
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.1.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-20 00:00:00.000000000 Z
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