muse 0.0.9 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
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