mass 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.
- checksums.yaml +8 -8
- data/README.md +9 -4
- data/lib/mass.rb +3 -40
- data/lib/mass/note.rb +23 -9
- data/lib/mass/pattern.rb +27 -13
- data/lib/mass/pitch.rb +19 -10
- data/lib/mass/sequence.rb +70 -0
- data/lib/mass/version.rb +1 -1
- data/mass.gemspec +1 -1
- metadata +4 -4
- data/lib/mass/pitch/not_found.rb +0 -10
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YTIyODFiODNmNzVlMTMyNDg5ZDA4MTZkZTJjOTMxNGE2MmQwOWNmNw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
NGMxY2JkYTcwZGVkYjEyZDBkMzExMTQ4MGVkYmFjY2U5YzU4MzU4YQ==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ZTY0ZjY4NmU5ODAyZmYyMjIyZTcxYjgyOGYwNjY0MGEyY2ViZjY4NWM0ZWRk
|
10
|
+
MTQ4OGEwNzhiN2FjNzBjNjliMDY2YzMzNmI5OWJiZDAyMzI2OWU0NjY5OGE1
|
11
|
+
MGQ5YzMxZDNkMmQ2NTk4YmY2Njc1MzE4Nzg5NzhiOWRlODg5NjQ=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MTk0ODQ4M2RjMmJhODU1NjIzYmYwMmE0Mzk1M2M2Mzk3MmM5MGJiMjhjYWZm
|
14
|
+
MDllN2I2NTg4YWVkZTc0MWI3ZTA4YWE3NzhmOGE2MTNiMzQ1ZDA4N2NiYWI3
|
15
|
+
NTg1ZjM0MDgwMDJjYTI1MzczZWNlNzhkMmM2YzM4YmYxYjFmMjA=
|
data/README.md
CHANGED
@@ -41,10 +41,10 @@ include Mass
|
|
41
41
|
|
42
42
|
bpm 128
|
43
43
|
pattern bars: 4 do
|
44
|
-
note 4, pitch: '
|
45
|
-
note 4, pitch: '
|
46
|
-
note 4, pitch: '
|
47
|
-
note 4, pitch: '
|
44
|
+
note 4, pitch: 'C2'
|
45
|
+
note 4, pitch: 'C3'
|
46
|
+
note 4, pitch: 'C4'
|
47
|
+
note 4, pitch: 'C3'
|
48
48
|
end
|
49
49
|
```
|
50
50
|
|
@@ -80,3 +80,8 @@ newly built `.gem` file to [RubyGems][gem]:
|
|
80
80
|
```bash
|
81
81
|
$ bin/rake release
|
82
82
|
```
|
83
|
+
|
84
|
+
[tubbo]: https://github.com/tubbo
|
85
|
+
[rdoc]: http://www.rubydoc.info/github/tubbo/mass/master/frames
|
86
|
+
[gem]: https://rubygems.org
|
87
|
+
[mit]: https://github.com/tubbo/mass/blob/master/LICENSE.txt
|
data/lib/mass.rb
CHANGED
@@ -4,48 +4,11 @@ require 'mass/version'
|
|
4
4
|
require 'mass/pitch'
|
5
5
|
require 'mass/note'
|
6
6
|
require 'mass/pattern'
|
7
|
+
require 'mass/sequence'
|
7
8
|
|
8
9
|
# A massive synth library.
|
9
10
|
module Mass
|
10
|
-
|
11
|
-
|
12
|
-
#
|
13
|
-
# @return [Integer]
|
14
|
-
def current_bpm
|
15
|
-
@current_bpm ||= 100
|
16
|
-
end
|
17
|
-
|
18
|
-
# Change BPM of the track.
|
19
|
-
#
|
20
|
-
# @example
|
21
|
-
# require 'mass'
|
22
|
-
# include Mass
|
23
|
-
#
|
24
|
-
# bpm 128
|
25
|
-
#
|
26
|
-
def bpm(new_bpm)
|
27
|
-
@current_bpm = new_bpm
|
28
|
-
end
|
29
|
-
|
30
|
-
# Create a pattern in Mass.
|
31
|
-
#
|
32
|
-
# @example
|
33
|
-
# require 'mass'
|
34
|
-
# include Mass
|
35
|
-
#
|
36
|
-
# pattern name: 'verse', bars: 1 do
|
37
|
-
# note 8, pitch: 'C4'
|
38
|
-
# note 8, pitch: 'C3'
|
39
|
-
# note 8, pitch: 'A3'
|
40
|
-
# note 8, pitch: 'B4'
|
41
|
-
# note 8, pitch: 'C4'
|
42
|
-
# note 8, pitch: 'Gb2'
|
43
|
-
# note 8, pitch: 'C4'
|
44
|
-
# rest 8
|
45
|
-
# end
|
46
|
-
#
|
47
|
-
def pattern(**params, &block)
|
48
|
-
Pattern.create(**params, &block)
|
49
|
-
end
|
11
|
+
def self.sequence(*args)
|
12
|
+
Sequence.define(*args)
|
50
13
|
end
|
51
14
|
end
|
data/lib/mass/note.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'forwardable'
|
2
|
+
require 'mass/pitch'
|
2
3
|
|
3
4
|
module Mass
|
4
5
|
# Represents a single note in the pattern.
|
@@ -49,6 +50,16 @@ module Mass
|
|
49
50
|
# @attr_reader [Mass::Pitch]
|
50
51
|
attr_reader :pitch
|
51
52
|
|
53
|
+
# Rhythmic duration value for this note.
|
54
|
+
#
|
55
|
+
# @attr_reader [Integer]
|
56
|
+
attr_reader :value
|
57
|
+
|
58
|
+
# BPM passed in from the sequence.
|
59
|
+
#
|
60
|
+
# @attr_reader [Integer]
|
61
|
+
attr_reader :bpm
|
62
|
+
|
52
63
|
# Hex value for sending to +UniMIDI+ that signals when
|
53
64
|
# this note should begin playing.
|
54
65
|
#
|
@@ -65,18 +76,15 @@ module Mass
|
|
65
76
|
# @param [String] pitch
|
66
77
|
# @param [Symbol | Integer] exp - Can be expressed as either
|
67
78
|
# @param [UniMIDI::Output] midi
|
68
|
-
def initialize(value: 1, pitch: nil, exp: :mp, midi: nil)
|
79
|
+
def initialize(value: 1, pitch: nil, exp: :mp, midi: nil, bpm: 100)
|
69
80
|
@value = value
|
81
|
+
@name = pitch
|
70
82
|
@pitch = Pitch.find pitch
|
71
83
|
@expression = exp
|
72
84
|
@midi = midi
|
85
|
+
@bpm = bpm
|
73
86
|
end
|
74
87
|
|
75
|
-
# The given note name.
|
76
|
-
#
|
77
|
-
# @return [String]
|
78
|
-
def_delegator :pitch, :name, :id
|
79
|
-
|
80
88
|
# This note as expressed in a MIDI pitch value.
|
81
89
|
#
|
82
90
|
# @return [Integer]
|
@@ -92,14 +100,20 @@ module Mass
|
|
92
100
|
# The given duration value divided by the BPM of
|
93
101
|
# the current song.
|
94
102
|
def duration
|
95
|
-
|
103
|
+
vpm * 0.01
|
96
104
|
end
|
97
105
|
|
98
106
|
# Play the current note through the +UniMIDI+ output.
|
99
107
|
def play
|
100
|
-
midi.puts ON, to_midi, to_velocity
|
108
|
+
midi.puts ON, to_midi, to_velocity unless pitch.nil?
|
101
109
|
sleep duration
|
102
|
-
midi.puts OFF, to_midi, to_velocity
|
110
|
+
midi.puts OFF, to_midi, to_velocity unless pitch.nil?
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
|
115
|
+
def vpm
|
116
|
+
bpm / value
|
103
117
|
end
|
104
118
|
end
|
105
119
|
end
|
data/lib/mass/pattern.rb
CHANGED
@@ -1,18 +1,22 @@
|
|
1
|
+
require 'unimidi'
|
2
|
+
require 'mass/note'
|
3
|
+
|
1
4
|
module Mass
|
2
5
|
# A single pattern written using the +Mass+ DSL. This is the
|
3
6
|
# "collection"-style object which holds each +Note+ and plays
|
4
7
|
# them in sequence, but has no control over their durations or
|
5
8
|
# pitches.
|
6
9
|
class Pattern
|
7
|
-
attr_reader :name, :bars, :notes
|
10
|
+
attr_reader :name, :bars, :notes, :sequence
|
8
11
|
|
9
12
|
# @param [String] name
|
10
13
|
# @param [Integer] bars
|
11
14
|
# @param block
|
12
|
-
def initialize(name: '', bars: 4,
|
15
|
+
def initialize(name: '', bars: 4, sequence: nil)
|
13
16
|
@name = name
|
14
17
|
@bars = bars
|
15
18
|
@notes = []
|
19
|
+
@sequence = sequence
|
16
20
|
yield if block_given?
|
17
21
|
end
|
18
22
|
|
@@ -21,9 +25,11 @@ module Mass
|
|
21
25
|
# @param [String] name
|
22
26
|
# @param [Integer] bars
|
23
27
|
# @param block
|
24
|
-
def self.create(
|
25
|
-
|
26
|
-
|
28
|
+
def self.create(
|
29
|
+
name: '', bars: 4, repeat: false, sequence: nil, &block
|
30
|
+
)
|
31
|
+
pattern = new(name: name, bars: bars, sequence: sequence, &block)
|
32
|
+
pattern.play in_loop: repeat if pattern.notes.any?
|
27
33
|
pattern
|
28
34
|
end
|
29
35
|
|
@@ -31,9 +37,16 @@ module Mass
|
|
31
37
|
# into it.
|
32
38
|
#
|
33
39
|
# @param [Boolean] in_loop - defaults to +false+.
|
34
|
-
def play
|
35
|
-
_play_once unless in_loop
|
36
|
-
|
40
|
+
def play(in_loop: false)
|
41
|
+
return _play_once unless in_loop
|
42
|
+
_play_in_loop
|
43
|
+
end
|
44
|
+
|
45
|
+
# Tests equivilance bases on name
|
46
|
+
#
|
47
|
+
# @return [Boolean] whether both patterns have the same name
|
48
|
+
def ==(other)
|
49
|
+
other.name == name
|
37
50
|
end
|
38
51
|
|
39
52
|
protected
|
@@ -53,7 +66,8 @@ module Mass
|
|
53
66
|
value: value,
|
54
67
|
pitch: pitch,
|
55
68
|
exp: expression,
|
56
|
-
midi: _midi
|
69
|
+
midi: sequence._midi,
|
70
|
+
bpm: sequence._bpm
|
57
71
|
)
|
58
72
|
end
|
59
73
|
|
@@ -63,12 +77,12 @@ module Mass
|
|
63
77
|
|
64
78
|
private
|
65
79
|
|
66
|
-
def
|
67
|
-
|
80
|
+
def _play_once
|
81
|
+
notes.all?(&:play)
|
68
82
|
end
|
69
83
|
|
70
|
-
def
|
71
|
-
|
84
|
+
def _play_in_loop
|
85
|
+
loop { _play_once }
|
72
86
|
end
|
73
87
|
end
|
74
88
|
end
|
data/lib/mass/pitch.rb
CHANGED
@@ -4,7 +4,10 @@ module Mass
|
|
4
4
|
# calculating the proper duration and actually playing out
|
5
5
|
# the note.
|
6
6
|
class Pitch
|
7
|
-
attr_reader :id
|
7
|
+
attr_reader :id
|
8
|
+
attr_reader :name
|
9
|
+
attr_reader :octave
|
10
|
+
attr_reader :value
|
8
11
|
|
9
12
|
# A dictionary of MIDI note values that are substituted
|
10
13
|
# for a given String note value.
|
@@ -37,10 +40,10 @@ module Mass
|
|
37
40
|
REQUIRED = %i(name octave value)
|
38
41
|
|
39
42
|
# @param [String] id - Identifier string of this pitch.
|
40
|
-
def initialize(
|
41
|
-
@id =
|
42
|
-
@name = id.gsub(/\d/, '').to_s
|
43
|
-
@octave = id.gsub(/#{name}/, '').to_i
|
43
|
+
def initialize(id: '')
|
44
|
+
@id = id.to_s
|
45
|
+
@name = @id.gsub(/\d/, '').to_s
|
46
|
+
@octave = @id.gsub(/#{name}/, '').to_i
|
44
47
|
@value = begin
|
45
48
|
VALUES[name]
|
46
49
|
rescue
|
@@ -50,12 +53,11 @@ module Mass
|
|
50
53
|
|
51
54
|
# Find a +Pitch+ by its given +id+.
|
52
55
|
#
|
56
|
+
# @param [String] by_id
|
53
57
|
# @return [Pitch] when the id is valid
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
fail NotFound, id unless pitch.valid?
|
58
|
-
pitch
|
58
|
+
def self.find(by_id = nil)
|
59
|
+
return if by_id.nil?
|
60
|
+
new id: by_id
|
59
61
|
end
|
60
62
|
|
61
63
|
# Make sure the +name+ and +octave+ attributes have
|
@@ -75,6 +77,13 @@ module Mass
|
|
75
77
|
value + octave_modifier
|
76
78
|
end
|
77
79
|
|
80
|
+
# Use the +id+ parameter to define equivalence.
|
81
|
+
#
|
82
|
+
# @return [Boolean] whether both pitches have the same ID.
|
83
|
+
def ==(other)
|
84
|
+
other.id == id
|
85
|
+
end
|
86
|
+
|
78
87
|
private
|
79
88
|
|
80
89
|
def required_params
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Mass
|
2
|
+
# A sequence of patterns that is played in order immediately
|
3
|
+
# as it is defined.
|
4
|
+
class Sequence
|
5
|
+
# Name of this sequence
|
6
|
+
#
|
7
|
+
# @attr_reader [String]
|
8
|
+
attr_reader :name
|
9
|
+
|
10
|
+
# Beats per minute speed of the sequence
|
11
|
+
#
|
12
|
+
# @attr_reader [Integer]
|
13
|
+
attr_reader :_bpm
|
14
|
+
|
15
|
+
# MIDI driver used to power all notes in the sequence.
|
16
|
+
#
|
17
|
+
# @attr_reader [UniMIDI::Output]
|
18
|
+
attr_reader :_midi
|
19
|
+
|
20
|
+
# @param [String] name
|
21
|
+
# @option [Integer] bpm - defaults to 100
|
22
|
+
def initialize(name, bpm: 100)
|
23
|
+
@name = name
|
24
|
+
@_bpm = bpm
|
25
|
+
@_midi ||= UniMIDI::Output.gets
|
26
|
+
yield if block_given?
|
27
|
+
end
|
28
|
+
|
29
|
+
# Define a new sequence into the global namespace
|
30
|
+
#
|
31
|
+
# @param [String] name
|
32
|
+
# @options [KeywordArguments] params
|
33
|
+
# @param [Proc] block
|
34
|
+
# @return [Mass::Sequence]
|
35
|
+
def self.define(name, **params, &block)
|
36
|
+
new name, **params, &block
|
37
|
+
end
|
38
|
+
|
39
|
+
# Change BPM.
|
40
|
+
#
|
41
|
+
# @param [Integer] new_bpm
|
42
|
+
# @example
|
43
|
+
# bpm 128
|
44
|
+
#
|
45
|
+
def bpm(new_bpm)
|
46
|
+
@_bpm = new_bpm
|
47
|
+
end
|
48
|
+
|
49
|
+
# Create a pattern. See the docs on +Mass::Pattern+ for more
|
50
|
+
# information about its requirements.
|
51
|
+
#
|
52
|
+
# @options [KeywordArguments] params
|
53
|
+
# @options [Proc] block
|
54
|
+
# @example
|
55
|
+
# pattern name: 'verse', bars: 1 do
|
56
|
+
# note 8, pitch: 'C4'
|
57
|
+
# note 8, pitch: 'C3'
|
58
|
+
# note 8, pitch: 'A3'
|
59
|
+
# note 8, pitch: 'B4'
|
60
|
+
# note 8, pitch: 'C4'
|
61
|
+
# note 8, pitch: 'Gb2'
|
62
|
+
# note 8, pitch: 'C4'
|
63
|
+
# rest 8
|
64
|
+
# end
|
65
|
+
#
|
66
|
+
def pattern(**params, &block)
|
67
|
+
Pattern.create(**params.merge(sequence: self), &block)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/lib/mass/version.rb
CHANGED
data/mass.gemspec
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mass
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tom Scott
|
@@ -98,14 +98,14 @@ dependencies:
|
|
98
98
|
name: unimidi
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- -
|
101
|
+
- - ~>
|
102
102
|
- !ruby/object:Gem::Version
|
103
103
|
version: '0'
|
104
104
|
type: :runtime
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
|
-
- -
|
108
|
+
- - ~>
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
111
|
description: Synth framework for Ruby. Build a cool synth!
|
@@ -143,7 +143,7 @@ files:
|
|
143
143
|
- lib/mass/note.rb
|
144
144
|
- lib/mass/pattern.rb
|
145
145
|
- lib/mass/pitch.rb
|
146
|
-
- lib/mass/
|
146
|
+
- lib/mass/sequence.rb
|
147
147
|
- lib/mass/version.rb
|
148
148
|
- mass.gemspec
|
149
149
|
homepage: https://github.com/tubbo/mass
|