mml2wav 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5a1e953bfb6d378660ab80310c24d6471113cb88
4
- data.tar.gz: e874322276558218393a43f6085bbbe795db653c
3
+ metadata.gz: 06613389b80c23f0feceb9a329027156ffdfa049
4
+ data.tar.gz: c885d9a54797cfe5a73c1e7b25dc6107b6bb3a4d
5
5
  SHA512:
6
- metadata.gz: 48d9b354f075604e7c2f485690ec8a1a6c73b59dcf186e84da1eeef6dab00947a67fcefcf4fbf413fe1c8f70f1eac080d1be8714e47b3688118ca4c0bf7d9941
7
- data.tar.gz: 51a6810935932876b27d5c23ea54701112e974aaa305ec24c095e051541f096bc8c53a348d01726c920898e15155cd0228073ca02d4cc10457cdade3957f9377
6
+ metadata.gz: 6c5d0613578307b8dc99cd947de6f7aab9c5e4bf42a2d4f0674a9bcca81c5b4238ae43a7f4f4ffe4d10e22c7e7bd88922ebb2e18df983f683e89391cc337abc6
7
+ data.tar.gz: 18ab290f8e4b791855cd7ac65f5532632063c759f09b0d5a0d40eb8b521e605a420c374724c3d3502e13c0a907f55350b7f333991a5bef40238b5696bc8f7cb7
@@ -10,7 +10,9 @@ module Mml2wav
10
10
 
11
11
  def initialize(arguments)
12
12
  @options = parse_options(arguments)
13
- @sounds = ARGF.readlines.join(" ")
13
+ channel_delimiter = @options[:channel_delimiter] || ","
14
+ channels = ARGF.readlines.join.split(/#{channel_delimiter}/)
15
+ @sounds = channels.reject {|channel| channel.empty? }
14
16
  end
15
17
 
16
18
  def run
@@ -35,6 +37,14 @@ module Mml2wav
35
37
  "Specify BPM (beats per minute)", Integer) do |bpm|
36
38
  options[:bpm] = bpm
37
39
  end
40
+ parser.on("--octave_reverse",
41
+ "Reverse octave sign (><) effects") do |boolean|
42
+ options[:octave_reverse] = boolean
43
+ end
44
+ parser.on("--channel_delimiter=DELIMITER",
45
+ "Specify channel delimiter") do |delimiter|
46
+ options[:channel_delimiter] = delimiter
47
+ end
38
48
  parser.parse!(arguments)
39
49
 
40
50
  unless File.pipe?('/dev/stdin') || IO.select([ARGF], nil, nil, 0)
@@ -0,0 +1,64 @@
1
+ require "mml2wav/scale"
2
+
3
+ module Mml2wav
4
+ class Parser
5
+ def initialize(sounds, sampling_rate, options={})
6
+ pattern = /T\d+|V\d+|L\d+|[A-G][#+-]?\d*\.?|O\d+|[><]|./i
7
+ @sounds = sounds.scan(pattern)
8
+ @sampling_rate = sampling_rate
9
+ @bpm = options[:bpm] || 120
10
+ @velocity = options[:velocity] || 5
11
+ @octave = options[:octave] || 4
12
+ @default_length = options[:default_length] || 4.0
13
+ @octave_reverse = options[:octave_reverse] || false
14
+ @cursor = 0
15
+ end
16
+
17
+ def wave!
18
+ @cursor.upto(@sounds.size - 1) do |i|
19
+ sound = @sounds[i]
20
+ base_sec = 60.0 * 4
21
+ length = @default_length
22
+ case sound
23
+ when /\AT(\d+)/i
24
+ @bpm = $1.to_i
25
+ when /\AV(\d+)/i
26
+ @velocity = $1.to_i
27
+ when /\AL(\d+)/i
28
+ @default_length = $1.to_f
29
+ when /\A([A-G][#+-]?)(\d+)(\.)?/i
30
+ length = $2.to_f
31
+ sound = $1
32
+ length = @default_length / 1.5 if $3
33
+ when /\AO(\d+)/i
34
+ @octave = $1.to_i
35
+ when "<"
36
+ @octave += @octave_reverse ? -1 : 1
37
+ when ">"
38
+ @octave -= @octave_reverse ? -1 : 1
39
+ end
40
+ sec = base_sec / length / @bpm
41
+ amplitude = @velocity.to_f / 10
42
+ frequency = Scale::FREQUENCIES[sound.downcase]
43
+ next unless frequency
44
+ frequency *= (2 ** @octave)
45
+ wave = sine_wave(frequency, @sampling_rate, sec, amplitude)
46
+ @cursor = i + 1
47
+ return wave
48
+ end
49
+ nil
50
+ end
51
+
52
+ private
53
+ def sine_wave(frequency, sampling_rate, sec, amplitude=0.5)
54
+ max = sampling_rate * sec
55
+ if frequency == 0
56
+ return Array.new(max) { 0.0 }
57
+ end
58
+ base_x = 2.0 * Math::PI * frequency / sampling_rate
59
+ 1.upto(max).collect do |n|
60
+ amplitude * Math.sin(base_x * n)
61
+ end
62
+ end
63
+ end
64
+ end
@@ -1,3 +1,3 @@
1
1
  module Mml2wav
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -1,66 +1,62 @@
1
1
  require "wavefile"
2
- require "mml2wav/scale"
2
+ require "mml2wav/parser"
3
3
 
4
4
  module Mml2wav
5
5
  class Wave
6
6
  class << self
7
7
  include WaveFile
8
8
 
9
- def write(sounds, options={})
9
+ def write(soundses, options={})
10
+ if soundses.is_a?(String)
11
+ n_channels = :mono
12
+ soundses = [soundses]
13
+ size = 1
14
+ elsif soundses.size == 1
15
+ n_channels = :mono
16
+ size = 1
17
+ elsif soundses.size == 2
18
+ n_channels = :stereo
19
+ size = soundses.size
20
+ else
21
+ n_channels = soundses.size
22
+ size = soundses.size
23
+ end
10
24
  output_path = options[:output] || "doremi.wav"
11
25
  sampling_rate = options[:sampling_rate] || 22050
12
- bpm = options[:bpm] || 120
13
- velocity = 5
14
- octave = 4
15
- default_length = 4.0
16
26
 
17
- format = Format.new(:mono, :pcm_8, sampling_rate)
27
+ format = Format.new(n_channels, :pcm_8, sampling_rate)
18
28
  Writer.new(output_path, format) do |writer|
19
- buffer_format = Format.new(:mono, :float, sampling_rate)
20
- sounds.scan(/T\d+|V\d+|L\d+|[A-G][#+-]?\d*\.?|O\d+|[><]|./i).each do |sound|
21
- base_sec = 60.0 * 4
22
- length = default_length
23
- case sound
24
- when /\AT(\d+)/i
25
- bpm = $1.to_i
26
- when /\AV(\d+)/i
27
- velocity = $1.to_i
28
- when /\AL(\d+)/i
29
- default_length = $1.to_f
30
- when /\A([A-G][#+-]?)(\d+)(\.)?/i
31
- length = $2.to_f
32
- sound = $1
33
- length = default_length / 1.5 if $3
34
- when /\AO(\d+)/i
35
- octave = $1.to_i
36
- when "<"
37
- octave += 1
38
- when ">"
39
- octave -= 1
29
+ buffer_format = Format.new(n_channels, :float, sampling_rate)
30
+ parsers = []
31
+ soundses.each do |sounds|
32
+ parsers << Parser.new(sounds, sampling_rate, options)
33
+ end
34
+ waves = Array.new(parsers.size) { [] }
35
+ loop do
36
+ parsers.each_with_index do |parser, i|
37
+ wave = parser.wave!
38
+ waves[i] += wave if wave
39
+ end
40
+ break if waves.all? {|wave| wave.empty? }
41
+ buffer_size = waves.reject {|wave| wave.empty? }.collect(&:size).min
42
+ break unless buffer_size
43
+ samples = []
44
+ buffer_size.times do
45
+ sample = []
46
+ waves.each do |wave|
47
+ if wave.first
48
+ sample << wave.shift
49
+ else
50
+ sample << 0.0
51
+ end
52
+ end
53
+ samples << sample
40
54
  end
41
- sec = base_sec / length / bpm
42
- amplitude = velocity.to_f / 10
43
- frequency = Scale::FREQUENCIES[sound.downcase]
44
- next unless frequency
45
- frequency *= (2 ** octave)
46
- samples = sine_wave(frequency, sampling_rate, sec, amplitude)
47
55
  buffer = Buffer.new(samples, buffer_format)
48
56
  writer.write(buffer)
49
57
  end
50
58
  end
51
59
  end
52
-
53
- private
54
- def sine_wave(frequency, sampling_rate, sec, amplitude=0.5)
55
- max = sampling_rate * sec
56
- if frequency == 0
57
- return Array.new(max) { 0.0 }
58
- end
59
- base_x = 2.0 * Math::PI * frequency / sampling_rate
60
- 1.upto(max).collect do |n|
61
- amplitude * Math.sin(base_x * n)
62
- end
63
- end
64
60
  end
65
61
  end
66
62
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mml2wav
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Masafumi Yokoyama
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-26 00:00:00.000000000 Z
11
+ date: 2015-04-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: wavefile
@@ -69,6 +69,7 @@ files:
69
69
  - examples/kaerunouta.sh
70
70
  - lib/mml2wav.rb
71
71
  - lib/mml2wav/command.rb
72
+ - lib/mml2wav/parser.rb
72
73
  - lib/mml2wav/scale.rb
73
74
  - lib/mml2wav/version.rb
74
75
  - lib/mml2wav/wave.rb