muse 0.0.9 → 0.0.10

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/lib/muse.old.rb ADDED
@@ -0,0 +1,222 @@
1
+ # Muse
2
+ # Copyright (C) 2012 Chang Sau Sheong
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ require "parallel"
18
+ require "#{File.dirname(__FILE__)}/muse/wav"
19
+ require "#{File.dirname(__FILE__)}/muse/config"
20
+
21
+ module Muse
22
+
23
+ NOTES = %w(_ a ais b c cis d dis e f fis g gis)
24
+ FREQUENCIES = {
25
+ :ais1 => -34, :b1 => -33, :cis2 => -32, :d2 => -31, :dis2 => -30,
26
+ :e2 => -29, :f2 => -28, :fis2 => -27, :g2 => -26, :gis2 => -25,
27
+ :a2 => -24, :ais2 => -23, :b2 => -22, :c3 => -21, :cis3 => -20,
28
+ :d3 => -19, :dis3 => -18, :e3 => -17, :f3 => -16, :fis3 => -15,
29
+ :g3 => -14, :gis3 => -13, :a3 => -12, :ais3 => -11, :b3 => -10,
30
+ :c4 => -9, :cis4 => -8, :d4 => -7, :dis4 => -6, :e4 => -5,
31
+ :f4 => -4, :fis4 => -3, :g4 => -2, :gis4 => -1, :a4 => 0,
32
+ :ais4 => 1, :b4 => 2, :c5 => 3, :cis5 => 4, :d5 => 5,
33
+ :dis5 => 6, :e5 => 7, :f5 => 8, :fis5 => 9, :g5 => 10,
34
+ :gis5 => 11, :a5 => 12, :ais5 => 13, :b5 => 14, :c6 => 15,
35
+ :cis6 => 16, :d6 => 17, :dis6 => 18, :e6 => 19, :f6 => 20,
36
+ :fis6 => 21, :g6 => 22, :gis6 => 23
37
+ }
38
+
39
+ class Note
40
+ attr :octave, :beat, :bpm, :frequency, :harmonic, :envelope, :volume, :name
41
+
42
+ def initialize(name, octave=4, bpm=120, options={})
43
+ if options
44
+ beat = options[:b].nil? ? (@beat || 1) : options[:b].to_f
45
+ volume = (options[:v].nil? ? (@volume.to_i || 5) : options[:v].to_i) * 1000
46
+ envelope = options[:a].nil? ? @envelope : 'default'
47
+ harmonic = options[:h].nil? ? @harmonic : 'default'
48
+ else
49
+ beats, volume, envelope, harmonic = (@beats || 1), 5000, @envelope || 'default', @harmonic || 'default'
50
+ end
51
+ @name, @octave, @bpm = name, octave, bpm
52
+ unless name == '_'
53
+ @frequency = frequency_of(FREQUENCIES["#{name}#{octave}".to_sym])
54
+ else
55
+ @frequency = 0
56
+ end
57
+ end
58
+
59
+
60
+ # shifting notes by semitones
61
+ def >>()
62
+ end
63
+
64
+ def to_stream
65
+ stream = []
66
+ duration = ((60 * WavHeader::SAMPLE_RATE * @beat)/@bpm)/WavHeader::SAMPLE_RATE.to_f
67
+ (0.0..duration.to_f).step(1.0/WavHeader::SAMPLE_RATE) do |i|
68
+ env = Envelope.send(@envelope.to_sym,i, duration)
69
+ har = Harmonic.send(@harmonic.to_sym, @frequency * i)
70
+ x = (env * har * @volume).to_i
71
+ stream << [x,x]
72
+ end
73
+ return stream
74
+ end
75
+
76
+ def to_s
77
+ "[#{@name}] -> b: #{@beat}, o: #{@octave} bpm: #{@bpm} e: #{@envelope} h: #{@harmonic}"
78
+ end
79
+
80
+ def frequency_of(step)
81
+ 440.0*(2**(step.to_f/12.0))
82
+ end
83
+
84
+ end
85
+
86
+ class Song
87
+
88
+ def self.record(name, options ={}, &block)
89
+ start_time = Time.now
90
+ puts "Start recording song named #{name}.wav"
91
+ @name = name
92
+ @bpm = options[:bpm] || 120
93
+ @envelope = options[:envelope] || 'default'
94
+ @harmonic = options[:harmonic] || 'default'
95
+ @bars = {}
96
+ puts "Processing ..."
97
+ instance_eval &block
98
+ save
99
+ end_time = Time.now
100
+ puts "Total time taken : #{((end_time - start_time)/60.0).round(3)} minutes"
101
+ puts "done."
102
+ end
103
+
104
+ class Bar
105
+ attr :bpm, :beats, :envelope, :harmonic
106
+ attr_accessor :stream
107
+
108
+ def initialize(id, options={})
109
+ @bpm = options[:bpm] || 120
110
+ @beats = (options[:b] || 1).to_f
111
+ @envelope = options[:e] || 'default'
112
+ @harmonic = options[:h] || 'default'
113
+ @volume = options[:v] || 5
114
+ @stream = []
115
+ end
116
+
117
+ def notes(&block)
118
+ instance_eval &block
119
+ end
120
+
121
+ def chord(notes,options={})
122
+ puts "chord with #{notes}"
123
+ triad =[]
124
+ notes.each do |name|
125
+ if name.start_with? *NOTES
126
+ octave = name[name.length-1].to_i
127
+ note = octave > 0 ? name.chop : name
128
+ octave = 4 if octave == 0
129
+ n = Note.new(note, octave, @bpm, options)
130
+ triad << n.to_stream
131
+ end
132
+ end
133
+ triad.transpose.map {|x| x.transpose.map {|y| y.reduce(:+)}}
134
+ end
135
+
136
+ def truncate_stream_by(num)
137
+ num.times {@stream.pop}
138
+ end
139
+
140
+ def add_to_stream(str)
141
+ @stream += str
142
+ end
143
+
144
+
145
+ def method_missing(name, *args, &block)
146
+ name = name.to_s
147
+ if name.start_with? *NOTES
148
+ if name.split('_').length > 1
149
+ notes = name.split('_')
150
+ add_to_stream chord(notes, args[0])
151
+ else
152
+ octave = name[name.length-1].to_i
153
+ note = octave > 0 ? name.chop : name
154
+ octave = 4 if octave == 0
155
+ add_to_stream Note.new(note, octave, @bpm, options).to_stream
156
+ end
157
+ end
158
+ end
159
+ end
160
+
161
+ private
162
+ class << self
163
+ def bar(id, options={})
164
+ puts "bar #{id}"
165
+ unless @bars[id]
166
+ @bars[id] = []
167
+ end
168
+ options[:bpm] = options[:bpm] || @bpm || 120
169
+ options[:envelope] = options[:envelope] || @envelope || 'default'
170
+ options[:harmonic] = options[:harmonic] || @harmonic || 'default'
171
+ @bars[id] << Bar.new(id, options)
172
+ @bars[id].last
173
+ end
174
+
175
+ def right_size(bars)
176
+ container = []
177
+ min_bar = bars.min_by {|x| x.stream.length}
178
+ bars.map do |bar|
179
+ bar.truncate_stream_by(bar.stream.length - min_bar.stream.length)
180
+ bar
181
+ end
182
+ end
183
+
184
+ def save
185
+ puts "Creating temporary files in parallel ..."
186
+
187
+ results = Parallel.each_with_index(@bars.values, :in_processes => Parallel.processor_count) do |item, id|
188
+ puts "Writing file - #{id}"
189
+ stream = []
190
+ container = []
191
+ item = right_size item
192
+ item.each do |i|
193
+ container << i.stream
194
+ end
195
+ stream += container.transpose.map {|x| x.transpose.map {|y| y.reduce(:+)}}
196
+ temp = TempData.new
197
+ stream.each_with_index do |s,i|
198
+ temp.stream[i].left = s[0]
199
+ temp.stream[i].right = s[1]
200
+ end
201
+ File.open("#{@name}-#{id.to_s.rjust(3,'0')}.tmp", "w") {|file| temp.write(file) }
202
+ puts "Completed file - #{id}"
203
+ end
204
+
205
+ stream_size = results.inject(0) do |memo, bars|
206
+ memo + bars.first.stream.size
207
+ end
208
+
209
+ puts "Combining temporary files ..."
210
+ WavHeader.new("#{@name}.wav", stream_size)
211
+ tmpfiles = Dir.glob("#{@name}-*.tmp").sort
212
+ File.open("#{@name}.wav", "ab+") do |wav|
213
+ tmpfiles.each do |file|
214
+ File.open(file, "rb") { |tmp| File.copy_stream(tmp, wav) }
215
+ File.delete file
216
+ end
217
+ end
218
+
219
+ end
220
+ end
221
+ end
222
+ end
data/lib/muse.rb CHANGED
@@ -19,6 +19,24 @@ require "#{File.dirname(__FILE__)}/muse/wav"
19
19
  require "#{File.dirname(__FILE__)}/muse/config"
20
20
 
21
21
  module Muse
22
+
23
+
24
+ NOTES = %w(_ a ais b c cis d dis e f fis g gis)
25
+ FREQUENCIES = {
26
+ :ais1 => -34, :b1 => -33, :cis2 => -32, :d2 => -31, :dis2 => -30,
27
+ :e2 => -29, :f2 => -28, :fis2 => -27, :g2 => -26, :gis2 => -25,
28
+ :a2 => -24, :ais2 => -23, :b2 => -22, :c3 => -21, :cis3 => -20,
29
+ :d3 => -19, :dis3 => -18, :e3 => -17, :f3 => -16, :fis3 => -15,
30
+ :g3 => -14, :gis3 => -13, :a3 => -12, :ais3 => -11, :b3 => -10,
31
+ :c4 => -9, :cis4 => -8, :d4 => -7, :dis4 => -6, :e4 => -5,
32
+ :f4 => -4, :fis4 => -3, :g4 => -2, :gis4 => -1, :a4 => 0,
33
+ :ais4 => 1, :b4 => 2, :c5 => 3, :cis5 => 4, :d5 => 5,
34
+ :dis5 => 6, :e5 => 7, :f5 => 8, :fis5 => 9, :g5 => 10,
35
+ :gis5 => 11, :a5 => 12, :ais5 => 13, :b5 => 14, :c6 => 15,
36
+ :cis6 => 16, :d6 => 17, :dis6 => 18, :e6 => 19, :f6 => 20,
37
+ :fis6 => 21, :g6 => 22, :gis6 => 23
38
+ }
39
+
22
40
  class Song
23
41
 
24
42
  def self.record(name, options ={}, &block)
@@ -40,28 +58,14 @@ module Muse
40
58
  class Bar
41
59
  attr :bpm, :beats, :envelope, :harmonic
42
60
  attr_accessor :stream
43
-
44
- NOTES = %w(_ a ais b c cis d dis e f fis g gis)
45
- FREQUENCIES = {
46
- :ais1 => -34, :b1 => -33, :cis2 => -32, :d2 => -31, :dis2 => -30,
47
- :e2 => -29, :f2 => -28, :fis2 => -27, :g2 => -26, :gis2 => -25,
48
- :a2 => -24, :ais2 => -23, :b2 => -22, :c3 => -21, :cis3 => -20,
49
- :d3 => -19, :dis3 => -18, :e3 => -17, :f3 => -16, :fis3 => -15,
50
- :g3 => -14, :gis3 => -13, :a3 => -12, :ais3 => -11, :b3 => -10,
51
- :c4 => -9, :cis4 => -8, :d4 => -7, :dis4 => -6, :e4 => -5,
52
- :f4 => -4, :fis4 => -3, :g4 => -2, :gis4 => -1, :a4 => 0,
53
- :ais4 => 1, :b4 => 2, :c5 => 3, :cis5 => 4, :d5 => 5,
54
- :dis5 => 6, :e5 => 7, :f5 => 8, :fis5 => 9, :g5 => 10,
55
- :gis5 => 11, :a5 => 12, :ais5 => 13, :b5 => 14, :c6 => 15,
56
- :cis6 => 16, :d6 => 17, :dis6 => 18, :e6 => 19, :f6 => 20,
57
- :fis6 => 21, :g6 => 22, :gis6 => 23
58
- }
61
+
59
62
 
60
63
  def initialize(id, options={})
61
64
  @bpm = options[:bpm] || 120
62
65
  @beats = (options[:b] || 1).to_f
63
- @envelope = options[:envelope] || 'default'
64
- @harmonic = options[:harmonic] || 'default'
66
+ @envelope = options[:e] || 'default'
67
+ @harmonic = options[:h] || 'default'
68
+ @volume = options[:v] || 5
65
69
  @stream = []
66
70
  end
67
71
 
@@ -91,13 +95,13 @@ module Muse
91
95
  stream = []
92
96
  if options
93
97
  beats = options[:b].nil? ? (@beats || 1) : options[:b].to_f
94
- volume = (options[:v].nil? ? 5 : options[:v].to_i) * 1000
98
+ volume = (options[:v].nil? ? (@volume.to_i || 5) : options[:v].to_i) * 1000
95
99
  envelope = options[:a].nil? ? @envelope : 'default'
96
100
  harmonic = options[:h].nil? ? @harmonic : 'default'
97
101
  else
98
102
  beats, volume, envelope, harmonic = (@beats || 1), 5000, @envelope || 'default', @harmonic || 'default'
99
103
  end
100
- puts "[#{note}] -> beats : #{beats}, octave : #{octave} bpm: #{@bpm} envelope: #{envelope} harmonic : #{harmonic}"
104
+ puts "[#{note}] -> b:#{beats}, o:#{octave}, e:#{envelope}, h:#{harmonic}"
101
105
  duration = ((60 * WavHeader::SAMPLE_RATE * beats)/@bpm)/WavHeader::SAMPLE_RATE.to_f
102
106
  note_frequency = note + octave.to_s
103
107
  unless note == '_'
@@ -141,7 +145,7 @@ module Muse
141
145
  private
142
146
  class << self
143
147
  def bar(id, options={})
144
- puts "bar #{id}"
148
+ puts "bar #{id} - bpm:#{@bpm}"
145
149
  unless @bars[id]
146
150
  @bars[id] = []
147
151
  end
@@ -162,10 +166,10 @@ module Muse
162
166
  end
163
167
 
164
168
  def save
165
- puts "Creating temporary files in parallel ..."
169
+ puts "\nCreating temporary files in parallel ..."
166
170
 
167
171
  results = Parallel.each_with_index(@bars.values, :in_processes => Parallel.processor_count) do |item, id|
168
- puts "Writing file - #{id}"
172
+ puts "Writing file #{id}"
169
173
  stream = []
170
174
  container = []
171
175
  item = right_size item
@@ -179,14 +183,14 @@ module Muse
179
183
  temp.stream[i].right = s[1]
180
184
  end
181
185
  File.open("#{@name}-#{id.to_s.rjust(3,'0')}.tmp", "w") {|file| temp.write(file) }
182
- puts "Completed file - #{id}"
186
+ puts "file #{id} done."
183
187
  end
184
188
 
185
189
  stream_size = results.inject(0) do |memo, bars|
186
190
  memo + bars.first.stream.size
187
191
  end
188
192
 
189
- puts "Combining temporary files ..."
193
+ print "\nCombining temporary files ..."
190
194
  WavHeader.new("#{@name}.wav", stream_size)
191
195
  tmpfiles = Dir.glob("#{@name}-*.tmp").sort
192
196
  File.open("#{@name}.wav", "ab+") do |wav|
@@ -195,7 +199,7 @@ module Muse
195
199
  File.delete file
196
200
  end
197
201
  end
198
-
202
+ puts " done."
199
203
  end
200
204
  end
201
205
  end
@@ -17,30 +17,32 @@
17
17
  module Muse
18
18
  module Harmonic
19
19
  class << self
20
+
21
+ def base(input)
22
+ 2 * Math::PI * input
23
+ end
24
+
20
25
  def default(input)
21
- Math.sin(2 * Math::PI * input)
26
+ Math.sin(base(input))
22
27
  end
23
28
 
24
29
  def second(input)
25
- Math.sin(2 * Math::PI * input) +
26
- Math.sin(3* 2 * Math::PI * input)
30
+ Math.sin(base(input))
31
+ Math.sin(base(input) * 3)
27
32
  end
28
33
 
29
34
  def third(input)
30
- Math.sin(2 * Math::PI * input) +
31
- Math.sin(3* 2 * Math::PI * input) +
32
- Math.sin(5 * 2 * Math::PI * input)
35
+ Math.sin(base(input)) +
36
+ Math.sin(base(input) * 3) +
37
+ Math.sin(base(input) * 5)
33
38
  end
34
39
 
35
- def organ(input)
36
- Math.sin(2 * 2 * Math::PI * input) +
37
- Math.sin(2 * Math::PI * input) +
38
- Math.sin(Math::PI * input)
39
-
40
+ def guitar(input)
41
+ Math.sin(base(input)) +
42
+ Math.sin(base(input) * 2) +
43
+ Math.sin(base(input) * 0.5)
40
44
  end
41
-
42
45
 
43
-
44
46
  end
45
47
  end
46
48
  end
data/lib/muse/version.rb CHANGED
@@ -15,5 +15,5 @@
15
15
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
16
 
17
17
  module Muse
18
- VERSION = "0.0.9"
18
+ VERSION = "0.0.10"
19
19
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: muse
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.0.10
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,11 +10,11 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-04-07 00:00:00.000000000Z
13
+ date: 2012-04-22 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bindata
17
- requirement: &2153178280 !ruby/object:Gem::Requirement
17
+ requirement: !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
@@ -22,10 +22,15 @@ dependencies:
22
22
  version: '0'
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: *2153178280
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ! '>='
29
+ - !ruby/object:Gem::Version
30
+ version: '0'
26
31
  - !ruby/object:Gem::Dependency
27
32
  name: parallel
28
- requirement: &2153177840 !ruby/object:Gem::Requirement
33
+ requirement: !ruby/object:Gem::Requirement
29
34
  none: false
30
35
  requirements:
31
36
  - - ! '>='
@@ -33,7 +38,12 @@ dependencies:
33
38
  version: '0'
34
39
  type: :runtime
35
40
  prerelease: false
36
- version_requirements: *2153177840
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
37
47
  description: Muse is a complete music creation package including writing and up to
38
48
  creating WAV files
39
49
  email:
@@ -49,6 +59,7 @@ files:
49
59
  - lib/muse/config.rb
50
60
  - lib/muse/version.rb
51
61
  - lib/muse/wav.rb
62
+ - lib/muse.old.rb
52
63
  - lib/muse.rb
53
64
  homepage: https://github.com/sausheong/muse
54
65
  licenses: []
@@ -71,7 +82,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
71
82
  version: '0'
72
83
  requirements: []
73
84
  rubyforge_project:
74
- rubygems_version: 1.8.17
85
+ rubygems_version: 1.8.22
75
86
  signing_key:
76
87
  specification_version: 3
77
88
  summary: Muse is a Ruby DSL for making music