pocket_miku 0.0.1

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: f408dc3c40f6552c6a5357168c4fdbc2293122df
4
+ data.tar.gz: 9c032fb8a87f28f706193f2aee927ea9cd8a23d1
5
+ SHA512:
6
+ metadata.gz: 39868af70e679c47bc9bd89aa22ac10712bb93a80553252249ae41ab889edc12ea58f086315b6073983eec4becec603097949bbb41bb2b9fd0c3e769b839c9fb
7
+ data.tar.gz: 8160fcd9b11cd5f25c329807d81c89e1df46c94bd9af4ca5bca015bc412c0e88d5a9920a308315306b0ad9cbcd8cd12e42ee2581e3e4c3c53a269cc501a0c106
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in pocket_miku.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Toshiaki Asai
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,50 @@
1
+ # PocketMiku
2
+
3
+ 『ポケット・ミク』(http://www.otonanokagaku.net/nsx39/index.html) を使用して、Rubyから初音ミクちゃんを調教しちゃうライブラリです。
4
+ Arch Linuxで作成・確認しています。思ってたのとは違う方向性ですが、ついにLinuxネイティブでミクを調教できる日が来ました(?)。嬉しい限りです。
5
+
6
+ いやー!自分のRubyコードで歌ってくれるミクちゃんは一味違いますねぇ。
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ gem 'pocket_miku'
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install pocket_miku
21
+
22
+ ## Usage
23
+
24
+ 『ポケット・ミク』をUSBケーブルで接続してUSBモードで起動すると、 /dev/ 以下にmidiなんとかというデバイスファイルが出てくると思います。
25
+ 開発環境では /dev/midi2 だったので、これをPocketMikuの引数に渡します。
26
+
27
+ `
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
+ end
35
+ `
36
+
37
+ 「ふぁ」「ぼ」等はメソッドで、この音を発音します。引数は「あ(音程, 強さ)」です。全ての発音は、ポケット・ミク付属の『ユーザーズマニュアル』の裏に掲載されている『ポケット・ミク デフォルト文字テーブル』に書いてある文字が全て使用できます。
38
+ なお、「ん」は「N\」のエイリアスです。ほかの「ん」を使用する時は、同備考欄の文字(ダブルクォートは不要)を指定してください。
39
+
40
+ ## そのうち
41
+
42
+ - 音の同期をsleepとかじゃなくてもっといい感じにしたい
43
+
44
+ ## Contributing
45
+
46
+ 1. Fork it ( http://github.com/toshia/pocket_miku/fork )
47
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
48
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
49
+ 4. Push to the branch (`git push origin my-new-feature`)
50
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,142 @@
1
+ # -*- coding: utf-8 -*-
2
+ class PocketMiku
3
+ CharTable = {
4
+ あ: 0,
5
+ い: 1,
6
+ う: 2,
7
+ え: 3,
8
+ お: 4,
9
+ か: 5,
10
+ き: 6,
11
+ く: 7,
12
+ け: 8,
13
+ こ: 9,
14
+ が: 10,
15
+ ぎ: 11,
16
+ ぐ: 12,
17
+ げ: 13,
18
+ ご: 14,
19
+ きゃ: 15,
20
+ きゅ: 16,
21
+ きょ: 17,
22
+ ぎゃ: 18,
23
+ ぎゅ: 19,
24
+ ぎょ: 20,
25
+ さ: 21,
26
+ すぃ: 22,
27
+ す: 23,
28
+ せ: 24,
29
+ そ: 25,
30
+ ざ: 26,
31
+ ずぃ: 27,
32
+ ず: 28,
33
+ ぜ: 29,
34
+ ぞ: 30,
35
+ しゃ: 31,
36
+ し: 32,
37
+ しゅ: 33,
38
+ しぇ: 34,
39
+ しょ: 35,
40
+ じゃ: 36,
41
+ じ: 37,
42
+ じゅ: 38,
43
+ じぇ: 39,
44
+ じょ: 40,
45
+ た: 41,
46
+ てぃ: 42,
47
+ とぅ: 43,
48
+ て: 44,
49
+ とぅ: 45,
50
+ だ: 46,
51
+ でぃ: 47,
52
+ どぅ: 48,
53
+ で: 49,
54
+ ど: 50,
55
+ てゅ: 51,
56
+ でゅ: 52,
57
+ ちゃ: 53,
58
+ ち: 54,
59
+ ちゅ: 55,
60
+ ちぇ: 56,
61
+ ちょ: 57,
62
+ つぁ: 58,
63
+ つぃ: 59,
64
+ つ: 60,
65
+ つぇ: 61,
66
+ つぉ: 62,
67
+ な: 63,
68
+ に: 64,
69
+ ぬ: 65,
70
+ ね: 66,
71
+ の: 67,
72
+ にゃ: 68,
73
+ にゅ: 69,
74
+ にょ: 70,
75
+ は: 71,
76
+ ひ: 72,
77
+ ふ: 73,
78
+ へ: 74,
79
+ ほ: 75,
80
+ ば: 76,
81
+ び: 77,
82
+ ぶ: 78,
83
+ べ: 79,
84
+ ぼ: 80,
85
+ ぱ: 81,
86
+ ぴ: 82,
87
+ ぷ: 83,
88
+ ぺ: 84,
89
+ ぽ: 85,
90
+ ひゃ: 86,
91
+ ひゅ: 87,
92
+ ひょ: 88,
93
+ びゃ: 89,
94
+ びゅ: 90,
95
+ びょ: 91,
96
+ ぴゃ: 92,
97
+ ぴゅ: 93,
98
+ ぴょ: 94,
99
+ ふぁ: 95,
100
+ ふぃ: 96,
101
+ ふゅ: 97,
102
+ ふぇ: 98,
103
+ ふぉ: 99,
104
+ ま: 100,
105
+ み: 101,
106
+ む: 102,
107
+ め: 103,
108
+ も: 104,
109
+ みゃ: 105,
110
+ みゅ: 106,
111
+ みょ: 107,
112
+ や: 108,
113
+ ゆ: 109,
114
+ よ: 110,
115
+ ら: 111,
116
+ り: 112,
117
+ る: 113,
118
+ れ: 114,
119
+ ろ: 115,
120
+ りゃ: 116,
121
+ りゅ: 117,
122
+ りょ: 118,
123
+ わ: 119,
124
+ うぃ: 120,
125
+ うぇ: 121,
126
+ うぉ: 122,
127
+ ん: 123,
128
+ :"N\\" => 123,
129
+ m: 124,
130
+ N: 125,
131
+ J: 126,
132
+ n: 127,
133
+ づぁ: 26,
134
+ ずぃ: 27,
135
+ づ: 28,
136
+ づぇ: 29,
137
+ づぉ: 30,
138
+ ゐ: 120,
139
+ ゑ: 121,
140
+ を: 122
141
+ }.freeze
142
+ end
@@ -0,0 +1,14 @@
1
+ # -*- coding: utf-8 -*-
2
+ class PocketMiku
3
+ # PocketMikuが定義する例外の基底クラス
4
+ class Exception < ::RuntimeError; end
5
+
6
+ # 送信するバイト列に不正な値があった
7
+ class InvalidByteError < Exception; end
8
+
9
+ # パラメータが不正
10
+ class ArgumentError < Exception; end
11
+
12
+ # 文字テーブルに存在しない文字を指定した
13
+ class CharMappingError < ArgumentError; end
14
+ end
@@ -0,0 +1,11 @@
1
+ class PocketMiku
2
+ VERSION = "0.0.1"
3
+ end
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
@@ -0,0 +1,141 @@
1
+ # -*- coding: utf-8 -*-
2
+ require "pocket_miku/version"
3
+ require "pocket_miku/chartable"
4
+ require "pocket_miku/exception"
5
+ require 'stringio'
6
+
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
37
+
38
+ # ポケットミクに直接MIDIパケットを送る
39
+ # ==== 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
51
+ end
52
+
53
+ # ポケットミクに発音させる情報をセットする
54
+ # ==== Args
55
+ # [key] Integer 音程
56
+ # [velocity] Integer 音の強さ
57
+ # [sound] Integer|Symbol 文字テーブルの文字コード(Integer)か文字(Symbol)
58
+ # ==== Return
59
+ # self
60
+ def set(key: nil, velocity: nil, sound: nil)
61
+ @key = byte_check(key, "invalid key `%d'".freeze) if key
62
+ @velocity = byte_check(velocity, "invalid velocity `%d'".freeze) if velocity
63
+ self.sound = sound if 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
+ end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'pocket_miku/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "pocket_miku"
8
+ spec.version = PocketMiku::VERSION
9
+ spec.authors = ["Toshiaki Asai"]
10
+ spec.email = ["toshi.alternative@gmail.com"]
11
+ spec.summary = %q{Play voice via PocketMiku}
12
+ spec.description = %q{Rubyコードから「ポケットミク」を使ってミクを調教するためのライブラリです。}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.5"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+
25
+ end
@@ -0,0 +1,66 @@
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
@@ -0,0 +1,9 @@
1
+ require 'bundler/setup'
2
+ Bundler.setup
3
+
4
+ require 'pocket_miku' # and any other gems you need
5
+
6
+ RSpec.configure do |config|
7
+ # some (optional) config here
8
+ end
9
+
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pocket_miku
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Toshiaki Asai
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-04-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Rubyコードから「ポケットミク」を使ってミクを調教するためのライブラリです。
56
+ email:
57
+ - toshi.alternative@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - Gemfile
64
+ - LICENSE.txt
65
+ - README.md
66
+ - Rakefile
67
+ - lib/pocket_miku.rb
68
+ - lib/pocket_miku/chartable.rb
69
+ - lib/pocket_miku/exception.rb
70
+ - lib/pocket_miku/version.rb
71
+ - pocket_miku.gemspec
72
+ - spec/pocket_miku_spec.rb
73
+ - spec/spec_helper.rb
74
+ homepage: ''
75
+ licenses:
76
+ - MIT
77
+ metadata: {}
78
+ post_install_message:
79
+ rdoc_options: []
80
+ require_paths:
81
+ - lib
82
+ required_ruby_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ requirements: []
93
+ rubyforge_project:
94
+ rubygems_version: 2.2.2
95
+ signing_key:
96
+ specification_version: 4
97
+ summary: Play voice via PocketMiku
98
+ test_files:
99
+ - spec/pocket_miku_spec.rb
100
+ - spec/spec_helper.rb