続・Max7日記 (2)

長嶋 洋一


→ Max7日記

→ 続・Max7日記(1)

→ 続・Max7日記(3)

→ 続・Max7日記(4)

→ 続・Max7日記(5)

→ 続・Max7日記(6)

→ 続・Max7日記(7)

→ 続・Max7日記(8)

2017年9月8日(金)

世界的に 太陽フレア の影響が心配されている1日が始まった。 昨日は新インターフェース「PAW-eight」が完成するところまで進んだが、予定のない週末に向かうこの日はいまいちテンションが上がらず、ネットで届いた「中国語の初音ミク」という情報を見て、とりあえずゼミのブンちゃんに「初音ミクの中国語版が出たそうです。以下の中国語のクオリティの感想をお知らせ下さい」 とメイルしたりしてスタートした。

そして2ちゃんのスレに「全巻揃えたい漫画」などというソソラレルものを発見し、眺めてみると「こち亀」・「ベルセルク」・「ガラスの仮面」・「うしおととら」・「かってにシロくま」・「小さな恋の物語」・「パタリロ」・「変態仮面」・「ヨコハマ買い出し紀行」・「孤独のグルメ」・「ワンピース」・「ハンターハンター」・「百鬼夜行抄」・「トイレット博士」・「あさりちゃん」・「野望の王国」・「はだしのゲン」・「いけない!ルナ先生」・「海人ゴンズイ」・「ドラゴンボール」・「背表紙のヤジロベー」・「ワイルド7」・「横山 三国志」・「風の谷のナウシカ」・「六三四の剣」・「石森章太郎全集」・「うる星やつら」・「めぞん一刻」・「エリア88」・「沈黙の艦隊」・「悪女」・「パタリロ」・「るろうに剣心」・「キャプテン翼」・「サーフサイド ハイスクール」・「さくらの唄」・「静かなるドン」・「パタリロ」・「ふりそで剣士」・「巨人獣」・「パットマンX」・「センゴク」・「殺し屋1」・「ホムンクルス」などと出ていて、3人から重複した「パタリロ」が目立っていた。 実は「大人買いサイト」で「横山 三国志」全60巻を衝動買いしたことがあったが、今回はパタリロから魔夜峰央に反応してしまった。

伝説の「黒のもんもん組」が、なんと「完全版」全4巻として出ている、と知って、迷わずamazonに行き、上のように一気に注文してしまった。 いずれも中古であるが、同じコミックスなのに巻数によって価格に大きなばらつきがあり、高いものは安いものの15倍だった(^_^;)。 まぁ、これは誤差ということで。 パタリロのエッセンスが圧縮された、久しぶりの魔夜峰央が楽しみである。

そして午後まであれこれ調べ物をしていると、ブンちゃんからメイルが届いた。 「音調が違う」のだという。 「音調」というのは調べたところでは「声調(四声)」(高低アクセント)のことのようである。 それを加味して書き直すと、届いたメイルは以下のような感じとなった。 「中国語で歌っている初音ミクは違和感が半端ないです。単に日本語の音を高くしたような感じがします。日本語は声調が少ないから初音ミクが可愛いのだと思います。中国語は声調(高低アクセント)の種類が多い(4種類ある)のです。そこで、この中国語版の初音ミクは可愛くないです」 なるほど、まだまだである(^_^;)。

2017年9月9日(土)

メキシコでM8.2の地震が起こったり、昨日の太陽フレアはさして問題を起こさなかったり、建国記念日の某隣国が今日はまた何かする・・・とキナ臭い週末である。 産経新聞による以下の図は、どう考えても「日本〜北朝鮮」・「日本〜中国」の関係を敢えて何も描かない、という作為に満ちた意図がミエミエの不備なものであり、こういうところからマスコミは世間から見放されていってるのだ、とよく分かった。

昨日の午後にネットの某所で呟いたのがきっかけで、今日は昼前から一旦帰宅して午後に某突発オフで歌えることになり、朝からテンションが高いのだが、Maxプログラミングについては来週までお預けである。 大きな構想としては2つのターゲットを見据えているので、来週はあれこれの予定の中で進めていこう。

2017年9月11日(月)

土曜日の午後には3時間+3時間に歌仲間と二人で38曲ずつ走破して生き返り、日曜はその余韻とともに休息した。 そして新しい週の月曜日である。 いよいよ新学期を前に、今日と明日は領域選択に関わる面接があったり、OG野口さんがまた個展のために「はやくスシになりたい」を借りに来たり、某打合せで京都日帰りしたり、教授会があったり、前期末卒業式があったり、週末のBF勉強会の準備があったり・・・と目白押しの週である。

そして今日はセプテンバーイレブンである。 確か去年のセプテンバーイレブンは 欧露ツアー2016 で、ICMC2016のためにオランダのユトレヒトに着いて、上のように鉄道博物館を散歩していた。 2001年9月11日のニューヨーク・ワールドトレードセンターへの航空機突入のあったこの日は、その後、アルカイーダが消滅するまでは毎年、警戒レベルが上がっていたが、ISに変わっただけで世界情勢はまったく好転していない。 これまで、ニューヨークに行った 2003年2007年 には、ともに以下の「グラウンド・ゼロ」に行ったが、今後もNYに行ったらまずは訪れたい。 沖縄に学生と行く時には必ず「ひめゆりの塔」に行くのと同じである。

考えてみれば、このセプテンバーイレブンのあった2001年には、そのテロの翌週に日本を出発する、というパリ/カッセル/ハンブルクの欧州ツアー2001 に行っていたのだった。 そこでせっかくの機会なので、この2001年から去年2016年までのセプテンバーイレブンに何をしていたか、探せる範囲で探してみることにした。 僕は常に予定を Web に上げているが、これは自分用の備忘録とアポを入れる学生のためのものなので、「過ぎたら消す」ルールのために、ここには何の記録も残っていない。 研究室ページ がかろうじて時系列なので、そこから関連情報を拾っていくしかない。 2001年9月11日については何も出てこなかったが、まぁ欧州ツアー2001の準備に忙殺されていたのだろう。

2002年9月11日についても何も記録は出てこなかった。 この年の8月は このように 1日も休まず頑張って、その後、9月下旬に上の「初めての座間味島」のように 4回目の沖縄 に行っていたようなので、9月11日あたりはその準備などをしていたのだろう。

2003年9月11日には、前日から上のポケモンジェットに乗って札幌に飛び、札幌学院大での FIT2003に発表参加 していたようである。

2004年には、7月下旬から9月下旬まで、パリを中心に58日間の海外出張( Sabbatical2004 )に行っていた。 途中でパリを離れてアムステルダムのSTEIMに1週間、続いてリンツのアルスエレクトロニカに1週間行って、2004年9月11日にはパリに戻ってきて、スタジオ"la kitchen"の地下に確保した部屋で上のように滞在研究をしていた。 写真は、翌週にパリで行ったレクチャーでのパフォーマンスのための作曲中のようである。

2005年には上のように、8/30から9/13まで、採択された「未踏」の出張 EUtour2005 ということで、リンツとバルセロナに行っていた。 2005年9月11日には、ホテルでの未踏Maxプログラミングもそこそこに、バルセロナ観光やフラメンコのライブを堪能していたようである。

2006年の夏休みには、 第23期「虎の穴」 の3人の新入生が1106研究室に3週間近く通いつめて、それぞれストップモーション・アニメーション作品の制作に挑戦していた。 2006年9月11日には上のように このように 作業も終盤となって、それぞれ映像作品としての編集作業をしていたようである。

2007年には8月末から9月上旬に、 ICMC2007/ArsElectronica2007 という出張に行き、コペンハーゲンとリンツ/ウイーンの合間の日程でロンドンにも行っていた。 2007年9月11日はほぼ帰国日だったようで、成田→セントレアのフライトがボンバルディアのプロペラ機だったので、上のように上空からSUACがきっちりと見えた。

2008年の9月にはゼミの学生と、上のように ゼミ有志合宿「飛騨高山」 に行っていた。 2008年9月11日は最終日で、朝市に行ったり、「獅子会館(からくり会館)」に行ったりしていた。

2009年の9月にはICEC2009参加とリンツのアルスエレクトロニカとウイーンに、 このように 学生2人と行った。 上のようにルーブルでは定位置に戻ってきた彼女と再会した。 2009年9月11日に何をしていたかは記録からはちょっと曖昧だが(^_^;)、ほぼ帰国に向けて最終盤だったようである。

2010年の9月には、またまた 5度目のリンツ としてアルスエレクトロニカに行って帰ってきた直後、2010年9月11日には メディア造形学科会議合宿 として「つま恋」に行っていたようである。 上は幻となってしまった吉田拓郎の企画展示コーナーである。

2011年の9月には、 6度目のリンツ としてアルスエレクトロニカに行って帰ってきて、翌週には 札幌から神戸へ という学会ハシゴ出張をしている合間であり、2011年9月11日には、 ジャミーズ娘。 (「第35期・虎の穴」)の学生たちと、上のように1106で鋭意、 ジャミネータを改造 していた。

2012年の9月は このように アルスエレクトロニカ視察とICMC2012発表のために、オーストリア(リンツ・ウイーン)と、 初めてとなるスロベニアのリュブリャナに行った。 同行した院生2人はウイーンで別れて帰国したが、その後、列車でスロベニアのリュブリャナに行き、さらに勢いでクロアチアのリエカまで日帰り越境ショートトリップした。 2012年9月11日には、リュブリャナのICMC2012で発表して、そのまま帰国の途についたところだった。

2013年の9月には、上のレトロゲームも並んでいたアルスエレクトロニカとウイーンの EUツアー2013 から帰国した翌々日、2013年9月11日は友人の中村文隆氏(東大)の 「Raspberry Pi本」 が出た(届いた)ようである。

2014年の9月は、上のような立派なビーチリゾートホテルでの 欧州ツアー2014 - 初のブルガリアと9回目のリンツ に行っていて、2014年9月11日にはちょうど国際会議で発表した日である。 リンツで持参したMacBookAirが死亡し(帰国後に復活)、ウイーンのApple Storeで購入したiPad miniで残り1週間を凌いだ、という苦い思い出がある。

2015年の9月には、上の筒井康隆の新作を1日で読んだ、という記録が2015年9月9日にあるだけで、2015年9月11日については不明である。 直後に 松山への出張(FIT2015)札幌への出張(EC2015) を控えていたので、その準備に追われていたのだろう。 そして2016年は冒頭の「欧露ツアー2016」(37日間6カ国7都市)、 Sabbatical 2016 に繋がるのである。

過去にWebに上げてある情報だけで新規の写真すら1枚もないが、リンクを整理して「これまでの9月11日」という16年間の記録を整理してみると、午前中から昼過ぎまでかかってしまった(^_^;)。 けっこう毎年、9月はあちこち行っているので、今年は格別に、なかなか落ち着いたものである。 ただし今朝は、研究室に出てみると、なんと以下のようなメイルが届いていた。

Yoichiさま、 毎年いい意味で唖然とさせられます

あまり時間がありません。

過去、あなたは膨大な数の利用者が使うウィキペディアを存続させるためにを寄付されました。

今週、あなたのご協力が必要です。前回と同じように寄付してくださいませんか。

私たちの小さなチームには、皆さまに何ヶ月間も寄付をお願いし続けるだけの体力がありません。そもそも、それは私たちの方針でもありません。
でも、ウィキペディアを健全に保つためにあなたのような寄付者がどれほど大切であるかをぜひ知っていてほしいと思います。

私たちは非営利組織です。寄付してくださるのは全読者の1%未満ですが、集まった寄付金で毎月何億人もの読者を支えています。もし、すべての
読者が寄付してくださったとしたら、どうでしょうか。インターネット上の知識の共有のされ方そのものを変革できるかもしれません。

寄付者の皆さまからの反響には、毎年良い意味で唖然とさせられます。でも、まだ目指す寄付金額にたどり着けていません。また、活動できる時間も
あまり残されていません。私たちは販売員ではありません。私たちは図書館員であり、情報の保管人であり、また情報中毒者でもあります。読者の
皆さまに寄付していただくことで、この15年間運営し続けることができました。

今年もまたウィキペディアを守り維持していくために、再度の寄付をご検討ください。

この1年間でウィキペディアを使った人全員が寄付してくだされば、今後数年間募金活動を行う必要はなくなるでしょう。私たちは、素晴らしい行いを
決意してくださった寄付者の皆さまのご支援によって維持されています。

よろしくお願いいたします。
ジミー・ウェールズ
ウィキペディア創設者

なんということか、先週ちゃんと寄付したというのに(^_^;)。 ネットで「Wikipediaクレクレ詐欺」と揶揄される、善意の寄付者に延々と物乞いメイルが届くという、これがソレなのか。 さすがに先週の今週ではもう嫌なので、「今後、Wikimedia Foundationからのメールを受け取りたくない場合は、今すぐ配信を停止するをクリックしてください」というのをクリックしてアドレスを送った。

そして午後には、今年もデザイン学科で我々の「ビジュアルサウンド領域」だけ定員を超過して、領域選択面談という、いわば「専攻選抜面接試験」という、学生にとっても教員にとってもあまり気持ちのいいものでもない「儀式」に臨んだ。 過去の3学科(生産造形・メディア造形・空間造形)時代には、入試でその学科に入ってしまえば、卒業までその専門でいる事が約束されていたが、1学科に合体して5領域の体制となった去年からは、領域定員を超えているビジュアルサウンド領域ではこのような試練が待ち受けることとなった。 新しいシステムにはメリットもデメリットもあるが、これは淡々と進めていくしかない「お仕事」なのだ。

その後、夕方に的場先生が研究室に来訪して、今年の後期の「インタラクション・プロダクト演習」についての打合せをした。 去年は非常勤の久世先生が「Arduino+タッチセンサ」をPureDataでやったが、今年から来ないので、僕が上のように 「TouchMIDI32+Max7」 として行うことにした。 Arduinoは別途に、アナログ値(連続量)として「Arduino2Max」でやればいい。 久しぶりに的場先生の前でやってみたが、繋いだら1分ほどで音が出たので、これなら簡単である。

2017年9月12日(火)

昨日の夕方には、OG野口さんが研究室にやってきて、また「はやくスシになりたい」のインスタとパソコンを貸し出した。 以下のようなイベントで展示するのだという。 今年は東京ビッグサイトでのイベントでも2度、展示しているというし、さすがである。

そして事務局に野口さん出展のチラシを持っていくと、メイルボックスに何やら郵便物が3つ、届いていた。 注文していたアレだろう・・・と開けてみると、なんと このように 1つは見知らぬ「講談社」の封筒で送られてきた本で、注文した4冊はまだ揃わず、3冊までだった。 献本として送られてきたのは「ArduinoとProcessing」というもので、どうも工学部の入門用という想定で、「教科書として検討ください」ということで、こういうのはたまに届く。 しかしザッと眺めてみると、どうも食い足りないというか魅力に乏しい本で、「講談社だとこうなるのか・・・」というサンプルとしてとても教訓溢れる本だった。

その後、午前から午後にかけて、明日の某ミーティングのための資料を集中して書き上げると、フトたまたま、 【前面展望】JR北海道 特急サロベツ(札幌-稚内) という、5時間55分19秒もある巨大なHD動画と出会ってしまった。 さすがに途中はパスして、先月末に行ったばかりの ゴールの稚内 を思い出そう・・・と最後のあたりにカーソルを移動させると、なんと特急が急停止して、車掌が「緊急停止したのは線路に鹿が入ったためですが衝突は避けられました」などという凄い瞬間(5時間41分35秒から) に遭遇してしまった(^_^;)。 その後、南稚内、そして終点の稚内、と懐かしい風景を堪能した。

その後、2日目に残っていた領域面談まで終えて、あとはいつもの医者(常用薬の処方箋のため)に行くために早めに終了となった。 こういうスローペースの夏休みも、意外と悪くないかも。

2017年9月14日(木)

昨日は某ミーティングのために「ひかり」で浜松〜京都を往復して、今後1年半の作戦が立った。 そして土曜日のBF勉強会のために発送する機材を梱包して発送手配したり、初めて向かう奈良学園大への行き方などを調べて辻下先生と照岡さんにメイルしたり、準備を進めた。 以下のように台風18号がやってくるので、翌日に照岡さんと予定していた「大阪・日本橋の散策」はなくなりそうな可能性がある。

そして、朝から約10本ほどのメイルが届いていたのだが、これはSketchingコミュニティのメンバー同士のものだった。 発端は以下のように、壁に導体を貼って実現したという、なかなかファンタスティックな プロジェクト である。 一定期間の展示であればいいのだが、どうもこれを住宅メーカが永続的なものとしたい、という話になったそうで、「こういう導体の経年変化・劣化とその対策についての情報を求む」というものだった。

ここに、Sketchingの猛者たちが、あれこれと情報提供・コメントを重ねてきたのである。 ある人は ビニールカッターの活用 などという、参考になって面白い情報を提供してくれた。 そしてここに、以下のような トンデモナイ作品 を今年のアルスエレクトロニカにも出した、というメンバーの情報が絡んできた。 ここでの電極についてコメントしたのだが、もう作品に引き込まれてそっちはどうでもいい感じである。

この作品はどうやら、体験者が腕を差し込むと電極に挟まれて、この電極からの電気信号で強制的に筋肉が痙攣してクランクを回して発電させられる(^_^;)、というものらしい。 さらには、向かい合った反対側の人の発電によって、こっち側の人の挟んだ電極が離れて解放される(最後の人は帰れない)、ということのようで、まさにアート、そして現代文明の「テクノロジーに翻弄される人類」というアイロニーが強烈である。

YouTube

そしてここから、フト昨夜(今朝の早朝)に思いついたアイデアを実験してみることにした。 発端は上のように、友人の長谷部さんが「奇楽堂」ブランドで公開している、TouchMIDI32である。 これはUSBを挿すだけで、Mac OSXはシステムとして「MIDIデバイス」と即刻、認識するのだが、これは今まではやった事がなかったので、調べてみたいと思いついたのだ。 さっそくスイッチサイエンスのTouchMIDI32から GitHub に行って ファームウェアのソース を落としてみると、どうやら「USBMIDI.h」というあたりが関係しそうだ、と見えてきた。 TouchMIDI32はマイコンが「PSoC4」なのでそのまま使う必要はなく、こうなればArduinoだ、ということで検索すると、 MIDIUSB library とか MIDI Device などに行き着き、 GitHub に行って ライブラリとサンプル をゲットすることが出来た(^_^)。 こうなれば実験してみるしかない。

長谷部さんのGitHubは色々なバージョンとかで大きかったが、Arduinoのものは上のようにとてもシンプルであり、何よりexamplesがいくつもあるので、まずはこいつらを試す・・・という一本道である。 Arduinoのサンプルは5本あったが、もっともシンプルには「ノートオン」→「500msec」→「ノートオフ」→「1500msec」というのを繰り返すという「MIDIUSB_write」がいいだろう、と手元のArduino Microを繋いでみたところ、 同じディレクトリに「src」ディレクトリから「MIDIUSB.h」・「MIDIUSB.cpp」という2本をコピー しておけばコンパイルのエラーが無くなり、Arduinoに転送してみると、その瞬間に以下のようにシステムのMIDIドライバに「Arduino Micro」という名前のMIDIデバイスが出現して、Max7から見てみるとちゃんとMIDIデバイスのリストに登場して、実際にmidiinでデータが届いていた(^_^)。 Arduinoのシリアル速度は115200であり31250ではない、というのもポイントである。

ものの30分もかからずに、なんと早朝に思いついた実験がうまく行ってしまった。 基幹部分のArduinoソースは以下のように超シンプルなのに。 こういう日もあるが、これは実は「大いなる収穫」である。 さっそく、後期の講義の中では、「TouchMIDI32」・「Arduino2Max」に並んで、この115200の「ArduinoをMIDIデバイスにする」という技を伝授していこう。 こんな素晴らしいライブラリとサンプルが普通にころがっているというのは、またまたオープンソースの凄さを実感してしまった。

#include "MIDIUSB.h"

void noteOn(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOn);
}

void noteOff(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOff);
}

void setup() {
  Serial.begin(115200);
}

void loop() {
  noteOn(0, 48, 64);
  MidiUSB.flush();
  delay(500);
  noteOff(0, 48, 64);
  MidiUSB.flush();
  delay(1500);
}
そして、これがArduino UNOでも使えるかを試したところ、どうもArduinoボードの性能を見るようで、ダメだった。 さらに「MIDIUSB.cpp」を眺めていると、以下のような記述を発見した。 これはつまり、「ちゃんとFIFOバッファでやっている」という事であり、割り込みではないので不完全ではあるものの、Arduino Microなど高性能のArduinoであれば、これまで僕が「ArduinoはMIDI受信で使えない」と断定していた事を撤回する可能性がある、と気付いた。
struct ring_bufferMIDI
{
	midiEventPacket_t midiEvent[MIDI_BUFFER_SIZE];
	volatile uint32_t head;
	volatile uint32_t tail;
};

ring_bufferMIDI midi_rx_buffer = {{0,0,0,0 }, 0, 0};
そこで、もう一つのサンプルとして、コメントを消して根幹部分だけを残せば以下のような「MIDIUSB_loop」というArduinoサンプルをそのままコンパイルして上書きしてから、以下のように、Max7から毎秒100回(10msec)のランダムノートを出し、さらに同時に最大7和音という、理論上はほぼ「MIDIギッシリ」という「いじわるトラフィックMIDI」を送ってループバックして受けてみて、過去の実験にように「ArduinoがMIDI受信をとりこぼす」かどうかを実験してみた。
#include "MIDIUSB.h"

void noteOn(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOn);
}

void noteOff(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOff);
}

void setup() {
  Serial.begin(115200);
  pinMode(LED_BUILTIN, OUTPUT);
}

void controlChange(byte channel, byte control, byte value) {
  midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
  MidiUSB.sendMIDI(event);
}

void loop() {
  //MidiUSB.accept();
  //delayMicroseconds(1);
  midiEventPacket_t rx;
  do {
    rx = MidiUSB.read();
    if (rx.header != 0) {
      //send back the received MIDI command
      MidiUSB.sendMIDI(rx);
      MidiUSB.flush();
    }
  } while (rx.header != 0);
}

YouTube

Max7の「metro 10」が本当にこの時間密度でちゃんとMIDI送信しているかどうか・・・という部分に実はトリックがあるのだが(^_^;)、しかし上のように、見たところこの「MIDIUSB_loop」が走るArduino Microは、きちんとMIDI受信した情報をループバックしていて、つまり「MIDIを取りこぼさない」で頑張っている、と確認できた。 一般論では(Arduino UNOでシリアル31250での送受信)結論は変わらないものの、今回のこの「ArduinoMIDIUSB」については、「ArduinoでもちゃんとMIDI送信だけでなくMIDI受信でも使えそうだ」という結論になった。 これは新たな発見である。(^_^)

2017年9月15日(金)

朝から某隣国のICBMがまた日本を飛び越えていったらしいが、そんなの関係ねえ(死語)。 明日の座禅+BF勉強会にも関わらず台風18号が近づいているらしいが、そんなの関係ねえ(死語)。 以下のような狡猾な女子中学生の手口に驚嘆したが、そんなの関係ねえ(死語)。

今日もまた、昨日の発見から、早朝に実験項目を3つほど思いついて、起き出してメモしていたのである。 調子が出てきた感じがするので、これはどんどん、進めていきたい。 ちょっと難航するものもあるが、簡単そうな方から順に列記すれば以下である。

そして、最初の項目は実際にArduinoを繋がなくてもArduino IDEでコンパイルエラーが出てすぐに判明するので、以下のように実験してみた。 全てのArduinoについて調べるほどの事はないので、手元にある(過去に使った)ものを調べてみると、「USB MCU」と分類されないArduinoはことごとく駄目であり、たまたま手元にあったArduino MicroだけがOKなのだ、と判明した。 Arduino nanoは重宝していたが、アナログ入力も6チャンネルでなく12チャンネルあるし、こうなると今後はArduino Microに大きくシフトしそうである。


Arduino UNO


Arduino Diecimila


Arduino nano


Arduino Pro / Pro MIni


Arduino Micro

そして、続いて第2項目の実験に進むことにした。 僕の手元にあったArduino IDEは1.8.2だったが、現在の最新は1.8.4である。 ダウンロードしようとすると、以下のような「寄付してね」というのが出たが、今後も活用するし、Wikipediaにも寄付したので、今回はPayPalで10ドル(1151円)を寄付して、最新の1.8.4をダウンロードした。 マイナーversion upなので大勢に影響はないと思われるので、今後はこれを使っていくことにする。

MIDIUSBデバイスとしてOSが認識するとデバイス名が表示されるので、そのどこかにデバイス名の定義フィールドがある筈である。 長谷部さんはそこをちゃんと「TouchMIDI32」と書き換えているからそのように表示され、何もしていない場合にはdefaultとして「Arduino Micro」と表示されるのだろう。 Arduino IDEではコンパイルの際にメニューでデバイスを選択するので、ソースコードに自分自身のデバイス名を記述する場所はない。 ということで、「Arduino Micro」を検索するという作戦は使えないが、とにかく「MIDIUSB.h」と「MIDIUSB.cpp」のどこかにこのエリアがある可能性をまずはチェックしていった。 もちろん、例えば「MIDIUSB.h」は「stdint.h」と「Arduino.h」(←これが怪しい!!)と「PluggableUSB.h」(←これも強烈に怪しい!!)をincludeしているので、見つからなければさらにここを探検することになる。

ここから午前中〜午後に、あれこれ探索しては実験コンパイルを繰り返しているところに、SketchingコミュニティのMLで、11月にイギリスで開催される「Unmaking」という シンポジウム の案内が流れてきた。 2人のKeynoteの紹介リンク : Christian Faubel氏、 Sarah Kenchington氏 を辿ってみたが、前者はだいぶ昔にSUACで堀尾寛太氏がやっていたパフォーマンスほぼそのまま同じだった。 後者はよく見てみると上のように、パフォーマーが自分で自転車を漕いで動力を提供しているようで、電気仕掛けというよりは「からくり楽器」だった。

「MIDIUSB.h」と「MIDIUSB.cpp」の端から端までじっくり眺めて、さらに「Arduino.h」はシステム中からゲットして眺めたが、とりあえずコレという場所が見つからないまま、もっともそれっぽい「PluggableUSB.h」を探してみると、コンピュータ内にはそれが存在しない(しかしインクルードされてエラーが出ない)、と確認できた。 つまりこれは、Arduino IDEの方で内部的に持っている可能性がある。 ちょっと手詰まりになったので、ここでTouchMIDI32の長谷部さんがどうやっているのか・・・を調べてみると、なんと「USBMIDI_pvt.h」というヘッダファイルのプライベートな「USBMIDI_STRING_DESCRIPTORS」という文字列配列の定義と、そこに具体的な文字列を定義している「USBMIDI_descr.c」というファイルを発見した。ただし以下のように、文字列として"TouchMIDI32"を定義しているのではなく、1文字ずついちいち定義して入れ込んでいた。

"USBMIDI_pvt.h"の一部

/*     Private Variables     */
/* Generated external references for descriptors. */
extern const uint8 CYCODE USBMIDI_DEVICE0_DESCR[18u];
extern const uint8 CYCODE USBMIDI_DEVICE0_CONFIGURATION0_DESCR[101u];
extern const T_USBMIDI_EP_SETTINGS_BLOCK CYCODE USBMIDI_DEVICE0_CONFIGURATION0_EP_SETTINGS_TABLE[2u];
extern const uint8 CYCODE USBMIDI_DEVICE0_CONFIGURATION0_INTERFACE_CLASS[2u];
extern const T_USBMIDI_LUT CYCODE USBMIDI_DEVICE0_CONFIGURATION0_TABLE[5u];
extern const T_USBMIDI_LUT CYCODE USBMIDI_DEVICE0_TABLE[3u];
extern const T_USBMIDI_LUT CYCODE USBMIDI_TABLE[1u];
extern const uint8 CYCODE USBMIDI_SN_STRING_DESCRIPTOR[2];
extern const uint8 CYCODE USBMIDI_STRING_DESCRIPTORS[221u];

"USBMIDI_descr.c"の一部

/*     String Descriptor Table     */
const uint8 CYCODE USBMIDI_STRING_DESCRIPTORS[221u] = {
・・・
・・・
・・・
/*  String Descriptor: "TouchMIDI32" */
/* Descriptor Length                       */ 0x18u,
/* DescriptorType: STRING                  */ 0x03u,
 (uint8)'T', 0u,(uint8)'o', 0u,(uint8)'u', 0u,(uint8)'c', 0u,(uint8)'h', 0u,
 (uint8)'M', 0u,(uint8)'I', 0u,(uint8)'D', 0u,(uint8)'I', 0u,(uint8)'3', 0u,
 (uint8)'2', 0u,
/* Marks the end of the list.              */ 0x00u};
そして、上記と対応するものを探していくと、「USBMIDI.h」の中に、以下のような記述を発見した。 どうやらこちらの処理系では、このあたりをどこかで参照して確定させているらしい。 しかしArduino IDEでは、おそらくツールがデバイスを選んで書き込む文字列なので、この手法とは違っていそうである。

"USBMIDI.h"の一部

/* Descriptor Types (Table 9-5) */
#define USBMIDI_DESCR_DEVICE                   (1u)
#define USBMIDI_DESCR_CONFIG                   (2u)
#define USBMIDI_DESCR_STRING                   (3u)
#define USBMIDI_DESCR_INTERFACE                (4u)
#define USBMIDI_DESCR_ENDPOINT                 (5u)
#define USBMIDI_DESCR_DEVICE_QUALIFIER         (6u)
#define USBMIDI_DESCR_OTHER_SPEED              (7u)
#define USBMIDI_DESCR_INTERFACE_POWER          (8u)
長谷部さんルートもちょっと手詰まりになったので、ここで再び「PluggableUSB.h」にトライした。 いい時代で、YAHOO.COMに「PluggableUSB.h Arduino」と入れると、以下のようにGitHubからちゃんと「PluggableUSB.h」をゲット出来た。 ただし、これはUSB処理全般のようで、残念ながら「USBMIDI」からは離れた、もっと上流であり、たぶん無関係である。

"PluggableUSB.h"のほぼ全部

#ifndef PUSB_h
#define PUSB_h
#include "USBAPI.h"
#include 
#if defined(USBCON)

class PluggableUSBModule {
public:
  PluggableUSBModule(uint8_t numEps, uint8_t numIfs, uint8_t *epType) :
    numEndpoints(numEps), numInterfaces(numIfs), endpointType(epType)
  { }
protected:
  virtual bool setup(USBSetup& setup) = 0;
  virtual int getInterface(uint8_t* interfaceCount) = 0;
  virtual int getDescriptor(USBSetup& setup) = 0;
  virtual uint8_t getShortName(char *name) { name[0] = 'A'+pluggedInterface; return 1; }
  uint8_t pluggedInterface;
  uint8_t pluggedEndpoint;
  const uint8_t numEndpoints;
  const uint8_t numInterfaces;
  const uint8_t *endpointType;
  PluggableUSBModule *next = NULL;
  friend class PluggableUSB_;
};

class PluggableUSB_ {
public:
  PluggableUSB_();
  bool plug(PluggableUSBModule *node);
  int getInterface(uint8_t* interfaceCount);
  int getDescriptor(USBSetup& setup);
  bool setup(USBSetup& setup);
  void getShortName(char *iSerialNum);
private:
  uint8_t lastIf;
  uint8_t lastEp;
  PluggableUSBModule* rootNode;
};

PluggableUSB_& PluggableUSB();
#endif
#endif
ここまでを整理すると、Arduinoの場合にはソースコード中に明示的にUSB-MIDIデバイス名を記述しなくても、そのdefault領域にIDEがArduinoの名前を入れるのだろう、と推定できる。 ここまで「MIDIUSB.h」と「MIDIUSB.cpp」を削ぎ落としてみれば、そこで定義されている何かの部分に、Arduinoソースのsetup()で明示的に文字列を定義するしかないのでは・・・と見立てた。 そこでここから絨毯攻撃を開始して、Arduinoプログラムを「定期的にMIDIノート送信、シリアルモニタにその数値を表示」という最低限の機能(MIDI受信は全てカット)して、エラーが出ない範囲でどこまで「MIDIUSB_test.ino」・「MIDIUSB.cpp」・「MIDIUSB.h」から関係ないものが削れるかに挑戦した。 Arduino IDEの画面で上下スクロールしなくてもいいように「詰めた」のでちょっと見にくいが(^_^;)、以下のようにかなーりコンパクト化できた。 この中におそらく、MIDIデバイスを定義できる場所が隠れているのでは・・・という見立てである。

"MIDIUSB_test.ino"(誤)

#include "MIDIUSB.h"

int x = 48;

void noteOn(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOn);
}

void noteOff(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOff);
}

void setup() {
  Serial.begin(115200);
}

void loop() {
  x = 48 + (++x % 12);
  Serial.print(x);
  Serial.print(" ");
  noteOn(0, x, 100);
  MidiUSB.flush();
  delay(500);
  noteOff(0, x, 100);
  MidiUSB.flush();
  delay(2500);
}

"MIDIUSB.cpp"(誤)

#include "MIDIUSB.h"
#define MIDI_INTERFACE 		((uint8_t)(pluggedInterface+1))
#define MIDI_FIRST_ENDPOINT pluggedEndpoint
#define MIDI_ENDPOINT_OUT	pluggedEndpoint
#define MIDI_ENDPOINT_IN	((uint8_t)(pluggedEndpoint+1))
#define MIDI_TX MIDI_ENDPOINT_IN

MIDI_ MidiUSB;

int MIDI_::getInterface(uint8_t* interfaceNum){
	interfaceNum[0] += 2;
	MIDIDescriptor _midiInterface = {
		D_MIDI_OUTJACK(MIDI_JACK_EMD, 0x3, 1, 2, 1),
		D_MIDI_OUTJACK(MIDI_JACK_EXT, 0x4, 1, 1, 1),
		D_MIDI_JACK_EP(USB_ENDPOINT_IN(MIDI_ENDPOINT_IN),USB_ENDPOINT_TYPE_BULK,MIDI_BUFFER_SIZE),
		D_MIDI_AC_JACK_EP (1, 3) };
	return USB_SendControl(0, &_midiInterface, sizeof(_midiInterface)); }

bool MIDI_::setup(USBSetup& setup __attribute__((unused))){ return false; }
int MIDI_::getDescriptor(USBSetup& setup __attribute__((unused))){ return 0; }
uint8_t MIDI_::getShortName(char* name){ memcpy(name, "MIDI", 4); return 4; }
void MIDI_::flush(void){ USB_Flush(MIDI_TX); }

size_t MIDI_::write(const uint8_t *buffer, size_t size){
	if (is_write_enabled(MIDI_TX)){
		int r = USB_Send(MIDI_TX, buffer, size);
		if (r > 0) { return r; } else { return 0; }
	} return 0; }

void MIDI_::sendMIDI(midiEventPacket_t event){
	uint8_t data[4];
	data[0] = event.header; data[1] = event.byte1; data[2] = event.byte2; data[3] = event.byte3;
	write(data, 4); }

MIDI_::MIDI_(void) : PluggableUSBModule(2, 2, epType){
	epType[0] = EP_TYPE_BULK_OUT_MIDI; epType[1] = EP_TYPE_BULK_IN_MIDI;
	PluggableUSB().plug(this); }

"MIDIUSB.h"(誤)

#include 
#include 
typedef struct{ uint8_t header; uint8_t byte1; uint8_t byte2; uint8_t byte3; }midiEventPacket_t;
#include "PluggableUSB.h"
#define EPTYPE_DESCRIPTOR_SIZE uint8_t
#define EP_TYPE_BULK_IN_MIDI EP_TYPE_BULK_IN
#define EP_TYPE_BULK_OUT_MIDI EP_TYPE_BULK_OUT
#define MIDI_BUFFER_SIZE USB_EP_SIZE
#define is_write_enabled(x) (1)
#define MIDI_CS_INTERFACE 0x24
#define MIDI_CS_ENDPOINT 0x25
#define MIDI_JACK_EMD 0x01
#define MIDI_JACK_EXT 0X02

typedef struct{
	uint8_t len; uint8_t dtype; uint8_t dsubType; uint8_t jackType; uint8_t jackID; uint8_t nPins;
	uint8_t srcJackID; uint8_t srcPinID; uint8_t jackStrIndex; } MIDIJackOutDescriptor;
typedef struct{ EndpointDescriptor len; uint8_t refresh; uint8_t sync; } MIDI_EPDescriptor;
typedef struct{ uint8_t len; uint8_t dtype; uint8_t subtype; uint8_t embJacks;
	uint8_t jackID; } MIDI_EP_ACDescriptor;
typedef struct{ MIDIJackOutDescriptor MIDI_Out_Jack_Emb; MIDIJackOutDescriptor MIDI_Out_Jack_Ext;
	MIDI_EPDescriptor MIDI_Out_Jack_Endpoint; MIDI_EP_ACDescriptor MIDI_Out_Jack_Endpoint_SPC;
} MIDIDescriptor;
#define D_MIDI_OUTJACK(jackProp, _jackID, _nPins, _srcID, _srcPin) \
	{ 0x09, MIDI_CS_INTERFACE, 0x3, jackProp, _jackID, _nPins, _srcID, _srcPin, 0  }
#define D_MIDI_JACK_EP(_addr,_attr,_packetSize) { 9, 5, _addr,_attr,_packetSize, 0, 0, 0}
#define D_MIDI_AC_JACK_EP(_nMIDI, _iDMIDI) { 5, MIDI_CS_ENDPOINT, 0x1, _nMIDI, _iDMIDI}

class MIDI_ : public PluggableUSBModule{
private:
	EPTYPE_DESCRIPTOR_SIZE epType[2];
protected:
  int getInterface(uint8_t* interfaceNum); int getDescriptor(USBSetup& setup);
  bool setup(USBSetup& setup); uint8_t getShortName(char* name);
public:
	MIDI_(void); void flush(void); void sendMIDI(midiEventPacket_t event);
	size_t write(const uint8_t *buffer, size_t size); operator bool(); };
extern MIDI_ MidiUSB;
かなり小さくなったが、これでもちゃんとコンパイル成功するのである。 しかし、午後まで頑張ってみたが、他にも後期の準備の些事が舞い込んで対応したりしているうちに、ここでオシマイとなってしまった。 道具と材料は揃っているのでいずれ再開してみたいが、忘れる可能性も少なくない(^_^;)。 とりあえず明日はまだ遠い台風に向かって、京都で座禅体験、そして奈良に移動してBF勉強会である。

2017年9月16日(土)

昨日の帰り際に、持参するMacBookAirに実験環境をコピーしていて気付いたことだが、昨日の午後の実験の後半に大きなバグ(失敗)があった、と判明した(^_^;)。 「Arduino IDEでコンパイルエラーが出ない(コンパイル成功)」というのと、「Mac OSXのシステムがUSB-MIDIデバイスとして認識する」というのは、イコールでは無かった、と判明したのである。 認識されなくなった場合にもシステムのMIDI環境設定には、正しく受け入れた時の「残像」が残っていて、ここを勘違いして残したまま、コンパイルエラーが出ないという条件だけを過信してズンズンとあれこれ消し過ぎた、ということである。 これは仕切り直しとなったので、京都に向かう新幹線の中でやることにした。

2017年9月17日(日)

昨日は昼前に京都に着いて、照岡さんと「毘沙門堂 勝林寺」で座禅体験(僕は3度目)をして、それから奈良に向かって奈良学園大の辻下先生のところでバイオフィードバック勉強会を行った。 台風が近付いてきている・・・ということで大阪日本橋散策をやめて今日の朝に浜松に帰って、10時過ぎから研究室であるが、なんと午後には以下のように晴れ渡ってている。 ただし強風なので、早めに帰ってきたのは正解だろう。

昨日の浜松→京都の新幹線内で、Arduino MicroをUSBに繋いだまま、コンパイルだけでなくアップロードして「MIDIデバイス」と認識されるギリギリまで圧縮した結果は以下である。 一昨日の「(誤)」との差分を調べれば、コンパイル成功しても「MIDIデバイス」と認識されない部分が該当するのだが、どうもこの部分にデバイス名のエリアは無いのかもしれない、という気もしてきた。 たぶん、「MIDIDescriptor」という構造体を、使わない項目であってもカットしたのが失敗だったようで、Mac OSXはこの構造体が正しいことをチェックしているようである。

"MIDIUSB_test.ino"(実験1)

#include "MIDIUSB.h"

void noteOn(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOn);
}

void noteOff(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOff);
}

void setup() {
  Serial.begin(115200);
}

void loop() {
  noteOn(0, 48, 64);
  MidiUSB.flush();
  delay(500);
  noteOff(0, 48, 64);
  MidiUSB.flush();
  delay(1500);
}

"MIDIUSB.cpp"(実験1)

#include "MIDIUSB.h"
#define MIDI_AC_INTERFACE 	pluggedInterface
#define MIDI_INTERFACE 		((uint8_t)(pluggedInterface+1))
#define MIDI_FIRST_ENDPOINT pluggedEndpoint
#define MIDI_ENDPOINT_OUT	pluggedEndpoint
#define MIDI_ENDPOINT_IN	((uint8_t)(pluggedEndpoint+1))
#define MIDI_RX MIDI_ENDPOINT_OUT
#define MIDI_TX MIDI_ENDPOINT_IN

MIDI_ MidiUSB;

int MIDI_::getInterface(uint8_t* interfaceNum){
	interfaceNum[0] += 2;
	MIDIDescriptor _midiInterface =
	{
		D_IAD(MIDI_AC_INTERFACE, 2, MIDI_AUDIO, MIDI_AUDIO_CONTROL, 0),
		D_INTERFACE(MIDI_AC_INTERFACE,0,MIDI_AUDIO,MIDI_AUDIO_CONTROL,0),
		D_AC_INTERFACE(0x1, MIDI_INTERFACE),
		D_INTERFACE(MIDI_INTERFACE,2, MIDI_AUDIO,MIDI_STREAMING,0),
		D_AS_INTERFACE,
		D_MIDI_INJACK(MIDI_JACK_EMD, 0x1),
		D_MIDI_INJACK(MIDI_JACK_EXT, 0x2),
		D_MIDI_OUTJACK(MIDI_JACK_EMD, 0x3, 1, 2, 1),
		D_MIDI_OUTJACK(MIDI_JACK_EXT, 0x4, 1, 1, 1),
		D_MIDI_JACK_EP(USB_ENDPOINT_OUT(MIDI_ENDPOINT_OUT),USB_ENDPOINT_TYPE_BULK,MIDI_BUFFER_SIZE),
		D_MIDI_AC_JACK_EP(1, 1),
		D_MIDI_JACK_EP(USB_ENDPOINT_IN(MIDI_ENDPOINT_IN),USB_ENDPOINT_TYPE_BULK,MIDI_BUFFER_SIZE),
		D_MIDI_AC_JACK_EP (1, 3)
	};
	return USB_SendControl(0, &_midiInterface, sizeof(_midiInterface));}

bool MIDI_::setup(USBSetup& setup __attribute__((unused))){	return false;}
int MIDI_::getDescriptor(USBSetup& setup __attribute__((unused))){	return 0;}
void MIDI_::flush(void){	USB_Flush(MIDI_TX);}

size_t MIDI_::write(const uint8_t *buffer, size_t size){
	if (is_write_enabled(MIDI_TX)) {
		int r = USB_Send(MIDI_TX, buffer, size);
		if (r > 0){	return r;	} else { return 0; }
	}	return 0; }

void MIDI_::sendMIDI(midiEventPacket_t event){
	uint8_t data[4];
	data[0] = event.header;	data[1] = event.byte1;	data[2] = event.byte2;	data[3] = event.byte3;
	write(data, 4);}

MIDI_::MIDI_(void) : PluggableUSBModule(2, 2, epType){
	epType[0] = EP_TYPE_BULK_OUT_MIDI;	epType[1] = EP_TYPE_BULK_IN_MIDI;
	PluggableUSB().plug(this);}

"MIDIUSB.h"(実験1)

#include 
#include 
typedef struct{	uint8_t header;	uint8_t byte1; uint8_t byte2;	uint8_t byte3;} midiEventPacket_t;
#include "PluggableUSB.h"
#define EPTYPE_DESCRIPTOR_SIZE		uint8_t
#define EP_TYPE_BULK_IN_MIDI 		EP_TYPE_BULK_IN
#define EP_TYPE_BULK_OUT_MIDI 		EP_TYPE_BULK_OUT
#define MIDI_BUFFER_SIZE			USB_EP_SIZE
#define is_write_enabled(x)			(1)
#define MIDI_AUDIO								0x01
#define MIDI_AUDIO_CONTROL						0x01
#define MIDI_CS_INTERFACE						0x24
#define MIDI_CS_ENDPOINT						0x25
#define MIDI_STREAMING							0x3
#define MIDI_JACK_EMD							0x01
#define MIDI_JACK_EXT							0X02

typedef struct{ uint8_t len; uint8_t dtype; uint8_t dsubType; uint16_t bcdADc;
	uint16_t wTotalLength; uint8_t bInCollection; uint8_t interfaceNumbers; } MIDI_ACInterfaceDescriptor;
typedef struct{ uint8_t len; uint8_t dtype; uint8_t dsubType; uint8_t jackType;
  uint8_t jackID; uint8_t jackStrIndex; } MIDIJackinDescriptor;
typedef struct{ uint8_t len; uint8_t dtype; uint8_t dsubType; uint8_t jackType; uint8_t jackID;
	uint8_t nPins; uint8_t srcJackID; uint8_t srcPinID; uint8_t jackStrIndex; } MIDIJackOutDescriptor;
typedef struct{ EndpointDescriptor len; uint8_t refresh; uint8_t sync; } MIDI_EPDescriptor;
typedef struct{ uint8_t len; uint8_t dtype; uint8_t subtype; uint8_t embJacks;
  uint8_t jackID;} MIDI_EP_ACDescriptor;
typedef struct{ uint8_t len; uint8_t dtype; uint8_t dsubType; uint16_t bcdADc;
  uint16_t wTotalLength; } MIDI_ASInterfaceDescriptor;

typedef struct{
	IADDescriptor                      iad;
	InterfaceDescriptor                Audio_ControlInterface;
	MIDI_ACInterfaceDescriptor         Audio_ControlInterface_SPC;
	InterfaceDescriptor                Audio_StreamInterface;
	MIDI_ASInterfaceDescriptor         Audio_StreamInterface_SPC;
	MIDIJackinDescriptor               MIDI_In_Jack_Emb;
	MIDIJackinDescriptor               MIDI_In_Jack_Ext;
	MIDIJackOutDescriptor              MIDI_Out_Jack_Emb;
	MIDIJackOutDescriptor              MIDI_Out_Jack_Ext;
	MIDI_EPDescriptor                  MIDI_In_Jack_Endpoint;
	MIDI_EP_ACDescriptor               MIDI_In_Jack_Endpoint_SPC;
	MIDI_EPDescriptor                  MIDI_Out_Jack_Endpoint;
	MIDI_EP_ACDescriptor               MIDI_Out_Jack_Endpoint_SPC;
} MIDIDescriptor;

#define D_AC_INTERFACE(_streamingInterfaces, _MIDIInterface) \
	{ 9, MIDI_CS_INTERFACE, 0x1, 0x0100, 0x0009, _streamingInterfaces, (uint8_t)(_MIDIInterface) }
#define D_AS_INTERFACE { 0x7, MIDI_CS_INTERFACE, 0x01,0x0100, 0x0041}
#define D_MIDI_INJACK(jackProp, _jackID) { 0x06, MIDI_CS_INTERFACE, 0x02, jackProp, _jackID, 0  }
#define D_MIDI_OUTJACK(jackProp, _jackID, _nPins, _srcID, _srcPin) \
	{ 0x09, MIDI_CS_INTERFACE, 0x3, jackProp, _jackID, _nPins, _srcID, _srcPin, 0  }
#define D_MIDI_JACK_EP(_addr,_attr,_packetSize) { 9, 5, _addr,_attr,_packetSize, 0, 0, 0}
#define D_MIDI_AC_JACK_EP(_nMIDI, _iDMIDI) { 5, MIDI_CS_ENDPOINT, 0x1, _nMIDI, _iDMIDI}
#define D_CDCCS(_subtype,_d0,_d1)	{ 5, 0x24, _subtype, _d0, _d1 }
#define D_CDCCS4(_subtype,_d0)		{ 4, 0x24, _subtype, _d0 }

class MIDI_ : public PluggableUSBModule{
private:
	EPTYPE_DESCRIPTOR_SIZE epType[2];
protected:
  int getInterface(uint8_t* interfaceNum);
  int getDescriptor(USBSetup& setup);
  bool setup(USBSetup& setup);
public:
	MIDI_(void);
	void flush(void);
	void sendMIDI(midiEventPacket_t event);
	size_t write(const uint8_t *buffer, size_t size);
	operator bool();
};
extern MIDI_ MidiUSB;
結局、一昨日に思いついた3項目のうち、1つ目しか追求しきれていないのだが、バイオフィードバック勉強会を受けて、当面はVPP-SUAC基板をきちんと稼働させるところから仕切り直したり、いよいよ後期に向けての準備に突入するので、これは例によって棚上げされるかもしれない。 風が強いし台風が確実に近付いてきているので、午後には早めに帰宅(途中でコロッケを仕入れて)することにした。

2017年9月18日(月/祝)

台風一過の祝日の朝である。 浜松を昨日の夜中に通過した台風は津軽海峡付近にあって、以下のように北海道全域が雨雲に覆われている。 東北から北海道は凄い暴風域になっていて、当然ながら飛行機も列車も市電も動いていないので、この連休に行楽に行った人はホテルに缶詰で停電しない事を祈っているだろう。

辻下先生のところに機材あれこれ一式を送って、おそらく返送の機材が届くのは明後日あたりなので、筋電センサVPP-SUACの実験が出来ない、と気付いたので、手元に余分にあるArduino Microを使って、昨日までの実験の確認と続きを進めることにした。 以下のYouTubeは、土曜日に新幹線の中でやっていた実験の再現であり、(1)テストArduinoスケッチをコンパイル→アップロード(書き換え)する、(2)システムの「MIDIデバイス」のところに「Arduino Micro」というデバイスが出現してMax7でMIDI情報の到着を確認できる、(3)サンプルの"BLINK"スケッチをアップロード(上書き)する、(4)「MIDIデバイス」の「Arduino Micro」が薄くなってデリート出来る(デバイスとして消えた)、というループを繰り返しつつ、テストArduinoスケッチをどんどん削ってみる、という作業である。

YouTube

さらに戻って長谷部さんのソースも眺めたり、やはり上部階層も関係しそうなので「PluggableUSB.h」とか、そこでincludeされている「USBAPI.h」(これはかなり膨大な予感がする(^_^;))の可能性・・・など、あれこれ妄想しつつの試行錯誤、そして合間には気分転換で「完全版」全4冊が手元に揃った「黒のもんもん組」(Amazon「中古」というものの完全に新品の綺麗な「お宝」)をペラペラと眺める、という幸せな休日である。 ネットからは 屋久島一周ウルトラecoマラニック というソソラレル企画の情報をゲットしたが、調べてみるとセンター試験監督、というお仕事があって無理と判明するまで15秒。 たった15秒だけ、いい夢を見させてもらった。

実験の途中で気付いた点としては、Arduino MicroをUSBに挿しっ放しにしてコンパイルを続けていると、一度「幽霊」(過去のUSBMIDIデバイス)を消して、再びコンパイルして登場した時に、システムの「MIDIデバイス」には同じ「Arduino Micro」が出現するのに対して、パッチを開き続けているMax7のパッチ内で「notein」オブジェクトをダブルクリックして「MIDIデバイス一覧」メニューを出すと、「Arduino Micro #2」、「Arduino Micro #3」・・・というように、名前がMaxによって自動的に「前と似ているけど違うよ」表示されることが分かった。 つまり、Max7の「MIDIデバイス一覧」メニューは、OSXから受け取ったデバイス名そのものを表示しているのでなく、Max7の内部的には前回との違いをきちんと把握しているようなのだ。 こうなると、Max7のオブジェクトのインスペクタをどう内部的に処理しているか、という部分から探るような可能性もありそうだが、あまりに枝葉の先は深遠な感じなので、当面はこの可能性はパスである。

"MIDIUSB_test.ino"(実験2)

#include "MIDIUSB.h"
int x = 0;
  
void noteOn(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOn);
}

void noteOff(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOff);
}

void setup() {
  Serial.begin(115200);
//  MidiUSB.setup(            );
}

void loop() {
  x = (++x)%36 + 36;
  noteOn(0, x, 64);
  MidiUSB.flush();
  delay(250);
  noteOff(0, x, 64);
  MidiUSB.flush();
  delay(750);
}

"MIDIUSB.cpp"(実験2)

#include "MIDIUSB.h"
#define MIDI_AC_INTERFACE 	pluggedInterface
#define MIDI_INTERFACE 		((uint8_t)(pluggedInterface+1))
#define MIDI_FIRST_ENDPOINT pluggedEndpoint
#define MIDI_ENDPOINT_OUT	pluggedEndpoint
#define MIDI_ENDPOINT_IN	((uint8_t)(pluggedEndpoint+1))
#define MIDI_RX MIDI_ENDPOINT_OUT
#define MIDI_TX MIDI_ENDPOINT_IN

MIDI_ MidiUSB;

int MIDI_::getInterface(uint8_t* interfaceNum){
	interfaceNum[0] += 2;
	MIDIDescriptor _midiInterface =
	{
		D_IAD(MIDI_AC_INTERFACE, 2, MIDI_AUDIO, MIDI_AUDIO_CONTROL, 0),
		D_INTERFACE(MIDI_AC_INTERFACE,0,MIDI_AUDIO,MIDI_AUDIO_CONTROL,0),
		D_AC_INTERFACE(0x1, MIDI_INTERFACE),
		D_INTERFACE(MIDI_INTERFACE,2, MIDI_AUDIO,MIDI_STREAMING,0),
		D_AS_INTERFACE,
		D_MIDI_INJACK(MIDI_JACK_EMD, 0x1),
		D_MIDI_INJACK(MIDI_JACK_EXT, 0x2),
		D_MIDI_OUTJACK(MIDI_JACK_EMD, 0x3, 1, 2, 1),
		D_MIDI_OUTJACK(MIDI_JACK_EXT, 0x4, 1, 1, 1),
		D_MIDI_JACK_EP(USB_ENDPOINT_OUT(MIDI_ENDPOINT_OUT),USB_ENDPOINT_TYPE_BULK,MIDI_BUFFER_SIZE),
		D_MIDI_AC_JACK_EP(1, 1),
		D_MIDI_JACK_EP(USB_ENDPOINT_IN(MIDI_ENDPOINT_IN),USB_ENDPOINT_TYPE_BULK,MIDI_BUFFER_SIZE),
		D_MIDI_AC_JACK_EP (1, 3)
	};
	return USB_SendControl(0, &_midiInterface, sizeof(_midiInterface));
}

bool MIDI_::setup(USBSetup& setup __attribute__((unused))){ return false; }
int MIDI_::getDescriptor(USBSetup& setup __attribute__((unused))){ return 0; }
void MIDI_::flush(void){ USB_Flush(MIDI_TX); }

size_t MIDI_::write(const uint8_t *buffer, size_t size){
	if (is_write_enabled(MIDI_TX)) {
		int r = USB_Send(MIDI_TX, buffer, size);
		if (r > 0){	return r;	} else { return 0; }
	}	return 0;
}

void MIDI_::sendMIDI(midiEventPacket_t event){
	uint8_t data[4];
	data[0] = event.header;	data[1] = event.byte1; data[2] = event.byte2;	data[3] = event.byte3;
	write(data, 4);
}

MIDI_::MIDI_(void) : PluggableUSBModule(2, 2, epType){
	epType[0] = EP_TYPE_BULK_OUT_MIDI; epType[1] = EP_TYPE_BULK_IN_MIDI; PluggableUSB().plug(this);
}

"MIDIUSB.h"(実験2)

#include 
#include 
#include "PluggableUSB.h"
#define EPTYPE_DESCRIPTOR_SIZE uint8_t
#define EP_TYPE_BULK_IN_MIDI EP_TYPE_BULK_IN
#define EP_TYPE_BULK_OUT_MIDI EP_TYPE_BULK_OUT
#define MIDI_BUFFER_SIZE USB_EP_SIZE
#define MIDI_AUDIO 0x01
#define MIDI_AUDIO_CONTROL 0x01
#define MIDI_CS_INTERFACE 0x24
#define MIDI_CS_ENDPOINT 0x25
#define MIDI_STREAMING 0x3
#define MIDI_JACK_EMD 0x01
#define MIDI_JACK_EXT 0X02
#define is_write_enabled(x) (1)

typedef struct{ uint8_t header; uint8_t byte1; uint8_t byte2; uint8_t byte3;} midiEventPacket_t;
typedef struct{ uint8_t len; uint8_t dtype; uint8_t dsubType; uint16_t bcdADc; uint16_t wTotalLength; uint8_t bInCollection; uint8_t interfaceNumbers; } MIDI_ACInterfaceDescriptor;
typedef struct{ uint8_t len; uint8_t dtype; uint8_t dsubType; uint8_t jackType; uint8_t jackID; uint8_t jackStrIndex; } MIDIJackinDescriptor;
typedef struct{ uint8_t len; uint8_t dtype; uint8_t dsubType; uint8_t jackType; uint8_t jackID; uint8_t nPins; uint8_t srcJackID; uint8_t srcPinID; uint8_t jackStrIndex; } MIDIJackOutDescriptor;
typedef struct{ EndpointDescriptor len; uint8_t refresh; uint8_t sync; } MIDI_EPDescriptor;
typedef struct{ uint8_t len; uint8_t dtype; uint8_t subtype; uint8_t embJacks; uint8_t jackID;} MIDI_EP_ACDescriptor;
typedef struct{ uint8_t len; uint8_t dtype; uint8_t dsubType; uint16_t bcdADc; uint16_t wTotalLength; } MIDI_ASInterfaceDescriptor;

typedef struct{
	IADDescriptor                      iad;
	InterfaceDescriptor                Audio_ControlInterface;
	MIDI_ACInterfaceDescriptor         Audio_ControlInterface_SPC;
	InterfaceDescriptor                Audio_StreamInterface;
	MIDI_ASInterfaceDescriptor         Audio_StreamInterface_SPC;
	MIDIJackinDescriptor               MIDI_In_Jack_Emb;
	MIDIJackinDescriptor               MIDI_In_Jack_Ext;
	MIDIJackOutDescriptor              MIDI_Out_Jack_Emb;
	MIDIJackOutDescriptor              MIDI_Out_Jack_Ext;
	MIDI_EPDescriptor                  MIDI_In_Jack_Endpoint;
	MIDI_EP_ACDescriptor               MIDI_In_Jack_Endpoint_SPC;
	MIDI_EPDescriptor                  MIDI_Out_Jack_Endpoint;
	MIDI_EP_ACDescriptor               MIDI_Out_Jack_Endpoint_SPC;
} MIDIDescriptor;

#define D_AC_INTERFACE(_streamingInterfaces, _MIDIInterface) { 9, MIDI_CS_INTERFACE, 0x1, 0x0100, 0x0009, _streamingInterfaces, (uint8_t)(_MIDIInterface) }
#define D_AS_INTERFACE { 0x7, MIDI_CS_INTERFACE, 0x01,0x0100, 0x0041}
#define D_MIDI_INJACK(jackProp, _jackID) { 0x06, MIDI_CS_INTERFACE, 0x02, jackProp, _jackID, 0  }
#define D_MIDI_OUTJACK(jackProp, _jackID, _nPins, _srcID, _srcPin) { 0x09, MIDI_CS_INTERFACE, 0x3, jackProp, _jackID, _nPins, _srcID, _srcPin, 0  }
#define D_MIDI_JACK_EP(_addr,_attr,_packetSize) { 9, 5, _addr,_attr,_packetSize, 0, 0, 0}
#define D_MIDI_AC_JACK_EP(_nMIDI, _iDMIDI) { 5, MIDI_CS_ENDPOINT, 0x1, _nMIDI, _iDMIDI}
#define D_CDCCS(_subtype,_d0,_d1)	{ 5, 0x24, _subtype, _d0, _d1 }
#define D_CDCCS4(_subtype,_d0)		{ 4, 0x24, _subtype, _d0 }

class MIDI_ : public PluggableUSBModule{
private:
	EPTYPE_DESCRIPTOR_SIZE epType[2];
protected:
  int getInterface(uint8_t* interfaceNum);
  int getDescriptor(USBSetup& setup);
  bool setup(USBSetup& setup);
public:
	MIDI_(void);
	void flush(void);
	void sendMIDI(midiEventPacket_t event);
	size_t write(const uint8_t *buffer, size_t size);
	operator bool();
};

extern MIDI_ MidiUSB;

"PluggableUSB.h"(実験2)

#ifndef PUSB_h
#define PUSB_h
#include "USBAPI.h"
#include 
#if defined(USBCON)

class PluggableUSBModule {
public:
  PluggableUSBModule(uint8_t numEps, uint8_t numIfs, uint8_t *epType) : numEndpoints(numEps), numInterfaces(numIfs), endpointType(epType) { }
protected:
  virtual bool setup(USBSetup& setup) = 0;
  virtual int getInterface(uint8_t* interfaceCount) = 0;
  virtual int getDescriptor(USBSetup& setup) = 0;
  virtual uint8_t getShortName(char *name) { name[0] = 'A'+pluggedInterface; return 1; }
  uint8_t pluggedInterface;
  uint8_t pluggedEndpoint;
  const uint8_t numEndpoints;
  const uint8_t numInterfaces;
  const uint8_t *endpointType;
  PluggableUSBModule *next = NULL;
  friend class PluggableUSB_;
};

class PluggableUSB_ {
public:
  PluggableUSB_();
  bool plug(PluggableUSBModule *node);
  int getInterface(uint8_t* interfaceCount);
  int getDescriptor(USBSetup& setup);
  bool setup(USBSetup& setup);
  void getShortName(char *iSerialNum);
private:
  uint8_t lastIf;
  uint8_t lastEp;
  PluggableUSBModule* rootNode;
};

PluggableUSB_& PluggableUSB();

#endif
#endif
そして、上のように「PluggableUSB.h」までを何度も精読しつつ実験した結果として、「このレベルではたぶん無理」と判明した。 つまり、ここで扱われているUSBMIDI関係のメソッド等は、全て「パラメータの読み出し」系であって、IDEの彼方にある、その「パラメータの書き込み」をArduinoスケッチのsetup()内から行うことは出来ないのである。 唯一、「MidiUSB.setup(・・・);」という書式の可能性を探ったが、ここでのsetup()というのはbooleanであって、ゼロか1の値を返すだけで、ここからシステム環境にあるであろう「USBMIDIデバイス名」については、上流まで辿っていってもし取得が出来たとしても、自分からここを設定する(書き換える)ことは無理なのだ。

その後、宿題として3つのアイデアがあった3番目、「mbedをシステムのUSB-MIDIデバイスとして認識させる」というのに取り掛かった。 元々、既にmbedのNucleoF401REについては、自前のFIFO利用のMIDIライブラリを完成してしまっているので、とりたてての必要性は無いのだが、せっかくArduinoで出来るのであれば、mbed NucleoF401REでも出来るかどうか試しておこう、というものだった。 そして午後じゅうかかって、色々と調べて、驚くべき事実が判明した。 途中経過を省略して結果だけ整理してみれば、以下のようなことである。

とても高性能で活用してきたNucleoF401REだが、まさかこんな所にヘンな弱点があるとは思わなかった。 ファームウェアのプログラミングを「ドラッグ&ドロップだけ」で実現する、というそのアイデア、そして全てのツールからライブラリまで全てWeb上でやる、というスマートさに感服したが、こういう弱点があったとは、驚きつつもかなりの収穫である。 僕はオリジナルのMIDIライブラリを完備しているので、とりたててこれは欠点ではないので、まぁ安心した。

2017年9月19日(火)

連休も明けて、いよいよ後期まであと2週間である。 新しくゼミに参加する山本さんとは、アポの時間を大幅に超過して2時間以上、インターンシップの収穫について、さらに後期「総合演習I」に向けてのアイデアなどについて議論した。 これからが楽しみである。 院生の馬ブンさんも午後にやってきたが、中国人は親戚のイベントが最優先ということで、今回は親戚の結婚式のために新学期までまた帰国するということで、後期の履修に関して教務室に行くように指示した。 リハビリや認知症対策のテーマについては、日本に戻ってきてから再開である。

YouTube

そして午後になって、奈良学園大からの機材返送も届いて、上のように、やりかけていた「PAW-eight」のためのOpen-GLプログラムを少しだけ改訂した。 前回はPAWセンサごとの4チャンネル出力の1個だけを利用していたのに対して、今回は簡易型ながら、それぞれのセンサの4チャンネル出力をそれぞれに対応させた光源の3次元空間内の位置に反映させているので、8個の光源を1箇所に集めるためには、8本の指の全てに対して、「うりうり」の微妙なバランスまで考慮したバイオフィードバック操作が必須となる。 これで認知症対策リハビリに持っていくにはさらにどうするか、ここからが考えどころだ。

2017年9月20日(水)

今日は放課後にOGの野口さんが「はやくスシになりたい」等の機材を返却にくるアポだけが入っているスカスカの日だったが、朝イチに届いていた辻下先生からのメイルで3回目のBFセミナーの日程が12/16-17と決まったり、ここには絶対に何も書けない大学の大事なお仕事関係の原稿を手直ししたり、なんと藤井4段の王座戦予選のライヴをabema.tvでやっているというのでBGV設定したり、と一気に密度が上がった。 そして何より、またまた昨夜に思いついた3つの予定(これはほぼ今年中かかる重いやつ)を整理して作業に入ったので、Max7日記の続きはちょっと今後、ペースダウンする可能性がありそうである。 後期がスタートしたら、これも細切れで作業していかないといけないので、残る夏休みに、少しでも進めていこう。

2017年9月22日(金)

昨夜は奥さんが箱根の美術館に行くというので早朝に駅に送って、午後も早めに帰宅してハムスターと留守番をしていたが、今朝、研究室に出てきたところにSMSが入って、遂に我が家の3代目のハムスターが旅立った、と連絡があった(;_;)(;_;)(;_;)。 ジャンガリアンハムスターの寿命はネットで調べると「2年〜2年半」とあり、まさに2年半も生きた彼は人間なら98歳ほどだという。 それも2年を過ぎたところで腹部の腫瘍が大きくなったのを齧り切って見つかったが、獣医も年齢と身体の小ささから何も出来ず「見守るだけ」と宣告されてから半年、この天候不順の夏から秋まで、どんどん痩せ細りながらも健気に生き続けたその生命力に圧倒された。

YouTube

上の写真は我が家に来て半年あたり、2015年12月16日の、まだ若々しい頃の彼である。 せっかくなのでiPadからここに転送してみた。 こんな日はお仕事も手につかず、「PAW-eight」のためのOpen-GLプログラムをさらに少しだけ改訂してオシマイである。

2017年9月27日(水)

愛するハムスターが昇天した後を追うように、9/24(日)の朝に、お仕事メインのMac miniが昇天した。 電源ボタンを押すと起動音がして電源インジケータLEDが点灯するが、何もディスプレイに出てこないのである。 その状態で電源ボタンを長押ししていると電源シャットダウンして、再び押せば起動音、つまりこの部分のハードウェアだけ、かろうじて生きている。 「Macが起動しない/起動に異常がある」という場合には、ネットで調べてみると以下のような対策 がある。 これを全部やってみたが、いずれにも該当しない、決定的に「何も出来ない」という状態であると判明した。 上記は全て、「画面に何か情報が表示される」という事が前提であり、 今回の昇天は問題外で駄目なのだった。 そこでSUACから徒歩5分のヤマダ電機に電話して、Mac miniの在庫を確認して取り置きしてもらい、速攻でカード購入してきて、 このように 慌てず騒がず、Time Machineのバックアップからの「システム復元」を進めた。 そして午前中から午後まで以下のようにタップリかかって、なんとかほぼ「元に戻った」(^_^)。 ただしSUACのネットワークシステムは、個々のPC/iPhone等のMACアドレスを事務局情報室に登録しないとネットワークに接続できない(DHCP出来ない)ので、これは休日は無理であり、さらに月火はアカペラ合宿なので、「MACアドレス登録申請書」をデザイン学部事務室に出したところで作業は終了した。

そして9/25(月)から昨日9/26(火)までの1泊2日、 アカペラ合宿 に行ってきた。 今年は欠席者も多かったが天気が良くて、もう昨日から早くも全身筋肉痛であるが、本当の全身筋肉痛は明日か明後日に来る、という確かな予感がある。 果たして「芍薬甘草湯」は効くだろうか(^_^;)。 月曜日の出発前、朝の集合までの間に調べてみると、今回昇天したMac miniはまだ購入1年以内で無償修理期間内だったので、Appleサポートに電話して、木曜日には修理回収業者(ヤマト代行)が取りに来ることになった。 生き返ったら、懸案だった「シリアルUSBドライバのバージョンを下げる」という実験が出来るかもしれない。

そして午前には、後期「インタラクティブプロダクト演習」の教材として、開発者の長谷部さんに直接、発注した20個はおいおい届くとして、別途に僕のところに購入して先に届いたTouchMIDI32の5枚を、まずは このように 加工して、いつでも使えるようにした。 他にもArduino UNO、Arduino nano、Arduino micro、NucleoF401RE、などあれこれ品揃えが整ってきた。 これはBFセミナーに向けて、さらにまた来年2月に開催予定のMedia Design Week Workshopに向けて、きちんとWebサイトを整備していく準備でもあり、これが「この年内の3つの大きな目標」のうちの一つなのである。

ここでフト気づいたのは、上のようにFirefoxのツールバーの右端に、噂の「Firefox screenshot」というボタンが現れていたことである。 これはたしか、ブラウズしている画面の全体(スクロールしないと見えない部分まで全部)を1枚の画像にするという、一見すると便利な機能であるが、実はプライバシーを完全に無視したものなのだ。 このボタンを押してscreenshotを撮ると、とりあえずその画像がMozillaのサイトに自動でアップロードされて蓄積されてしまう、という恐ろしい機能である。 これを欲しければもちろんダウンロード出来るものの、Mozillaのサイトに貯められた画像データは消せないし、他の誰かに見られることも、Mozillaが蓄積して個人プロファイリングその他に利用することも、全て同意したと見做される、というものなのだ。 さっそく、 このページ を発見して、以下の手順を実行して、無事に消すことが出来た。 これは今後のFirefoxのアップデートでおそらくまたdefaultでは「出てくる」ので、以下のように手順をまとめておいた。

その後、午後は懸案のスケッチングサイトの制作(正確には過去のページの内容改訂)を進めた。 完成してから公開する予定なので当面はクリックしても「謎のNot Found」が出るが(^_^;)、およそ ここら になる予定である。

2017年9月28日(木)

新学期直前の週末である。 午前中にはアップルから修理PCの引き取りに来る予定があり、午後にはデザイン学科会議で後期に向けてのあれこれを相談して、明日の午前はデザイン学科1回生ガイダンス、午後はデザイン学科2回生ガイダンス、続けてビジュアルサウンド領域2回生ガイダンスがある。 実はさらに土曜日に後期直前アカペラ有志とのカラオケマラソン7時間の予定が立っているので、余裕の週末なのだ。

そんなテンションでふとヤフオクを眺めていて、新品未開封の「原色図典 日本美術史年表 集英社 定価18000円 1986年 560ページ」2,187円というのを、勢いの大人買いで落札してしまったのだが、ここで驚きの現象に遭遇した。 ゆうパックの送料800円を含めて、合計2,987円をカードで支払ったつもりなのに、なんとヤフオク画面では勝手にTポイントから1,325円が引かれて、それだけ安く買えてしまった。

僕はYAHOOにログインするたびに出てくる「Tポイントへの入会」という画面をいつも執拗に拒否し続けてきたので、これはとっっっても気持ち悪いのだ。 Tポイントと言えば、ツタヤのデータベースに全ての個人情報や購入履歴が蓄積される、という悪名高いプライバシー侵害の巨塔であり、もちろん僕はTポイントカードも持っていないし、登録申し込みをした事もない。 ところがヤフオクには僕の個人情報やカード情報も登録されているのだが、今回のこれで、YAHOOからTポイントに勝手に個人情報が繋げられている、という事が判明したのだ。 1300円安く落札できてラッキー、というよりは、朝からなんだか気持ち悪いスタートとなった。(^_^;)

そしてここから午前中、タイムスリップのような体験をした。 上のヤフオクの出展者の「その他の出展」というのを見ていたら、なんと上のような「初代メトロイド・攻略本」というのが出てきた。 僕は一切、ゲームをやらない人間だが、かつて1本だけハマりまくったのが、この初代ファミコン・ディスクシステム用の「メトロイド」だったのだ。 当時まだサラリーマン(研究開発者)だった僕は、仕事の関係でファミコンの音楽ソフトを解析(クリアするまでやってボーナスステージの「作曲モード」を調べる)したりしていたが、そこで登場したファミコン・ディスクシステムの調査のために、お仕事で朝から晩までこれを続けて、最後にはクリアしていた。 そこで必要なのが、マップその他の攻略法の載った「攻略本」であり、この本にはお世話になったのだ。 なんと定価480円のものが、ヤフオクとアマゾンをじっくり調べてみると、この2,430円というのが一番、安かった。

たしか僕の力では、クリアするのに10時間以上もかかったのだが、調べてみると上のように、1時間半ほどで正規にクリアする、という動画もいくつか上がっていた。 初代メトロイドは、今回出てきたファミコンミニにも入っているので、久しぶりに挑戦するのもいいかな・・・と思いつつ調べていると、なんと下のように、8分19秒でクリアするという超絶裏技バージョンもあり、伝説の「ビキニエンディング」をここで初めて見ることになった(クリア時間でエンディングが変わる。僕はレオタードエンディングまで)。 しかし逆にこれを見て、10時間とか20時間とかをかけてこのゲームを再び、最初から最後までやるという「暇」と「気力」はもう今の僕には無い、という事実に気付いて、一気に萎えてしまい、ヤフオクの入札を断念してこの件は終了となった。(^_^;)

そして午後の3限と、学科会議を挟んで5限にわたって、やりかけていたPAWセンサを使った「微妙な触覚フィードバック」の追求を進めた。 以下のYouTubeは、動作させているデモではなくて、8個のサブパッチを順にコピペして改訂している、最後の8個目のプログラミングの様子である。 たまには、こういうのもいいだろう。(^_^;)

YouTube

結果として、かなり想定しているような動きになってきたものの、8本の指を全てコントロールして8個の光源を中央の球体内部に閉じ込めるように移動させるための制御は、とんでもなく難易度が上がってしまった。 狙った以上になってしまって当惑したが、せっかくなのでこの方向で進めていくことにした。 あと少しで、とりあえずこのシステムで想定しているものは仕上がりそうな気がするが、これを後期「メディア数理造形演習」の初日に見せるかどうか、はまだ未定である。

2017年9月29日(金)

たくさんのファイルを延々と同時並行処理していると、Macではデスクトップ(というフォルダの内部処理)が満杯になるのか、アイコンが出てこなくなったりする。 そのためのTipsは、 「command」+「option」+「esc」キーを押して「アプリケーションの強制終了」ウインドウを開き、「Finder」を選択し、「再度開く」ボタンをクリックして「Finder」を強制終了(再起動)させる である。 これはとりあえず、ここにメモしておこう。 つまりは今朝もこのトラブルからスタートした、という事である(^_^;)。 来週からの後期開始を前に、今日の午前にはデザイン学科新入生ガイダンス、午後には2回生ガイダンスと引き続き領域別ガイダンスがあるのだが、考えてみれば午前のガイダンスは、プログラムに僕の出番は特に無くて、関係教員以外の出席はご自由に、という事だった。 そこで、昨日に届いていた20枚のTouchMIDI32基板にコネクタを付ける、という作業を、午前〜昼休みまで このように 進めて、以下のように完了させた。

そして午後イチで永田さんのアポで、前期に「サウンドデザイン」を履修しなかったものの後期に「メディア数理造形演習」を受講するための特訓補習を行う、という相談をして、さらに2回生ガイダンスと領域別ガイダンスに参加した。 前期の講義で顔を知っている多くの学生がいて、アウェー感が無かったものの、この中でインタラクティブをしたい、という学生がほとんどいない、という現実は変わらない(^_^;)。

そして、ここにAppleからメイルが届き、上のように「修理完了したので送る」とのこと。 ただし、「修理の詳細」をクリックしてもそこには何も中身が無く(^_^;)、どうなったのかはまったく不明である。 素晴らしく迅速で、素晴らしくお役所的な対応にちょっと感銘を受けた。 リンク先のクロネコヤマトにはまだ伝票番号の登録確認が出てこないので、電話して受け取るのは来週になりそうだ。

2017年10月1日(日)

昨日はいつものBIG ECHOでなく、榎本さんがバイトしているというジャンカラでアカペラの榎本さんとちひろちゃんと3人で7時間カラオケ。僕は2人が(バイトに)帰った後、フリータイム終了までさらに1時間粘ったので計36曲とまずまずだった。 そして今日は休養日、いよいよ後期に向けて、「インタラクティブプロダクト演習」の初日について検討して、場所をマルチメディア室にすると こんな感じ で出来ますよ、と的場先生にメイルした。 実際には GHI2014 はやらないのだが、せっかくなので、明日と明後日の2日で、上のような品揃えでの「オリジナル楽器」のデモを準備して、木曜1-2限の「インタラクティブプロダクト演習」初日だけでなく、金曜4-5限の「メディア数理造形演習」初日でも学生に見せよう、という作戦である。 だいぶ昔のものなので(「光る絃」インスタは外部ビデオカメラからIEEE1394入力していたが、今であればUSB-WebカメラやMac内蔵カメラで実現できる筈)、最近のMax7にリプレースするには、そこそこMaxプログラミングを楽しめそうである。

2017年10月2日(月)

後期初日である。 放課後に1回生男子2人の履修相談アポが入っていたが、さらにアカペラメンバーでもある涼音+芽生の2人の履修相談アポも朝イチに入って、いよいよ始まるんだ・・・という雰囲気が高まる。 こういう節目だからこそ、ということで、お仕事Mac miniと研究室MacBookAir(3)と出張用MacBookAir(4)とで、微妙にバージョンに齟齬がある研究関係のデータを統合整理する、という作業に取り掛かった。 まずは以下のように、お仕事Mac miniの「ファイル共有」をONにして、2台のMacBookAirそれぞれからログインして、転送領域としてお仕事Mac miniのデスクトップを利用する、という作戦である。

1限の涼音+芽生アポで、デザイン学科1回生の履修登録のおよその雰囲気を掴めたが、その後も今週から来週に、次々に新入生からの履修相談アポが入ってくる中、2限をマルマル使って、ようやくお仕事Mac miniと研究室MacBookAir(3)と出張用MacBookAir(4)とのデータ同期をとりつつ最新に更新完了した。 地味な作業だが、これを節目でやっておかないと、次第に齟齬が拡大するので、いい機会となった。 ついでに裏作業として、認識されないトラブルに遭遇していた3台のHDDもフォーマットを完了して、一応「復帰」させてみた。

そして昼休みには、修理に出していたMac miniがAppleから返ってきた。 上のようにHDD交換ということで、ちゃんとOSは10.11.6にしてくれているようで、Time Machineからバックアップすれば元に戻るようだが、もしかすると壊れたやつのHDDは250GBほどだったので、今回500GBの新品で返ってきた、というのはなんだか得した気分でもある(^_^;)。 この復元にはほぼ半日かかるので、走らせておいて、その横でいよいよ、「新楽器デモ」のためのMaxプログラミングに取り掛かった。 その合間にもどんどん履修相談のアポのメイルが届き、以下のようにどんどん埋まってきた。 まさに新学期初日である。

そして無事に修理済Mac miniが立ち上がり、午前の作業で整理統一されたMax環境などを反映させよう・・・と調べていて気付いたのは、まさにTime Machineから復元させる直前にこの作業が午前中で終わっていたので、その最新のTime Machineから復元された修理済Mac miniのMaxデータは、当然ながらその最新になっていたのだった。 作業の様子は こんな感じ である。 その後、修理済Mac miniを片付けて、「光る絃インスタ」・「MRTI2015」・「Cyber Kendang」・「Peller-Min」という4つのかつての新楽器のためのMaxパッチを発掘してMax7版に差し替えたりした。 「Cyber Kendang」については、ニューヨークでの公演のパッチは楽器本体とちょっと関係ないので、「叩いたら光る」だけのデモとして、公演の記録ムービーを見せるために用意した。

ネット上では、「2ちゃんねるが5ちゃんねるになった」という訳の解らない話題で盛り上がっていたが、上のようにニュースヘッドラインが「見えなく」なってしまい、いちいちクリックして中身を見ないといけない、という困った事になった(後に このスクリプト ならOK、という情報も出てきたが)。 いつもたいてい、一瞥して10個か20個ぐらいに1件、チェックしたい記事があり、あとはほぼゴミなので、この状態では使い物にならない。 後期が始まったことでもあるし、ここらでニュースソースとしての2ちゃんねるニュースヘッドラインと決別すべきタイミングなのかもしれない。 およそ14年間〜15年間ほどお世話になってきたが、まぁ無くても困らないのが2ちゃんなのだ。

2017年10月3日(火)

後期2日目。 放課後には久しぶりのアカペラ、というテンションで5時起きして研究室に出て、「メディア数理造形演習」のページを改訂していると、いつものようにSketchingコミュニティMLからのメイルが届いた。 中身は以下のようにシンプルなもので、自分のスタジオのオープンスタジオに来てよ・・・という、アメリカ西海岸の軽いノリの案内である。 きっと、シリコンバレーのSketching関係者は、ドライブがてら遊びに行くのだろう。

Hi Sketchers!

I wanted to invite you all to our shop-warming open house this weekend:

When: Saturday, October 7, 4 pm to 8 pm
Where: Evil Mad Scientist Laboratories
1285 Forgewood Avenue, Sunnyvale, CA 94089

Our annual open house is also a shopwarming party this year! You can tour our new location, 
see the MOnSter 6502 in action, check out an AxiDraw demonstration, maybe meet Zener 
the cat (she’s not fond of parties), and share in food and conversation.

We’d love to see you!
Lenore

さすがにこの週末にこのためにカリフォルニアには行けないが、たまたま 彼のサイト ( PDF版backup 、中に埋め込んであるYouTubeは これ ) "Making the World a Better Place, One Evil Mad Scientist at a Time" を覗いたところで、驚くべきものを発見した。 以下のように、なんだか凄い基板である。 さっそく、 このページ (中に埋め込んである動画は これ ) に行ってみると、「トランジスタで6502を実現した」というクレイジーなものだった(^_^;)。

6502といえば伝説のAppleIIやファミコンの心臓部であり、何より、僕がKAWAIで最後に作ったLSI(CPUコア内蔵音源LSI)の心臓部もまた、この6502なのである。 内部は3000トランジスタほどのシンプルな8ビットCPUであるが、データバスが完全に50%サイクルで動くので、ファミコンではCPUの50%サイクルの裏拍(CPUがアクセスせず内部処理しているタイミング)で、グラフィックLSIがこのバスを利用することで当時としては傑出したパフォーマンスを実現した。 もちろん僕の設計したチップでも同様にこのサイクルスチールを実現して、電子楽器制御のCPU処理のパフォーマンスを低下させることなく、裏側のタイミングで音源(楽音合成信号処理)データ転送を行うことで、チップ価格あたりのパフォーマンスとして傑出したものとなり、キーボードやシンセサイザーや電子ピアノなど、多くの製品で活躍したのである。

この基板は基本的に6502を置換できるが、クロックスピードは60kHzと相当に遅い。 当時の6502でも2MHzあたりだったが、これはトランジスタでは当然、無理なので仕方ない。 この方法で68000を作ると1.7メートル四方の基板になるらしいが、作るつもりは無いという。 これは、少なくともこのクレイジーなSketching仲間に熱いメッセージを送るしかない・・・と引っ張り出してきたのは、僕が1990年頃?に作ったチップ(中身が見える)2種である。 以下のようにスキャンしてみると、あれこれ思い出してきた。

左のチップKTG101は1.5ミクロンルールで作った音源LSIで、同時発音数16チャンネル(個別panpot・個別音色)・ステレオ出力する約15,000ゲート(2入力NAND換算)のLSIである。 そして右のチップK009-FPが6502CPUまで内蔵した1.2ミクロンルールの音源LSIで、同時発音数16チャンネル・ステレオ出力の楽音合成信号処理を、CPUと同じバスで実行する(CPUプログラム用と音源データ用のマスクROMを共用してパフォーマンスを下げずにCPUから音源パラメータをリアルタイム制御できる)、という優れものである。 チップ上のブロックにちょっとだけ解説を加えたものが これ である。

CPU以外のディジタル信号処理回路の部分については、 作るサウンドエレクトロニクス の第5章、 ディジタルシンセサイザ のところに解説している。 上はその全体ブロック図と、実際に製作した基板の写真である。 以下の3枚でその回路図全体となる。

この基板の写真は当時のデジカメがしょぼかったのでちょっと撮り直して、以下のようになった。 まぁ、サイズはVGAなので、あまり変わり映えしないのはご愛嬌である(^_^;)。 このシステムは「LSIの音源DSPをロジックICで実現した」というところも凄いが、実は本当に凄いのは、AKI-H8でアセンブラで実装した「MIDI音源」ソフト(ファームウェア)なのである。 MIDI割り込み受信、そして16チャンネルの音源に対して刻々とピッチや音色やエンペロープ情報を転送するわけだが、重要なのは「 アサイナ 」である。 既に16音が鳴っているところにさらに新しい「発音ON」情報が届いたらどうするのか・・・というのは楽器業界では伝説的な難問であり、少なくともこのシステムではハードウェアだけでなく ファームウェア としても完成しているのである。

さらに、 作るサウンドエレクトロニクス の付録CDROMの販売をやめて久しいので、そこに入っている全てのテキストファイルをzipにまとめたものと、付録CDROMに収めたAIFFサウンドファイルをmp3化してzipにまとめたものを以下に置いてみた。

そして2限にはデザイン学科新入生3人(同じ熊本の高校から来た、というのも素晴らしい)の履修相談アポがあり、午後には4回生の卒制に関する相談アポ、と次々に予定をこなしつつ、来週末に予定している水戸行きの宿でようやくキャンセル待ちで取れたり・・・と些事もこなして1日が過ぎた。 充実しているがなかなか綱渡りの日々である。

2017年10月6日(金)

さすが新学期、日々が一気に過ぎていく。 一昨日の10/4(水)には1限に準備をして 2限にゼミ 、午後にはこれら機材を台車でソロソロとマルチメディア室に運搬して、5限には「Max特訓講座(1)」、さらに放課後に履修相談の1回生男子が4人来訪して、あっという間に1日が終わった。 ただし合間には、来週末に備えてGoogleMapで 「バーチャル水戸」散歩 して、宮町〜南町〜水戸駅から久しぶりの母校まで行ってみたりした。

そして昨日の10/5(木)の朝イチからの1-2限は、いよいよ「インタラクティブプロダクト演習」の初日であり、1限の全体ガイダンスに続いて、2限の後半では全員にマルチメディア室に移動してもらって、現場で設置してあれこれ「新楽器」のデモと体験などをした。 これは相当に大変だったので、せっかくマルチメディア室に運んだ機材を活用して、さらに今日の4-5限の「メディア数理造形演習」でも、学生に見せるという作戦である。 実際には、Peller-Minを現場で組み立ててデモったところ、小さい方のリングのセンサ出力が出なくて、大きなリングとブルーLEDの「空中モミモミ」だけという変則的なデモとなった。 講義が終わって撤収(別の講義があるのでいったんバラして片付ける)の際に気付いたのだが、リングから出ているセンサケーブルのコネクタのうち、commonの電源ピンが緩んで引っ込んでしまっていた。 さらに、大きなリングからのセンサケーブルのうち1本が以下のように断線してしまった。

そこで今日、10/6(金)の朝イチでマルチメディア室に行って両方のリングを1106に持ってきて、 このように 断線をハンダ付け修理した上で、コネクタ部分をグルーガンで保護してみた。 考えてみると、グルーガンでコネクタ部分を保護補強する、というテクニックは、まだPeller-Minを作った頃には徹底していなかったのだが、これで 夏休み中の修理 と合わせて、完全にPeller-Minが「今後も使える楽器」として蘇ったことになる。

そしてせっかくの「Max7日記」なので、午前中に、昨日のデモで用意したものをここで整理しておくことにした。 上は、説明のために見せる様に用意したmovieで、改造三味線、改造ジャミネータ、そして僕の作った新楽器を神戸やバンクーバーやニューヨークやエカテリンブルクやオスロでのコンサートで公演している記録ムービーの一部である。 実際には全て、 YouTubeのリンク のページから行くことが出来るので、講義の中で紹介するのは「ごく一部」となる。

上は、「Image_Harp」というディレクトリの最新の「test012.maxpat」を開いて、さらにサブパッチも全て開いた様子である。 「光の絃」からのMIDI情報を受けて、Macの内蔵音源のハープの音で鳴らしているが、pipeで送らせてベロシティを段階的に下げた処理によって擬似的なエコーがかかっている。 jitterでライヴカメラ画像を表示して、その中でキーボードの「a」「b」「c」「d」を押しては「光の絃」の四隅の場所をクリックすることで、任意のセッティングの現場で、演奏に応じて放射状に出てくるCGパターンの位置を設定できるところがミソである。 メインパッチがとても小さいのは、当時のMacBookの画面のためである。(^_^;)

上は、「Peller-Min」というディレクトリの最新の「untouchable_027.maxpat」を開いて、さらにサブパッチも開いた様子である。 実際には、FM音源のサブパッチは8チャンネルそれぞれに4パターン、計32個あるが、ここでは1チャンネルの4パターンの4個だけしか開いていないので、もっともっと内部的には凄いことになっているのである。 これは今回の講義デモ(学生も体験)のためにサッと作ったものであり、コンサートで公演したものとは違う。

上の左側は、「UniUni_single」というディレクトリの「uniuni_voice_sample.maxpat」である。 これはPAWセンサを初めて実験した時のもので、NucleoF401REからMaxにシリアル伝送している。 自動4音シーケンサで、PAWセンサからのパラメータ4種で擬似的なフォルマント合成をしている。
上の右側は、「UniUni_single」というディレクトリ内の「宮本」ディレクトリの「4nen_2nd_02.maxpat」である。 「音楽情報科学」を4回生で受講したメディア造形学科の宮本さんが、「いやらしく触ったらいやらしい音が出るインスタ」を目指したものだが、実際にはとても可愛らしくなった。 デモではこのパッチでなく、実際に「音楽情報科学」の最終合評で宮本さん自身がデモっている動画を見せることにしている。 僕がうりうりやって宮本さんの声をいじくるよりも、ずっと本人バージョンの方が優れているのだ。

上は、「Multi_Uniuni」というディレクトリの最新の「MultiUniuni_09.maxpat」を開いて、さらにサブパッチも全て開いた様子である。 これは去年の欧露ツアーでオランダやロシアなどでデモったもので、その前年、2015年にアリゾナのスケッチングと、シンガポールのサイエンスミュージアムでデモッったものからバージョンは変化していない。 そして残り2つのMaxパッチは、「PAW-eight」と「OpenCampus2017」であり、前者はまだ開発中、後者はこのMax日記で作っている様子を中継したので、ここで再びパッチのスクリーンショットを載せるのは省略する。

YouTube   YouTube   YouTube   YouTube   YouTube   YouTube   YouTube   YouTube   YouTube

そして4-5限は、 このように 豊富な「メディア数理造形演習」初日となった。 今年は精鋭9人、3チームでビッグな成長を期待したい。 初日からヘトヘトになったが、この手応えは何物にも代え難い。 なんといっても明日には、またまたアカペラの2人と8時間マラソンの予定があるのだ。(*^o^*)

2017年10月8日(日)

今日は昨日のカラオケマラソンの休養日であり、明日も祝日ということで、講義の続く週の後半と対照的に、のんびりした連休である。 昨日の僕のリモコンの「りれき」の途中経過は以下のようにある意味で異常だったが(^_^;)、無事に35曲を完走した。

これは、何ヶ月か前にAmazonで予約していて最近届いた、以下のDVDを2夜連続で視聴して、僕の陽水レパが驚くほど含まれていたので、ここでさらに充実させよう、と「知っていたがリストに加えていなかった」4曲までトライしたためである。 しかし、ヤフオクで多量に仕入れたシングルCDの約70曲がここに加わるには、まだ時間がかかるだろう。 そして休養日と決めていたこの日は、あれこれYouTubeの動画を見てさらにその横にあるリンクから別の動画を見て・・・という怠惰な時間をまったりと過ごした。 世間も連休であり、学会とかからのメイルも無く、こういう日もいいものだ。

そして夕方になって、事態は急変した。 近所(徒歩5分)の遠州病院の休日急患診療窓口に電話したところ「今日は当番日ではない」と断られ、紹介された当番日の聖隷三方原病院までSUACからクルマで40分かけて行き、連休で混雑している休日急患診療の受診に1時間以上待たされ、帰宅したら20時半になった。 この詳細は次の日の日記として書くことにしよう。

2017年10月9日(月/祝)

さて、昨日の晩に、以下のようにSUACからわざわざ聖隷三方原病院まで行った、という「病気」のお話である。 しかし、この伏線は、ちょうど Max7日記(part6) の最後の「2017年4月20日(木)」から、 続・Max7日記(part1) の冒頭の「2017年8月1日(火)」までの空白の期間、たしか6月あたりに、もう一つ、あったのだ。 せっかくなので、話はここからスタートさせることにした。

蜂窩織炎

思い返してみると、まだあった。 伏線はさらに数年前の昔に遡る。 僕はアトピー体質で、耳鼻科で処方してもらっている「アレグラ」を一年中飲んでいるだけでなく、いつも遠州病院の皮膚科でたくさんのステロイド軟膏を処方してもらって、日々、症状に応じて微妙に使い分けしつつ塗布している。 せっかくなので列記すると以下である。(^_^;) アトピーの宿命として、夜中に寝ていて無意識に痒いところを掻くので、朝に起きて気づくと患部が赤く腫れていたり、傷ついていたりする。 そして何年か前に、太腿の裏側あたりをいつものように掻いた傷に黄色ブドウ球菌が入って、ひどく腫れて発熱して、抗生物質の投与とともに最終的には皮膚科で切開して膿を出してもらって治療した、という事があった。 この病名が「蜂窩織炎」(ほうかしきえん)というものだった。 YAHOO検索で「蜂窩織炎 画像」とやると強烈なのばかり出てくるので、この画像は省略である。(^_^;)

滑液包炎

そして今年のたしか6月あたり、またまた左肘のあたりを無意識に掻いたらしく、腫れてきた。 上の写真はネットから拾ったものだが、だいたいこういう感じだった。 場所が肘だったので、一応、整形外科に回されてレントゲンやエコーも撮ったが、骨や関節に問題はなかった。 どうせまた黄色ブドウ球菌が入ってしまったのだろう・・・と抗生物質をもらったものの、3日してもまったく効かずに腫れと患部発熱が続き、整形外科で採っていた組織培養の結果、判明したのは、MRSA(耐性黄色ブドウ球菌)による「滑液包炎」(かつえきほうえん)というものだった。 普通の抗生物質が効かないのは当然で、ステロイドや抗生物質「ジスロマック」好きの僕の体内で、常在菌である黄色ブドウ球菌は抗生物質に耐性を持つMRSAに進化していて、これが肘の関節にある「滑液包」というところにまで入ってしまって炎症を起こしたのだった。

帯状疱疹

そして今回の話に繋がってくる。 3日前ぐらいから、目覚めた時に右の脇腹の付近が寝違えたように痛くて二度寝できない、というのが毎日、続いていた。 これはネットで調べると典型的な初期症状なのだった。 そして昨日の朝、いつものシャワーを浴びると、右胸の乳首の下あたりに、帯状に赤く腫れているのを見つけた。 また寝ている間に掻いたんだろう、と、いつもの「リンデロンVG」を塗って大学に来た。 これを塗っておけば、半日もしないうちにアトピーの腫れは収まるのである。

ところが午後になって、その部分がなんだか熱い、と気になって見てみると、朝よりもしっかり赤くなっていた。 上の写真は、デジカメで自撮りした、僕の患部である。 そこでネットで調べてみると、どうやらこれは「帯状疱疹」(たいじょうほうしん)らしい、と判明した。 またまた4文字熟語みたいな病名である。 子供の頃にやった「水ぼうそう」の「水痘・帯状疱疹ウイルス(Varicella-zoster virus)」が神経節にずっと潜伏していて、なんと半世紀もたった今、「ストレス、心労、老齢、抗がん剤治療、日光等の刺激などにより免疫力が低下」という原因で、出てきたというわけなのだ。 まぁ、飲み続けていて免疫力低下、というのはあまりに思い当たる(^_^;)。 紅斑がちょうど肋骨に沿って、つまり肋間神経に沿って並んでいるので、まさに教科書通りと言えそうだ。

ネットによれば「なるべく早期に医者に行け」とあったので、ちょうど連休で遠州病院の皮膚科に行けるのは早くても火曜日の朝だからと、日曜の夕方に遠路、聖隷三方原病院の休日急患診療にまで出かけたのである。 しかしこれは正しい選択だったようで、診察してくれた医師は「もしかしたら」という2種類の軟膏を処方しかけていたところ、たまたま聖隷三方原の皮膚科の先生が院内にいたので来てくれて、一瞥した瞬間に「間違いなく帯状疱疹」と断定してくれた。 そこで、「ゲンタシン軟膏0.1%」(細菌の増殖を阻害)と、「ファムビル錠250mg」(帯状疱疹ウイルスの増殖を抑制)と「カロナール錠200」(解熱鎮痛)とを処方してもらい、火曜日の朝に遠州病院の皮膚科に行くための紹介状を書いてもらった。 悪化する前に投薬が始まったので、昨日の晩のどたばたは正解だったようだ。 この週末に予定していた水戸行きはキャンセルで、つくばの母親のところに行く日帰りに変更となったが、まぁしばらく断酒ということで、やれやれである。

YouTube

そして、ここは大人しくMaxプログラミングするしかなくなったので、午後までかけて久しぶりに、"PAW-eight"センサをインターフェースとするMaxパッチを上のように進めた。 大きな進展としては、8つの光源から座標中心(中央の球体)までの距離の総計をバーグラフにまとめたこと、そして懸案の「自動で座標回転・ズーミング・反射球体サイズを刻々と変化させる」というのを実装してみた。 フルスクリーンにするとなかなかの迫力であるが、まだまだインターフェースとしての操作性については満足できない。 これは僕の習熟が不足しているためなのか、基本的にHCI設計に問題があるのか、もう少し検討していくことにしたい。

2017年10月10日(火)

この日は朝イチで遠州病院の皮膚科に行って、帯状疱疹の治療の続き「ファムビル錠250mg」(残り5日分)と「カロナール錠200」(1週間分)をもらって来週火曜日に再診の予約をした。 その後さらに、月イチの耳鼻科主治医に行って、鼓膜のアトピーのお掃除とアレルギー関係の薬一式の処方をもらって大学に帰ると、既に昼休みになっていた(^_^;)。

そして午後には、 Max7日記(5) の最後、さらに Max7日記(6) の「2017年3月21日(火)」のところに整理した、懸案に取り掛かることにした。 怪我の功名というか、お仕事Mac miniが死んで新品を買い換えてTime Machineで全環境を戻して、さらに無償修理で返ってきたMac miniにもTime Machineで全環境を復旧しているので、いまここで、このお仕事Mac miniでカーネルに関する実験をして失敗したところで、Time Machineには30分前までの全てがBackUpされていて、いつでも最悪はHDDをフォーマットしてから全環境を復元できる(その間、お仕事には何も差し障りがない)、という状況になったので、心置きなくこの恐怖の実験に進めるのだ。 ターゲットは Fixing FTDI InBufferSize for OS X にあるように、上のFTDI USBドライバを、「最新のv2.3から安定版のv2.2.18に戻す」(それぞれをインストールした時の環境構築方法が異なるので、旧版の単なる上書きでは駄目)という作業である。

Step 1: open Terminal

そして以下のように、 このページ をテキストとして画面内に置いて、慎重にステップを追って真似ていく、という作業に取り掛かった。 「Step 1: open Terminal」ではターミナルを開くだけであるが、ここにさりげなく「!!! WARNING !!!」として「Be very careful when using the sudo rm command. It is used to remove files from your system. Never EVER enter the following command by itself, without specifying a filepath. That will wipe your hard drive.」と書いてあるが、本当に「sudo rm」だけをするとHDD内のシステムが全て消えてしまう(^_^;)のだ。

Step 2: Remove any existing FTDI drivers & reboot

いきなりである。 マシン内の全てのFTDIカーネルを消す、というもので、まず2.3を消すために「sudo rm -rf /System/Library/Extensions/FTDIUSBSerialDriver.kext」と打つ。 そして2.1.18を消すために、「sudo rm -rf /Library/Extensions/FTDIUSBSerialDriver.kext」と打つ。 ファイルパスの指定をしないでリターンを押せばお陀仏である。 そしてコンピュータを再起動である。

Step 3: get the FTDI driver (2.2.18, not 2.3)

ここで、最新の2.3でなく2.2.18のFTDI driverをゲットせよ、とある。 僕は上のように既に持っており、確認してみたが64ビット版だった。 解凍すると「FTDIUSBSerialDriver_10_3」と「FTDIUSBSerialDriver_10_4_10_5_10_6_10_7」の2つがあるが、もちろん後者でインストールする。 以下のようにインストール終了時に再起動を求めない、というのはちょっと意外だった。

Step 4: enable dev mode

これはなかなかトリッキーである。 kext fileを手作業で編集していくのだが、「kext dev mode」をenableして、さらに「signature verification」をdisableする必要がある。 OSX10.10とそれ以前の場合には、ターミナルから「sudo nvram boot-args="kext-dev-mode=1"」としてから次の「Step 5: reboot your computer」でいいのだが、僕のはOSX 10.11.6なので、以下のようにするのだという。 これはスクリーンショットを撮ってプリントしておかないと忘れそうだ(^_^;)。

Step 6: plug in your dongle

上記の「csrutil disable」に対してsuccessfulが出てきたので再起動してここに来た。 ここでスライドスイッチをGPIO6(resetではない方)にしたOpenBCIドングルを、以下のようにUSBに挿した。

Step 7: unload the FTDI kernel extension

ターミナルに「sudo kextunload /System/Library/Extensions/FTDIUSBSerialDriver.kext」と入れる。

Step 8: make sure it’s unloaded

ターミナルに「kextstat | grep FTDI」と入れる。 全てがうまく行っていれば何も出ないというが、確かに以下のように何も出なかった。

Step 9: open the Info.plist file:

ここでいよいよ、FTDIドライバの環境設定ファイル「Info.plist」を編集するのだが、ターミナルから行うので、「emacs」か「vim」(viの拡張版)を使わなければならない。emacsなら「sudo emacs /System/Library/Extensions/FTDIUSBSerialDriver.kext/Contents/Info.plist」、vimなら「sudo vim /System/Library/Extensions/FTDIUSBSerialDriver.kext/Contents/Info.plist」でいいのだが、実は僕はどちらもほとんど使ったことが無いのだ(^_^;)。 そこで Emacsの基本的キー操作 というページと、 Vimの使い方 基本操作まとめ というページとを眺めた結果、とりあえず以下のように、後者のVimでいってみる事にした。

Step 10: edit the config data

探す場所は“FT X Series”のconfigデータなので、ひたすら「ctrl+f」で下スクロールして行き、該当する場所を見つけた。 このページ には「BEFORE」と「AFTER」が上下に並んでいるが、どうやら「dict」の次からの16行はまったく同じで、ここに新たに「ConfigData」と「dict」「/dict」で挟まれた、計5行を追加するだけらしい。 ここはブラウザからターミナル(Vimはインサートモード)にコピペが効いて、以下のようにたぶん修正できた。

Step 11: save & close

まだまだ安心できず、ここが肝心である。 この修正を保存する必要がある。 Vimでは「esc」でコマンドモードに戻り、「:wq」で保存してquitできた。

Step 12: reload the kernel extension

まだまだ恐怖のsudoコマンドが続く。 「sudo kextload /System/Library/Extensions/FTDIUSBSerialDriver.kext」 とやって、カーネル拡張をリロードした。 体感では、コマンドからカーソルが戻ってくるまでに「一瞬」の時間があった(およそ100msecほど)ので、内部的に相当な処理が行われた筈である。

Step 13: make sure it’s loaded

ここでまたまた確認である。 「kextstat | grep FTDI」 とやると、今度は以下のように2.2.18がキチンと表示された。

Step 14: have fun with real time data

これでオシマイである。 「Open the OpenBCI Processing GUI (or other software), connect to your device, and begin streaming the data. Check out the improved latency!」 とある。 最後のコマンドサンプルは「\m/-(^.^)-\m/」であった。

なんとなんと、長らくの懸案だった「FTDI-USBドライバのバージョンを下げる」という危険な改造が、これで出来たことになる。 調べてみると、この懸案の発端となった Max7日記(5) の最後、さらに Max7日記(6) の「2017年3月21日(火)」というのは、いずれもTWE-Lite関係でストップしていたところであり、OpenBCIはもっと前だった。 これはまたまた、どこまでやってきたのかを「発掘」する必要がありそうだ。

YouTube

とりあえず「お仕事」directoryにあった、OpenBCIのツールで試した感じでは、上のようになんとなくスムースになったような気がする。 同じところにあったMaxパッチも走らせてみたが、このデータフォーマットはもはや忘却の彼方であり、過去の実験を発掘する必要がある。 とりあえず、トラブルもなく「FTDI-USBドライバのバージョンを下げる」ことに成功したので、機会をみて、MacBookAirの環境もこれと同じようにしてみたいが、まずはOpenBCIのMax料理、というのが目標となった。

2017年10月11日(水)

帯状疱疹の経過はまずまずで、治療スタートが遅れると七転八倒するらしい痛みも、6時間ごとの鎮痛剤を飲んでいれば肋間神経にピリッとくる程度である。 患部の紅斑も、想定された水疱が出てきたものの、患部が広がることもなく、赤みも幾分、収まってきたように思える。 そんな朝、2限のゼミまでのお仕事として、以下の2台のMacBookAirに対して、一気に昨日の「FTDI-USBドライバのバージョンを下げる」という作業をやっつけてしまおう、と決心した。 あんな面倒な手順は、忘れないうちにやってしまうに限るのだ。

調べてみると上のように、2台のMacBookAir「Air3」・「Air4」の「download」ディレクトリには、FTDI-USBドライバはv2.2.18しか無かったが、お仕事MacはいつもAirの後追いで環境のバージョンを上げるので、これら2台も中身は2.3となっている筈なのである。 おそらく気軽に「最新に」上げて、dmgをバックアップしていなかったのだろうと推察した。
そして、ついでに発見した古いArduino IDEのバージョンを最新の1.8.5に、さらにMax7のバージョンも最新の7.3.4になっていなかった1台を上げつつ、慎重に作業すること約30分、 このように(前半) なんとか無事に両方とも安定の2.2.18に戻すことに成功した。 こうなると、過去のOpenBCIの実験ページを発掘して、出来合いのツールでなく、いよいよ「Max7でOpenBCI」に挑戦ということになる。

そして2限には このように(後半) ゼミがあって中国から院生の馬ブンちゃんも無事に帰ってきて合流した。 帯状疱疹というのはいわば「熱の出ない風邪みたいなもの」とのことで体力低下しているらしく、昼休みあたりには研究室のデスクでうとうとしたが(^_^;)、午後の履修登録相談アポを挟んで、過去のOpenBCIネタの発掘に取り掛かった。 うっすらとした記憶では、今年2017年の1-2月だった・・・と調べてみると、 このように OpenBCIが1106に届いたのは、たしかに2017年1月11日だった。

そしてこのページのリンクのある、 Max7日記(5) の「2017年1月11日(水)」から辿ってみると、同じ日記の「2017年1月30日(月)」のところで このように OpenBCIを組み立てて(この時の無理な加工の筋肉断裂は半年以上も跡をひいた)、 このページ の存在にまで到達していたことを確認した。

さらに Max7日記(5) の「2017年2月9日(木)」のところで、TWE-Liteも登場していたのには驚いた。 OpenBCIとTWE-Liteとは、それぞれ、もっと離れた頃にやっていたと思っていたが、意外に隣接していたのだった。

そして、TWE-Liteに関して、同じ日記の「2017年2月16日(木)」と「2017年2月17日(金)」のところに続いていて、ここで遂にOpenBCIと同様にTWE-Liteでも このページ の問題がある、と壁に当たっていたのを発見した。 さらにTWE-Liteについては、 Max7日記(6) に入っても続き、「2017年2月24日(金)」のところでチラッと触り、「2017年3月20日(月)」に続きがあり、さらに「2017年3月21日(火)」のところで、以下のような嫌な情報を再発見してしまった。 そう、10.11.6(El Capitan)に対応しているのは「FTDIUSBSerialDriver_v2_3.dmg」の方であり、ここに無理矢理に「FTDIUSBSerialDriver_v2_2_18.dmg」を入れるのは推奨されないのだった。 (^_^;)

TWE-Liteについては上記のところでストップしていたようで、これで Max7日記(6) が終わってしばらく時が流れ、再開した 続・Max7日記(1) をさらに探っていくと、以下のように「MUSEとネコミミを同時に装着」というのをやっていた。 せっかくであれば、「MUSEとOpenBCIとネコミミを同時に装着」というのをやってみたいものである。(^_^;)

そして判明したのは、「OpenBCIについてはその後は何もしていない」という事実だった。 ということは、昨日の この動画 に登場していたMaxパッチは何だったのか不明である。 とりあえず再開の起点としては、推奨されない「FTDIUSBSerialDriver_v2_2_18.dmg」とともに、 Max7日記(5) の「2017年1月31日(火)」にあるリストから探っていくことになる。 せっかくなので、他モデルとかハードウェア関係など、不要なものをカットして、関係しそうなものだけ、以下に再掲してみた。

そして、これらをザザッと眺めていて確信したのは、ここできっちりと解析すべきページは、 Cyton Data Format のページのデータ形式定義と、 OpenBCI Cyton SDK のページのコマンド/インタラクション定義、というところに収束してきた。 謎のMax7パッチも、どこかでこの定義をなぞっていたもののようだ。 5限には「メディア数理造形演習」のための「Max特訓補習」のために永田さんがやって来る、ということで、今日はここまでとなった。 明日は予定されていたデザイン学科会議とメディア造形学科会議も「議題無し」で流会となりそうなので、終日、空き時間が出来る。 これはどうあっても「OpenBCI・再挑戦」の時間という天啓と信じて、チャレンジしてみる事にした。 とりあえずHTMLがほぼ200KB近くになったようなので、ここで区切りとしてpart2を終えて、続きは part3 にいくことにしよう。

→ 続・Max7日記(3)

「日記」シリーズ の記録