pocket_miku 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 224a1798a6222b6fdfcdd075c49fc64f7b4371cd
4
+ data.tar.gz: bfc29cc865f43426d18aa17c434c9b5e9386e823
5
+ SHA512:
6
+ metadata.gz: 0480a64f8a7b28ae31ee6a6499ce0ba3de4a980398c90659f043a8fa0798b97808c98fe944d8066e9f79d7dcd72c17863368ddafb33944095da0d6f3851e12df
7
+ data.tar.gz: 17bcbffc83eaac450af442fa9beb127d9aa0ca03ca26b0407842f19d516450ec81b4ad75981c039d46cefef094521c44bb84fd38b31cd2819dc90dd3da3c625f
data/README.md CHANGED
@@ -26,21 +26,97 @@ Or install it yourself as:
26
26
 
27
27
  ```ruby
28
28
  require 'pocket_miku'
29
- PocketMiku.new('/dev/midi2') do
30
- ふぁ(75,127)
31
- sleep 0.12
32
- ぼ(82,127)
33
- sleep 0.12
34
- stop
29
+ PocketMiku.sing '/dev/midi2' do
30
+ tempo 240
31
+ ふぁ 75; ぼ 82
35
32
  end
36
33
  ```
37
34
 
38
- 「ふぁ」「ぼ」等はメソッドで、この音を発音します。引数は「あ(音程, 強さ)」です。全ての発音は、ポケット・ミク付属の『ユーザーズマニュアル』の裏に掲載されている『ポケット・ミク デフォルト文字テーブル』に書いてある文字が全て使用できます。
35
+ *ふぁ (音階)* などと書くと、その高さで「ふぁ」と発音します。ポケット・ミク付属の『ユーザーズマニュアル』の裏に掲載されている『ポケット・ミク デフォルト文字テーブル』に書いてある文字が全て使用できます。
39
36
  なお、「ん」は「N\」のエイリアスです。ほかの「ん」を使用する時は、同備考欄の文字(ダブルクォートは不要)を指定してください。
37
+ ### 休符
38
+ 「っ」です。引数は数値一つで、「長さ」(後述)です。
39
+
40
+ ### ノートの追加パラメータ
41
+ 音毎に追加パラメータを設定できます。追加パラメータを利用する場合、例えば *あ 60* を *あ key:60* と書き換え、
42
+ その後に *, 追加パラメータ名: 値* と書きます。
43
+
44
+ #### 長さ
45
+ 音の長さを指定するには、 *length: [長さ]* と指定します。
46
+ 長さは、32分音符が1で、長さが倍になると倍になります。又、以下の定数も用意されています。
47
+
48
+ |定数|意味|
49
+ |:-:|:-|
50
+ |PocketMiku::Note1|全音符|
51
+ |PocketMiku::Note2|2分音符|
52
+ |PocketMiku::Note4|4分音符|
53
+ |PocketMiku::Note8|8分音符|
54
+ |PocketMiku::Note16|16分音符|
55
+ |PocketMiku::Note32|32分音符|
56
+
57
+ 以下のサンプルでは見やすさのために変数を使ってます。
58
+
59
+ ```ruby
60
+ PocketMiku.sing '/dev/midi2' do
61
+ f8 = PocketMiku::Note8
62
+ f16 = PocketMiku::Note16
63
+
64
+ ま key: 79, length: f8; っ f16; る key: 79, length: f16
65
+ end
66
+ ```
67
+
68
+ #### ベロシティ
69
+ 音の強さは、 *velocity: [0..127]* のように指定します。0から127まで、数字が大きいほうが音が大きくなります。
70
+ さっきのサンプルにベロシティを追加してみました。
71
+
72
+ ```ruby
73
+ PocketMiku.sing '/dev/midi2' do
74
+ f8 = PocketMiku::Note8
75
+ f16 = PocketMiku::Note16
76
+
77
+ ま key: 79, length: f8; っ f16; る key: 79, length: f16, velocity: 80
78
+ end
79
+ ```
80
+
81
+ ### 楽譜パラメータ
82
+
83
+ #### デフォルト値
84
+ *default.velocity = 100* などと書くと、これ以降の音符のデフォルト値が設定できます。
85
+
86
+ |定義|意味|
87
+ |:-|:-|
88
+ |default.key = |音の高さ|
89
+ |default.length|長さ|
90
+ |default.velocity|ベロシティ|
91
+
92
+ #### テンポ
93
+ *tempo 100* などと書くと、これ以降のテンポを変更できます。曲のテンポを設定する時は最初に書いてください。
94
+ テンポの数字は、1分間に4分音符がいくつ入るか、です。
95
+
96
+ 先ほどのサンプルにテンポをつけてみました
97
+
98
+ ```ruby
99
+ PocketMiku.sing '/dev/midi2' do
100
+ tempo 80
101
+ f8 = PocketMiku::Note8
102
+ f16 = PocketMiku::Note16
103
+
104
+ ま key: 79, length: f8; っ f16; る key: 79, length: f16, velocity: 80
105
+ た key: 79, length: f8; っ f16; け key: 79, length: f16, velocity: 80
106
+ え key: 79, length: f8; っ f16; べ key: 77, length: f16, velocity: 80
107
+ す key: 79, length: f8; っ f16; に key: 77, length: f16, velocity: 80
108
+ お key: 79, length: f8; っ f16; し key: 79, length: f16, velocity: 80
109
+ お key: 74, length: f8; っ f16; い key: 74, length: f16, velocity: 80
110
+ け key: 74, length: f8 * 1.5
111
+ っ f16 + PocketMiku::Note4;
112
+ end
113
+ ```
40
114
 
41
115
  ## そのうち
42
116
 
43
- - 音の同期をsleepとかじゃなくてもっといい感じにしたい
117
+ - 音の同期処理本当にどうしよう
118
+ - ピッチベンド実装したい
119
+ - 発音中に音のパラメータを操作したい(だんだん高く、だんだん弱く等)
44
120
 
45
121
  ## Contributing
46
122
 
data/lib/pocket_miku.rb CHANGED
@@ -1,141 +1,23 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  require "pocket_miku/version"
3
- require "pocket_miku/chartable"
3
+ require "pocket_miku/literal"
4
4
  require "pocket_miku/exception"
5
+ require "pocket_miku/packet_factory"
6
+ require "pocket_miku/base"
7
+ require "pocket_miku/chartable"
8
+ require "pocket_miku/note"
9
+ require "pocket_miku/score"
10
+ require "pocket_miku/device"
5
11
  require 'stringio'
12
+ require 'rational'
6
13
 
7
- class PocketMiku
8
-
9
- attr_reader :sound, :key, :velocity
10
-
11
- # ==== Args
12
- # [device]
13
- # - String :: MIDIデバイスファイル名
14
- # - IO,StringIO :: 出力するIOオブジェクト
15
- # ==== Exception
16
- # PocketMiku::ArgumentError
17
- # ファイル device が見つからず、ストリームとしても利用できない場合
18
- def initialize(device)
19
- @key = 60
20
- @velocity = 100
21
- @io = case device
22
- when IO,StringIO
23
- device
24
- when String
25
- open(device, 'w')
26
- else
27
- raise PocketMiku::ArgumentError, "device should give IO or String. but give `#{device.class}'"
28
- end
29
- if block_given?
30
- begin
31
- self.instance_eval(&Proc.new)
32
- ensure
33
- @io.close
34
- end
35
- end
36
- end
14
+ module PocketMiku
15
+ extend self
37
16
 
38
- # ポケットミクに直接MIDIパケットを送る
17
+ # ポケットミクに歌わせるためのショートカットメソッド
39
18
  # ==== Args
40
- # [packet]
41
- # - Array :: バイト値配列をpack("C*")して送る
42
- # - Integer :: 対応するキャラクタを送る
43
- # ==== Exception
44
- # PocketMiku::InvalidByteError
45
- # packetの中に、1byte(0..255)に収まらない数値がある場合
46
- # ==== Return
47
- # self
48
- def send(packet)
49
- @io << pack(packet)
50
- @io.flush
19
+ # [device] String|IO デバイスファイルの場所
20
+ def sing(device)
21
+ PocketMiku::Device.new(device, &Proc.new)
51
22
  end
52
-
53
- # ポケットミクに発音させる情報をセットする
54
- # ==== Args
55
- # [key] Integer 音程
56
- # [velocity] Integer 音の強さ
57
- # [sound] Integer|Symbol 文字テーブルの文字コード(Integer)か文字(Symbol)
58
- # ==== Return
59
- # self
60
- def set(options)
61
- @key = byte_check(options[:key], "invalid key `%d'".freeze) if options[:key]
62
- @velocity = byte_check(options[:velocity], "invalid velocity `%d'".freeze) if options[:velocity]
63
- self.sound = options[:sound] if options[:sound]
64
- self
65
- end
66
-
67
- # ポケットミクに発音させる文字テーブル情報をセットする
68
- # ==== Args
69
- # [new] Integer|Symbol セットする文字テーブルの文字コード(Integer)か文字(Symbol)
70
- # ==== Exceptions
71
- # PocketMiku::CharMappingError
72
- # newが文字テーブルに存在しない場合
73
- # PocketMiku::InvalidByteError
74
- # newが1byte(0..255)に収まらない数値である場合
75
- # ==== Return
76
- # 新しい sound の値。Symbolをセットしても必ず数値になる。
77
- def sound=(new)
78
- case new
79
- when Fixnum
80
- @sound = byte_check(new, "invalid sound `%d'".freeze)
81
- when -> _ {CharTable.include? _}
82
- @sound = CharTable[new]
83
- else
84
- raise CharMappingError, "unknown sound `#{new}'"
85
- end
86
- end
87
-
88
- # 設定されている情報でサウンドを再生開始する
89
- # ==== Exception
90
- # PocketMiku::InvalidByteError
91
- # packetの中に、1byte(0..255)に収まらない数値がある場合
92
- def play
93
- send([0xF0, 0x43, 0x79, 0x09, 0x11, 0x0A, 0, @sound, 0xF7])
94
- send([0x90, @key, @velocity])
95
- end
96
- alias +@ play
97
-
98
- # 設定されているサウンドを再生停止する
99
- # ==== Exception
100
- # PocketMiku::InvalidByteError
101
- # packetの中に、1byte(0..255)に収まらない数値がある場合
102
- def stop
103
- send([0x80, @key, 0])
104
- end
105
- alias -@ stop
106
-
107
- alias sing instance_eval
108
-
109
- def method_missing(method, *args)
110
- case method
111
- when -> _ {CharTable.include? _}
112
- set(key: args[0], velocity: args[1], sound: CharTable[method]).play
113
- else
114
- super
115
- end
116
- end
117
-
118
- def close
119
- stop
120
- @io.close
121
- end
122
-
123
- def closed?
124
- @io.closed?
125
- end
126
-
127
- private
128
-
129
- def pack(bytes)
130
- bytes = [bytes] if bytes.is_a? Integer
131
- bytes.each(&method(:byte_check))
132
- bytes.pack "C*".freeze
133
- end
134
-
135
- def byte_check(byte, error_message="byte should 0...255 but give `%d'".freeze)
136
- raise InvalidByteError, "`#{byte}' is not integer." unless byte.is_a? Integer
137
- raise InvalidByteError, error_message % byte unless (0..0xFF).include?(byte)
138
- byte
139
- end
140
-
141
23
  end
@@ -0,0 +1,2 @@
1
+ class PocketMiku::Base
2
+ end
@@ -1,5 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
- class PocketMiku
2
+ module PocketMiku
3
3
  CharTable = {
4
4
  あ: 0,
5
5
  い: 1,
@@ -0,0 +1,99 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module PocketMiku
4
+ class Device < PocketMiku::Base
5
+
6
+ # ==== Args
7
+ # [device]
8
+ # - String :: MIDIデバイスファイル名
9
+ # - IO,StringIO :: 出力するIOオブジェクト
10
+ # ==== Exception
11
+ # PocketMiku::ArgumentError
12
+ # ファイル device が見つからず、ストリームとしても利用できない場合
13
+ def initialize(device)
14
+ @io = case device
15
+ when IO,StringIO
16
+ device
17
+ when String
18
+ open(device, 'w')
19
+ else
20
+ raise PocketMiku::ArgumentError, "device should give IO or String. but give `#{device.class}'"
21
+ end
22
+ if block_given?
23
+ begin
24
+ self.sing(&Proc.new)
25
+ ensure
26
+ @io.close
27
+ end
28
+ end
29
+ end
30
+
31
+ # ポケットミクに直接MIDIパケットを送る
32
+ # ==== Args
33
+ # [packet]
34
+ # - Array :: バイト値配列をpack("C*")して送る
35
+ # - Integer :: 対応するキャラクタを送る
36
+ # ==== Exception
37
+ # PocketMiku::InvalidByteError
38
+ # packetの中に、1byte(0..255)に収まらない数値がある場合
39
+ # ==== Return
40
+ # self
41
+ def send(packet)
42
+ @io << PocketMiku::PacketFactory.pack(packet)
43
+ @io.flush
44
+ end
45
+
46
+ # score をこのデバイスで再生する
47
+ # ==== Array
48
+ # [score] PocketMiku::Score 楽譜情報
49
+ # ==== Exception
50
+ # PocketMiku::InvalidByteError
51
+ # packetの中に、1byte(0..255)に収まらない数値がある場合
52
+ def play(score)
53
+ score.map{|note|[note, note.to_s.freeze]}.each do |note, packet|
54
+ case note
55
+ when RestNote
56
+ sleep Rational(60.to_f, score.tempo) * Rational(note.length.to_f, Note4)
57
+ when Note
58
+ @io << packet
59
+ @io.flush
60
+ sleep Rational(60.to_f, score.tempo) * Rational(note.length.to_f, Note4)
61
+ stop 0, note.key
62
+ @io.flush
63
+ end
64
+ end
65
+ end
66
+ alias +@ play
67
+
68
+ # 特定のトラックとキーのサウンドを再生停止する
69
+ # ==== Args
70
+ # [track] トラック番号
71
+ # [key] 音程
72
+ # ==== Exception
73
+ # PocketMiku::InvalidByteError
74
+ # packetの中に、1byte(0..255)に収まらない数値がある場合
75
+ def stop(track, key)
76
+ send([0x80 + track, key, 0])
77
+ end
78
+ alias -@ stop
79
+
80
+ # ブロックをこのインスタンスのコンテキストで実行してから、ポケットミクで再生する
81
+ # ==== Array
82
+ # [score] PocketMiku::Score 楽譜情報
83
+ # ==== Return
84
+ # ブロックの評価結果
85
+ def sing(score=nil)
86
+ score = PocketMiku::Score.new(&Proc.new) if block_given?
87
+ play score
88
+ end
89
+
90
+ def close
91
+ #stop
92
+ @io.close
93
+ end
94
+
95
+ def closed?
96
+ @io.closed?
97
+ end
98
+ end
99
+ end
@@ -1,5 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
- class PocketMiku
2
+ module PocketMiku
3
3
  # PocketMikuが定義する例外の基底クラス
4
4
  class Exception < ::RuntimeError; end
5
5
 
@@ -0,0 +1,11 @@
1
+ module PocketMiku
2
+ Note32 = 1
3
+ Note16 = Note32*2
4
+ Note8 = Note16*2
5
+ Note4 = QuarterNote = Note8*2
6
+ Note2 = HalfNote = Note4*2
7
+ Note1 = Note2*2
8
+ DoubleNote = Note1*2
9
+ LongaNote = DoubleNote*2
10
+ MaximaNote = LongaNote*2
11
+ end
@@ -0,0 +1,123 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module PocketMiku
4
+ class Note < PocketMiku::Base
5
+ attr_reader :sound, :key, :velocity, :pitchbend, :length
6
+
7
+ # ==== Args
8
+ # [options]
9
+ # - sound :: 発音する文字テーブルコード
10
+ # - key :: 音程 (0-127)
11
+ # - velocity :: 強さ (0-127)
12
+ # - pitchvend :: ピッチベンド
13
+ # - length :: 音の長さ(相対)
14
+ def initialize(options={})
15
+ self.sound = options[:sound]
16
+ self.key = options[:key]
17
+ self.velocity = options[:velocity]
18
+ self.pitchbend = options[:pitchbend]
19
+ self.length = options[:length]
20
+ end
21
+
22
+ def to_s
23
+ PocketMiku::PacketFactory.pack(to_a)
24
+ end
25
+
26
+ def to_a
27
+ [0xF0, 0x43, 0x79, 0x09, 0x11, 0x0A, 0, sound, 0xF7,
28
+ 0x90, key, velocity]
29
+ end
30
+
31
+ def to_h
32
+ { sound: sound,
33
+ key: key,
34
+ velocity: velocity,
35
+ pitchbend: pitchbend,
36
+ length: length }
37
+ end
38
+
39
+ # ポケットミクに発音させる文字テーブル情報をセットする
40
+ # ==== Args
41
+ # [new] Integer|Symbol セットする文字テーブルの文字コード(Integer)か文字(Symbol)
42
+ # ==== Exceptions
43
+ # PocketMiku::CharMappingError
44
+ # newが文字テーブルに存在しない場合
45
+ # PocketMiku::InvalidByteError
46
+ # newが1byte(0..255)に収まらない数値である場合
47
+ # ==== Return
48
+ # 新しい sound の値。Symbolをセットしても必ず数値になる。
49
+ def sound=(new)
50
+ case new
51
+ when Fixnum
52
+ raise CharMappingError, "sound out of range 0..127" unless (0..127).include? new
53
+ @sound = new
54
+ when -> _ {CharTable.include? _}
55
+ @sound = CharTable[new]
56
+ else
57
+ raise CharMappingError, "unknown sound `#{new}'"
58
+ end
59
+ end
60
+
61
+ # ポケットミクに発音させる音程をセットする
62
+ # ==== Args
63
+ # [new] Integer 設定する音程(0-127)
64
+ # ==== Exceptions
65
+ # PocketMiku::ArgumentError
66
+ # new 0-127の範囲外
67
+ # ==== Return
68
+ # new
69
+ def key=(new)
70
+ raise ArgumentError, "key out of range 0..127" unless (0..127).include? new
71
+ @key = new
72
+ end
73
+
74
+ # ポケットミクに発音させるベロシティをセットする
75
+ # ==== Args
76
+ # [new] Integer 設定するベロシティ(0-127)
77
+ # ==== Exceptions
78
+ # PocketMiku::ArgumentError
79
+ # new 0-127の範囲外
80
+ # ==== Return
81
+ # new
82
+ def velocity=(new)
83
+ raise ArgumentError, "velocity out of range 0..127" unless (0..127).include? new
84
+ @velocity = new
85
+ end
86
+
87
+ # ポケットミクに発音させるピッチベンドをセットする
88
+ # ==== Args
89
+ # [new] Integer 設定するピッチベンド(-8192 - 8191)
90
+ # ==== Exceptions
91
+ # PocketMiku::ArgumentError
92
+ # new -8192 - 8191の範囲外
93
+ # ==== Return
94
+ # new
95
+ def pitchbend=(new)
96
+ raise ArgumentError, "pitchbend out of range -8192..8191" unless (-8192..8191).include? new
97
+ @pitchbend = new
98
+ end
99
+
100
+ # ポケットミクにこの音を発音する長さをセットする
101
+ # ==== Args
102
+ # [new] Integer 設定する長さ(1以上)
103
+ # ==== Exceptions
104
+ # PocketMiku::ArgumentError
105
+ # new -8192 - 8191の範囲外
106
+ # ==== Return
107
+ # new
108
+ def length=(new)
109
+ raise ArgumentError, "length must than 1" unless 1 <= new
110
+ @length = new
111
+ end
112
+ end
113
+
114
+ class RestNote < Note
115
+ def initialize(length)
116
+ super(sound:0, key:0, velocity:0, pitchbend:0, length: length)
117
+ end
118
+
119
+ def to_a
120
+ []
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,15 @@
1
+ module PocketMiku::PacketFactory
2
+ extend self
3
+ def pack(bytes)
4
+ bytes = [bytes] if bytes.is_a? Integer
5
+ bytes.each(&PocketMiku::PacketFactory.method(:byte_check))
6
+ bytes.pack "C*".freeze
7
+ end
8
+
9
+ def byte_check(byte, error_message="byte should 0...255 but give `%d'".freeze)
10
+ raise PocketMiku::InvalidByteError, "`#{byte}' is not integer." unless byte.is_a? Integer
11
+ raise PocketMiku::InvalidByteError, error_message % byte unless (0..0xFF).include?(byte)
12
+ byte
13
+ end
14
+
15
+ end
@@ -0,0 +1,96 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module PocketMiku
4
+ class Score < PocketMiku::Base
5
+ include Enumerable
6
+
7
+ attr_reader :default
8
+
9
+ def initialize
10
+ @default = PocketMiku::Note.new(sound: 0,
11
+ key: 60,
12
+ velocity: 100,
13
+ pitchbend: 0,
14
+ length: QuarterNote)
15
+ @playlist = []
16
+ @tempo = 120
17
+ if block_given?
18
+ record(&Proc.new)
19
+ end
20
+ end
21
+
22
+ alias record instance_eval
23
+
24
+ def to_a
25
+ @playlist.dup
26
+ end
27
+
28
+ def each
29
+ @playlist.each(&Proc.new)
30
+ end
31
+
32
+ # 再生速度を取得/設定する。テンポの値は、1分間に再生する四分音符の数
33
+ # ==== Args
34
+ # [new]
35
+ # - nil(指定なし) :: 現在のテンポを返す
36
+ # - Integer :: テンポをこの値に設定
37
+ # ==== Return
38
+ # 現在のテンポ
39
+ def tempo(new=nil)
40
+ case new
41
+ when nil
42
+ @tempo
43
+ when Integer
44
+ @tempo = new
45
+ else
46
+ raise ArgumentError, "new mush nil or Integer but give `#{new.class}'"
47
+ end
48
+ end
49
+
50
+ # PocketMiku::Note を末尾に追加する
51
+ # ==== Args
52
+ # [note] PocketMiku::Note
53
+ # ==== Return
54
+ # self
55
+ def add(note)
56
+ @playlist << note
57
+ self
58
+ end
59
+
60
+ # Note を作成して、再生キューの末尾に追加する
61
+ # ==== Args
62
+ # [sound] Symbol|Integer 発音する文字テーブルの文字(Symbol)か番号(Integer)
63
+ # [options] 以下のいずれか
64
+ # - Integer :: 音の高さ(key)
65
+ # - Hash :: PocketMiku::Noteの第一引数
66
+ # 設定されたなかった Note のオプションは、 default の値が使われる
67
+ # ==== Return
68
+ # self
69
+ def generate_note(sound, options=nil)
70
+ add case options
71
+ when NilClass
72
+ PocketMiku::Note.new default.to_h.merge sound: sound
73
+ when Integer
74
+ PocketMiku::Note.new default.to_h.merge sound: sound, key: options
75
+ when Hash, -> _ {_.respond_to? :to_h}
76
+ PocketMiku::Note.new default.to_h.merge(options).merge sound: sound
77
+ else
78
+ raise ArgumentError, "options must nil, Integer, or Hash. but given `#{options.class}'"
79
+ end
80
+ end
81
+
82
+ def っ(length)
83
+ add PocketMiku::RestNote.new(length)
84
+ end
85
+
86
+ def method_missing(method, *args)
87
+ case method
88
+ when -> _ {CharTable.include? _}
89
+ generate_note method, *args
90
+ else
91
+ super
92
+ end
93
+ end
94
+
95
+ end
96
+ end
@@ -1,5 +1,5 @@
1
- class PocketMiku
2
- VERSION = "0.0.2"
1
+ module PocketMiku
2
+ VERSION = "0.1.0"
3
3
  end
4
4
 
5
5
 
@@ -0,0 +1,34 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ describe PocketMiku::Device, "pocket miku" do
5
+ before do
6
+ @stream_body = String.new
7
+ @stream = StringIO.new(@stream_body, 'w')
8
+ @pocketmiku = PocketMiku::Device.new(@stream)
9
+ end
10
+
11
+ it "should send raw data" do
12
+ @pocketmiku.send [0, 128, 255]
13
+ expect(@stream_body.unpack('C*')).to eq([0, 128, 255])
14
+ end
15
+
16
+ it "should error send out of range raw data" do
17
+ expect { @pocketmiku.send [257] }.to raise_error(PocketMiku::InvalidByteError)
18
+ expect { @pocketmiku.send [-1] }.to raise_error(PocketMiku::InvalidByteError)
19
+ end
20
+
21
+ it "should play DSL Context" do
22
+ @pocketmiku.sing do
23
+ あ 60
24
+ end
25
+ expect(@stream_body.unpack('C*')).to eq([0xF0, 0x43, 0x79, 0x09, 0x11, 0x0A, 0, 0, 0xF7, 0x90, 60, 100, 0x80, 60, 0])
26
+ end
27
+
28
+ it "should raise IOError try to output after close" do
29
+ expect(@pocketmiku.closed?).to eq false
30
+ @pocketmiku.close
31
+ expect(@pocketmiku.closed?).to eq true
32
+ expect { @pocketmiku.sing { あ 60 } }.to raise_error IOError
33
+ end
34
+ end
data/spec/note_spec.rb ADDED
@@ -0,0 +1,86 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ describe PocketMiku::Note, "pocket miku note" do
5
+ before do
6
+ @note = PocketMiku::Note.new(sound: 0,
7
+ key: 0,
8
+ velocity: 0,
9
+ pitchbend: 0,
10
+ length: 1)
11
+ end
12
+
13
+ it "should set sound parameter" do
14
+ expect { @note.sound=-1 }.to raise_error(PocketMiku::CharMappingError)
15
+ expect { @note.sound=128 }.to raise_error(PocketMiku::CharMappingError)
16
+ expect { @note.sound=:亜 }.to raise_error(PocketMiku::CharMappingError)
17
+ expect { @note.sound=Object }.to raise_error(PocketMiku::CharMappingError)
18
+
19
+ @note.sound=0
20
+ expect(@note.sound).to eq 0
21
+
22
+ @note.sound=127
23
+ expect(@note.sound).to eq 127
24
+
25
+ @note.sound=:あ
26
+ expect(@note.sound).to eq 0
27
+ end
28
+
29
+ it "should set key parameter" do
30
+ expect { @note.key=-1 }.to raise_error(PocketMiku::ArgumentError)
31
+ expect { @note.key=128 }.to raise_error(PocketMiku::ArgumentError)
32
+ @note.key=0
33
+ expect(@note.key).to eq 0
34
+ @note.key=127
35
+ expect(@note.key).to eq 127
36
+ end
37
+
38
+ it "should set velocity parameter" do
39
+ expect { @note.velocity=-1 }.to raise_error(PocketMiku::ArgumentError)
40
+ expect { @note.velocity=128 }.to raise_error(PocketMiku::ArgumentError)
41
+ @note.velocity=0
42
+ expect(@note.velocity).to eq 0
43
+ @note.velocity=127
44
+ expect(@note.velocity).to eq 127
45
+ end
46
+
47
+ it "should set pitchbend parameter" do
48
+ expect { @note.pitchbend=-8193 }.to raise_error(PocketMiku::ArgumentError)
49
+ expect { @note.pitchbend=8192 }.to raise_error(PocketMiku::ArgumentError)
50
+ @note.pitchbend=-8192
51
+ expect(@note.pitchbend).to eq(-8192)
52
+ @note.pitchbend=8191
53
+ expect(@note.pitchbend).to eq 8191
54
+ end
55
+
56
+ it "should set length parameter" do
57
+ expect { @note.length=0 }.to raise_error(PocketMiku::ArgumentError)
58
+ @note.length=1
59
+ expect(@note.length).to eq 1
60
+ @note.length=9999
61
+ expect(@note.length).to eq 9999
62
+ end
63
+
64
+ it "should return sound packet" do
65
+ note = PocketMiku::Note.new(sound: 1,
66
+ key: 2,
67
+ velocity: 3,
68
+ pitchbend: 4,
69
+ length: 5)
70
+ expect(note.to_a).to eq([0xF0, 0x43, 0x79, 0x09, 0x11, 0x0A, 0, 1, 0xF7,
71
+ 0x90, 2, 3])
72
+ end
73
+
74
+ it "should write out to Hash" do
75
+ note = PocketMiku::Note.new(sound: 1,
76
+ key: 2,
77
+ velocity: 3,
78
+ pitchbend: 4,
79
+ length: 5)
80
+ expect(note.to_h).to eq(sound: 1,
81
+ key: 2,
82
+ velocity: 3,
83
+ pitchbend: 4,
84
+ length: 5)
85
+ end
86
+ end
@@ -0,0 +1,25 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ describe PocketMiku::PacketFactory, "pocket miku note" do
5
+ it "should pack array to string" do
6
+ result = PocketMiku::PacketFactory.pack([32])
7
+ expect(result.unpack('C*')).to eq [32]
8
+
9
+ result = PocketMiku::PacketFactory.pack(32)
10
+ expect(result.unpack('C*')).to eq [32]
11
+ end
12
+
13
+ it "should raise exception too big/small bytes" do
14
+ expect { PocketMiku::PacketFactory.pack([-1]) }.to raise_error(PocketMiku::InvalidByteError)
15
+ expect { PocketMiku::PacketFactory.pack([256]) }.to raise_error(PocketMiku::InvalidByteError)
16
+ PocketMiku::PacketFactory.pack([0])
17
+ PocketMiku::PacketFactory.pack([255])
18
+
19
+ expect { PocketMiku::PacketFactory.pack(-1) }.to raise_error(PocketMiku::InvalidByteError)
20
+ expect { PocketMiku::PacketFactory.pack(256) }.to raise_error(PocketMiku::InvalidByteError)
21
+ PocketMiku::PacketFactory.pack(0)
22
+ PocketMiku::PacketFactory.pack(255)
23
+ end
24
+
25
+ end
@@ -0,0 +1,40 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ describe PocketMiku::Score, "pocket miku score" do
5
+ before do
6
+ @score = PocketMiku::Score.new
7
+ end
8
+
9
+ it "should get/set default data" do
10
+ expect { @score.default.key = -1 }.to raise_error(PocketMiku::ArgumentError)
11
+ expect { @score.default.key = 128 }.to raise_error(PocketMiku::ArgumentError)
12
+ expect { @score.default.velocity = -1 }.to raise_error(PocketMiku::ArgumentError)
13
+ expect { @score.default.velocity = 128 }.to raise_error(PocketMiku::ArgumentError)
14
+ expect { @score.default.pitchbend = -8193 }.to raise_error(PocketMiku::ArgumentError)
15
+ expect { @score.default.pitchbend = 8192 }.to raise_error(PocketMiku::ArgumentError)
16
+ expect { @score.default.length = 0 }.to raise_error(PocketMiku::ArgumentError)
17
+
18
+ @score.default.key = 0
19
+ expect(@score.default.key).to eq 0
20
+ @score.default.key = 127
21
+ expect(@score.default.key).to eq 127
22
+ @score.default.velocity = 0
23
+ expect(@score.default.velocity).to eq 0
24
+ @score.default.velocity = 127
25
+ expect(@score.default.velocity).to eq 127
26
+ @score.default.pitchbend = -8192
27
+ expect(@score.default.pitchbend).to eq(-8192)
28
+ @score.default.pitchbend = 8191
29
+ expect(@score.default.pitchbend).to eq 8191
30
+ @score.default.length = 1
31
+ expect(@score.default.length).to eq 1
32
+ end
33
+
34
+ it "should can recording" do
35
+ @score.record do
36
+ あ 60
37
+ end
38
+ end
39
+
40
+ end
metadata CHANGED
@@ -1,62 +1,55 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pocket_miku
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
5
- prerelease:
4
+ version: 0.1.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Toshiaki Asai
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2014-04-04 00:00:00.000000000 Z
11
+ date: 2014-04-05 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: bundler
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ~>
17
+ - - "~>"
20
18
  - !ruby/object:Gem::Version
21
19
  version: '1.5'
22
20
  type: :development
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ~>
24
+ - - "~>"
28
25
  - !ruby/object:Gem::Version
29
26
  version: '1.5'
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: rake
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ! '>='
31
+ - - ">="
36
32
  - !ruby/object:Gem::Version
37
33
  version: '0'
38
34
  type: :development
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ! '>='
38
+ - - ">="
44
39
  - !ruby/object:Gem::Version
45
40
  version: '0'
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: rspec
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ! '>='
45
+ - - ">="
52
46
  - !ruby/object:Gem::Version
53
47
  version: '0'
54
48
  type: :development
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ! '>='
52
+ - - ">="
60
53
  - !ruby/object:Gem::Version
61
54
  version: '0'
62
55
  description: Rubyコードから「ポケットミク」を使ってミクを調教するためのライブラリです。
@@ -66,43 +59,54 @@ executables: []
66
59
  extensions: []
67
60
  extra_rdoc_files: []
68
61
  files:
69
- - .gitignore
62
+ - ".gitignore"
70
63
  - Gemfile
71
64
  - LICENSE.txt
72
65
  - README.md
73
66
  - Rakefile
74
67
  - lib/pocket_miku.rb
68
+ - lib/pocket_miku/base.rb
75
69
  - lib/pocket_miku/chartable.rb
70
+ - lib/pocket_miku/device.rb
76
71
  - lib/pocket_miku/exception.rb
72
+ - lib/pocket_miku/literal.rb
73
+ - lib/pocket_miku/note.rb
74
+ - lib/pocket_miku/packet_factory.rb
75
+ - lib/pocket_miku/score.rb
77
76
  - lib/pocket_miku/version.rb
78
77
  - pocket_miku.gemspec
79
- - spec/pocket_miku_spec.rb
78
+ - spec/device_spec.rb
79
+ - spec/note_spec.rb
80
+ - spec/packet_factory_spec.rb
81
+ - spec/score_spec.rb
80
82
  - spec/spec_helper.rb
81
83
  homepage: https://github.com/toshia/pocket_miku
82
84
  licenses:
83
85
  - MIT
86
+ metadata: {}
84
87
  post_install_message:
85
88
  rdoc_options: []
86
89
  require_paths:
87
90
  - lib
88
91
  required_ruby_version: !ruby/object:Gem::Requirement
89
- none: false
90
92
  requirements:
91
- - - ! '>='
93
+ - - ">="
92
94
  - !ruby/object:Gem::Version
93
95
  version: '0'
94
96
  required_rubygems_version: !ruby/object:Gem::Requirement
95
- none: false
96
97
  requirements:
97
- - - ! '>='
98
+ - - ">="
98
99
  - !ruby/object:Gem::Version
99
100
  version: '0'
100
101
  requirements: []
101
102
  rubyforge_project:
102
- rubygems_version: 1.8.23
103
+ rubygems_version: 2.2.2
103
104
  signing_key:
104
- specification_version: 3
105
+ specification_version: 4
105
106
  summary: Play voice via PocketMiku
106
107
  test_files:
107
- - spec/pocket_miku_spec.rb
108
+ - spec/device_spec.rb
109
+ - spec/note_spec.rb
110
+ - spec/packet_factory_spec.rb
111
+ - spec/score_spec.rb
108
112
  - spec/spec_helper.rb
@@ -1,66 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- require 'spec_helper'
3
-
4
- describe PocketMiku, "pocket miku" do
5
- before do
6
- @stream_body = String.new
7
- @stream = StringIO.new(@stream_body, 'w')
8
- @pocketmiku = PocketMiku.new(@stream)
9
- end
10
-
11
- it "should send raw data" do
12
- @pocketmiku.send [0, 128, 255]
13
- expect(@stream_body.unpack('C*')).to eq([0, 128, 255])
14
- end
15
-
16
- it "should error send out of range raw data" do
17
- expect { @pocketmiku.send [257] }.to raise_error(PocketMiku::InvalidByteError)
18
- expect { @pocketmiku.send [-1] }.to raise_error(PocketMiku::InvalidByteError)
19
- end
20
-
21
- it "should error set invalid data" do
22
- expect { @pocketmiku.set(key: -1) }.to raise_error(PocketMiku::InvalidByteError)
23
- expect { @pocketmiku.set(key: 257) }.to raise_error(PocketMiku::InvalidByteError)
24
- expect { @pocketmiku.set(velocity: -1) }.to raise_error(PocketMiku::InvalidByteError)
25
- expect { @pocketmiku.set(velocity: 257) }.to raise_error(PocketMiku::InvalidByteError)
26
- expect { @pocketmiku.set(sound: -1) }.to raise_error(PocketMiku::InvalidByteError)
27
- expect { @pocketmiku.set(sound: 257) }.to raise_error(PocketMiku::InvalidByteError)
28
- expect { @pocketmiku.set(sound: :亜) }.to raise_error(PocketMiku::CharMappingError)
29
- expect { @pocketmiku.set(sound: Object) }.to raise_error(PocketMiku::CharMappingError)
30
- end
31
-
32
- it "should error set invalid sound" do
33
- expect { @pocketmiku.sound = -1 }.to raise_error(PocketMiku::InvalidByteError)
34
- expect { @pocketmiku.sound = 257 }.to raise_error(PocketMiku::InvalidByteError)
35
- expect { @pocketmiku.sound = :亜 }.to raise_error(PocketMiku::CharMappingError)
36
- expect { @pocketmiku.sound = Object }.to raise_error(PocketMiku::CharMappingError)
37
- end
38
-
39
- it "should play current data" do
40
- @pocketmiku.set(key: 100, velocity: 101, sound: 102)
41
- expect(@stream_body.unpack('C*')).to eq []
42
- @pocketmiku.play
43
- expect(@stream_body.unpack('C*')).to eq [0xF0, 0x43, 0x79, 0x09, 0x11, 0x0A, 0, 102, 0xF7, 0x90, 100, 101]
44
- @stream_body.clear
45
- @stream.seek 0
46
- @pocketmiku.stop
47
- expect(@stream_body.unpack('C*')).to eq [0x80, 100, 0]
48
- end
49
-
50
- it "should play DSL Context" do
51
- @pocketmiku.sing {あ(60, 100) }
52
- expect(@stream_body.unpack('C*')).to eq([0xF0, 0x43, 0x79, 0x09, 0x11, 0x0A, 0, 0, 0xF7, 0x90, 60, 100])
53
- end
54
-
55
- it "should raise InvalidByteError try to play that not yet set sound" do
56
- expect { @pocketmiku.play }.to raise_error PocketMiku::InvalidByteError
57
- end
58
-
59
- it "should raise IOError try to output after close" do
60
- @pocketmiku.set(key: 100, velocity: 101, sound: 102)
61
- expect(@pocketmiku.closed?).to eq false
62
- @pocketmiku.close
63
- expect(@pocketmiku.closed?).to eq true
64
- expect { @pocketmiku.play }.to raise_error IOError
65
- end
66
- end