ブログデザイン変更

| | Save This Page to del.icio.us このエントリーを含むはてなブックマーク

またしてもご無沙汰してしまいました。
今度は四ヶ月。年に 3 回しか更新しないブログ。すみません。

この半年間で、弊社も少し変化がありました。
ずいぶん前になりますが、オフィスが拡張されて倍の広さになりました

プログラマが多い会社だけにえいっとオフィスを extend して新しい機能(人)が加わった、というわけです。
イメージソース時代から一緒にやってきたデザイナーの PONY さんが S2 にやってきたのです。

早速、長らく MT デフォルトのデザインのまま放置されていたスタッフブログのデザインを
新しくしてくれています。

良い機会なので、私のブログも新しいデザインにしてみました。
と言っても私はデザイン出来ないので、スタイルが充実している WordPress から
良さそうなテーマを選んできて、それを MT に移植しただけです。

Minimalist by techdesigns

http://wordpress.org/extend/themes/minimalist

適当に移植しただけなので、汎用的に通用するとは思いませんが
何となく弄ったCSS のことを書いておきます。

#page          -> #container
#leftcol       -> #beta
#menu          -> #beta-inner
#maincol       -> #alpha
.contentheader -> .entry-title

これでだいたいいけます。後の細かいところは適当に MT に合わせて調整すれば完璧です。

(いい加減なこと書いてすみません...)

最後に宣伝を。

仕事とは直接関係ありませんが、私が参加する number0 のアルバム chroma がリリースされました。

19301388.jpg

2009 年の私のエネルギーの大半はこの作品に注ぎ込まれました。
その分、他のアウトプットの量が減ってしまったのが悔やまれます。

良かったら聴いてみてください。
http://www.myspace.com/number0number0

iPhone アプリ AMG: Ambient Music Generator を始めとして、音関連のプログラムは私の得意分野なので、
その辺の話もネタにしながら、何か書けると良いのかなと思ってます。

もちろん、iPad や HTML5 も気になっているのでその辺の話もキャッチアップして行きたいです。

Data::AMF 0.03

| | Save This Page to del.icio.us このエントリーを含むはてなブックマーク

すっかりご無沙汰してしまいました。
書く習慣がなくなると駄目ですね。

というわけで、Data::AMF 0.03 がリリースされました。
http://search.cpan.org/dist/Data-AMF/

このバージョンから AMF3 がサポートされました。

あと、Data::AMF::Remoting というのが追加されていて、
NetConnection を使った Flash Remoting と、Flex の RemoteObject
を使った Flex RPC が簡単に出来るようになりました。

Plack でゲートウェイを実装するとこんな感じです。

use Data::AMF::Remoting;
use Plack::Request;
use UNIVERSAL::require;

sub
{
    my $env = shift;
    my $req = Plack::Request->new($env);
    my $res = $req->new_response(200);
	
    if ($req->path =~ /\/amf\/gateway$/)
    {
        my $remoting = Data::AMF::Remoting->new(
            source => $req->raw_body,
            message_did_process => sub
            {
                my $message = shift;
                my ($class_name, $method) = split '\.', $message->target_uri;
                $class_name->require;
                my $controller = $class_name->new;
                return $controller->$method($message->value);
            }
        );
        $remoting->run;
		
        $res->content_type('application/x-amf');
        $res->body($remoting->data);
    }
	
    return $res->finalize;
};

source に POSTデータを渡して、message_did_process というハンドラで、
メッセージ毎に処理しています。ヘッダー用には別途 header_did_process という
ハンドラが用意されています。

$message->target_uri に、Controller.method という形式の文字列が渡ってくるので、
これを使ってディスパッチします。

$message->value は Perl オブジェクトにデシリアライズされた引数です。


コントローラクラスの方は MooseX::Declare を使うと良い感じに書けます。

use MooseX::Declare;

class HelloController
{
    method echo(Str $text)
    {
        return $text;
    }
}


Flex 側はこんな感じです。

<mx:RemoteObject id="helloService"
    endpoint="http://localhost:5000/amf/gateway"
    destination="perlamf"
    source="HelloController"
    showBusyCursor="true"
    result="trace(event.result)"
    fault="trace(event.fault.faultDetail)"
/>
<mx:Button label="Hello" click="helloService.echo('Hello, world!')" />

destication は特に使われないのですが、空にするとランタイムエラーになるので、
適当に書いておきます。

source がサーバー側のクラス名になります。

これでボタンがクリックされると、HelloController クラスの echo メソッドが
コールされます。

WWDC 2009 四日目 五日目 (San Francisco Day 5, Day 6)

| | Save This Page to del.icio.us このエントリーを含むはてなブックマーク

IMG_0812.JPG

 四日目の夜には Beer Bash という Apple 主催のパーティがありました。Yerba Buena Gardens という公園でビールやワインと食事が振る舞われました。ステージが設置されていて、名前はわかりませんがバンドが出て来て盛り上がっていました。

IMG_0830.jpg

 五日目は早めにセッションが終わったので、フィッシャーマンズワーフに行ってみました。右へ習えでクラムチャウダーを食べたりエビを食べたり、遠巻きにアルカトラズやゴールデンゲートブリッジを眺めました。ケーブルカーや muni にも乗りました。

 あっという間に過ぎた時間でしたが、集中して iPhone 開発の知識を聞いて、眠くなるまでコード書いて、わからなければすぐに聞けるという環境は非常にすばらしく、高いお金を払ってでも来る価値はあると思いました。オーディオ処理、OpenGL ES、パフォーマンス、アプリケーションアーキテクチャ、Cocoa のアーキテクチャ、それから新機能をいくつか、と知りたかったことをたくさん覚えられたので、アプリケーション開発に活かしていきたいと思います。

 ところで、前回アメリカに来た時にも思いましたが、1 年から 3 年くらい英語圏で生活しないと駄目だな、と思いました。なかなか難しいとは思いますが、これから先のことを考えると、ビジネスレベルで英語を使いこなせないとやりたいことがやれなくなるような気がしています。

WWDC 2009 二日目 三日目 (San Francisco Day 3, Day 4)

| | Save This Page to del.icio.us このエントリーを含むはてなブックマーク

 セッションに関しては NDA があるので書けませんが、朝から晩までみっちり学べて幸せです。一人だとご飯食べたり、どこかに出かけたりするのが無精になり、引き蘢ってコードを書き続けることになるので、不健康ながら充実しています。

 時差ぼけが未だに直らず、たぶん最後まで直らないだろうなと諦め始めていますが、ここ二日間は、ホテルに帰還、手早く晩ご飯を済ます、力尽きて寝る、深夜に起きる、コード書く、セッションに行く、というサイクルで動くことでうまいこと保たれております。

 日本時間に直すと朝の 11 時 頃に寝て、夕方 5 時頃に起きているので、いつもよりちょっと寝るのが遅いくらいです...

WWDC 2009 初日 (San Francisco Day 2)

| | Save This Page to del.icio.us このエントリーを含むはてなブックマーク

IMG_0798.JPG

 時差ぼけで 3 時頃に目が覚め、Blog などを書きながら基調講演に並ぶ列の状況を探っていました。そして 6 時頃にホテル出て会場に向かうと列はすでに長蛇になっていました。どうやら私は 572 番のようでした。

 確か 7 時半くらいには会場の中に入れてもらうことが出来、中でコーヒや甘い甘いパンをいただきながら待ちました。中は暖かく、絨毯のので座り心地もまずまずだったので割と楽に過ごせました。

 列が動き始めたのは 9 時半頃で、基調講演が行われた部屋まで辿り着くと、何だか大御所ロックスターのライブを見に来ているような感覚がありました。

 発表の内容については皆さんご存知の通りです。MacBook Pro、Snow Leopard、iPhone OS 3.0、そして iPhone 3G S とハードもソフトも大量に発表されました。私が記憶する限りでは、例年に比べてもとても濃い WWDC の基調講演だったのではないかな、思いました。

 Snow Leopard が Leopard ユーザーに対してたったの $29 で販売されるということが発表された時に、何故かはわかりませんが一番身震いしました。「みんなに使って欲しいから」と言って、スクリーン上の $129 の「1」が落ちた瞬間です。

 WWDC に来てしまうくらい Apple に傾倒しているので勘違いの可能性が高いですが、それでも Apple の時代を感じずにはいられませんでした。

 午後からはいよいよ NDA のセッションが始まりました。夜はアップルジャパンがレセプションパーティを開催していたので行き、二日目も終了です。

 余談ですが、Apple の人のプレゼンで一番出現頻度が高かった単語は「incredible」でした。以前アメリカに来た時にも思ったのですが、実際に現地で使われている頻度の高い英単語をもっと教えてくれれば良いのになと思いました。「suppose to」とかもかなりの頻度で聞くのですが、以前はあまり馴染みのない言葉でした。
 

WWDC 2009 開催前夜 (San Francisco Day 1)

| | Save This Page to del.icio.us このエントリーを含むはてなブックマーク

IMG_0791.JPG

 現地時間午前 11 時頃、サンフランシスコに到着しました。思っていたよりも交通網が充実していて、迷うことなくホテルに到着出来ました。チェックインは 3 時だったのですが、12 時頃に荷物を預けに行ってみると、そのままチェックインすることが出来ました。

 少し休んでから、早速会場の Moscone West へ登録に行ってきました。会場まで来ると色々感慨深くなり、いよいよだなという実感が湧きました。「Snow Loopard」の文字がデカデカと掲げられていたりしてワクワクします。受付でバックパックと T シャツを受け取って、回線の設定などをして後にしました。

 その後、時間があったので SF MoMA へ。量の多さに圧倒されましたが、非常に良い刺激になりました。全てをじっくり見る時間がなかったので気になっていた作品と、気になった作品をじっくり見ました。写真を撮る余裕がなかったので、諦めて脳に刷り込みました。

 MoMA を出て、近くの Jewish Musium にも行ってみようと思ったのですが、疲労と空腹がピークで、バーガーキングを持ち帰ってホテルに戻りました。戻ってからふと鏡を見ると、あまりにひどい顔をしていたので、これはまずいと思って寝ることにしました。

 唯一のオフだったので、本当はもう少し回りたかったのですが、本来の目的に支障が出てはいけないので、体を休めることを優先した初日になりました。

WWDC に参加してきます。

| | Save This Page to del.icio.us このエントリーを含むはてなブックマーク

明日から一週間、WWDC に参加するためにサンフランシスコに行ってきます。
iPhone アプリのおかげで一開発者として参加することが出来るのが非常に嬉しいです。

WWDC にいつか行ってみたいなと思いながら、一 Apple ファンとしてお祭り気分だけで参加するにはあまりに敷居が高く、そもそも数年前まで英語がまったく喋れない状態だったりして、なかなか参加することは出来なかったのですが、今回思い切って行ってみることにしました。

スケジュールの都合で、特にツアーなどに参加することなく単独で動いているので、もし現地でお見かけしましたらよろしくお願いします。

Mail: yoshizu [at] s2factory.co.jp
Twitter: seagirl

このモチベーションに乗っかってまた新しいアプリを開発し始めようと思います!

Progression で Flex アプリケーションを作る

| | Save This Page to del.icio.us このエントリーを含むはてなブックマーク

Progression を使って Flex アプリケーションを作る場合、
自分ならどんな風に書くかな?と思って試してみました。

サンプル
ソース

--
まず、Progression と Flex を共存させるための基本的な考え方は、
コントローラを Progression で、ビューを Flex で書く、ということになります。

これを踏まえた、アーキテクチャは以下のようになります。

 
・View (MXML)

View は MXML で書きます。逆に考えると、MXML で書いた部分が View です。したがって、基本的に MXML にはビジュアルコンポーネントしか書きません。

・Delegate

Application、ItemRenderer など、View を生成するところで Flex の作法に逆らえないところは、View を操作するロジックを非ビジュアルコンポーネントとして View に記述します。Delegate は、後述する ViewController とは別のものになります。通常、View が ViewController を保持/参照することはありません。

・ViewController (Cast)

Progression の CastObject クラスを継承し、View オブジェクトを保持します。View の操作とイベントハンドリングを記述します。

・Scene

Progression の Scene です。Scene 毎に必要になる Model や View を生成し、それらを用いて ViewController を生成します。また、必要となるリソースは都度 Command を用いて取得し、生成した Model で処理/保持します。

・Service (Command)

外部サービスとの連携には Progression の Command を使います。これらの Command の生成と実行は、Scene が行います。

・Model

Model は ViewController の単位で生成します。ViewController が Model の値を View に適用します。値を保持する役割の他に、サービスから取得した値をデコードする処理なども担います。

--
次に、処理の流れを具体的に見て行きましょう。

1. ProgressionSample.mxml

Flex フレームワークを使う場合、メインクラスは Application クラス (MXML) になります。Application クラスは Flex のコンテナなので、直接 MXML を使って View を構築することも出来ますが、前述したアーキテクチャに従うために、ProgressionSampleDelegate コンポーネントのみが記述されています。

<?xml version="1.0" encoding="utf-8"?>
<mx:Application
	xmlns:mx="http://www.adobe.com/2006/mxml"
	xmlns:local="*"
	layout="absolute"
	viewSourceURL="srcview/index.html"
>
	<mx:Style source="ProgressionSample.css" />
	<local:ProgressionSampleDelegate />
</mx:Application>

2. ProgressionSampleDelegate

ProgressionSample の FlexEvent.INITIALIZE イベントで ProgressionSampleDelegate の initialize() が呼ばれます。initialize() が呼ばれるまでの処理は、親クラスの ApplicationDelegate に隠蔽しています。initialize() で Progression インスタンスを生成し、ここからの処理の流れは Progression に委ねます。

public class ProgressionSampleDelegate extends ApplicationDelegate
{
	public var view:ProgressionSample;
	
	override protected function initialize():void
	{
		SWFWheel.initialize(view.systemManager.stage);
		FilterShortcuts.init();
		
		var progression:Progression = new Progression("main", view.systemManager.stage, MainScene);
		progression.sync = true;
		progression.autoLock = false;
		progression.goto(progression.firstSceneId);	
	}
	
}

3. MainScene

MainScene は Page1Scene と Page2Scene を生成し、さらに Header/Navigation/Contents の View と ViewController を生成しています。スタティックなコンテンツなので難しいところは特にないと思います。これらは onLoad で Application に AddChild されます。さらに、onInit で Page1Scene に Goto するようになっています。

public function MainScene(initObject:Object = null)
{
	super("main", initObject);
	
	addScene(new Page1Scene());
	addScene(new Page2Scene());
	
	application = Application.application as Application;
	
	header = new HeaderController(null, new Header());
	navigation = new NavigationController(null, new Navigation());
	contents = new ContentsController(null, new Contents());
}
override protected function _onInit():void
{
	addCommand(
		new Goto(getSceneAt(0).sceneId)
	);
}

override protected function _onLoad():void
{
	addCommand(
		[
			new AddChild(application, header),
			new AddChild(application, navigation),
			new AddChild(application, contents)
		]
	);
}

4. Page1Scene

Page1Scene では、PageModel と Page1 を生成し、Page1Controller を生成しています。onLoad で外部 XML を読んで、PageModel に渡し、それから Contents に View1Controller を AddChild しています。

public function Page1Scene(initObject:Object = null)
{
	super("page1", initObject);
	
	addScene(new Page1DetailScene());

	controller = new Page1Controller(new PageModel(), new Page1());
}

public var controller:Page1Controller;

override protected function _onLoad():void
{
	addCommand(
		new LoadURL(new URLRequest("assets/data.en.xml")),
		
		function ():void
		{
			controller.model.parse(this.previous.data);
		},
		
		new AddChild(MainScene(parent).contents.view, controller)
	);
}

override protected function _onUnload():void
{
	addCommand(
		new RemoveChild(MainScene(parent).contents.view, controller)
	);
}

5. Page1Controller

Page1Controller は view プロパティに Page1 オブジェクトを保持しています。view の表示アニメーションを DoTweener コマンドで定義し、さらに view.dataGrid の MouseEvent.DOUBLE_CLICK イベントをハンドリングしています。データグリッドがダブルクリックされると、Page1DetailScene がダイナミックに生成する Scene に Goto しています。

public var model:PageModel;
public var view:Page1;

override protected function _onCastAdded():void
{
	view.alpha = 0;
	
	view.dataGrid.dataProvider = model.words;
	view.dataGrid.addEventListener(MouseEvent.DOUBLE_CLICK, dataGridDoubleClickHandler);
	
	addCommand(
		new DoTweener(
			view,
			{
				_Blur_blurX : .1,
				_Blur_blurY : .1,
				alpha: 1,
				time: 1
			}
		)
	);
}

override protected function _onCastRemoved():void
{
	view.dataGrid.removeEventListener(MouseEvent.DOUBLE_CLICK, dataGridDoubleClickHandler);
	
	addCommand(
		new DoTweener(
			view,
			{
				_Blur_blurX : .1,
				_Blur_blurY : .1,
				_Blur_quality : 3,
				alpha: 0,
				time: 1
			}
		)
	);
}

private function dataGridDoubleClickHandler(event:MouseEvent):void
{	
	new Goto(new SceneId("/main/page1/detail/" + view.dataGrid.selectedItem.@id)).execute();
}

6. Page1DetailScene

Page1DetailScene は通過専用の Scene で、ここで目的地となる Scene をダイナミックに生成しながら、遷移しています。この辺りは muraken さんの記事 を多いに参考(と言うより、ほぼそのまま...)にさせていただきました。遷移が終わったら、View を持たない Controller を生成し、Alert.show() でモーダルウィンドウを表示させています。

public function Page1DetailScene()
{
	super("detail");
	
	controller = new Page1DetailController();
}

public var controller:Page1DetailController;

override protected function _onLoad():void
{
	super._onLoad();
	
	var parentController:Page1Controller = Page1Scene(parent).controller;
	var item:XML = parentController.model.getItemById(current.name);
		
	controller.show(item, parentController.view);
}
public function show(item:XML, target:Sprite):void
{
	if (item == null)
		Alert.show("Couldn't find.", "Error", 4, target, closeHandler);
	else
		Alert.show(item.@value, "No." + item.@id, 4, target, closeHandler);		
}

private function closeHandler(event:CloseEvent):void
{
	new Goto(new SceneId('/main/page1')).execute()
}

--
基本的な流れは以上です。

DataGrid の DataGridColumn に無駄に豪華な ItemRenderer を当てていますが、ItemRenderer と ItemRendererDelegate はこんな具合に書くよ、というサンプルのつもりで敢えてそうしてあります。

html-template は Flex Builder でデプロイするのに最適なようにカスタマイズしてあります。

--
以下は余談ですが、今回の検証で本格的な Flex アプリケーションを Progression を使って実装出来ることがわかりました。

Flex フレームワークはページ管理、状態管理といった部分の機能が非常に貧弱なので、大規模な開発を管理するのが難しいという側面があります。それを補うために、Cairngorm や PureMVC といった Flex アプリケーション向けのフレームワークが開発されていますが、Progression もそれらと比較しても遜色はないと思いました。

特に Scene という概念が秀逸で、Scene が Facade になって内部の MVC を隠蔽してくれるため、Scene 単位でアプリケーションを分けることが出来ます。Scene 毎に分散して開発することで、大規模な開発もしやすいと思いました。

さらに余談ですが、MXML に非ビジュアルコンポーネントを記述することは、Flash Professional でタイムラインにスクリプトを書くのと同じ感覚なので、実際のプロジェクトでは使用されていないスタイルだと思います。

個人的には Cocoa + Interface Builder のように、View に相当する部分は GUI で構築してしまって、中のソースコードは意識しなくて済むように隠蔽されている、というのが案外望ましいのかな、と思っているので、Flash Catalyst + Flash Builder の開発はそこを目指して欲しいなと思っています。残念ながら Beta から汲み取れる雰囲気ではそうなっていないようですが...。

Subversive のインストール

| | Save This Page to del.icio.us このエントリーを含むはてなブックマーク

メモ:

インストールに必要な URL

SVNKit
http://eclipse.svnkit.com/1.3.x/

SVN Connectors
http://www.polarion.org/projects/subversive/download/eclipse/2.0/update-site/

Subversive
http://download.eclipse.org/technology/subversive/0.7/update-site/

SVN Connectors と Subversive は一度に入れる
Leopard 標準の Subversion は 1.4 系なので、MacPorts で 1.6 系を入れてしまう
Subversion 1.6 系を入れると、zsh の補完がおかしくなるので対処する

% cd /usr/share/zsh/site-functions
% sudo wget -c http://gvn.googlecode.com/svn/trunk/contrib/zsh/_subversion

ActionScript でコマンドラインツールを作る方法

| | Save This Page to del.icio.us このエントリーを含むはてなブックマーク

Flex SDK に含まれる AIR 開発用の adl コマンドを使って、ActionScript で簡単なコマンドラインツールが作れることに気が付きました。

コンソールに Hello, world! と引数の中身を適当に出力するツールは、こんな感じで実装出来ます。

コマンドラインツールなので、最後に exit() を呼んでやる必要があります。
引数は InvokeEvent 経由で受け取るようになっています。

// hello.as
package {
	import flash.desktop.NativeApplication;
	import flash.display.Sprite;
	import flash.events.InvokeEvent;

	import mx.utils.ObjectUtil;

	public class hello extends Sprite
	{
		public function hello()
		{
			NativeApplication.nativeApplication.addEventListener(InvokeEvent.INVOKE, initialize);
		}
		
		private function initialize(event:InvokeEvent):void
		{
			trace("--------------------------------------------------------------------------------");
			trace("Hello, world!");
			trace("");
			
			// コマンドライン引数を受け取る
			var args:Array = event.arguments;
			
			trace(ObjectUtil.toString(args));
			
			trace("");
			NativeApplication.nativeApplication.exit();	
		}
	}
}

// hello-app.xml
<?xml version="1.0" encoding="UTF-8"?>
<application xmlns="http://ns.adobe.com/air/application/1.5">
	<id>HelloASCommandLineTool</id>
	<filename>hello</filename>
	<name>hello</name>
	<version>v1</version>
	<initialWindow>
		<content>hello.swf</content>
	</initialWindow>
</application>

後は、これを適当に amxmlc でコンパイルし、adl で実行するだけです。

% amxmlc -output hello.swf hello.as
Loading configuration file /Applications/Adobe Flex Builder 3/sdks/3.2.0/frameworks/air-config.xml
hello.swf (14304 bytes)

% adl hello-app.xml -- Hoge Fuga "`pwd`"
--------------------------------------------------------------------------------
Hello, world!

(Array)#0
  [0] "Hoge"
  [1] "Fuga"
  [2] "/Users/yoshizu/Desktop/ASCLTool"

ちなみに、trace ログの出力は、mm.cfg で flashlog.txt に書き込まれるようにしている場合は、flashlog.txt に向きます。mm.cfg 作っていない場合は、そのままコンソールに出力されます。

ただ、このままだと hello-app.xml を置いているディレクトリを使う時にいちいち意識しないといけないので、簡単なラッパーとなるシェルスクリプトを作っておいて、パスが通る場所に置いておくと便利です。

今回は、ホームディレクトリ以下にこんな構成で配置しました。

bin
  |- as
  |- astools
      |- hello
          |- hello.as
          |- hello-app.xml
          |- hello.swf

#!/bin/sh

if [ ${1:-0} = 0 ]
then
	echo "usage: % as hello"
	exit
fi

path=${0%/*}

adl ${path}/astools/${1}/${1}-app.xml -- $2 $3 $4 $5 $6 $7 $8 $9

exit

すると、こんな風にどこからでも叩けるようになりました。

% as hello Hoge Fuga "`pwd`"
--------------------------------------------------------------------------------
Hello, world!

(Array)#0
  [0] "Hoge"
  [1] "Fuga"
  [2] "/Users/yoshizu/Desktop"

違うツールを作った時にも、astools 以下に放り込んでおけば、as コマンドは共通して使えるので便利です。

--
追記 (2009.05.15)

mm.cfg で trace が flashlog.txt にいってしまう人は、一時的に mm.cfg の中身を書き換えてあげるとコンソールに trace が表示されるようになります。

#!/bin/sh

function replace
{
	sed -e $1 $2 > $3
	mv $3 $2
	return 0;
}

mm=${HOME}/mm.cfg
path=${0%/*}

if [ ${1:-0} = 0 ]
then
	echo "usage: % as hello"
	exit
fi

replace "s/^\(.*\)=1$/\1=0/g" $mm ${path}/as-tmp

adl ${path}/astools/${1}/${1}-app.xml -- $2 $3 $4 $5 $6 $7 $8 $9

replace "s/^\(.*\)=0$/\1=1/g" $mm ${path}/as-tmp

exit

ネットワーク越しのディスクを使って TimeMachine する

| | Save This Page to del.icio.us このエントリーを含むはてなブックマーク

メモ:

defaults write com.apple.systempreferences TMShowUnsupportedNetworkVolumes 1

AFP でマウントしておくと TimeMachine の対象ディスクに表示されるようになる

AMG: Ambient Music Generator 1.0 リリースしました。

| | Save This Page to del.icio.us このエントリーを含むはてなブックマーク

amg_1_1.jpg

AMG: Ambient Music Generator 1.0 リリースしました。
App Store

--
AMG: Ambient Music Generator
http://seagirl.jp/iphone/amg/

Ambient Music Generator は、アンビエント・ミュージックを動的に生成するためのツールです。

使い方

音の生成を始めるには iPhone をシェイクします。あるいは、Algorithm を「None」から「Random」に変更する必要があります。

もう一度シェイクすると生成が止まります。

ジェネレータ
ジェネレータは全部で 3 つあります。フリックすることで、それぞれのジェネレータを切り替えることが出来ます。それぞれのジェネレータはいくつかのパラメータを持っています。これらのパラメータを調整することで音楽を生成することが出来ます。

アルゴリズム
音楽の生成に用いられるアルゴリズムを選択します。いずれかのアルゴリズムを与えることで、ジェネレータは音を鳴らし始めます。

キー
ルートキー、スケール、音程の範囲を選択することが出来ます。

インターバル
白い丸を左右にドラッグすることで、音と音の間隔を調整することが出来ます。

エンベロープ
二つの白い丸を上下左右にドラッグすることで、音の性質を調整することが出来ます。

SWFSound (Draft)

| | Save This Page to del.icio.us このエントリーを含むはてなブックマーク

Adobe MAX Japan 2009 への参加を通じて、
たくさんの発見とインスピレーションを得ることが出来たので、
もう少しコミュニティに貢献していきたいなと思いまして、
新しくサウンド系のライブラリを作ろうと思います。

Spark project の音系ライブラリと言えば sazameki がありますが、
充実した機能を持っている反面、音を鳴らすまでに必要な手続きが少し長いので、
プログラムに不慣れな人にとっては少し敷居が高いように思えました。

そこで、もっと手軽に音を鳴らすことが出来るライブラリを作ろうと思いました。

手軽に使えるという部分を意識するようになったのは、
Spark project の TeraFire から大きなインスピレーションを得たからです。

TeraFire は、new して addChild することで炎を作ることが出来ますが、
SWFSound は、new して play するだけで音が鳴らすことが出来ます。

var instrument:Instrument = new Instrument();
instrument.play();

音程や音量や音の長さも気軽に変えることが出来ます。

// 音程を変える
instrument.noteNumber = 60; // 0 〜 127 の MIDI ナンバーでで音程を決める
instrument.frequency = 440; // 周波数で音程を決める

// 音量を変える
instrument.volume = 0.8; // 0  〜 1.0 の範囲の値

// 音の長さを変える
instrument.lentgth = 3.0; // 単位は秒

音色は IPreset を実装したクラスのインスタンスを与えることで変えられます。
豊富なプリセットを用意する予定です。

// ピコピコな音にします
var preset:IPreset = new PicoPico();
instrument.preset = preset;

プリセットを微調整することも出来ますし、全く新しく作ることも出来ます。

// オシレータをサイン波にする
preset.oscillator1 = new Sinewave();

// ADSR エンベロープを調整する (0 〜 1.0 の範囲の値)
preset.attack = 0.8;
preset.decay = 1.0;
preset.sustain = 0.4;
preset.release = 0.6;

// 新しくプリセットを作る
var customPreset:IPreset = new Preset();
customPreset. oscillator1 = new SquareWave();
customPreset. oscillator2 = new Noise();
customPreset.attack = 0;
customPreset.decay = 1.0;
customPreset.sustain = 0;
customPreset.release = 0;

また、楽器をいくつか組み合わせたキットを作ることも出来ます。
デフォルトでも、DrumKit や WebSiteKit などを搭載する予定です。

// ドラムキット
var drums:IKit = new DrumKit();
drums.play(0); // キック
drums.play(1); // スネア
drums.cymbal.play(); // シンバル
drums.closeHighHat.play(); // クローズハイハット

// ウェブサイト用の音を集めたキット
var website:IKit = new WebSiteKit();
website.click.play(); // クリック
website.rollover.play(); // ロールオーバー
website.rollout.play(); // ロールアウト

もちろん、新しくキットを作ることも出来ます。

// 汎用的なキット
var kit:IKit = new Kit();
kit.addInstrument(instrument1);
kit.addInstrument(instrument2);
kit.play(0);

エフェクトも使えます。

// エフェクトを作る
var effect:IEffect = new Delay();

// 楽器に適用
instrument.addEffect(effect);

// プリセットに適用
preset.addEffect(effect);

// キットに適用
kit.addEffect(effect);

楽器、プリセット、キットという単位で好きなようにカスタマイズ出来るので、
ユーザーにたくさんの音色を作ってもらって、どんどん公開してもらうのが狙いです。

さらにおまけとして、Ambient Music Generator の開発を通じて得たノウハウを元に、
スケールを定義するクラスを同梱しようと思います。

// スケールを作る
var scale:IScale = new MajorScale();
scale.rootkey = 5; キーを E に変更

// 音程の範囲を制限する
scale.min = 40; // 最小値
scale.max = 80; // 最大値

// 作ったスケールを使ってランダムに鳴らす
var noteNumber:int = scale.notes[Math.random() * scale.numNotes];
instrument.noteNumber = noteNumber;
instrument.play();

これらを Timer とかで適当に回したりすると、自動作曲っぽいことが出来ます。

というようなライブラリを絶賛開発中です。
公開予定は今春として濁しておきたいと思います...。

要望などございましたらどしどしお寄せ下さい!

yoshizu [ at ] s2factory.co.jp
twitter.com/seagirl

Wonderfl ワンダフル!

| | Save This Page to del.icio.us このエントリーを含むはてなブックマーク

KAYAC さんの新しいサービス Wonderfl がおもしろいです。

ブラウザで書いた AS3 コードが即座にコンパイルされてプレビュー出来るといったサービスみたいです。

まだベータテスト中(?)らしいのですが、すでに Twitter 界隈の ASer たちが続々とコードを投稿しています。

嬉しいのが、Flash Player 10 に対応した Flex SDK でコンパイルしているっぽくて、
Dynamic Sound Generation とかも普通に動いてます。

さらに外部ライブラリもすでにいくつか組み込まれており、Thread とか Tweener などが使えます。

というわけで、僕もいくつか投稿してみました。

1. Dynamic Sound Generation
http://wonderfl.kayac.com/code/8b17ddb1ce4c73ebe8165c95d30f208bd393d037

2. BitmapFilter
http://wonderfl.kayac.com/code/b9c68bf8505c61b9b617dade4491ee8d2b3b98f

Objective-C 向けの静的解析ツール clang

| | Save This Page to del.icio.us このエントリーを含むはてなブックマーク

Objective-C 2.0 からガーベジコレクションが導入されて話題になりましたが、
iPhone OS ではサポートされていないので、iPhone アプリを作ろうと思うと
カウント方式と言われる方法で、メモリ管理を自分でしなければなりません。

しかし普段 AS で、ガーベジコレクションに頼ったプログラムを書いている人からすると
このメモリ管理になかなか慣れることが出来ず、ついついメモリリークしてしまいます。

それを防ぐための clang というツールを アシアルブログ で目にしたので、
早速、試してみました。

Picture 1.png

メモリリークがたくさん見つかってしまいました...
ファイル名と行数が書かれているので、簡単に場所を特定することが出来ます。

しかし、これはとても便利ですね。驚きました。
Xcode に統合されれば良いのに、と思いました。

使い方は、プロジェクトディレクトリで

% scan-build -V -o ~/Desktop xcodebuild

で、解析が行われて HTML をブラウザに表示してくれます。

オプションの -o は出力先を指定していて、-V は解析後にブラウザを自動で
起動するためのものです。引数の xcodebuild はコンパイルに使われるコマンドです。

なお、実行すると実際にコンパイルされて、それが解析対象になるので、
もう一度、実行する時は clean してやる必要があります。

% xcodebuild clean

Ambient Music Generator 1.2

| | Save This Page to del.icio.us このエントリーを含むはてなブックマーク

Picture 2.png

Ambient Music Generator 1.2 をリリースしました。
http://seagirl.jp/ambient/ambient.air

主な変更点は、新たにビジュアル表現を追加したことと、全体的なアルゴリズムの見直しによるパフォーマンスの向上です。

なお、バージョンアップに伴って、AGF ファイルのフォーマットが新しくなったため、古いバージョンのファイルを開く事が出来なくなっています。

ある音階の周波数の求める式

| | Save This Page to del.icio.us このエントリーを含むはてなブックマーク

AS3 である音階の周波数の求める式

var midiNumber:int = 0;
var frequency:Number = 440 * Math.pow(2, (midiNumber - 69) / 12);

(参考)MIDI Number と音階の対応表
http://www.phys.unsw.edu.au/jw/notes.htm

ある MIDI Number の周波数をぱっと知りたい時の Perl ワンライナー

% perl -e 'printf "%.03f", 440 * (2 ** ((0 - 69) / 12))'
8.176

Ambient Music Generator

| | Save This Page to del.icio.us このエントリーを含むはてなブックマーク

capture_001.png

Spark project 勉強会 #05 で Ambient Music Generator という AIR アプリケーションのデモをさせていただきました。

今回の勉強会のお題が「Flash Player 10 の新しい機能を使った何か」だったので、Dynamic Sound Generation を使ったアプリケーションを何か作れないか、というのが動機でした。

新機能を使っている点としては、他にも Vector や AIR 1.5 から SDK に組み込まれた Adobe AIR Update Framework など。


Ambient Music Generator は、アンビエント・ミュージックを動的に生成するためのツールです。次に鳴らす音をダイナミックに変化させていくという点では楽器とも言えますし、自動的に音が生成され続けるという点では、BGM マシンとも言えます。

仕組みとしては、リズムや音程にある程度の制約を与えた中で、ランダムに音を選択していくことで、音楽らしさをなるべく損なわない形で、音を生成するようになっています。

制約に関しては、スケール、キー、音の間隔、音量といったパラメータで与えていて、これらを GUI で操作出来るようにしています。その他にプログラムにハードコーディングしてあるパラメータがいくつかあります。

今後の課題としては、音色を増やしたり、アルゴリズムを増やしたり、絵を見せたりすることが考えられますが、目指している方向として「簡単にそれらしい音楽を生成するツール」というのがあるので、そこはバランスを取りながら考えたいです。


Ambient Music Generator
http://seagirl.jp/ambient/ambient.air
(予め Adobe AIR をインストールする必要があります)

Leopard と mod_xsendfile

| | Save This Page to del.icio.us このエントリーを含むはてなブックマーク

画像ファイルを出力する CGI を作るのに、
mod_xsendfile を使うことが最近増えてきているので、
ローカル環境にもインストールしてみようと思って試してみたら、
うまくいかなくて困ったのでメモ。


1. ソースをダウンロード

http://tn123.ath.cx/mod_xsendfile/ の Download のところから tarball を取ってきて適当に展開する。


2. コンパイルとインストール

apxs -cia -Wc,"-arch x86_64 -arch ppc -arch i386 -arch ppc64" -Wl,"-arch x86_64 -arch ppc -arch i386 -arch ppc64" mod_xsendfile.c


どうも、サイトに従って、

apxs -cia mod_xsendfile.c

とすると、i386 のバイナリしか作ってくれないみたいなので、
オプションに色々付けて必要な分を追加しているみたいです。

こんなにたくさんオプション付けなくても必要なのがあれば良いのだけど、
色んな人がコピペすることを考えてそうしているのであろう。


【参考】
Compiling mod_xsendfile for OS X

WEB+DB PRESS Vol.46

| | Save This Page to del.icio.us このエントリーを含むはてなブックマーク

24日発売の WEB+DB PRESS Vol.46 で、「Adobe AIR開発入門」という特集記事を書きました。

ザ・ ストリッパーズの大塚さん にお誘いいただいて、執筆することになったのですが、
何ぶん初めての経験だったので四苦八苦しながらやりました。

「初心者向け」ということだったので、出来るだけわかりやすく書くのを心がける一方、
入門記事にありがちな発展性のないサンプルコードにしたくなくて、より実践に近いものにしてあります。

ぜひ読んでやってください。
お手柔らかに。