PWMDAC_Synth更新(ピッチベンド関連のバグ修正)

連休前のこのときにCAmiDionでプログラムチェンジの受信をサポートして以来、自分のHDDに眠っているさまざまなMIDIファイルを再生し、テストを兼ねてBGMとして楽しんでいたわけですが、一つだけ、どうしても気になっていたことがありました。

それは、ニコニ・コモンズに上がっているButter-Fly(デジモンアドベンチャーOP曲)のMIDIデータを再生したときの、あのかっこいいイントロのところ。ピッチベンドで音程が一瞬上がるところで、本来なら半音しか上がらないのに、3全音近くまで上がって聞こえるのです(あぁっ、せっかくのかっこいいイントロが…どうしてこうなった)。

Windows内蔵のMIDI音源で再生するとこの現象は出ませんでした(CAmiDionに再生させたときにだけ発生する現象)。

そこで、6月の初めくらいから本格的に調査。
PWMDAC_Synthのピッチベンド周りの処理が怪しいと思い、桁あふれや桁落ちか?と思って型キャストの方法を見直してみたり、計算順を見直してみたり、いろいろやってみたのですが、改善せず。

じゃあ、処理が重いせい?
と思って問題のパートだけをソロ演奏してみたものの、現象は変わらず。

で、たまたま休みだった6月10日(金)に、問題の切り分けをしているうちに気づいたこと。

それは、ベンド幅(Pitch Bend Sensitivity)を変数から持ってくると上記の現象が再現し、12で固定すると再現しないことです。

もしかして、ベンド幅が間違って代入されてしまっている…!?

さらに調べていると…
あっ!これかもしかして!?

気づいたところでさっそくツイート:

ベンド幅が、最大12半音(= 1オクターブ)と指定されていたわけですが、そのあとにも Data Entry の項目で64と指定されているのを、MIDIエディタソフトDominoで見ていて発見。

RPN MSB=0 LSB=0 と来て、Pitch Bend Sensitivity だと判断して Data Entry 12 だからベンド幅12と解釈されたはいいが、その後にNRPNの Data Entry もやってきて、こっちは64だけど、ベンド幅を後から上書きしたものとプログラムが誤認し、結果としてベンド幅が64/12=5.3倍に。

うん、たしかに5.3半音ぐらいに聞こえた気が。
本来半音になるはずのところが、ドを基準にしてファのちょっと高めぐらいになるくらいの音程。どうりで音程が大きく外れた状態になるわけです。

ベンド幅に対応したのは2015年9月頃ですが、NRPNが来た場合を想定せずに実装して9か月近くそのままになっていたようです。

さっそくバグフィックスしました。

その後、動画もniconicoに上げました

Samba共有フォルダ上のファイルをWindowsのcopy *で結合すると順序が狂ってしまう問題

Linuxのcatコマンドみたいにファイルを結合する機能ってWindowsにないの?
typeコマンドは1個のファイルを表示するだけだし、catみたいに複数のファイルを指定しても結合されないし…

と思ってWebで調べてみると、Linuxで

cat aaa bbb ccc > ddd
cat * > xxx

に相当することが Windowsでは

copy /b aaa+bbb+ccc ddd
copy /b * xxx

のような書き方で可能、これは便利!

…というようなブログ記事がよく見受けられます。

しかし!
対象ファイルがSamba共有フォルダにある場合、ワイルドカード * を使うとファイル名の順序が狂ってしまうことがあります。

例えば、Samba共有サーバとなっているLinux上のsplitコマンドでファイルを xaa xab xac … のように分割し、それを Windows上から Samba 共有上で直接 copy * で結合して復元しようとすると、意図した順序で結合されず、元通りに復元できなかったりします。

どうやらこれ、Sambaの既知の問題と関連があるらしい。対応策として

dir /on

でソートする方法があります。この方法で copy * の順不同問題を回避するには、for 文と copy + を組み合わせて1個ずつ結合していくようなバッチファイルを書くとよいでしょう。

例えば、分割されたファイルだけが自分のデスクトップ(%USERPROFILE%\desktop)の test というフォルダの中に存在している場合、次のようなバッチファイルで結合結果がデスクトップに保存されます。

copy /b nul %USERPROFILE%\desktop\結合結果.txt
for /f "usebackq" %%f in (`dir /b /on %USERPROFILE%\desktop\test\*`) do (
copy /b %USERPROFILE%\desktop\結合結果.txt+%USERPROFILE%\desktop\test\%%f %USERPROFILE%\desktop\結合結果.txt
)

copy のオプション /b は忘れずにつけましょう。なぜなら、バイナリーモードにしないとtypeコマンドの^Z問題と似たような現象に遭遇してうまく結合できなかったりするからです。
拡張子が.txtになっていますが、copy /b がついてさえいればバイナリーファイルもOKです。

Ctrl-Zで終わるファイルをWindows7のtypeコマンドに食わせるとどうなるか実験してみた

Linuxのcatと同じだから…
と、バイナリファイルをtypeコマンドを使ってリダイレクトしようとすると、こんな落とし穴に遭遇することがあります。

この画像がすべてを物語っています。

WIndowsのtypeコマンドで^Zで終わるファイルを追加するとこうなる

WIndowsのtypeコマンドで^Zで終わるファイルを追加するとこうなる

中央と終端にCtrl-Z(EOF、16進で1A)の入ったctrl-z-test.txtというファイルをバイナリエディタで作ってみます。さて、これをtypeコマンドで表示させるとどうなるでしょう?

中央のCtrl-Zを「ファイルの終わり = End Of File」と勘違いしてしまい、そこまでしか表示してくれません。

しかし、別のファイルに新規作成モードでリダイレクトして保存してみたところ、中央のCtrl-Zも終端のCtrl-Zも保存されました。

そうか、リダイレクトなら、バイナリファイルを扱っても大丈夫なんだ…
と思いがちですが、実はここが落とし穴。
追加でリダイレクトしてみると…

なんと、1回目のリダイレクトで終端についていたはずのCtrl-Zが、2回目のリダイレクトで上書きされてしまいました!

バイナリファイルをtypeコマンドで追加リダイレクトして結合しようとして、たまたまCtrl-Z(16進:1A)で終わっているファイルがあったりすると、気づかぬうちにこの落とし穴にはまる場合があるので要注意です。

typeコマンドはやっぱりテキストファイル用みたいですね…

くそー!
copyコマンドみたいな/bオプションがあるといいのに…! -_-;
Windowsのダメなところの一つです。Windows 7 の時代になってもまだCtrl-ZをEOF扱いしてるとか、時代遅れですよね…。Linuxだとそんなことないのに…。

PWMDAC_Synthの配列生成マクロ

少し前のブログ記事で、PWMDAC_Synthライブラリにおける音階の作り方を解説しましたが、そのためにどんな関数を使っているか、といった計算式の説明が中心でした。

この計算式は、AVRマイコン上でランタイム(実行時)に動かすためではなく、PC上でのコンパイル時にC++のプリプロセッサで字面の置き換えをして配列を生成するためのものです。

従来は

#define F(x) …
PROGMEM const byte table[] = {F(0), F(1), ... , F(127)};

のように0~127まで書き並べる方法で波形テーブルを作っていましたが、新しいPWMDAC_Synthではよりスマートなこの方法に切り替えました。

#define FX2(f,x) f(x), f(x + 1)
#define FX4(f,x) FX2(f,x), FX2(f,x + 2)
#define FX8(f,x) FX4(f,x), FX4(f,x + 4)
#define FX16(f,x) FX8(f,x), FX8(f,x + 8)
#define FX32(f,x) FX16(f,x),FX16(f,x + 16)
#define FX64(f,x) FX32(f,x),FX32(f,x + 32)
#define FX128(f,x) FX64(f,x),FX64(f,x + 64)
#define ARRAY128(f) {FX128(f,0)}
#define ARRAY256(f) {FX128(f,0),FX128(f,128)}
:
#define PWMDAC_CREATE_WAVETABLE(table, function) PROGMEM const byte table[] = ARRAY256(function)

FXn(f,x) で、n/2 個の要素を2倍に増やし、n 個の要素を持つf(x)の並びを作る、ということを7回繰り返します。たったこれだけで 27 = 128 個のカンマ区切り数値の並びができてしまいます。

これを活用して作ったマクロ ARRAY256(function) や ARRAY128(function) を使えば、その引数 function にマクロ関数名を入れるだけで、関数の結果を使った配列が簡単に作れます。

それをさらにマクロにしてまとめれば、ライブラリを呼び出す側でそのマクロを指定するだけで、インスタンス(実体)を重複なく必要な分だけ作れるようになります。タイマー割り込み処理に欠かせない ISR() (Interrupt Service Routine) の定義もインスタンスとみなして一緒に定義することすら可能になります。

最初の頃はExcelのワークシート関数で配列初期化のソースを作らせていたのですが、このような計算を#defineでC++のプリプロセッサに任せることだってできるのです。

ただし、一つだけ注意点が。
この方法を使ってノイズ波形を作るために random() を使った乱数表を作ろうとすると、なぜかうまくいかないようです。コンパイルして実行したら動きませんでした。
random() は呼び出すたびに値が変わるため、実行時に値を作るようにコンパイルされてしまったのでしょうか…?
このような特殊なデータはExcelに作らせるか、エディタを使って手動で作るしかなさそうです。

電子楽器CAmiDion ソフトウェア更新・その2:パフォーマンスチューニング

前回もこのブログでCAmiDionとPWMDAC_Synthの更新をアナウンスしましたが、あのあとまた更新が色々入りました。

チューニングの考え方

今回の主な更新は、リファクタリングはもちろん、それによって判明したパフォーマンスチューニングすべき箇所の修正による、使用RAM領域の節約が中心です。Flashメモリであるプログラム領域については、削減できればいいなと思いつつ、余裕があることや速度を犠牲にしたくないこともあり、それほど重視はしませんでした。

節約の際は、速度を犠牲にしないよう、以下の3つの処理を常に意識しておく必要があります。

  • 割り込み処理ISR()でその瞬間の波形ポイントをPWMのパルス幅にして出力(最高頻度・最優先:できる限り手早く処理しなければならない)
  • エンベロープ音量更新(loop()から定期的に呼ばれるので、あまり遅い処理は禁物だが、頻度が高くないので上記ほどシビアではない)
  • 通常の処理(これもシビアではないが、あまり遅いと全体の処理に影響するかも)

主なリファクタリング/パフォーマンスチューニング項目

PWMDAC_Synth

  • ADSRのenumを外出ししたうえで、エンベロープパラメータをよりコンパクトな形式に変更
  • 音量を16bit/8bit両方持たせていたのを共用体に置き換えた
  • 位相速度(dphase)を構造体にまとめてリファクタリングした。これによりオリジナル値を保持するのが無駄なことが判明したので、保持するのをやめた
  • Voice(発声子)の優先度(「温度」と呼ぶことにした)を見直し、音量をより重視した

CAmiDion

  • ソースを整理し、使えそうな箇所でtemplateを使うようにしたり、ボタンIDのenumを外出しすることで型の明確化に役立てた

エンベロープパラメータ

これまではbyteとunsigned intを両方使っていましたが、16ビット分という細かい値までMIDIチャンネル16個分保持するのはRAMの無駄になることなどから、すべて8ビット(= 1 byte)に統一しました。これに伴って配列化も容易になったので、ADSRのenumを使ったbyte配列として参照や更新が出来るようにしました。これに伴い、値だけでなくメソッドを持たせられるよう、struct から class への「昇格」も行いました。

音量、位相速度のコンパクト化

発声状態(VoiceStatus)には、現在の音量と位相速度(phase speed、音の高さに比例)が常に保持されていますが、これらを保持する変数のサイズ削減も行いました。発声状態はデフォルトで6重和音分あるので、ここのサイズ削減もRAMの節約に役立ちます。

【音量】最終的には高頻度割り込み処理ISR()にて8bitで掛け算されますが、エンベロープ状態の更新はそれに比べて低頻度なので、より細かい16bitで保持しています。今まではこの2つの値をvolume8とvolume16という別々の変数で持たせていたので3バイト占有していました。
しかしよく見ると、8bitで音量を得るには16bitの上位8bitをそのまま参照すればいいことに気づきます。そこで、この部分を共用体(union)で定義し直しました。これにより2バイトの占有で済むようになるだけでなく、8bitシフトしようとして >> 8 とか書かなくても共用体メンバーを参照すればよくなり、ソースが読みやすくなります。

【位相速度】ピッチベンド前の値(dphase original)はNoteOnやピッチベンドのタイミングでその都度wavetableから読み出せばいいことがわかったので、なくしました。位相速度はunsigned longで4バイトも食っているので、これも削減できました。ISRの割り込みに比べて低頻度なので、その都度読み出しても処理速度への影響は少なく、RAMの節約効果が大きいです。

発声優先度の見直しで「温度」の概念を導入

同時発音数いっぱいに発声中でも、受信したNoteOnを無視するわけにはいきません。反応が鈍ったように感じてしまうからです。

これを解決するのが優先度の概念ですが、内部的にはこれを「温度」(temperature)と呼ぶことにしました。ADSRのAttackでは音量が上がるほど下がり、Decay以降は音量が下がるほど下がる、そのような値を「温度」としています。発声が始まったときが最高温度(最も熱い状態)で、ADSRのReleaseが終わって音が止まったときが最低温度(最も寒い状態)になる、という考え方です。こうすると、同時発音数が足りなくなったとき、温度の低い(=寒い)ものを優先的に「横取り」することで、急に音が止まったような感じを抑えることができます。

最初はADSRの状態を優先していましたが、Attackとそれ以外で分け、あとは音量を重視するようにしました。このほうが急に音が止まったような感じがしにくいからです。

templateの活用

CAmiDionのソースでは、ノート番号(byte型)とコード(Chordクラス)が違うだけのメソッドがあるので、この違いを吸収すべくC++のtemplateを初めて活用しました。

同時に、ボタンIDをbyte型からButtonIDというenum型にし、これを広く活用する形にして型を明確化しました。これによりソースが読みやすくなったと思います。

手持ちのCAmiDionハードにも反映しました

以前よりチューニングの効果が出たので、頒布待ちの在庫10セットを含め、ファームウェアを更新しました。基板頒布のリクエストは引き続き受け付けています。欲しいという方はぜひお知らせください。

PWMDAC_Synthライブラリにおける音程を決める式

PWMDAC_Synthライブラリのソースには、さまざまな計算式が、主にマクロで記述されています。

ここでは、音の高さを決めるマクロ、PHASE_SPEED_OF() について解説します。

#define PHASE_SPEED_OF(note_number) ( \
pow( 2, ((double)note_number - 69)/12 + BitSizeOf(unsigned long) ) \
* PWMDAC_NOTE_A_FREQUENCY * 0xFF * 2 / F_CPU )

これは「位相速度」、すなわち単位時間あたり音波の位相をどれくらい進めるかを計算するマクロです。この式では、位相は最終的には unsigned long の整数値で表わされます。整数値がオーバーフローして一周すると 0 == 2π [rad] の位相ということになります。

単位時間

ここで「単位時間」は、PWMのパルス幅を更新するための割り込みサービスルーチン ISR() が呼ばれる周期です。最高速の位相基準PWM(Phase-correct PWM)の設定にすることにより、カウンタがCPUクロックごとに 0, 1, 2, … ,254, 255, 254, … 2, 1, のように往復しながら繰り返されることで、0 → 254の255個(0xFF個)、255 → 1 の255個、計510個ごとに割り込みがかかります。つまり、

255 * 2 / CPUクロック周波数

ということになります。CPUクロック周波数は F_CPU としてすでに定義済みで、16MHzになっています。これにより

0xFF * 2 / F_CPU

という、割り込み周期(単位時間)を表す式ができました。

音階の周波数

PHASE_SPEED_OF(note_number) の引数 note_number は MIDI のノート番号(0 ~ 127)ですが、これをもとに周波数を決める式が MIDI Tuning Standard として次のように決められています。

2(note_number - 69)/12・440Hz

これは、オクターブが周波数2倍、平均律に基づく半音がその1/12乗(12乗根)であることに由来します。69 は、A=440Hz の音階に対応するノート番号です。

440Hz を PWMDAC_NOTE_A_FREQUENCY として別途 #define し、これを使ってマクロで書くと

pow( 2, ((double)note_number - 69)/12 ) * PWMDAC_NOTE_A_FREQUENCY

のようになります。指数部分は12で割る段階で実数でなければならないので(double)でキャストしています。

周波数を位相速度へ

周波数は1秒当たりのサイクル数なので、これに単位時間を掛けると、その単位時間あたりのサイクル数に変わります。

pow( 2, ((double)note_number - 69)/12 ) * PWMDAC_NOTE_A_FREQUENCY * 0xFF * 2 / F_CPU

単位時間は音波の周期よりもはるかに短いため、サイクル数は1以下の小数になるはずです。これを位相速度にするには unsigned long の最大値+1を掛ける必要があります。unsigned long は 4 バイトなので、4 * 8 = 32 ビット。つまり unsigned long の最大値+1は、232 です。

が、当然のことながらこの数値は大きすぎて unsigned long で表すことはできません。ではどうするか?

ここで音階の周波数計算で使っている pow(2, …) に注目してください。

232 を掛けるということは、pow(2, n) の n に 32 を足すことと同じであることに気づきましたか?

そうです。
指数 n のところにビット数 32 を足すだけでよいのです!

これで、以下のように計算式ができあがりました。

#define BitSizeOf(type) (8 * sizeof(type))
#define PHASE_SPEED_OF(note_number) (pow( 2, ((double)note_number - 69)/12 + BitSizeOf(unsigned long) ) * PWMDAC_NOTE_A_FREQUENCY * 0xFF * 2 / F_CPU )

位相速度の活用

ではこの「位相速度」はどう活用されるか?

位相速度は unsigned long(32ビット)ですが、波形テーブルのインデックスはbyte(8ビット)です。これを変換するには 24 ビット右にシフトする必要があります。

変換できれば、あとはインデックスをもとに波形テーブル(値もインデックスも0~255の範囲)から現在あるべきパルス幅を読み出し、パルス幅を決めるレジスタを設定するだけです。この処理を割り込みサービスルーチンの中で行うことで、一定の単位時間でパルス幅を更新し続けることができるのです。
6重和音の場合は、その数だけこのパルス幅を合算します。
エンベロープでボリュームがコントロールされる場合は、そのボリュームを掛けたりします。

割り込みサービスルーチンでは、あまり時間のかかる処理を行うとそれ以外の処理を行う暇がなくなってしまうので、割り算などクロック数を食うような処理はできません。しかし、クロック数を最小限に抑えれば、6重和音も平気で出せるようになるのです。

電子楽器CAmiDion ソフトウェア更新

電子楽器CAmiDionと、シンセライブラリPWMDAC_Synthのソフトウェアを更新しました。

主な修正点

CAmiDion

  • クラス構造の見直し
  • ソースファイルの分割
  • 新たな#defineパラメータ(同時発音数、A音の周波数など)を追加し、CAmiDionConfig.hへ集約
  • ボタンのチャタリング対策(一定回数以上ボタンOFFが検出されるまで「ボタンが離された」ことにしない)
  • 最新のPWMDAC_Synthに対応

PWMDAC_Synth

  • 処理を見直し、多くの処理を*.cppから*.hに移行
  • 同時発音数、A音の周波数をライブラリを変えることなく#defineで変更できるようにした
  • 波形や位相速度テーブルに設定する値をべた書きせず#defineを駆使してプリプロセッサに計算させるようにした
  • 波形テーブルの実体定義をマクロ化し、必要な波形テーブルだけを実体定義できるようにした
  • ピッチベンド・センシティビティに対応

これに伴い、先ほど、更新したソフトウェアを手持ちの全CAmiDionと、未頒布の基板部品付セットに付属のATMEGA328に反映しました。

現時点で部品付セットの在庫が10セットあります。
欲しいという方はこちらを参照してください。

CAmiDionチャタリング対策後、あのパン屋で演奏してみたら…

なんか職場の飲み会から帰ってくる途中で9月が来てしまったようですが、酔った勢いでブログ書きますw

スケッチ更新しました

CAmiDionのスケッチを大幅にリファクタリングし、ソースファイルの分割を行いました。ソースの整理ができたところで、土曜日(8/29)にはボタンのチャタリング軽減対策を行いました。あと define によるプリプロセッサ定義も CAmiDionConfig.h に分離し、ハードウェア環境に応じてカスタマイズしやすいようにしました。
詳細はOSDNのGitリポジトリ参照。

CAmiDionでは中央付近のボタンをよく使うので、そのボタンから先に劣化し、押しても反応が鈍くなったり、チャタリングで複数回押されたような動作をしてしまうことがありました。これ、結構イラっときますよね。そこでこの影響を抑えて少しでも長持ちさせようと、チャタリング軽減対策に踏み切ったというわけです。チャタリングがうざい!と思ったCAmiDionユーザの方はぜひお試しください。

あのみっくみくなパン屋で演奏

日曜日(8/30)にはパン屋コンピ「ジョバンニと魔女」リリースパーティーというイベントへ行くため、田端の近くにあるあのパン屋へ。

先日夏コミに一般参加したときにyukkyさんのブースで「ジョバンニと魔女」というCDを買ったのですが、よーく見ると参加資格にこれを買った人ってのがある!

2ヶ月ほど前に道に迷ったあげくニアミスで終わって以来、あのパン屋に行けて、またCAmiDionでセッションできそう!ということで参加してきました。コトリ店長に会うのも花見でミク見以来5ヶ月ぶりくらい。パン屋に入れたのはお正月にyukkyさんに連れられて以来実に8ヶ月ぶりくらいでしょうか。
今度は道に迷わず行けました。

昼飯がまだだったのでさっそくパンを食べました(まぁ、パン屋だから当然のごとくそうなりますよねw)
パン屋の中では演奏機材の準備とリハーサルが。さっそくCAmiDionを接続させてもらいました。…が、なんかいきなり暴走することがあるぞ…最初は基板むき出しだからかなーと思っていたのですが、アクリルケース入りの電池式CAmiDionでも再現するので、色々弾いているうちにこんなことが判明。

キーがデフォルトのCのとき、E♭sus4、E♭、Cm のボタンを押すと、LEDが発狂して暴走する!
何やら、チャタリング対策でどっかバグってしまったようだ!
E♭は地雷ボタンか!?

この影響で「魔法のメロディ」でここのコードへ進行するところで「地雷」を踏んでしまい、電源を入れなおさないと復活しないので、ここを避けて演奏してなんとか乗り切りましたww ちょっともどかしいけど仕方ない…
(キーDだと中央から左3つ移動したところがFコードになりますが、このFコードが【まさかの地雷ボタン】になっていたわけです)

楽譜もありましたがあまり見てなくて結局聞いてこれだって思ったコードを押していく感じでしたねー(慣れるとこのほうが早い)

MIDI IN を装備した音楽キーボードを持ち込んでいた人がいたのでCAmiDionをつながせてもらったら、この音源めちゃいい!(しばらくはまってましたw) やっぱりちゃんとしたMIDI音源は音色が違うなぁ…小型のMIDI音源とかないかな…

CAmiDionに興味津々な人が何人かいて説明したりとか、なかなか楽しかったですw

この日は翌日が初音ミク8周年ということで、こんなケーキも。

考えたら、当時8歳だった上の娘も16歳になって初音ミクの設定に追いついたり、自分は娘の3倍の歳になってCAmiDionのボタンの数と同じになっていたりして、何もかもが8の倍数づくしです。プログラマーにとっては区切りのいい数だらけ。

パン屋にはスクリーンまであって、おぐぎんざ商店街を歩く人の目に留まるよう工夫されていました。

このパン屋が話題になるきっかけともなった「恋する縞パン」も2周年なんですね!

しかしながら「恋する縞パン」のうp主である肝心のyukkyさんが残念ながら参加できず、本人そっくりのぬいぐるみが代わりをつとめるような演出が始まったり。

帰ってすぐにデバッグ

さて、帰ってきたら日付が変わってたわけですが(さっきと同じで2日連続だw)
さっそくソースをチェックしたら…チャタリング待ち時間配列(ボタンの数だけある)のインデックスの計算が間違ってたことに気づく!

間違った計算式だとインデックスがこうなります:
0 1 2 3 4 5
8 9 10 11 12 13
16 .. 21
24 .. 29
32 .. 37
40 .. 45
48 .. 53 ← ここで配列サイズ48をはみ出す。E♭ボタンとかまさにここ。
56 57 58 59 60 61 ← B♭とかもここなのでやばかったけど何とか乗り切れた。

早速修正してみたら「地雷除去」に成功!
もう青の真ん中を押しても大丈夫。

前の夜に直して、使用頻度低めのボタンであまり試してなくて気づくのが遅れたのかも…

アルカリ電池x3本動作時のLCDパラメータを調整

これまでCAmiDionでは、電池内蔵タイプを NiMH x 4 本で動作させるようにしてきましたが、8本のNiMHを10Wアンプに回してしまったことに伴い、NiMHの本数が不足するようになってしまいました。

そこで、これを機会に、アルカリ電池 x 3 本で動作させるよう、電池ボックスを単3 x 4本用から単3 x 3本用にしました。

これにより、足を取り付けるネジ穴が確保でき、いままでの貼り付け式ゴム足がずれてしまうという問題が解決。4 本用だとうっかりアルカリ電池を入れて電圧が高すぎる状態になる心配がありましたが、3 本用ならその心配はありません。

ただ、電圧が下がった分、それほど電池が消耗していなくてもLCDが薄くなるという気になる点も。これを解決するために、I2C LCDライブラリの初期化(クラスコンストラクタ)パラメータを調整することにしました。
CAmiDionで使っているのはST7032iタイプなのでそれ用のコンストラクタを使います。今までは5v用に合わせてコントラストを最大の63にしていました。

#define LCD_CONSTRUCTOR_ARGS (uint8_t)63,(bool)true

4.5vという低めの電圧の場合、3.3v用にします。こうすると電圧ブースタが働くことで電圧が上がってLCDが濃くなるわけですが、コントラスト63のままではあまりにも濃すぎる状態に。そこで、新品の電池と、ある程度減った電池で調整してみた結果、コントラスト13に落ち着きました。

#define LCD_CONSTRUCTOR_ARGS (uint8_t)13,(bool)false

これをコメントで入れる形にしてGitリポジトリを更新しました。
アルカリ電池 x 3本で使っていて液晶が暗くなるのがやけに早いなーと思ったら、ぜひ上記のようにパラメータを調整してスケッチを書き直してみてください。

MIDI Chord Helper のソースコードをSVNからGitに移行

SourceForgeに置いてあるMIDI Chord Helper のソースコードですが、今までSubversion(SVN)レポジトリに置いてあった内容をGitレポジトリに移行しました。

取り込み手順の概要はこんな感じ:

SourceForge上の既存のリモートSVNレポジトリ
→ git svn clone で一時的なローカルGitレポジトリにクローニングする(はまりどころ1)
→ SourceForge上のリモートGitレポジトリにpush (→ ※1)

eclipseのworkspaceにローカルGitレポジトリを作る
→ 手元のworkspaceにあるソースをこのレポジトリにコミット
→ (→ ※1)で作ったリモートGitレポジトリからpull
→ 同じソースコードのはずなのになぜか競合してるって言われた
→ 仕方ないのでどっちかを全面採用という形でマージ(これもちょっと大変だった)

はまりどころ1

SVNレポジトリの構成ですが、標準だと思っていたら実はそうではなかったという。

2010年頃にはtrunkの中に置いていました(これが標準、ただしリビジョンはr2までそうしてた)。当時はRIMNETのHPの容量制限に引っかかりそうだったので、じゃあそのままSVNレポジトリにしてSourceForgeに引っ越しちゃおう、ということで単なるソース保存場所としてしか使っていませんでした。

その後、2013年頃にeclipseを使い始めたのに伴い、r3からはMIDIChordHelperという名前に移行しました。どうもこの時点から標準じゃない構成になっていたらしく、Git へ移行しようとしたときに git svn の -s オプションでr2まで(つまり2010年当時)しか反映されないという現象に悩まされました。

いろいろ調べた末、このブログ記事が参考になりました:git svn cloneで、標準構成じゃないときのbranches指定方法

cd 一時作業ディレクトリ
git svn clone -trunk=MIDIChordHelper --authers-file=authers.txt レポジトリURL

のようにtrunkが違うところにあることを教えた上で取り込んだら、r4以降が取り込めるようになりました。それより前のリビジョンはというと、eclipseを使い始める前で事実上ほとんど更新しておらず、これじゃGitに載せても意味ないよなーってことで対象外としました。
以後の更新はこのGitレポジトリに積み上げていこうと思います。

ちなみに –authers-file=authers.txt で指定したファイル authers.txt の中身は、

kamide = Akiyoshi Kamide <kamide@yk.rim.or.jp>

の1行を指定しただけです。= の左辺がSubversionに記録されているユーザ名、右辺がGitで使用するユーザ名とメールアドレスです。これがないとGitレポジトリで変なメールアドレスのようなものが勝手につけられてしまうので、ちゃんと指定するようにしました。

trunkを切り替えてcloneすることはSourceTreeではできなかったので、これだけはコマンドラインから行いました。あとはSourceTreeとeclipseの組み合わせでなんとかなりました。