shlisp_tools 0.0.1 → 0.0.2

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.
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # ShlispTools
2
2
 
3
- Tools for shlisp/shnth developers. If you don't recognize both of words starting with "sh", this is probably not for you.
3
+ [![Gem Version](https://badge.fury.io/rb/shlisp_tools.png)](http://badge.fury.io/rb/shlisp_tools)
4
+
5
+ Tools for shlisp/shnth developers. If you don't recognize both words starting with "sh", this is probably not for you.
4
6
 
5
7
  Executables:
6
8
  * shlerb (a templating and uploading tool for txts; an ERB wrapper for shlisp)
@@ -110,6 +112,16 @@ You can also define your own scales and add a scaling factor to bring them into
110
112
 
111
113
  %>
112
114
 
115
+ ## Caveats
116
+
117
+ * Ratio, Scale, and the Scales collection all assume "arab" mode.
118
+
119
+ ## TODO
120
+
121
+ * write tests
122
+ * write more complete documentation
123
+ * allow Ratio and Scale classes to work in "dirac" mode as well as "arab" mode
124
+
113
125
  ## Contributing
114
126
 
115
127
  1. Fork it
data/bin/shlerb CHANGED
@@ -1,36 +1,36 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'erb'
4
-
5
4
  require 'shlisp_tools'
6
5
 
7
- # for the binding
6
+ #:nodoc: all
8
7
  Scales = ShlispTools::Scales
9
8
  Shnth = ShlispTools::Shnth
10
9
 
11
- def error(s)
10
+ def error(s) #:nodoc:
12
11
  puts s
13
12
  exit 1
14
13
  end
15
14
 
16
- class Shlerb
17
-
15
+ class Shlerb #:nodoc: all
18
16
  TEMP_FILE = "_shlerb_temp"
19
17
 
20
18
  def self.perform(infile)
21
19
  template_file = File.open(infile, 'r').read
22
20
  out = nil
23
21
 
22
+ puts "Generating shlisp..."
24
23
  begin
25
24
  out = herb(template_file)
26
25
  rescue Exception => e
27
- # do again and show verbos output
26
+ # do again and show verbose output
28
27
  $VERBOSE = true
29
28
  puts herb(template_file)
30
29
  exit 1
31
30
  end
32
31
 
33
32
  if out
33
+ puts "Compiling generated shlisp (#{TEMP_FILE}) and sending to shnth..."
34
34
  File.open(TEMP_FILE, 'w+') { |f| f.write(out) }
35
35
  system("shlisp #{TEMP_FILE}")
36
36
  end
data/bin/shtool CHANGED
@@ -4,7 +4,7 @@
4
4
  # ops
5
5
  #------------------------------------------------------------------------------
6
6
 
7
- class OpResult
7
+ class OpResult #:nodoc: all
8
8
  attr_reader :args, :result
9
9
 
10
10
  def initialize(args=nil, result=nil)
@@ -18,7 +18,7 @@ class OpResult
18
18
  end
19
19
 
20
20
  # base class for operations
21
- class Op
21
+ class Op #:nodoc: all
22
22
  def self.name
23
23
  ""
24
24
  end
@@ -49,7 +49,7 @@ end
49
49
 
50
50
  # operations
51
51
 
52
- class OpSr < Op
52
+ class OpSr < Op #:nodoc: all
53
53
  CLOCK = 72000000.0
54
54
 
55
55
  def self.name
@@ -82,7 +82,7 @@ class OpSr < Op
82
82
  end
83
83
  end
84
84
 
85
- class OpRatMul < Op
85
+ class OpRatMul < Op #:nodoc: all
86
86
  def self.name
87
87
  "mul"
88
88
  end
@@ -118,7 +118,7 @@ class OpRatMul < Op
118
118
  end
119
119
  end
120
120
 
121
- class OpRange < Op
121
+ class OpRange < Op #:nodoc: all
122
122
  Min = -128
123
123
  Max = 128
124
124
 
@@ -154,7 +154,7 @@ class OpRange < Op
154
154
  end
155
155
  end
156
156
 
157
- class OpReduce < Op
157
+ class OpReduce < Op #:nodoc: all
158
158
  def self.name
159
159
  "reduce"
160
160
  end
@@ -192,20 +192,20 @@ class OpReduce < Op
192
192
  end
193
193
 
194
194
  # known operations
195
- Ops = [ OpSr, OpRatMul, OpRange, OpReduce ]
195
+ Ops = [ OpSr, OpRatMul, OpRange, OpReduce ] #:nodoc:
196
196
 
197
197
  #------------------------------------------------------------------------------
198
198
  # mainline code
199
199
  #------------------------------------------------------------------------------
200
200
 
201
- def usage
201
+ def usage #:nodoc:
202
202
  puts "usage: 'shtool OP [args ...]'"
203
203
  puts "where OP is one of: #{Ops.collect{ |op| op.name}.join(" ") }"
204
204
  puts "or try 'shtool help'"
205
205
  exit 1
206
206
  end
207
207
 
208
- def main(argv)
208
+ def main(argv) #:nodoc:
209
209
  if argv.length < 1
210
210
  usage
211
211
  else
@@ -3,7 +3,7 @@
3
3
  Slew_add = 5
4
4
  Modo_mul = 2
5
5
  %>
6
- <% s = Scales::Hexany1357.scale(127) %>
6
+ <% s = Scales::Hexany1357.mul(127) %>
7
7
  {
8
8
  <%= Shnth::Situation_1 %>
9
9
 
@@ -3,7 +3,7 @@
3
3
  Slew_add = 5
4
4
  Modo_mul = 2
5
5
  %>
6
- <% s1 = Scales::MetaSlendro_1.scale(120) %>
6
+ <% s1 = Scales::MetaSlendro_1.mul(120) %>
7
7
  {
8
8
  <%= Shnth::Situation_1 %>
9
9
 
@@ -32,7 +32,7 @@
32
32
 
33
33
  )
34
34
  }
35
- <% s2 = Scales::MetaSlendro_2.scale(120) %>
35
+ <% s2 = Scales::MetaSlendro_2.mul(120) %>
36
36
  {
37
37
  <%= Shnth::Situation_2 %>
38
38
 
@@ -1,81 +1,95 @@
1
1
  module ShlispTools
2
+
3
+ # A Shlisp-oriented representation of a pitch in just/rational intonation.
4
+ # Numerators are "numes" and denoninators are "denos" as is customary for
5
+ # Shlisp. All terms 0 < n < 256 ("arab" mode in Shlisp).
2
6
  class Ratio
3
7
  include Enumerable
4
8
 
5
- attr_reader :nume, :deno, :rat
9
+ # numerator
10
+ attr_reader :nume
11
+ # denominator
12
+ attr_reader :deno
13
+ # rational form
14
+ attr_reader :rat
6
15
 
7
- def initialize(nume, deno, scale=nil)
16
+ def initialize(nume, deno, _mul=nil)
8
17
  @nume = nume
9
18
  @deno = deno
10
19
  _set_rat
11
- scale(scale)
12
- end
13
-
14
- # pos: scale up (multiply)
15
- # neg: scale down (divide)
16
- def scale(mul)
17
- if mul
18
- if mul >= 0
19
- @nume *= mul
20
- @deno *= mul
21
- @nume = 255 if @nume > 255
22
- @deno = 255 if @deno > 255
23
- else
24
- mul = mul.abs
25
- @nume /= mul
26
- @deno /= mul
27
- @nume = 1 if @nume <= 0
28
- @deno = 1 if @deno <= 0
29
- end
30
- end
20
+ mul(_mul)
31
21
  end
32
22
 
23
+ # Get the nume(rator).
33
24
  def n
34
25
  @nume
35
26
  end
36
27
 
28
+ # Set the nume(rator).
37
29
  def n=(nume)
38
30
  @nume = nume
39
31
  _set_rat
32
+ n
40
33
  end
41
34
 
35
+ # Get the deno(minator).
42
36
  def d
43
37
  @deno
44
38
  end
45
39
 
40
+ # Set the deno(minator).
46
41
  def d=(deno)
47
42
  @deno = deno
48
43
  _set_rat
44
+ d
49
45
  end
50
46
 
51
- def reduce
52
- Ratio.new(@rat.numerator, @rat.denominator)
47
+ # Multiply both nume and deno by same factor for Shnth amplitude scaling.
48
+ def mul(factor)
49
+ if factor
50
+ factor = factor.abs
51
+ @nume = (@nume * factor) % LIMIT
52
+ @deno = (@deno * factor) % LIMIT
53
+ end
54
+ self
53
55
  end
54
56
 
55
- def reduce!
57
+ def scale(factor) #:nodoc:
58
+ mul(factor)
59
+ end
60
+
61
+ # Return to the canonical (reduced) value.
62
+ def reset!
56
63
  @nume = @rat.numerator
57
64
  @deno = @rat.denominator
58
65
  end
59
66
 
67
+ # String representation
60
68
  def to_s
61
69
  "#{@nume}/#{@deno}"
62
70
  end
63
71
 
72
+ # Rational representation
64
73
  def to_r
65
74
  @rat
66
75
  end
67
76
 
68
- def each
77
+ # Iterator
78
+ def each #:nodoc:
69
79
  yield @rat
70
80
  end
71
81
 
72
- def <=>(other)
82
+ # Comparator, for sorting
83
+ def <=>(other) #:nodoc:
73
84
  @rat <=> other.rat
74
85
  end
75
86
 
76
87
  private
77
- def _set_rat
88
+ LIMIT = 256 #:nodoc:
89
+
90
+ def _set_rat #:nodoc:
78
91
  @rat = Rational(@nume, @deno)
79
92
  end
80
93
  end
94
+
81
95
  end
@@ -1,9 +1,15 @@
1
1
  module ShlispTools
2
+
3
+ # A scale is a series of Ratio instances, always maintained in canonical
4
+ # (reduced) form and ascending order, but available with amplitude scaling
5
+ # for use in a Shlisp/Shnth context.
2
6
  class Scale
3
7
  include Enumerable
4
8
 
9
+ # The default separator (' ') between scale degrees when scale is printed.
5
10
  DEF_SEP = ' '
6
11
 
12
+ # Arg: either nothing, or an array of Ratios
7
13
  def initialize(degrees=nil)
8
14
  @degrees = []
9
15
  if degrees && !degrees.empty?
@@ -12,72 +18,103 @@ module ShlispTools
12
18
  end
13
19
  end
14
20
 
21
+ # Add a new scale degree (Ratio).
15
22
  def add(degree)
16
23
  @degrees << degree
17
24
  _sort
25
+ self
18
26
  end
19
27
 
20
- def remove(idx)
21
- @degrees.delete_at(idx) rescue nil
28
+ # Add a new scal degree (Ratio) using string/array notation; i.e., myScale << Ratio.new(5,4)/
29
+ def <<(degree)
30
+ add(degree)
31
+ self
22
32
  end
23
33
 
24
- def scale(mul)
25
- unless empty?
26
- @degrees.each_with_index do |note,i|
27
- if i == 0
28
- note.scale(mul)
29
- else
30
- tmp = ((mul > note.deno) ? mul : mul*2)
31
- note.scale((tmp / note.deno).to_i)
32
- end
33
- end
34
- end
34
+ # Remove the scale degree at the specified position (0-based).
35
+ def remove(idx)
36
+ @degrees.delete_at(idx) rescue nil
35
37
  self
36
38
  end
37
39
 
40
+ # Return the scale degree at a specified postion (0-based).
38
41
  def [](idx)
39
42
  @degrees[idx] rescue nil
40
43
  end
41
44
 
45
+ # Return the number of degrees (notes) in the scale.
42
46
  def length
43
47
  @degrees.length
44
48
  end
45
49
 
50
+ # Return true if scale is empty, false otherwise.
46
51
  def empty?
47
52
  @degrees.empty?
48
53
  end
49
54
 
50
- def <<(degree)
51
- add(degree)
55
+ # Apply a multiplicative factor to every ratio for Shnth amplitude scaling.
56
+ # For example, myScale.scale(100) transforms 1/1 to 100/100. Other notes are brought into
57
+ # as close a range as possible while keeping all terms in the 1..255 range.
58
+ def mul(factor)
59
+ unless empty?
60
+ @degrees.each_with_index do |note,i|
61
+ if i == 0
62
+ note.mul(factor)
63
+ else
64
+ tmp = ((factor > note.deno) ? factor : factor*2)
65
+ note.mul((tmp / note.deno).to_i)
66
+ end
67
+ end
68
+ end
69
+ self
52
70
  end
53
71
 
54
- def each(&block)
55
- @degrees.each(&block)
72
+ def scale(factor) #:nodoc:
73
+ mul(factor)
56
74
  end
57
75
 
76
+ # Print the scale (multipied).
58
77
  def to_s
59
- scaled
78
+ multiplied
60
79
  end
61
80
 
62
- def scaled(sep=DEF_SEP)
81
+ # Print out the scale (multiplied).
82
+ def multiplied(sep=DEF_SEP)
63
83
  @degrees.inject([]) { |out,d| out << d.to_s; out }.join(sep)
64
84
  end
65
85
 
66
- def reduced(sep=DEF_SEP)
86
+ def scaled(sep=DEF_SEP) #:nodoc:
87
+ multiplied(sep)
88
+ end
89
+
90
+ # Print out the scale in canonical form (reduced rations).
91
+ def canonical(sep=DEF_SEP)
67
92
  @degrees.inject([]) { |out,d| out << d.to_r.to_s; out }.join(sep)
68
93
  end
69
94
 
95
+ def reduced(sep=DEF_SEP) #:nodoc:
96
+ canonical(sep)
97
+ end
98
+
99
+ # Print out all the nume(rator)s, multiplied.
70
100
  def numes(sep=DEF_SEP)
71
101
  @degrees.inject([]) { |out,d| out << d.n; out }.join(sep)
72
102
  end
73
103
 
104
+ # Print out all the deno(minators), multiplied.
74
105
  def denos(sep=DEF_SEP)
75
106
  @degrees.inject([]) { |out,d| out << d.d; out }.join(sep)
76
107
  end
77
108
 
109
+ # iterator
110
+ def each(&block) #:nodoc
111
+ @degrees.each(&block)
112
+ end
113
+
78
114
  private
79
115
  def _sort
80
116
  @degrees.sort!
81
117
  end
82
118
  end
119
+
83
120
  end
@@ -1,10 +1,13 @@
1
1
  require 'shlisp_tools/scale'
2
2
 
3
3
  module ShlispTools
4
+
5
+ # Predefined scales.
4
6
  module Scales
5
7
 
6
8
  # 1-3-5-7 hexany, utonal stellated
7
9
  # second degree (49/48) and 2/1 removed to fit eight buttons
10
+ # 1/1 25/24 7/6 5/4 35/24 3/2 5/3 7/4
8
11
  Hexany1357 = Scale.new([
9
12
  Ratio.new( 1, 1),
10
13
  Ratio.new(25, 24),
@@ -16,6 +19,7 @@ module ShlispTools
16
19
  Ratio.new( 7, 4)
17
20
  ])
18
21
 
22
+ # 1/1 37/32 21/16 49/32 7/4 2/1
19
23
  MetaSlendro_1 = Scale.new([
20
24
  Ratio.new( 1, 1),
21
25
  Ratio.new(37, 32),
@@ -25,6 +29,7 @@ module ShlispTools
25
29
  Ratio.new( 2, 1)
26
30
  ])
27
31
 
32
+ # 1/1 9/8 151/128 3/2 25/16 2/1
28
33
  MetaSlendro_2 = Scale.new([
29
34
  Ratio.new( 1, 1),
30
35
  Ratio.new( 9, 8),
@@ -34,6 +39,7 @@ module ShlispTools
34
39
  Ratio.new( 2, 1)
35
40
  ])
36
41
 
42
+ # 1/1 21/20 7/6 3/2 14/9 2/1
37
43
  CentaurPelog = Scale.new([
38
44
  Ratio.new( 1, 1),
39
45
  Ratio.new(21, 20),
@@ -44,4 +50,5 @@ module ShlispTools
44
50
  ])
45
51
 
46
52
  end
53
+
47
54
  end
@@ -1,5 +1,24 @@
1
1
  module ShlispTools
2
+
3
+ =begin
4
+ Macros and constants for use with the shlerb tool.
5
+
6
+ *Light_\**: simple light values, 1-8 across
7
+
8
+ *Situation_\**: macros representing stevek's idiom for switching through situations using the tar button, using the lights from left to right
9
+ to show which situation is running:
10
+ - <tt>\<%= Situation_1 %></tt> emits <tt>(jump (tar 1)) (lights 1)</tt>
11
+ - <tt>\<%= Situation_2 %></tt> emits <tt>(jump (tar 1)) (lights 4)</tt>
12
+ - etc.
13
+
14
+ *Bar_\**: scale indexes by bar (Uppercase=major, lowercase=minor), using stevek's arrangement:
15
+ - <tt>Bar_A = 0</tt>
16
+ - <tt>Bar_B = 1</tt>
17
+ - etc.
18
+ =end
19
+
2
20
  module Shnth
21
+
3
22
  Light_1 = 1
4
23
  Light_2 = Light_1 * 4
5
24
  Light_3 = Light_2 * 4
@@ -17,8 +36,7 @@ module ShlispTools
17
36
  Situation_6 = "(jump (tar 1)) (lights #{Light_6})"
18
37
  Situation_7 = "(jump (tar 1)) (lights #{Light_7})"
19
38
  Situation_8 = "(jump (tar 1)) (lights #{Light_8})"
20
-
21
- # scale indexes by bar (A=major, a=minora), using stevek's arrangement
39
+
22
40
  Bar_A = 0
23
41
  Bar_B = 1
24
42
  Bar_C = 2
@@ -27,5 +45,7 @@ module ShlispTools
27
45
  Bar_c = 5
28
46
  Bar_b = 6
29
47
  Bar_a = 7
48
+
30
49
  end
50
+
31
51
  end
@@ -1,3 +1,3 @@
1
1
  module ShlispTools
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shlisp_tools
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-12-12 00:00:00.000000000 Z
12
+ date: 2013-12-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler