mml2wav 0.0.3 → 0.0.4
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 +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
|