juicy 0.1.2 → 0.1.3

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,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NDk5YWVkNTIyMzU4OWQyOGE3NmM4MTllYWMwODFhMTJiNmZmMmU1Nw==
4
+ YjIwNTk4OWI5YjJhM2M1N2Q2MjEwMGRiN2Q5ZjVlNjk0YzgzMzQzNg==
5
5
  data.tar.gz: !binary |-
6
- MGRiOTRkYzRiOWQzYmFhNWUyNjZmOWIzNzNlY2JmNzJjYjA5NTBjOQ==
6
+ MGNjOWNlMDBkMzVmMWUzNjE5YTQxY2RiZmVjMTJjOWQxOWExZWQ2ZA==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- MzMyOTllNGI2ZmRhODIzYjg4ZjA4ODIwYWMwMGYwNTUyN2Y3MTdiODQ0N2Uw
10
- N2I0MjJhN2MwZjk1ZjAxMTM4YTdiOGEzNWMxZWUwYmJjNWJjZTAyZjVkN2Uw
11
- YWRmZjM3ZDUyOTMwZGIyNDY4MjMyOGEyM2M5ZTZhMzY5YzVjYTM=
9
+ NWYyOTgxNzQ5ZjViZDIxNzA3YjFiMTdlZjA3ODRjMWZmOGUwODAxZTk3YWFk
10
+ ZTA1M2JjMTMzMTk3YzllZjhkZGU3MGY2ZGEwN2RlM2U2M2U3NzExODYxZmU4
11
+ NTVmODFiODE0YmY4ZGNlNWNhN2I2OWIzYzZhOGJlODY2ZjU2YmU=
12
12
  data.tar.gz: !binary |-
13
- NjlkMjZmNGNlMmUxMzU3NzUyNmFlNGViNzM0MWU4MTMzNjYwNmIwMzk5Yjdl
14
- YjhmYjdlOWUzYjMzZmRlNmZlMzhkOTBmMjQyZGNlMmNkOTBjNzc1MmZkZjlm
15
- MzFkYzg4NDU0YjJiNzE3MjYyZGFhYWZkMzQwYTQ1NjMyZTU5MDY=
13
+ ZTA5N2E4NDA1NWRlZmJkMTdhOWQ5M2VlN2Y0ZjM5ZDhkZDI1MmNmZmZlY2Fm
14
+ NDlkYzA0ZDI2Nzk5ODlhMTQ2MDlhMDQ3Nzg5MWM3NGE5Y2Y5ZTE4YzA1YjY4
15
+ MmNlMzIzODNjMGZmNTkyMWE1MjRkMjFiYTY5NWQ1Yzc5MDUzNzQ=
@@ -1,4 +1,4 @@
1
- require_relative '../lib/juicy.rb'
1
+ require 'juicy'
2
2
  include Juicy
3
3
  play = true
4
4
  # To make a pitch, give it a frequency.
@@ -45,7 +45,8 @@ sleep 0.3
45
45
  puts "----------"
46
46
  # Of course, this is cumbersome to do all on our own,
47
47
  # so you have a Scale available to you.
48
- scale = Scale.new(:major, Note.new(name: "D", octave_change: -1))
48
+ root = Note.new(name: "D", octave_change: -1)
49
+ scale = Scale.new(mode: :major, root: root)
49
50
  puts scale
50
51
  scale.each_note do |note|
51
52
  note.play if play
@@ -63,13 +64,13 @@ end
63
64
  # and a beat sequencer to bring it all together.
64
65
 
65
66
  sleep 0.3
66
- scale = Scale.new(:major, Note.new(name: "G", octave_change: -1))
67
+ root = Note.new(name: "G", octave_change: -1)
68
+ scale = Scale.new(mode: :major, root: root)
67
69
  puts scale
68
70
  scale.each_note do |note|
69
71
  note.play if play
70
72
  end
71
73
 
72
- puts
73
74
 
74
75
  # threads = []
75
76
  #
@@ -1,19 +1,18 @@
1
- # require 'win32-sound'
1
+
2
2
  #require 'pry'
3
3
  require 'sound'
4
4
 
5
- require_relative 'juicy/pitch' #toned (or not) frequency in a chosen pitch space (temperament/intonation)
6
- require_relative 'juicy/note' #named pitch
7
- require_relative 'juicy/duration' #length of note in musical time (quarter note, eighth note, etc.)
8
- require_relative 'juicy/chord' #collection of notes
9
- require_relative 'juicy/chord_progression' #collection of chords in sequence
10
- require_relative 'juicy/melody' #collection of chords in sequence
11
-
12
- require_relative 'juicy/scale' #sequence of relative pitch changes ex. chromatic, diatonic, whole-note, pentatonic
13
- require_relative 'juicy/mode' #'flavor' of diatonic scale
14
- require_relative 'juicy/scale_degree' #index of given scale relative to root/tonic
15
- require_relative 'juicy/key' #scale at a given root note, i.e. Juicy::Note
16
- require_relative 'juicy/voice' #an instrument
17
- require_relative 'juicy/measure' #a measure of beats
18
- require_relative 'juicy/track' #a track of notes
19
- require_relative 'juicy/song' #
5
+ require 'juicy/pitch' #toned (or not) frequency in a chosen pitch space (temperament/intonation)
6
+ require 'juicy/note' #named pitch
7
+ require 'juicy/duration' #length of note in musical time (quarter note, eighth note, etc.)
8
+ require 'juicy/chord' #collection of notes
9
+ require 'juicy/chord_progression' #collection of chords in sequence
10
+ require 'juicy/melody' #collection of chords in sequence
11
+ require 'juicy/scale' #sequence of relative pitch changes ex. chromatic, diatonic, whole-note, pentatonic
12
+ require 'juicy/mode' #'flavor' of diatonic scale
13
+ require 'juicy/scale_degree' #index of given scale relative to root/tonic
14
+ require 'juicy/key' #scale at a given root note, i.e. Juicy::Note
15
+ require 'juicy/voice' #an instrument
16
+ require 'juicy/measure' #a measure of beats
17
+ require 'juicy/track' #a track of notes
18
+ require 'juicy/song' #
@@ -6,8 +6,7 @@ module Juicy
6
6
  :major => [0, 4, 7],
7
7
  :minor => [0, 3, 7],
8
8
  :diminished => [0, 3, 6],
9
- :augmented => [0, 4, 8],
10
-
9
+ :augmented => [0, 4, 8]
11
10
  }
12
11
 
13
12
  attr_reader :duration, :notes
@@ -5,23 +5,31 @@ module Juicy
5
5
 
6
6
  class Mode
7
7
 
8
- attr_reader :rotate
8
+ attr_reader :rotate, :type
9
9
 
10
- def initialize(type = :ionian)
11
- @type = type
12
- @rotate = case @type
13
- when :major
14
- 0
15
- when :minor
16
- -2
17
- else
18
- 0
19
- end
20
- end
21
-
22
- def to_s
23
- "#{@type}"
24
- end
10
+ def initialize(type = :ionian)
11
+ @type = type
12
+ @rotate = case @type
13
+ when :major
14
+ 0
15
+ when :minor
16
+ -2
17
+ else
18
+ 0
19
+ end
20
+ end
21
+
22
+ def to_s
23
+ "#{@type}"
24
+ end
25
+
26
+ def ==(other_mode)
27
+ if other_mode.kind_of? Mode
28
+ type == other_mode.type
29
+ elsif other_mode.kind_of? Symbol
30
+ type == other_mode
31
+ end
32
+ end
25
33
 
26
34
  end
27
35
 
@@ -4,7 +4,10 @@ module Juicy
4
4
 
5
5
  include Comparable
6
6
 
7
- @@default_octave = 5
7
+ class << self
8
+ attr_reader :default_octave
9
+ end
10
+ @default_octave = 5
8
11
  attr_reader :name, :pitch, :duration, :octave, :occupying_beat
9
12
  attr_accessor :sum_of_queued_note_durations, :how_far_into_the_song_you_are
10
13
  attr_accessor :distance_from_beat_in_milliseconds
@@ -16,7 +19,7 @@ module Juicy
16
19
  @name = parse_note_name(options[:name])
17
20
  @pitch = Pitch.new(@name)
18
21
  @duration = Duration.new(options[:duration])
19
- @octave = @@default_octave + options[:octave_change]
22
+ @octave = Note.default_octave + options[:octave_change]
20
23
  end
21
24
 
22
25
  def to_s
@@ -25,46 +28,38 @@ module Juicy
25
28
  name += "b" if @name=~/flat/
26
29
  "#{name}#{@octave}"
27
30
  end
28
-
31
+
29
32
  def inspect
30
- "#{@name}"
33
+ "#{@name}#{@octave}"
31
34
  end
32
35
 
33
- def play(options = {duration: 200, octave: (@octave-@@default_octave)})
36
+ def play(options = {duration: 200, octave: (@octave-Note.default_octave)})
34
37
  if @name == :_
35
38
  options[:volume] = 0
36
39
  end
37
40
  @pitch.play(options)
38
41
  end
39
42
 
40
- def prepare(options = {duration: 200, octave: (@octave-@@default_octave)})
43
+ def prepare(options = {duration: 200, octave: (@octave-Note.default_octave)})
41
44
  options[:duration] = options[:duration] || 200
42
- options[:octave] = options[:octave] || (@octave-@@default_octave)
45
+ options[:octave] = options[:octave] || (@octave-Note.default_octave)
43
46
  if @name == :_
44
47
  options[:volume] = 0
45
48
  end
46
49
  Thread.pass
47
50
  @prepared_note = @pitch.prepare(options)
48
51
  @prepared_note[:sleep_time] = @distance_from_beat_in_milliseconds/1000.0
49
- #puts @prepared_note.status
50
52
  until @prepared_note.status.eql? "sleep"
51
53
  sleep 0.001
52
- #puts @prepared_note.status
53
54
  end
54
55
  @prepared_note
55
56
  self
56
57
  end
57
58
 
58
59
  def play_prepared
59
- #puts @prepared_note.status
60
- #puts "playing"
61
60
  until @prepared_note.status.eql? "sleep"
62
61
  sleep 0.001
63
- #puts @prepared_note.status
64
- #Thread.pass
65
62
  end
66
- #Thread.pass
67
- #puts "waking up"
68
63
  @prepared_note.wakeup
69
64
  end
70
65
 
@@ -114,10 +109,6 @@ module Juicy
114
109
  @duration.duration_in_milliseconds(tempo)
115
110
  end
116
111
 
117
- def self.default_octave
118
- @@default_octave
119
- end
120
-
121
112
  def plays_during(beat)
122
113
  @occupying_beat = beat
123
114
  end
@@ -133,7 +124,7 @@ module Juicy
133
124
  private
134
125
 
135
126
  def octave_change
136
- @octave - @@default_octave + @step/12
127
+ @octave - Note.default_octave + @step/12
137
128
  end
138
129
 
139
130
  def step(interval)
@@ -147,21 +138,19 @@ module Juicy
147
138
  def parse_note_name(name)
148
139
  # parses note name input
149
140
  # user should be able to say "A#" or "a#" or "a sharp" or "A_sharp" or "a_s"
150
- groups = name.to_s.match(/([a-gA-G])( |_)?(.*)/)
151
- #binding.pry
152
- puts "name: #{name}" if groups.nil?
153
- if name.to_s.match "rest"
141
+ groups = name.to_s.match(/(?<name>[a-gA-G])(?<space> |_)?(?<accidental>.*)/)
142
+ if name.to_s.match "rest" || name.to_s.match(/^_$/)
154
143
  note_name = "_"
155
144
  else
156
- note_name = groups[1].upcase
157
- unless groups[3].nil? || groups[3].empty?
158
- note_name += case groups[3]
145
+ note_name = groups[:name].upcase
146
+ unless groups[:accidental].nil? || groups[:accidental].empty?
147
+ note_name += case groups[:accidental]
159
148
  when /^(s|#)/
160
149
  "_sharp"
161
150
  when /^(f|b)/
162
151
  "_flat"
163
152
  else
164
- puts "Unknown note modifier: '#{groups[3]}'"
153
+ puts "Unknown note modifier: '#{groups[:accidental]}'"
165
154
  ""
166
155
  end
167
156
  end
@@ -30,20 +30,25 @@ module Juicy
30
30
  class Pitch
31
31
 
32
32
  include Comparable
33
- @@temperament = :equal
34
- @@pitch_standard = 440.0
33
+ @temperament = :equal
34
+ @pitch_standard = 440.0
35
+
36
+ class << self
37
+ attr_reader :temperament, :pitch_standard
38
+ end
35
39
 
36
40
  attr_reader :frequency, :confidence
37
41
 
38
- def initialize(pitch = @@pitch_standard, tune_now = true)
42
+ def initialize(pitch = Pitch.pitch_standard, tune_now = true)
39
43
 
40
44
  if pitch.kind_of? Numeric
41
45
  @frequency = pitch
42
46
  @tuned = false
43
47
  tune if tune_now
44
48
  else
49
+ raise ArgumentError unless pitch.kind_of? Symbol
45
50
  step = PITCHES[pitch.to_sym]
46
- @frequency = @@pitch_standard*2**(step/12.0)
51
+ @frequency = Pitch.pitch_standard*2**(step/12.0)
47
52
  @tuned = true
48
53
  end
49
54
 
@@ -57,7 +62,7 @@ module Juicy
57
62
  if out_of_tune
58
63
  step = Math.log(@frequency/440.0,2)*12
59
64
  @confidence = (1.0-2*(step - step.round).abs)*100.0
60
- @frequency = @@pitch_standard*2**((step.round)/12.0)
65
+ @frequency = Pitch.pitch_standard*2**((step.round)/12.0)
61
66
  @tuned = true
62
67
  end
63
68
  self
@@ -80,7 +85,10 @@ module Juicy
80
85
  options[:duration] ||= 200
81
86
  options[:octave] ||= 0
82
87
  options[:volume] ||= 1
83
- ::Sound::Out.play_freq(@frequency*2**(options[:octave]), options[:duration], options[:volume])
88
+ device = Sound::Device.new
89
+ data = Sound::Data.new(device.format)
90
+ data.generate_sine_wave(@frequency*2**(options[:octave]), options[:duration], options[:volume])
91
+ device.play data
84
92
  end
85
93
 
86
94
  def prepare(options = {duration: 200, octave: 0, volume: 1})
@@ -102,7 +110,7 @@ module Juicy
102
110
  end
103
111
 
104
112
  def change_by (interval)
105
- if @@temperament.eql? :equal
113
+ if Pitch.temperament.eql? :equal
106
114
  Pitch.new(@frequency*2**(interval/12.0))
107
115
  end
108
116
  end
@@ -24,9 +24,13 @@ module Juicy
24
24
 
25
25
  class Scale
26
26
  include Enumerable
27
+
28
+ attr_reader :root, :mode
27
29
 
28
- def initialize(type = :major, root = Note.new)
29
- case type
30
+ def initialize(options = {mode: :major, root: Note.new})
31
+ options[:mode] ||= :major
32
+ options[:root] ||= Note.new
33
+ case options[:mode]
30
34
  when :major
31
35
  @type = :diatonic
32
36
  when :minor
@@ -34,8 +38,8 @@ module Juicy
34
38
  else
35
39
  @type = type
36
40
  end
37
- @mode = Mode.new(type)
38
- @root = root
41
+ @mode = Mode.new(options[:mode])
42
+ @root = options[:root]
39
43
  generate_notes
40
44
 
41
45
  end
@@ -49,7 +53,7 @@ module Juicy
49
53
  end
50
54
 
51
55
  def play
52
-
56
+ each_note &:play
53
57
  end
54
58
 
55
59
  def mode=(type)
@@ -72,9 +76,13 @@ module Juicy
72
76
  end
73
77
  end
74
78
 
75
- def each_note
76
- (SCALE_TYPES[@type].size+1).times do
77
- yield @notes.next
79
+ def each_note &block
80
+ if block_given?
81
+ (SCALE_TYPES[@type].size+1).times do
82
+ yield @notes.next
83
+ end
84
+ else
85
+ @notes
78
86
  end
79
87
  end
80
88
 
@@ -98,6 +106,48 @@ module Juicy
98
106
  half_steps
99
107
  end
100
108
 
109
+ def do
110
+ if @mode == :major
111
+ @root
112
+ end
113
+ end
114
+
115
+ def re
116
+ if @mode == :major
117
+ @root + 2
118
+ end
119
+ end
120
+
121
+ def mi
122
+ if @mode == :major
123
+ @root + 4
124
+ end
125
+ end
126
+
127
+ def fa
128
+ if @mode == :major
129
+ @root + 5
130
+ end
131
+ end
132
+
133
+ def so
134
+ if @mode == :major
135
+ @root + 7
136
+ end
137
+ end
138
+
139
+ def la
140
+ if @mode == :major
141
+ @root + 9
142
+ end
143
+ end
144
+
145
+ def ti
146
+ if @mode == :major
147
+ @root + 11
148
+ end
149
+ end
150
+
101
151
  private
102
152
 
103
153
  def generate_notes
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: juicy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dominic Muller
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-03 00:00:00.000000000 Z
11
+ date: 2014-08-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sound
@@ -19,7 +19,7 @@ dependencies:
19
19
  version: '0.0'
20
20
  - - ! '>='
21
21
  - !ruby/object:Gem::Version
22
- version: 0.0.2
22
+ version: 0.0.6
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -29,14 +29,28 @@ dependencies:
29
29
  version: '0.0'
30
30
  - - ! '>='
31
31
  - !ruby/object:Gem::Version
32
- version: 0.0.2
32
+ version: 0.0.6
33
+ - !ruby/object:Gem::Dependency
34
+ name: rspec
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ~>
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
33
47
  description: Generates songs
34
48
  email: nicklink483@gmail.com
35
49
  executables: []
36
50
  extensions: []
37
51
  extra_rdoc_files: []
38
52
  files:
39
- - bin/juicy.rb
53
+ - examples/juicy.rb
40
54
  - lib/juicy.rb
41
55
  - lib/juicy/chord.rb
42
56
  - lib/juicy/chord_progression.rb