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 +4 -4
- data/lib/mml2wav/command.rb +11 -1
- data/lib/mml2wav/parser.rb +64 -0
- data/lib/mml2wav/version.rb +1 -1
- data/lib/mml2wav/wave.rb +42 -46
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 06613389b80c23f0feceb9a329027156ffdfa049
|
4
|
+
data.tar.gz: c885d9a54797cfe5a73c1e7b25dc6107b6bb3a4d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6c5d0613578307b8dc99cd947de6f7aab9c5e4bf42a2d4f0674a9bcca81c5b4238ae43a7f4f4ffe4d10e22c7e7bd88922ebb2e18df983f683e89391cc337abc6
|
7
|
+
data.tar.gz: 18ab290f8e4b791855cd7ac65f5532632063c759f09b0d5a0d40eb8b521e605a420c374724c3d3502e13c0a907f55350b7f333991a5bef40238b5696bc8f7cb7
|
data/lib/mml2wav/command.rb
CHANGED
@@ -10,7 +10,9 @@ module Mml2wav
|
|
10
10
|
|
11
11
|
def initialize(arguments)
|
12
12
|
@options = parse_options(arguments)
|
13
|
-
|
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
|
data/lib/mml2wav/version.rb
CHANGED
data/lib/mml2wav/wave.rb
CHANGED
@@ -1,66 +1,62 @@
|
|
1
1
|
require "wavefile"
|
2
|
-
require "mml2wav/
|
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(
|
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(
|
27
|
+
format = Format.new(n_channels, :pcm_8, sampling_rate)
|
18
28
|
Writer.new(output_path, format) do |writer|
|
19
|
-
buffer_format = Format.new(
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
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.
|
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-
|
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
|