pocket_miku 0.0.2 → 0.1.0

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 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