tonal-tools 8.5.3 → 8.7.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d35ccfb34bc36393de62b66954048131b48eff9a9aa0c3af8c9f5d97d79d8406
4
- data.tar.gz: 16b2e4235caeaf796ddd7ceec8e6b881eb2291b4ec0f7f6389ac2faaca1fe243
3
+ metadata.gz: 65ae90958bc67835b5792e9d248eebf51ef5625f5bf3e1fa2da75064f76865d9
4
+ data.tar.gz: b9620ff46f3ded909da90d12af35326fa85387000f1432b768d8377b205f78c4
5
5
  SHA512:
6
- metadata.gz: 6849510f855a326970cf7a7ad4ee619b05251b15331659192c4a7d1cf17a08eb64cdd55e70232300587f6f263cb906ddde329fba2d7923002b34f303f1ee4bd1
7
- data.tar.gz: ab77a51fb2c82acf98fb1b65b1d33ace5baac0fbfc4c823140fb1a746995468f8cf3621824af17b07f0f099300dd7b4b244da4578711705e8a62f9d22c1976cd
6
+ metadata.gz: d73630cb8dec599a68d9f85731f676c3193d0f4f038f5757ace29a77ae8af65b5c74a5808f808605baa0e7392137b3200a4241b22f73870a788de4afb6c4f11a
7
+ data.tar.gz: 18977208ddb36b81b446e5559acf7e1618baf360fdf49f75b567e0c6407727077840846b0ce0ada874a428e1c2ae3d281abe484d4f0d27c115c905cc76c1b191
@@ -1,4 +1,4 @@
1
1
  module Tonal
2
2
  TOOLS_PRODUCER = "mTonal"
3
- TOOLS_VERSION = "8.5.3"
3
+ TOOLS_VERSION = "8.7.0"
4
4
  end
data/lib/tonal/hertz.rb CHANGED
@@ -10,7 +10,7 @@ class Tonal::Hertz
10
10
  #
11
11
  def initialize(arg)
12
12
  raise ArgumentError, "Argument is not Numeric or Tonal::Hertz" unless arg.kind_of?(Numeric) || arg.kind_of?(self.class)
13
- @value = arg.kind_of?(self.class) ? arg.inspect : arg
13
+ @value = arg.kind_of?(self.class) ? arg.value : arg
14
14
  end
15
15
 
16
16
  # @return [Tonal::Hertz] 440 Hz
@@ -46,6 +46,16 @@ class Tonal::Hertz
46
46
  Tonal::Cents.new(ratio: to_r / reference.to_r)
47
47
  end
48
48
 
49
+ # @return [Tonal::Midi::Note] the midi representation of self
50
+ # @example
51
+ # Tonal::Hertz.new(440).to_midi => 69.0 MIDI
52
+ # @param reference [Tonal::Hertz, Numeric] the reference frequency to compare to
53
+ #
54
+ def to_midi_note
55
+ Tonal::Midi::Note.new(frequency: to_f)
56
+ end
57
+ alias :to_midi :to_midi_note
58
+
49
59
  # @return [String] the string representation of Tonal::Hertz
50
60
  # @example
51
61
  # Tonal::Hertz(1000.0).inspect => "1000.0 Hz"
data/lib/tonal/midi.rb ADDED
@@ -0,0 +1,39 @@
1
+ module Tonal::Midi
2
+ class Note
3
+ include Comparable
4
+
5
+ REFERENCE_FREQUENCY = 440.0
6
+ A4_MIDI_NUMBER = 69
7
+ C4_MIDI_NUMBER = 60
8
+
9
+ attr_reader :number, :frequency
10
+
11
+ # @return [Tonal::Midi::Note]
12
+ # @example
13
+ # Tonal::Midi::Note.new(number:60) => 60.0 MIDI
14
+ # @param arg [Numeric, Tonal::Midi::Note]
15
+ #
16
+ def initialize(number: A4_MIDI_NUMBER, frequency: nil)
17
+ if frequency
18
+ raise ArgumentError, "Frequency argument is not Numeric or Tonal::Hertz" unless frequency.kind_of?(Numeric) || frequency.kind_of?(Tonal::Hertz)
19
+ @frequency = Tonal::Hertz.new(frequency)
20
+ @number = (A4_MIDI_NUMBER + 12 * Math.log2(frequency.to_f / REFERENCE_FREQUENCY)).round
21
+ else
22
+ raise ArgumentError, "Number argument is not Integer" unless number.kind_of?(Integer)
23
+ @number = number.kind_of?(self.class) ? number.inspect : number
24
+ @frequency = Tonal::Hertz.new(REFERENCE_FREQUENCY * (2 ** ((number - A4_MIDI_NUMBER) / 12.0)))
25
+ end
26
+ end
27
+
28
+ alias :value :number
29
+
30
+ # @return [String] representation of self
31
+ def inspect
32
+ "#{number} MIDI"
33
+ end
34
+
35
+ def <=>(other)
36
+ number <=> (other.kind_of?(self.class) ? other.number : other)
37
+ end
38
+ end
39
+ end
data/lib/tonal/step.rb CHANGED
@@ -29,7 +29,7 @@ class Tonal::Scale
29
29
  end
30
30
  alias :to_s :inspect
31
31
 
32
- # @return [Tonal::Scale::Step] new step with the ratio mapped to the new modulo
32
+ # @return a new [Tonal::Scale::Step] with the ratio mapped to the new modulo
33
33
  # @example
34
34
  # Tonal::Scale::Step.new(ratio: 3/2r, modulo: 31).convert(12)
35
35
  # => 7\12
@@ -38,7 +38,7 @@ class Tonal::Scale
38
38
  self.class.new(log: log, modulo: new_modulo)
39
39
  end
40
40
 
41
- # @return [Rational] of the step
41
+ # @return the [Rational] representation of the step/modulo of self
42
42
  # @example
43
43
  # Tonal::Scale::Step.new(ratio: 3/2r, modulo: 31).step_to_r
44
44
  # => (18/31)
@@ -49,7 +49,7 @@ class Tonal::Scale
49
49
  Rational(step, modulo)
50
50
  end
51
51
 
52
- # @return [Tonal::Ratio] of the step/modulo
52
+ # @return the [Tonal::Ratio] representation of the step/modulo of self
53
53
  # @example
54
54
  # Tonal::Scale::Step.new(ratio: 3/2r, modulo: 31).step_to_ratio
55
55
  # => 18/31
@@ -58,7 +58,23 @@ class Tonal::Scale
58
58
  Tonal::Ratio.new(step, modulo)
59
59
  end
60
60
 
61
- # @return [Rational] of the ratio
61
+ # @return the [Tonal::Midi::Note] representation of the step
62
+ #
63
+ # @example
64
+ # Tonal::Scale::Step.new(ratio: 3/2r, modulo: 31).step_to_midi
65
+ # => 78
66
+ # Tonal::Scale::Step.new(ratio: 3/2r, modulo: 12).step_to_midi
67
+ # => 67
68
+ # Tonal::Scale::Step.new(ratio: 3/2r, modulo: 12).step_to_midi(midi_root: Tonal::Midi::Note::A4_MIDI_NUMBER)
69
+ # => 76
70
+ #
71
+ # @param midi_root [Integer] the MIDI number that corresponds to the 0 step of the scale. Default is C4 (60 MIDI).
72
+ #
73
+ def step_to_midi(midi_root: Tonal::Midi::Note::C4_MIDI_NUMBER)
74
+ Tonal::Midi::Note.new(number: step + midi_root)
75
+ end
76
+
77
+ # @return the [Rational] representation of the ratio of self
62
78
  # @example
63
79
  # Tonal::Scale::Step.new(ratio: 3/2r, modulo: 31).ratio_to_r
64
80
  # => (3/2)
@@ -67,7 +83,7 @@ class Tonal::Scale
67
83
  ratio.to_r
68
84
  end
69
85
 
70
- # @return [Tonal::Cents] measure of tempered in cents
86
+ # @return the [Tonal::Cents] measure of tempered in cents
71
87
  # @example
72
88
  # Tonal::Scale::Step.new(ratio: 3/2r, modulo: 31).tempered_to_cents
73
89
  # => 696.77
@@ -76,7 +92,7 @@ class Tonal::Scale
76
92
  tempered.to_cents
77
93
  end
78
94
 
79
- # @return [Tonal::Cents] measure of ratio in cents
95
+ # @return the [Tonal::Cents] measure of ratio in cents
80
96
  # @example
81
97
  # Tonal::Scale::Step.new(ratio: 3/2r, modulo: 31).ratio_to_cents
82
98
  # => 701.96
@@ -85,7 +101,7 @@ class Tonal::Scale
85
101
  ratio.to_cents
86
102
  end
87
103
 
88
- # @return [Tonal::Cents] the difference between the tempered number and the ratio
104
+ # @return the [Tonal::Cents] measure of the difference between the tempered number and the ratio
89
105
  # @example
90
106
  # Tonal::Scale::Step.new(ratio: 3/2r, modulo: 31).efficiency => 5.19 ¢
91
107
  #
@@ -104,6 +120,10 @@ class Tonal::Scale
104
120
  step.coprime?(modulo)
105
121
  end
106
122
 
123
+ # @return a new [Tonal::Scale::Step] with the step added to the current step
124
+ # @example
125
+ # Tonal::Scale::Step.new(step: 5, modulo: 12) + Tonal::Scale::Step.new(step: 7, modulo: 12) => 0\12
126
+ #
107
127
  def +(rhs)
108
128
  self.class.new(step: (rhs % modulo), modulo: modulo)
109
129
  end
data/lib/tonal/tools.rb CHANGED
@@ -12,6 +12,7 @@ module Tonal
12
12
  require "tonal/log"
13
13
  require "tonal/log2"
14
14
  require "tonal/approximation"
15
+ require "tonal/midi"
15
16
  require "tonal/ratio"
16
17
  require "tonal/reduced_ratio"
17
18
  require "tonal/extended_ratio"
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tonal-tools
3
3
  version: !ruby/object:Gem::Version
4
- version: 8.5.3
4
+ version: 8.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jose Hales-Garcia
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2026-05-03 00:00:00.000000000 Z
10
+ date: 2026-06-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: yaml
@@ -168,6 +168,7 @@ files:
168
168
  - lib/tonal/irb_helpers.rb
169
169
  - lib/tonal/log.rb
170
170
  - lib/tonal/log2.rb
171
+ - lib/tonal/midi.rb
171
172
  - lib/tonal/ratio.rb
172
173
  - lib/tonal/reduced_ratio.rb
173
174
  - lib/tonal/step.rb