Development」カテゴリーアーカイブ

雰囲気メガネのMIDI/OSCプロトコル

間もなく(おそらく)出荷される雰囲気メガネでは、独自のアプリケーション開発のためにSDKが提供されます。これはObjective-CまたはSwiftというプログラミング言語を用いる本格的なものなので、もう少しお手軽な方法としてMIDIとOSCを用意しています。OSC(OpenSound Control)はMaxなどで簡単に扱えますし、MIDIなら鍵盤を弾いたり、ツマミをグリグリするだけです。

MIDIやOSCをサポートしているウェアラブル・デバイスやモノのインターネットと呼ばれる製品は珍しいと思いますが、これこそが雰囲気メガネの特徴のひとつですね。そこで、ここでは一足早く雰囲気メガネのMIDIとOSCのプロトコル【暫定版】を説明します。正式なドキュメントは開発者向けサイトで公開されるはずです。

雰囲気メガネでのMIDI/OSC

MIDIもOSCも雰囲気メガネのiOSアプリに対してデータを送り、アプリは雰囲気メガネとリンクされている必要があります。つまり、雰囲気メガネ・アプリがMIDIやOSCと雰囲気メガネとの中継役になるわけです。雰囲気メガネ・アプリでは設定ボタンからMIDI/OSC画面を開いて設定を行い、この画面でのみMIDIやOSCを受け取るようになっています。

Fun-iki-MIDI-OSC

雰囲気メガネのMIDIプロトコル

MIDIに関しては、MIDI/OSC画面でMIDIスイッチをオンにするだけで、それ以外の設定はありません。MIDIのすべての経路を受け入れて、すべてのMIDIチャンネルを受け付けます。CoreMIDIに対応していればネットワークMIDIでもバーチャルMIDIでも構わないし、物理的なMIDIインターフェースでも構いません。最近登場したMIDI Over Bluetooth LEも制約があるようですが一応動作しました。何らかのMIDIメッセージを受け取ると、MIDIスイッチの左横にある小さな丸が点滅します。

Network MIDI

MIDIメッセージでは、まず、もっともポピュラーなノート・オンおよびノート・オフ・メッセージに対応しています。MIDI鍵盤を弾けば雰囲気メガネがピカピカと色とりどりに光るわけです。雰囲気メガネの紹介ビデオでもグランド・ピアノを弾いているシーンがありましたね(気分はディスクラビア)。この場合は、ノート・ナンバーを色相として扱い、どのオクターブでもド(C)が赤色で12半音で色環を一周する割当になります。ベロシティは明度の指定で、最大値である127なら最も明るく光り、数値が小さいと弱い光りとなり、0なら光りが消えます。強く(速く)鍵盤を叩くほど明るく光り、鍵盤から指を離せば光りが消えるわけですね。ノート・オフ・メッセージはどのような値でも光りが消えます。

MIDIノート・オン・メッセージ
ノート・ナンバー:色相(図参照)
ベロシティ:明度(0:消灯〜127:最も明るい)

Fun-iki-midi-note
MIDIノート・オフ・メッセージ
消灯

ノート・オンとノート・オフでは色相と明度しか指定できないので、彩度はコントロール・チェンジの1番で指定します。これはモジュレーションなので、多くのMIDIキーボードでは鍵盤の左横にあるホイールやレバーを動かせば彩度が変わります。ただし、コントロール値がゼロの時に彩度が最大で色がはっきりし、値が大きくなるにつれて彩度が下がって白っぽくなります。モジュレーションを上げて「白熱」した演奏になるわけです。

MIDIコントロール・チェンジ
コントロール・ナンバー1(モジュレーション):彩度(0:彩度最大〜127:彩度最小)

指定した色に変化する遷移時間はコントロール・チェンジの5番と56番で設定できます。コントロール・チェンジの5番はポルタメント・タイム、同じく65番はポルタメント・スイッチですから、それっぽいですよね。コントロール・チェンジ5番の値が0であれば遷移時間は0秒、127であれば4秒とリニアに変化します。コントロール・チェンジ65番の値が0から63までなら遷移は無効、64から127までなら遷移が有効になります。

MIDIコントロール・チェンジ
コントロール・ナンバー5(ポルタメント・タイム):遷移時間(0:0.0秒〜127:4.0秒)
コントロール・ナンバー65(ポルタメント・スイッチ):遷移設定(0〜63:有効、64〜127:無効)

さらに、コントロール・チェンジの16番、17番、18番を使ってHSB形式で光りを設定することもできます。これらは汎用操作子の1番から3番で、汎用だから何でも良いでしょうってことです。

MIDIコントロール・チェンジ
コントロール・ナンバー16(汎用操作子1):色相(0:最小〜127:最大)
コントロール・ナンバー17(汎用操作子2):彩度(0:最小〜127:最大)
コントロール・ナンバー18(汎用操作子3):明度(0:最小〜127:最大)

遷移時間の設定以外は、どのMIDIメッセージを受け取っても、ただちに雰囲気メガネの色が変わります。これは、できるだけ簡単に、まさに演奏するように雰囲気メガネをコントロールしたいとの意図です。しかし、逆に言えば効率的ではありませんし、MIDIでは左右個別に色を設定することはできません。より柔軟なコントロールにはOSCをお勧めします。

雰囲気メガネのOSCプロトコル

OSCを利用する場合は、送信するMacやiPhoneと雰囲気メガネ・アプリが動作しているiPhoneとを同じWi-Fiネットワークに繋ぎます。OSCの受信ポート番号はデフォルトで2061で、どこかで聞いたような数値ですが、任意のポート番号に変更しても構いません。雰囲気メガネ・アプリが動作しているiPhoneのIPアドレスが表示されているので、送信元からはこのIPアドレスに対して設定したポート番号でOSCパケットを送ります。OSCのスイッチをオンし、何らかのOSCパケットを受信すれば、スイッチの左横の小さな丸が点滅するはずです。

OSCパケットのフォーマットは以下の通りで、/fun-iki/performというアドレスに続けて7つの数値を与えます。最初の3つの数値は左側レンズの色をHSB形式で指定し、いずれも0.0から1.0までの範囲の実数です。続く3つの数値は右側レンズの色です。最後の数値は指定した色に変化する遷移時間を秒数で指定します。遷移時間として指定できる有効な数値の範囲は0.0秒から655.34秒で、分解能は0.01秒です。

/fun-iki/perform <左色相> <左彩度> <左明度> <右色相> <右彩度> <右明度> <遷移時間>

例えば、次のパケットを送ると、左側は明るい赤色に、右側は暗めの青色にすぐに変わります。

/fun-iki/perform 0.0 1.0 1.0 0.666 1.0 0.5 0.0

そして、次のパケットと送ると、両側のレンズの光りが2秒かけてゆっくり消えます。

/fun-iki/perform 0.0 0.0 0.0 0.0 0.0 0.0 2.0

ちなみに、OSCでは実数を使って細かく制御できるように思えますが、しかし、高い精度は期待しないでください。iPhoneなどのディスプレイに比べると、雰囲気メガネのカラーLEDの色域や精度は広くないですからね。また、データを送ってから色の変化が始るまでの時間的な遅れや、単位時間あたりに送れるデータ量の制限もあります。演奏するように雰囲気メガネをコントロールしたいものの、大量のデータを送ればパケ詰まりになります。このような制限はMIDIでも同じで、実際にデータを送って光り方を確かめながら制作していただけると良いかと思います。

雰囲気メガネのシミュレータ

雰囲気メガネはMIDIやOSCによって光り方をコントロールできるようになっています。そこで製品より一足先にMaxで作成した雰囲気メガネ《非公式》シミュレータを公開します。これで雰囲気メガネへどのようにMIDIメッセージやOSCパケットを送れば良いかが分ると思います。

OSC-Fun'iki 1.0

MIDI-Fun'iki 1.0 SimFun'iki 1.0

雰囲気メガネ《非公式》シミュレータ(Maxパッチ)をダウンロード

ダウンロードしたアーカイブには3つのファイルが含まれていて、そのうちSimFun’ikiがシミュレータ本体で、MIDI-Fun’ikiはMIDIメッセージ送信のサンプル、OSC-Fun’ikiはOSCパケット送信のサンプルとなっています。Maxでプログラミングされる方はMIDI-Fun’ikiやOSC-Fun’ikiを改造すれば良いですね。Maxを使わない場合も同等のMIDIメッセージやOSCパケットをSimFun’iki(を開いているMaxアプリケーション)に送ればOKです。SimFun’ikiは雰囲気メガネのように光る(色が変わる)はずです。実際に雰囲気メガネを使う場合は、ペアリングしたiOSデバイスに対してMIDIメッセージやOSCパケットを送信するだけです。

もっとも、シミュレータは雰囲気メガネの挙動を忠実に表しているわけではありません。雰囲気メガネはディスプレイのように色域が広いわけでも、応答が速いわけでもないからです。応答速度などは出荷直前まで調整が続けられますので、現時点では具体的な数値を挙げられません。ただ、高速に光が点滅するようなコントロールは無理だと考えたほうが良いですね。そのような制限もありますが、ご自身のアイディアで雰囲気メガネを制御する楽しさと可能性にご期待いただければ嬉しいです。よろしくお願いします〜!

aka.leapmotionリリース

Leap Motion社の3次元センサーThe Leap Motion controllerのDeveloper unitが届いたので、Maxオブジェクトaka.leapmotionを作成して公開しています。Leap Motionはまだ製品版は発売されておらず、受け取ったデバイスも外装なしの基盤剥き出し状態でしたが、動作自体は安定しています。

aka.leapmotionはLeap Motionから得られるデータを忠実に出力しており、ヘルプ・パッチから分かるようにかなりの量のデータが得られます。基本的には人の手や指の認識に特化しており、手に持ったペンやお箸なども(指ではないものとして)認識できます。認識範囲はそれほど広くないものの、テルミン的な範囲はOKかと思います。

ちなみにLeap Motionのデバイスは二つのカメラの画像をUSBでMacに送り、Macで動作するLeapアプリケーションが画像解析をしているようです(想像)。このため、MacBook Pro (Mid 2012, 2.7GHz)でのLeapアプリケーションのCPU使用率は、何もない状態で30%、片手を認識すると40%、両手なら50%といった具合です。Maxオブジェクトではデータを受け取るだけなのでCPU使用率は少なくて済みます。なお、このマシンは4コア・8スレッドなのでフル稼働なら800%となり、単純にはLeap Motionは全体の数パーセントを使っていることになります。

ともあれ、現状のLeap Motionは具体的に何かができるわけではなく、デベロッパーによるアプリケーションの充実を目指している状況のようです。マルチタッチ・トラックパッドのエミュレーションなども期待したいところですね。

Mountain LionでのMax SDK

久々にMaxオブジェクトを作ろうとして、Max SDKをダウンロードしたら付属のサンプルすらビルドできない。これはビルド設定の内容が古いからでした。

OS X 10.8 & Xcode 4.5でMaxSDK-6.0.4を利用する場合は、maxmspsdk.xcconfigの33〜34行目を以下のように修正します。これでOK!

SDKROOT = /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk
MACOSX_DEPLOYMENT_TARGET = 10.8

iOS 3.1.3をサポートする方法

iOS SDKは年々進化を続けているのはイイんだけど、後方互換性は一部犠牲になっている。他のプラットフォームに比べると数倍マシだとは思うけどね。ともあれ、最新OS最新モデルに対応しつつも、以前のOSや機種を切り捨てられない場合も少なくない。しかも初期のSDKで作成したプロジェクトをアップデートし続けるのもスッキリしないので、最新SDKから新しいプロジェクトを作ったりすると、それなりに問題が発生する。

そこでiOS SDK 5.1 (Xcode 4.3.2)で作ったプロジェクトを初代iPhoneの最終OSであるバージョン3.1.3に対応させる方法を書いておくね。ここではテンプレートとしてUtility Applicationを用い、iPhone/iPad両用のユニバーサル・アプリを作ることにします。もちろん、ARCはオフ、Storyboardも使えませんよ。

まず、何はともあれDeploymentを3.1に設定する。

■ プロジェクトのiOS Deployment Targetを 3.1 に設定。

次いで、初代iPhone、iPhone 3G、iPod touch(第1世代と第2世代)のCPUであるarmv6でも動作するように指定する。

■ プロジェクトのBuild SettingsのArchitecturesのArchitecturesに armv6 を追加。

■ プロジェクトのBuild SettingsのArchitecturesのBuild Active Architecture Onlyを NO に設定。

■ ウィンドウの下部にあるValidate Settingsをクリックし、Perform Changesを実行。

■ Info.plistにある Required device capabilities を削除。

Blocksを使う場合には以下の設定も必要。

■ プロジェクトのBuild SettingsのLinkingのOther Linker Flagsに -weak-lSystem を追加。

次に、テンプレートが生成するコードはiOS 3では存在しないクラスやメソッドを使っているので、iOS 3でも動作するように変更する。

まず、テンプレートはiPad用にUIPopoverControllerを使っているので、UIKitのリンクを弱める。

■ ターゲットのBuild PhasesのLink Binary With LibrariesにあるUIKit.frameworkを Optional に設定。

また、デバイスの判断にuserInterfaceIdiomメソッドもiOS 3では使えない。そこで汎用的に利用できるマクロを用意して、ソースコードを書き換える。

■ 〜-Prefix.pchに以下のマクロを定義。

#define UI_USER_INTERFACE_IDIOM() ([[UIDevice currentDevice] respondsToSelector:@selector(userInterfaceIdiom)] ? [[UIDevice currentDevice] userInterfaceIdiom] : UIUserInterfaceIdiomPhone)

■ ソースコードの該当箇所を書き換える。AppDedegateに1ヵ所、MainViewControllerに3ヵ所、FlipsideViewControllerに1ヵ所あるはず。

[[UIDevice currentDevice] userInterfaceIdiom]

UI_USER_INTERFACE_IDIOM()

に置き換える。

また、UIWindowのrootViewControllerプロパティもiOS 3では使えない。

■ AppDedegate の application:didFinishLaunchingWithOptions: の、

self.window.rootViewController = self.mainViewController;

if([self.window respondsToSelector:@selector(rootViewController)])
    self.window.rootViewController = self.mainViewController;
else
    [self.window addSubview:self.mainViewController.view];

に置き換える。

同じく、UIViewControllerのcontentSizeForViewInPopoverプロパティもiOS 3では使えない。

■ FlipsodeViewController.m の initWithNibName:bundle: の、

self.contentSizeForViewInPopover = CGSizeMake(320.0, 480.0);

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
	self.contentSizeForViewInPopover = CGSizeMake(320.0, 480.0);

に置き換える。

以上の作業でiOS 3.1.3からiOS 5.1までのすべてのデバイスで動作するユニバーサル・アプリになったハズ。お疲れさまでした。

このようにして作ったテスト用のプロジェクト一式も入れておきますね。
Download RunOnOS3Test.zip

【追記】最後のcontentSizeForViewInPopoverプロパティの説明を追加しました。併せてテスト用プロジェクトも更新しました。

iSuperColliderのビルド方法

先日のワークショップでiOS用のSuperColliderを紹介したことで、その入手方法の問い合わせが何度かあったので、ビルド方法のメモを書いておきます。ただし、これは2012年3月7日時点のレポジトリでの作業方法です。その後にソースコードが変更されることもあるでしょうから、同じように作業してもビルドできるとは限らないです。従って、質問されてもお答えできないってことでご了承願います。

How to build SuperCollider for iOS (March 7th, 2012)

Don’t ask me any questions 😉

Getting source codes

(1) Open Terminal

git clone git://supercollider.git.sourceforge.net/gitroot/supercollider/supercollider isc
cd isc
git checkout 3.5
git submodule init && git submodule update

Building SuperCollider.app (Language)

(1) Open isc/platform/iphone/iPhone_Language.xcodeproj

(2) Set Scheme to ‘SuperCollider > iOS Device’

(3) Set Build Configuration to ‘Release’

(4) Click iPhone_Language in the navigator area
Click SuperCollider in TARGETS
Click Build Settings
Scroll down to Search Paths and open Header Search Paths
Change ../../external_libraries/yaml-cpp-0.2.6/include to ../../external_libraries/yaml-cpp-0.3.0/include

(5) Open externals/yaml group of iPhone_Language in the navigator area
Remove src group
Add isc/external_libraries/yaml-cpp-0.3.0/src into externals/yaml group

(6) Click iPhone_Language in the navigator area
Click SuperCollider in TARGETS
Click Build Phases
Remove libsndfile_iphone.a from Link Binary With Libraries
Add isc/platform/iphone/lib/ libsndfile_iphone.a to Link Binary With Libraries

(7) Connect your iOS device and run

Building iscsynth.app (Synth)

(1) Open isc/platform/iphone/iPhone_Language.xcodeproj

(2) Set Scheme to ‘iscsynth > iOS Device’

(3) Set Build Configuration to ‘Release’

(4) Open Resources group in iPhone_Synth.xcodeproj in the navigator area
Click iscsynth_MainWindow.xib
Remove Dir Browser View Controller from Tab Bar Controller in Objects

(5) Click iPhone_Language in the navigator area
Click iscsynth in TARGETS
Click Build Phases
Remove scUBlibsndfile.a from Link Binary With Libraries
Add isc/platform/iphone/lib/ libsndfile_iphone.a to Link Binary With Libraries

(6) Connect your iOS device and run


以上です。

なお、このビルド作業ではFredrik Olofsson氏にヘルプしていただきました。感謝!(でも彼にも迷惑をかけないようにお願いしますね〜)

また、ワークショップで使用したiSuperColliderは、スリープを自動禁止にしたり、スピーカー選択のコードを修正したり、といった変更を少々加えています。

【追記】本記事初出時には2012年1月末時点のレポジトリでのビルド方法を記載しましたが、2012年3月7日に再度手順を検証して記事を書き換えました。

Dashcodeでアプリ・アイコン効果

iOSが自動的に付加するアプリ・アイコンの角丸グロッシー効果、もちろん画像編集ソフトでできるんだろうけど、ここでは以前にTwitterで教えていただいたDashcodeでの手法をご紹介。DashcodeはXcodeの一部として提供されているAppleの無料ツールね。

(1) Dashcodeで新規プロジェクトを作成。
一番シンプルなSafariのカスタムのテンプレートが最適。

(2) ライブラリから四角形をキャンバスにドラッグ&ドロップ。

(3) インスペクタでサイズを設定。
使用するアイコン画像のサイズに一致させる。ここでは512×512ピクセルとする。

(4) インスペクタで塗りつぶしをイメージに設定し、画像ファイルを選択。

(5) インスペクタで角の丸さを設定。
アイコン画像が512×512ピクセルの場合は100ピクセルくらいになる。

(6) エフェクトのガラスを有効にし、パラメータを設定。
  シャイン:50%
   トーン:80%
    水平:50%
    湾曲:-20%

iOSでの効果とは微妙に違う気がしないでもないけど、まぁ、そこそこ雰囲気は出てるんじゃないでしょうか。

MoMu-STKでシンセシス処理

先に紹介したMoMuでのオーディオ処理は、基本的な入出力を肩代わりしてくれるものの、それ以上のことは自前でやらなくてはいけない。実際にもMoMuオーディオは内部的にRemoteIOを呼び出しているだけ。自前でデジタル信号処理を書くのは、お勉強にはイイけど、面倒で難解であることも確か。

一方、MoMuを使うメリットは、同時に用意されたThe Synthesizer Toolkit (STK)を簡単に利用できること。STKはCCARMAを中心に開発されている音響合成ライブラリで、そのクラス・リストを見れば分かるように、基本的なオシレータやフィルタ、エフェクタはもちろんのこと、フィジカル・モデリング系の音源が充実している。Maxな人にはPeRColateという移植ライブラリで有名かもね。

と言う訳で例によってナンチャッテ路線で、MoMu-STKを使ってみよう。まずは「MoMuでオーディオ処理」に示した手順で爆音が出るようにしておく。そして、The Synthesis Toolkit (STK): MoMu ReleaseのサイトからMoMu-STKをダウンロード。その上での手順は以下の通り。ここではTubeBellクラスを用いて、鐘(チューブラー・ベル)を鳴らす。

(1) プロジェクトにMoMu-STK-1.0.0フォルダを追加。

(2) ソースコード(例えば〜ViewController.mm)で、ヘッダをインポートし、定数と鐘のオブジェクトを定義。

#import "mo_audio.h"
#import "TubeBell.h"

#define SRATE         44100
#define FRAMESIZE     128
#define NUMCHANNELS   2

stk::TubeBell	*myBell;

(3) 適切なメソッド(例えばviewDidLoad)でMoMuのオーディオ処理の初期化と開始の後、鐘のインスタンスを生成し、鳴らす。

MoAudio::init(SRATE, FRAMESIZE, NUMCHANNELS );
MoAudio::start(audioCallback, nil);
	
myBell = new stk::TubeBell();
myBell->keyOn();

(4) コールバック関数では、tick()メソッドによって返される値でバッファを満たす。

Float32 *data = buffer;
for (int i=0; i<framesize; i++)
{
	Float32 value = 0;
	if (myBell != nil)
		value = myBell->tick();
		
	*data++ = value;
	*data++ = value;
}

このようにしてアプリを起動すると鐘が鳴り響くハズ。シミュレータでも実機でもOK。はい、おしまい。

というのも味気ないので、もう少しシンセシスらしいことをしておこう。

まずボタンを作り、Touch DownでplayBell:メソッドを呼び出すようにアクションを定義する。

- (IBAction)playBell:(UIButton *)sender
{
	myBell->keyOn();
}

同じくスライダーを作り、Value ChangedでmodulationChanged:メソッドを呼び出すようにアクションを定義する。

- (IBAction)modulationChanged:(UISlider *)sender
{
	myBell->controlChange(2, sender.value * 127.0);
}

これで、ボタンをタップすると鐘が鳴り、スライダーを動かすと鐘の音色が変わる。シンプルながら、これだけでもサンプリング音の再生では難しい音響合成ですね。他にもパラメータは沢山あるので、いろいろとイヂってみてください。

はい、おしまい。

iOSデバイスとOSバージョン一覧表

問題:iPhone OS 3.0以降に対応するアプリの動作確認のために必要なiOSデバイスは何台?

先のオプティマイザ問題もあって、iOSデバイスとOSのバージョンを調べてみました。この表での最小OSは、そのデバイスが発売された時点のOSのバージョンで、最大OSはどのバージョンのOSまで対応しているかを示している。(5.0.1)は現在の最新バージョンで、今後も対応するバージョンが上がる可能性があります。

3.xアプリの欄にマル印が付いているのは、OSのバージョン3.xに対応するアプリが動作することを示しており、動作確認をする必要がある。例えば、iPhone 4はOS 4.0以降に対応するので、3.xアプリの欄にはマル印は付いていない。つまり、動作確認をする必要はない(そもそもできない)。そして、iPhone 4はOS 4.xとOS 5.xについてアプリの動作確認をすることになる。

一般にOSのバージョンを下げることはできないので、メジャー・バージョンごとに動作確認用のデバイスを用意する。つまり、iPhone 4ならOS 4.xとOS 5.xの2台が必要になるわけ。厳密にはマイナー・バージョンごとにも動作確認すべきかもしれないが、これは最大のマイナー・バージョンに限って良いはずね(たぶん)。

そこで、この表のマル印を数えれば、今回の問題に対する回答になる。

回答:23台

ただし、iPhone 4 (GSM)とiPhone 4 (CDMA)の違いは僅かで、個別に検証する必要はないかもしれない。この場合は必要台数は21台となる。逆にiPadもiPad 2も、Wi-FiモデルとWi-Fi+3Gモデルがある(iPad 2の3GはさらにGSMとCDMAに分かれる)ので、これらは区別して動作確認するべきかもしれない。このように考え方によっては23台以外の回答も有り得るよ。

ともあれ、動作確認のためには数多くのデバイスが必要だってことが分かるね。OS 4.x対応であれば17台、OS 5.x対応で8台が必要となる。個人や小規模なグループなら、これだけの台数を揃えるのは難しいかもしれない。初代iPhoneのように入手が難しい機種もある。しかし、万全を期するにはこれだけの台数が必要だし、何か問題が発生した場合には手の打ちようがないよね。

え?私?CDMA以外は必要台数全部揃っています(笑)。

【追記】iPhone OSにはバージョン2.xも存在するけど、現在のXcode 4.2では2.x用のアプリを開発するのは困難なので、ここでは省略しています。また、初代iPhoneが登場した時のOSはバージョン1.0で、これはApp Storeに対応していない。

最終確認はReleaseビルドで

先日リリースしたBanner 1.5.2について、iPhone 3Gで三角形みたいに歪んでいる、というメールあり。何それ?と思いながら確認しても、特に異常はなさそう。そもそもサブミット前にiPhone 3Gでもチェックしている…とここまではXcodeでの話。もしや!と思ってiPhone 3GでApp Storeからダウンロードしてインストールして起動すると、しっかり歪んでました。歪むと言うよりグルグル斜めに廻っている感じ。でも、もう一度Xcodeから実行すると正常に表示される。しかも4Sなど他のiPhoneではApp Storeのアプリでも問題がない。謎!

原因はXcodeのオプティマイザでした。オプティマイザは実行速度が速くサイズが小さくなるようにコードを最適化してくれる。ところが、iPhone 3Gに対して(arm6に対して)はオプティマイザがお馬鹿さんらしく、変なコードになる場合があるらしい。そして、開発中に使うDebugビルドはオプティマイザがオフだけど、App Storeへのサブミットに用いるReleaseビルドではオプティマイザがオンになる。つまり、オプティマイザが馬鹿とは言え、Releaseビルドで動作確認をしなかった私が愚か者でした、ってワケ。

ちなみに、DebugビルドかReleaseビルドかは、Schemeポップアップ・メニューから「Edit Scheme…」を選び、Build Configurationで指定する。これをReleaseにしてRunすれば、App Storeからダウンロードするアプリと同じ状態になる(はず)。なので、アプリの最終動作確認はReleaseビルドで行うべし、ですね。ただし、Releaseビルドではデバッグ情報もなくなるので要注意。デバッグが必要であれば、Debugビルドのままターゲットの設定でオプティマイザだけをオンにする。

さて、オプティマイザがiPhone 3G用にどのようなコードを生成しているかまでは分からない(調べるのは大変)。そこで、あれこれソースコードを書き換えて、オプティマイザがオンでも正常動作するよう修正する。半ば手探りだけど、今回は表示なので見当を付けやすい。オプティマイザが間違えようもない(と思われる)馬鹿丁寧な処理にして解決。

と言う訳で、修正版のBannerをサブミットしていますので、iPhone 3Gユーザの方は今しばしお待ちください。ご迷惑をおかけして、申し訳ありませんでした。

【追記】ってことは、AppleはiPhone 3Gで動作確認していない、ってこと?