<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Objective-Audio</title>
    <link rel="alternate" type="text/html" href="http://objective-audio.jp/" />
    <link rel="self" type="application/atom+xml" href="http://objective-audio.jp/atom.xml" />
    <id>tag:objective-audio.jp,2008-07-26://13</id>
    <updated>2010-07-17T13:18:52Z</updated>
    <subtitle>MacとiPhoneでオーディオプログラミング</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type 5.01</generator>

<entry>
    <title>BigStopWatch v2.4.1 リリース</title>
    <link rel="alternate" type="text/html" href="http://objective-audio.jp/2010/07/bigstopwatch-v241.html" />
    <id>tag:objective-audio.jp,2010://13.180</id>

    <published>2010-07-17T09:13:33Z</published>
    <updated>2010-07-17T13:18:52Z</updated>

    <summary> BigStopWatchのv2.4.1が公開されました。 一つ前のv2.4でR...</summary>
    <author>
        <name>Yasoshima</name>
        
    </author>
    
        <category term="BigStopWatch" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://objective-audio.jp/">
        <![CDATA[<p>
BigStopWatchのv2.4.1が公開されました。</p>

<p>
一つ前のv2.4でRetina対応にしたためiOS4.0以降でしかインストールできないようにしていたのですが、iPhone 2GなどiOS4.0にアップグレードできないデバイスを使っている方から3.1.3にも対応してほしいという要望があったので修正しました。他に変更点はありません。
</p>]]>
        
    </content>
</entry>

<entry>
    <title>OpenGL ESのRetina対応</title>
    <link rel="alternate" type="text/html" href="http://objective-audio.jp/2010/07/opengl-esretina.html" />
    <id>tag:objective-audio.jp,2010://13.179</id>

    <published>2010-07-09T09:19:56Z</published>
    <updated>2010-07-12T11:47:32Z</updated>

    <summary> OpenGL ESのRetina対応の方法をちょっとメモしておきます。Open...</summary>
    <author>
        <name>Yasoshima</name>
        
    </author>
    
        <category term="全般 - iPhone" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://objective-audio.jp/">
        <![CDATA[<p>
OpenGL ESのRetina対応の方法をちょっとメモしておきます。OpenGL以外のRetina対応については@k_katsumiさんの記事「<a href="http://d.hatena.ne.jp/KishikawaKatsumi/20100707/1278522113">アプリケーションを iPhone 4 の Retina Display に対応するための方法いろいろ</a>」がとても参考になると思います。というか、この記事を見てOpenGLについては書いてなかったので触発されて書くことにしました。
</p>

<p>
Xcodeの「OpenGL ES Application」で作成したプロジェクトの場合で書きますと、EAGLViewのViewのサイズはRetinaディスプレイでも変わらず320x480です。iOS4からUIView（およびEAGLViewなどのサブクラス）にcontentScaleFactorというメソッドが追加され、この値を変更することでUIViewの中の解像度を変更することができるようになりました。もうひとつ、UIViewがもってるCALayerのcontentsScaleでも解像度を変えることができるようです。デフォルトでは1.0になっていますので、Retinaディスプレイの解像度に合わせるには2.0にします。実際には、UIScreenのscaleからディスプレイのサイズの比率が取得できますので、そこからセットします。
</p>

<p>
ちょっとやってみましょう。AppDelegateのapplication:didFinishLaunchingWithOptions:メソッドに次のコードを書き加えてください。
</p>

<pre class="prettyprint">
glView.contentScaleFactor = [UIScreen mainScreen].scale;
</pre>

<p>
基本、これだけでRetinaディスプレイのiPhone4だと倍の解像度になるのですが、「OpenGL ES Application」のデフォルト状態の描画内容だと効果が全然わからないので、さらにコードを変えてみます。
</p>

<p>
まず、シェーダーとか使ってるとめんどくさいのでES2Rendererを使わないようにします。以下のようにEAGLViewのinitWithCoderの中の一行を書き換えてください。
</p>

<pre class="prettyprint">
renderer = [[ES2Renderer alloc] init];
↓
renderer = nil;
</pre>

<p>
次に、ES1Rendererのrenderメソッドの中の縦に動かしている一行を、高解像度の効果がわかりやすいように回転に変更します。
</p>

<pre class="prettyprint">
glTranslatef(0.0f, (GLfloat)(sinf(transY)/2.0f), 0.0f);
↓
glRotatef(transY, 0, 0, 1.0);
</pre>

<p>
コードの変更は以上です。一番最初にAppDelegateに追加したglView.contentScaleFactorの一行のありなしでそれぞれiPhone 4で実行してみると四角形のエッジのスムーズさの違いがわかると思います。iPhone 4実機をもっていなくても、iPhone simulatorのデバイスをiPhone 4にすることで確認できます。
</p>

<p>
OpenGL的には単純に解像度が倍になりますので、ディスプレイのサイズに依存してアプリを作っていたら結構な修正を余儀なくされると思います。場所がずれたりとか、テクスチャも荒く表示されちゃったりとかすると思います。さらにやっかいなのが、UITouchの位置は２倍にならないってことです。scaleに応じて位置を調整する必要があります。
</p>

<p>
ちなみに、EAGLViewのcontentScaleFactorをセットするだけで解像度が変わっているのではなく、scaleをセットしてからESRendererのresizeFromLayerメソッドの中の[context renderbufferStorage:GL_RENDERBUFFER fromDrawable:layer]が呼ばれて始めてGLの解像度が変わります。もし、glView生成時でなく、後からscaleを変更したいなんていう場合には、contentScaleFactorをセットしたあとにresizeFromLayerを呼んでください。
</p>

<p>
あと今、iOS4より前のバージョンもサポートするなら、iPadのiPhoneシミュレータで動くことも考えないといけなそうです。iPadでiPhoneアプリを２倍に表示するとUIScreenのscaleが2.0になってしまいますが、UIViewにはcontentScaleFactorがありません。また、CALayerのcontentsScaleはiPadでも受け付けることができますが、GLの解像度が変わることはありません。プロパティの有無やOSのバージョンなどでscaleを無視する必要がありそうです。
</p>]]>
        
    </content>
</entry>

<entry>
    <title>BigStopWatch v2.4公開されました</title>
    <link rel="alternate" type="text/html" href="http://objective-audio.jp/2010/07/bigstopwatch-v24.html" />
    <id>tag:objective-audio.jp,2010://13.178</id>

    <published>2010-07-07T00:27:22Z</published>
    <updated>2010-07-07T00:42:19Z</updated>

    <summary> BigStopWatchのv2.4が公開されました。ダウンロードはこちらから。...</summary>
    <author>
        <name>Yasoshima</name>
        
    </author>
    
        <category term="BigStopWatch" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://objective-audio.jp/">
        <![CDATA[<p>
BigStopWatchのv2.4が公開されました。ダウンロードは<a href="http://itunes.apple.com/jp/app/bigstopwatch/id301615836?mt=8">こちら</a>から。
</p>

<p>
主な変更点はRetina対応で、iPhone 4をお持ちの方はより美しく表示されます。今までもアンチエイリアスがかかるようにして文字や線の美しさにはこだわっていたのですが、Retina対応することで一段クオリティの高い美しさになってます。iPhone 4をお持ちの方はぜひアップデートをお願いします。
</p>

<p>
あとはバッテリーインジケータを標準のものに近い形に変えてたり、タッチしたときのアニメーションを変えたりくらいですね。カウントダウンの時に自分的に意図していない表示になっていたところとかも修正したりしてます。
</p>]]>
        
    </content>
</entry>

<entry>
    <title>AVPlayerでムービーを再生する方法</title>
    <link rel="alternate" type="text/html" href="http://objective-audio.jp/2010/07/avplayer.html" />
    <id>tag:objective-audio.jp,2010://13.177</id>

    <published>2010-07-06T11:00:00Z</published>
    <updated>2010-07-06T11:53:11Z</updated>

    <summary> AVFoundationといえばOS3.xではAVAudioPlayerとAV...</summary>
    <author>
        <name>Yasoshima</name>
        
    </author>
    
        <category term="全般 - iPhone" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="ios40ムービーavplayer" label="iOS4.0 ムービー AVPlayer" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://objective-audio.jp/">
        <![CDATA[<p>
AVFoundationといえばOS3.xではAVAudioPlayerとAVAudioRecorderくらいだったのですが、iOS4.0から一気にいろんなものが増えてます。僕が以前予想していたように、オーディオだけじゃなくて映像関係も扱えるように進化していますね。なんかいろいろありすぎて、かつ自分がAudioUnitでやりたいことを置き換えるようなものじゃなさそうなので基本的にはスルーしているのですが、一番手軽で役に立ちそうだったけどちょっと使い方にハマったAVPlayerを取り上げたいと思います。
</p>

<p>
AVAudioPlayerはサウンドファイルを再生するだけでしたが、AVPlayerはサウンドもムービーも関係なくこれひとつで再生できます。サウンドはファイルパス渡してプレイってするだけでなんとなく鳴ってしまうのであえて説明する必要はないと思いますが、ちょっと使い方を知らないと厄介なのがムービーの再生です。
</p>

<p>
僕がハマってしまったのは、AppleのAVPlayerLayerのリファレンスに嘘が書いてあるところです。いや嘘というよりも、OS4.0のベータが進んでいくうちに使い方が変わってしまっているのにリファレンスがそのまま残っているというところです。
</p>

<p>
以下が、AVPlayerLayerのリファレンスに書いてあるコードです。
</p>

<pre class="prettyprint">
AVPlayer *player = &lt;#A configured AVPlayer object#&gt;;
CALayer *superlayer = &lt;#Get a CALayer#&gt;;
AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:player];
[superlayer addSublayer:playerLayer];
</pre>

<p>
どっかのCALayerのサブレイヤーにAVPlayerLayerをのせろと書いてあります。ですが、この通りにやっても正常にムービーは映し出されないようです。一瞬だけ映像が見えることもありますが、音だけが鳴り、映像が再生されることはありません。最初この状態になったときには、きっとGMの頃には再生できるようになるだろうとおもっていたのですが、GMになっても再生できず、じゃあ別のやり方に変わったんだろうと妄想を膨らませて解決しました。
</p>

<p>
ではどうするかというと、UIViewのサブクラスを作り、そのlayerClassメソッドをオーバーライドして、UIViewのlayerをAVPlayerLayerに差し替えます。OpenGLのEAGLViewでやっているのと同じ手法です。
</p>

<p>
さっそく、その方法でムービーを再生するサンプルを作ってみたいと思います。まずは、XcodeでWindow-based Applicationを「AVPlayerTest」とかの名前で作成して、AVFoundationをインポートしてください。
</p>

<p>
次に、UIViewのサブクラスを作成してください。名前は「AVPlayerView」としておきます。コードを以下のような感じで書き換えてください。
</p>

<pre class="prettyprint">

//
//   AVPlayerView.h
//

#import &lt;UIKit/UIKit.h&gt;
#import &lt;AVFoundation/AVFoundation.h&gt;

@interface AVPlayerView : UIView {

}

@end


//
//   AVPlayerView.m
//

#import "AVPlayerView.h"

@implementation AVPlayerView

+ (Class)layerClass
{
    return [AVPlayerLayer class];
}

@end
</pre>

<p>
AVPlayerViewを書き換えたら、今度はAVPlayerTestAppDelegateのapplication:didFinishLaunchingWithOptions:メソッドにもろもろセットアップする処理を記述します。以下のようなコードをAppDelegateに書き足してください。
</p>


<pre class="prettyprint">

//
//   AVPlayerTestAppDelegate.m
//

#import "AVPlayerView.h"

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
    
    [UIApplication sharedApplication].statusBarHidden = YES;
    
    CGRect viewFrame = CGRectMake(0, 0, window.frame.size.height, window.frame.size.width);
    AVPlayerView *view = [[AVPlayerView alloc] initWithFrame:viewFrame];
    view.center = CGPointMake(window.frame.size.width / 2.0, window.frame.size.height / 2.0);
    view.transform = CGAffineTransformMakeRotation(M_PI_2);
    [window addSubview:view];
    [view release];
    
    // ↓m4vのところを再生したいムービーの拡張子に変更してください
    NSArray *paths = [[NSBundle mainBundle] pathsForResourcesOfType:@"m4v" inDirectory:nil];
    NSURL *url = [NSURL fileURLWithPath:[paths objectAtIndex:0]];
    AVPlayer *player = [AVPlayer playerWithURL:url];
    
    AVPlayerLayer *playerLayer = (AVPlayerLayer *)view.layer;
    playerLayer.player = player;
    
    [player play];
	
    [window makeKeyAndVisible];
    
    return YES;
}
</pre>


<p>
コードはこんなところでしょうか。あとはバンドルになにかひとつムービーを入れてアプリを起動させればムービーが再生されると思います。上のコードではムービーの拡張子をm4vとしているので、違う拡張子のムービーであれば変更してください。
</p>

<p>
あと、AVPlayerを使ってみて気になったのが、ムービーの元のサイズとかの情報が、AVPlayerを生成したときには取得できなさそうだということです。どうもAVPlayerの中での初期化処理がバックグラウンドで行われているような感じで、それが終わってAVPlayerのstatusがReadyToPlayになってはじめて情報が取得できるという感じです。それなのに、その初期化終わった通知とかが無さそうなのが、いまいちわからないところです。
</p>]]>
        
    </content>
</entry>

<entry>
    <title>iOS4.0のオーディオ</title>
    <link rel="alternate" type="text/html" href="http://objective-audio.jp/2010/06/ios40.html" />
    <id>tag:objective-audio.jp,2010://13.175</id>

    <published>2010-06-25T15:00:00Z</published>
    <updated>2010-06-25T15:50:06Z</updated>

    <summary> iOS4.0がリリースされましたので、個人的に気になった変更点などをまとめてお...</summary>
    <author>
        <name>Yasoshima</name>
        
    </author>
    
        <category term="全般 - iPhone" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="ios40iphonesdk" label="iOS4.0 iPhone SDK" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://objective-audio.jp/">
        <![CDATA[<p>
iOS4.0がリリースされましたので、個人的に気になった変更点などをまとめておきたいと思います。大々的に告知されていたような目玉機能の羅列ではなく、主にオーディオ周りで気になったところです。
</p>

<h3>
バックグラウンドオーディオ
</h3>

<p>
これはiOS4.0のオーディオ系では一番の改良点と思われます。自分のアプリがバックグラウンドに入っても音を流し続けられることができます。対応しているのはたしかiPhone 3GSとiPod touch第３世代とiPhone 4あたりですね。マルチタスク非対応のデバイスでは残念ながら使うことはできません。
</p>

<p>
とりあえずバックグラウンドで流せればいいのであれば設定は簡単です。info.plistに「Required background modes」という項目を作って、そこで選べるモードの中から「App plays audio」を選択するだけです。これでバックグラウンドに入ってもAudioUnitなどが止まらずに動き続けてくれます。
</p>

<p>
<img alt="appplaysaudio.jpg" src="http://objective-audio.jp/2010/06/24/appplaysaudio.jpg" width="378" height="91" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" />
</p>

<p>
しかし、自分のアプリが音を流しっぱなしにできるということは、iPodアプリだけでなく、他のいろいろなアプリも同じようにしてくるということです。iOS4デバイスの中でオーディオの主導権を握る仁義なき戦いが繰り広げられることになります。
</p>

<p>
そこでやっぱり重要なのがカテゴリの設定です。自分のアプリから音を出すときに、他のアプリの音をどうするか。逆に自分のアプリをバックグラウンドで流すときにどうするのか。OS3.xの時と比べて結構シビアになってくると思います。ガッツリ音を鳴らすようなアプリでもないのに他のアプリの音を消してしまったりしたら、ユーザーさんからクレームが来るかもしれません。
</p>

<p>
あとバッテリーのことを考えると、アプリがバックグラウンドに入るときに継続して音が鳴らないタイミングであれば、AudioUnitを止めておくことも必要と思われます。まぁ、これはバックグラウンドじゃなくてもそうかもしれませんが、再生するときのレスポンスとかもありますし。
</p>

<p>
また、オーディオに限りませんが、マルチタスキング対応にしていると基本的にずっとアプリが起動しているような状態になっていますので、ユーザデフォルトが設定アプリから変更されたり、File Sharingでドキュメントフォルダの内容が変更されたりということもあります。自分のアプリがアクティブになったらデータを更新するということも忘れないようにしないといけないでしょう。
</p>

<h3>
オーディオカテゴリが厳格になった？
</h3>

<p>
もしかするとiOS4.0からではないのかもしれませんが、オーディオ関連の挙動がオーディオカテゴリの設定にかなり厳格になっているようです。
</p>

<p>
たしかOS3.0とかの頃に試していたときにはカテゴリはあくまでルーティングが変わるというような影響でしかなかったのですが、iOS4.0を試していたところ、カテゴリをRecordにするとAudioUnitでアウトプットを生成できなかったり、MediaPlaybackにするとインプットを生成できなかったりします。イレギュラーな事にはカテゴリのオーバーライドで対応しろということでしょうかね。
</p>

<p>
あ、もし全然前からだったらすみません。前のバージョンを調べるのって自分的には意味がなくてめんどくさいので調べてません。
</p>

<h3>
Accelerate Framework
</h3>

<p>
iOSにもいよいよ念願のAccelerate Frameworkが実装されました。
</p>

<p>
といっても、MacのAccelerate Frameworkそのままではなく、vecLibのみ。その中でも限定されていて、vDSPとcblasとclapackだけが使えるようです。FFTは使えますし、deq22もあるのでEQも楽に作れそうです。でも、vForceあたり（サイン・コサインとか）は全滅です。ちょっと残念。
</p>

<p>
とりあえずこんなところです。まだ全然チェックしてませんが、iPhone Dev CenterのサンプルコードもどっさりiOS4.0に対応しているみたいです。オーディオ以外や、ちゃんとまとめておきたいことでまた何かエントリを書くかもしれません。
</p>]]>
        
    </content>
</entry>

<entry>
    <title>METRONOME STAR 1.0.1 公開しました</title>
    <link rel="alternate" type="text/html" href="http://objective-audio.jp/2010/06/metronome-star-101.html" />
    <id>tag:objective-audio.jp,2010://13.176</id>

    <published>2010-06-22T23:35:53Z</published>
    <updated>2010-06-23T10:56:18Z</updated>

    <summary> METRONOME STAR v1.0.1がリリースされました。ダウンロードは...</summary>
    <author>
        <name>Yasoshima</name>
        
    </author>
    
        <category term="METRONOME STAR" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://objective-audio.jp/">
        <![CDATA[<p>
METRONOME STAR v1.0.1がリリースされました。ダウンロードは<a href="itms://itunes.apple.com/jp/app/metronome-star/id365846943?mt=8">こちら</a>。
</p>

<p>
変更点はiOS 4.0対応ということで、マルチタスキング対応デバイスであれば、アプリを終了しても音が鳴り続けるようになりました。iPhone 3Gなどの非対応デバイスでは、おそらく何も変わってません。むしろよけいな処理が増えている分、パフォーマンスが落ちているかも...。あと、高解像度にも対応して、iPhone 4だとグラフィックがたぶんきれいになっているはずです。iPhone4実機の本予約がまだ確定していないので、その美しさを自分で体験するのがいつになるのがわからないのがもどかしいですね。iPhoneシミュレータだとすごく動きがカクカクしててパフォーマンスも不安ですし。
</p>

<p>
まあMETRONOME STARは正直ダウンロード数が少ないので万が一何かあっても被害が少ないかな、と。あと、グラフィックもサウンドもそれなりに使ってるアプリなので、新しい環境で試すにはちょうどいいアプリだというのもありました。何より、新OSと同時にリリースしてみたかったんですよね。（iOS4にはちょっと遅れましたが、iPhone 4には間に合った）
</p>

<p>
iOS4.0に対応したといっても、新機能を使ってみたという感じでバックグラウンドの作法は全く考えておらず、バックグラウンドに入る前に不必要なメモリを解放するとかやってないので、もしかするとシステムに迷惑なアプリになっているかもしれません。再生していないときのAudioUnitを止めたりとかはしてるくらいですかね。このへんは今後の課題かなぁと思っています。
</p>

<p>
あと、ほんとうにメトロノームをバックグラウンドでならす必要があるのかということも頭をよぎりましたが、逆にいろんなアプリがバックグラウンドオーディオ対応して、iPhoneユーザさんたちがどう感じるかというのを様子見するのがよいのかなと思いました。
</p>

<p>
ちなみに、BigStopWatchのiPhone 4高解像度対応バージョンというのも出来上がってはいますが、保留しています。こちらはいままでのダウンロード数が多いので、慎重に実機で試してからリリースしようと思っています。
</p>]]>
        
    </content>
</entry>

<entry>
    <title>離散フーリエ変換 その３</title>
    <link rel="alternate" type="text/html" href="http://objective-audio.jp/2010/05/post-20.html" />
    <id>tag:objective-audio.jp,2010://13.170</id>

    <published>2010-05-31T14:11:35Z</published>
    <updated>2010-05-31T14:17:46Z</updated>

    <summary> 前回記事を書いてからだいぶ時間が経ってしまって5月にエントリがひとつもないのも...</summary>
    <author>
        <name>Yasoshima</name>
        
    </author>
    
        <category term="オーディオ全般" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="プログラミング" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://objective-audio.jp/">
        <![CDATA[<p>
前回記事を書いてからだいぶ時間が経ってしまって5月にエントリがひとつもないのもさみしいので、書きかけだった記事をアップしておきます。iPadから書き込んでみたいというのもあったので...。
</p>

<p>
最近はiPhoneOS4.0にどっぷり使っていまして、あまり書けることがないんですよねぇ。ってことで、フーリエ変換の流れで今回は位相の話です。逆離散フーリエ変換とか行きたいところですが、またの機会にします。
</p>

<h3>
位相とは
</h3>

<p>
これまでの説明で何度か位相という言葉を使ってきたと思いますが、ちゃんとその定義を調べずに使っていたので、改めてwikipediaなどを見てみますと...
</p>

<p>
<a href="http://ja.wikipedia.org/wiki/位相">位相 (Wikipedia)</a>
</p>

<p>
「ひとつの周期中の位置を示す無次元量」なんて書いてあって、無次元量って何だ？なんて思ってしまうわけですが、まぁ、DFTで使っているサイン波でいえば、サイン波の中のどの位置かということと思われます。さらに、周期のスタート位置の位相は「初期位相」というそうで、初期位相の事を単純に位相といわれたりすることもある、だそうです。「位相が○度ずれている」と言ったときには、２つの同じ周波数のサイン波を同じ時間軸にならべた状態で「初期位相が○度ずれている」という理解になるかと思います。
</p>

<p>
サイン関数を使ってサイン波を作る場合などは位相をラジアンで渡して値を取得しますが、0〜2π（角度で表すなら0°〜360°）が一周期で、2π以上や0以下の値を渡しても、返ってくるのは同じ値の繰り返しとなります。たとえば、0から始まるサイン波と、2πや4πや-2πから始まるサイン波というのは、全く同じ形となりますので、同じ位相といえます（たぶん）。DFTの周波数成分は、繰り返されているサイン波の１周期ですので、その位相はどこか2π分の範囲の中の位置だけを考えれば良い事になります。
</p>

<p>
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="DFT03_01.jpg" src="http://objective-audio.jp/2010/04/12/DFT03_01.jpg" width="450" height="200" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></span>
</p>

<h3>
直線位相特性
</h3>

<p>
よくデジタルフィルタの本をみていると、FIRフィルタだと位相のずれがない直線位相特性のフィルタが実現できるなんて書いてあったりします。下の図が直線位相特性のグラフなのですが...
</p>

<p>
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="DFT03_03.jpg" src="http://objective-audio.jp/2010/04/12/DFT03_03.jpg" width="312" height="288" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></span>
</p>

<p>
これを最初見た時は位相がずれないといってるのに、位相が周波数によってずれるというのが僕はよく理解できなかったのですが、いくつかのサイン波を並べて同じ時間遅らせて、遅らせたタイミングでも同じ波形になるようにしてみるとわかります。
</p>

<p>
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="DFT03_02.jpg" src="http://objective-audio.jp/2010/04/12/DFT03_02.jpg" width="450" height="704" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></span>
</p>

<p>
上の図では1Hzのサイン波を3/4周期遅らせて、同じ時間2Hzと3Hz遅らせて並べてみています。元のサイン波が緑色で、遅らせたサイン波が青色です。各周波数を同じ時間遅らせているので、遅らせたあとの波形はどの周波数も元の波形と同じ形に保たれます。
</p>

<p>
1Hzの3/4周期の遅れに対して、2Hzは3/2周期、3Hzは9/4周期、と位相がずれています。このような感じで周波数に比例して位相がずれるというのが直線位相特性です。直線位相特性を実現したフィルタを使用すれば、周波数によって位相のずれがないので、クオリティの高い処理ができるということのようです。
</p>]]>
        
    </content>
</entry>

<entry>
    <title>METRONOME STAR v1.0 公開しました</title>
    <link rel="alternate" type="text/html" href="http://objective-audio.jp/2010/04/metronome-star.html" />
    <id>tag:objective-audio.jp,2010://13.173</id>

    <published>2010-04-08T12:21:32Z</published>
    <updated>2010-04-08T12:39:02Z</updated>

    <summary> 先月末に予告していたメトロノームアプリがリリースされました。 ダウンロードはこ...</summary>
    <author>
        <name>Yasoshima</name>
        
    </author>
    
        <category term="METRONOME STAR" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://objective-audio.jp/">
        <![CDATA[<p>
先月末に予告していたメトロノームアプリがリリースされました。
</p>

<p>
ダウンロードは<a href="itms://itunes.apple.com/jp/app/metronome-star/id365846943?mt=8">こちら</a>から。（iTunesへ飛びます）
</p>

<p>
まあ、機能的にはたいした事はできませんが、星が揺れているさまをみてなごんでいただければうれしいです。無料ですのでお気軽にどうぞ。
</p>

<p>
プログラミング的な所をいいますと、サンプル単位のシーケンス+ホストタイムにスピードを合わせているので、iPhoneアプリにおいては結構リズムが正確なんじゃないかと思います。逆に言えば、オーディオデバイスのクロックからはタイミングがずれているので、同じテンポのiPodのミュージックと一緒に鳴らしてもぴったり同じタイミングには鳴りません。
</p>]]>
        
    </content>
</entry>

<entry>
    <title>近日公開予定メトロノームアプリ</title>
    <link rel="alternate" type="text/html" href="http://objective-audio.jp/2010/03/post-21.html" />
    <id>tag:objective-audio.jp,2010://13.171</id>

    <published>2010-03-27T12:02:29Z</published>
    <updated>2010-04-08T12:40:51Z</updated>

    <summary> もうほとんど修正しないだろうなというところまで出来上がってきたので、来月あたり...</summary>
    <author>
        <name>Yasoshima</name>
        
    </author>
    
        <category term="METRONOME STAR" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://objective-audio.jp/">
        <![CDATA[<p>
もうほとんど修正しないだろうなというところまで出来上がってきたので、来月あたりに出そうかと思っているアプリの動画を公開しておきます。星が揺れてリズムを刻むメトロノームアプリです。
</p>

<p>
<object width="600" height="385"><param name="movie" value="http://www.youtube.com/v/jkJu4DppM50&hl=ja_JP&fs=1&"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/jkJu4DppM50&hl=ja_JP&fs=1&" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="600" height="385"></embed></object>
</p>]]>
        
    </content>
</entry>

<entry>
    <title>離散フーリエ変換 その２</title>
    <link rel="alternate" type="text/html" href="http://objective-audio.jp/2010/02/post-19.html" />
    <id>tag:objective-audio.jp,2010://13.169</id>

    <published>2010-02-07T03:00:00Z</published>
    <updated>2010-02-07T08:09:26Z</updated>

    <summary> 離散フーリエ変換の第２回目という事で、実際にどういうことをやっているのかをコー...</summary>
    <author>
        <name>Yasoshima</name>
        
    </author>
    
        <category term="オーディオ全般" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="プログラミング" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://objective-audio.jp/">
        <![CDATA[<p>
離散フーリエ変換の第２回目という事で、実際にどういうことをやっているのかをコードで見ていきたいと思います。前回のDFTのコードの変換を行っているところが以下の部分です。
</p>

<pre class="prettyprint">
// iは抜き出す周波数
for (int i = 0; i < n; i++) {
    
    tmpReal[i] = 0.0;
    tmpImag[i] = 0.0;
    
    // 1サンプルの位相の差分
    double d = 2.0 * M_PI * i / n;
    
    for (int j = 0; j < n; j++) {
        
        double phase = d * j;
        
        // コサインをかけた結果を加算する
        tmpReal[i] += real[j] * cos(phase);
        // マイナスサインをかけた結果を加算する
        tmpImag[i] -= real[j] * sin(phase);
    }
}
</pre>

<p>
変換するオーディオデータに対して、抜き出す周波数のcosをかけ算して全て足し合わせた値が実部、-sinをかけて足し合わせた値が虚部になります。具体的に説明はしませんが、このようにする事で、それぞれの周波数のcosやsinがオーディオデータにどれくらい含まれているかを得る事ができます。（ちゃんと理解したい方は、なにかしらフーリエ変換の本などを参考にしてください）
</p>

<p>
抜き出す周波数というのは、0Hzから始まって1Hz、2Hz...と続いて、変換するサンプル数-1Hzまでです。つまり、変換するサンプル数と同じ数の周波数成分に分けられます。DFTは、変換するオーディオデータが延々とループしていると仮定して周波数成分を取り出しますので、1Hz以上の周波数はぴったり整数の周波数になります。
</p>

<p>
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><a href="http://objective-audio.jp/assets_c/2010/02/DFT02ri-85.html" onclick="window.open('http://objective-audio.jp/assets_c/2010/02/DFT02ri-85.html','popup','width=929,height=1012,scrollbars=yes,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0'); return false"><img src="http://objective-audio.jp/assets_c/2010/02/DFT02ri-thumb-450x490-85.jpg" width="450" height="490" alt="DFT02ri.jpg" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></a></span>
</p>

<p>
上の図を見ると、cosもsinも0Hzの時は横一直線になっています。0HzはDC成分といわれたりしてちょっと特別です。cos0Hzでは全体に1がかけられますので、波形全体がプラスとマイナスのどちらにバランスが偏っているかという要素になります。sinは0をかけているので、元がどんな波形だろうと結果は0になります。
</p>

<p>
ちなみに、下の図の1.23Hzみたいな中途半端な周波数のサイン波などというのは途中で急激に途切れた状態で繰り返されることになりますので、DFTをすると1Hzを中心に高い周波数まで全体的に成分が含まれることがわかります。
</p>

<p>
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="DFT02s123.jpg" src="http://objective-audio.jp/2010/02/06/DFT02s123.jpg" width="450" height="500" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></span>
</p>

<p>
また、ちょっと説明が後回しになりましたが、なぜDFTでcosとsinを抜き出すかといえば、同じ周波数のcosとsinを足し合わせることで、360度どの位相のサイン波でも表現できるからです。
</p>

<p>
本当にcosとsinの足し算でサイン波が作れるのか、検証してみたのが以下のコードです。stRadを0〜2πの間で変えてみて実行してみてください。sinはDFTと同じようにマイナスにしています。もちろん計算の誤差はあると思いますので、近ければOKという基準で判断すれば、どの位相のサイン波でも、スタート位置がゼロのcosとsinの足し合わせで作り出せる事がわかると思います。（てきとうに書いたので、なんかおかしかったらすみません。0〜2πの範囲外では正確な結果が出るようになってません）いちおうDFTと同じように、sinはマイナスsinでやってます。
</p>

<pre class="prettyprint">
#include &lt;stdio.h&gt;
#include &lt;math.h&gt;

int main (int argc, const char * argv[]) {
    
    double stRad = 0.0; //sinの開始位置。0〜2πの間で！
    int n = 16;
    
    double xcos = 0;
    double xsin = 0;
    double co = fabs(sin(stRad));
    double si = sqrt(1.0 - co * co);
    
    if (stRad < M_PI_2) {
        //第一象限
        xcos = co;
        xsin = -si;
    } else if (stRad < M_PI) {
        //第二象限
        xcos = co;
        xsin = si;
    } else if (stRad < M_PI_2 * 3) {
        //第三象限
        xcos = -co;
        xsin = si;
    } else {
        //第四象限
        xcos = -co;
        xsin = -si;
    }
    
    for (int i = 0; i < n; i++) {
        
        double phase = (double)i / n * 2.0 * M_PI;
        double sinVal = sin(stRad + phase);
        double mixVal = cos(phase) * xcos - sin(phase) * xsin;
        
        printf("sin %03d %f / sin+cos %f\n", i, sinVal, mixVal);
        if (fabs(sinVal - mixVal) > 0.000001) {
            printf("error\n");
            return 0;
        }
    }
    
    printf("success\n");
    
    return 0;
}
</pre>]]>
        
    </content>
</entry>

<entry>
    <title>離散フーリエ変換 その１</title>
    <link rel="alternate" type="text/html" href="http://objective-audio.jp/2010/01/post-18.html" />
    <id>tag:objective-audio.jp,2010://13.168</id>

    <published>2010-01-17T03:00:00Z</published>
    <updated>2010-01-17T06:47:36Z</updated>

    <summary> MacとかiPhoneとかあまり関係なく基礎を固めようと思っていろいろ勉強モー...</summary>
    <author>
        <name>Yasoshima</name>
        
    </author>
    
        <category term="オーディオ全般" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="プログラミング" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://objective-audio.jp/">
        <![CDATA[<p>
MacとかiPhoneとかあまり関係なく基礎を固めようと思っていろいろ勉強モードに入っていまして、すこしずつまとめていこうと思います。まずはフーリエ変換についてです。
</p>

<p>
あくまでプログラムで使う事を前提に書いていきますので、いろいろおかしかったりするかもしれませんがご了承ください。もし、明らかに変だったら突っ込んでいただけるとうれしいです。基本的に小難しそうな数式とかはできるだけ出さずにコード重視、ビジュアル重視で書いていくつもりです。
</p>

<p>
プログラミングでフーリエ変換というと、高速フーリエ変換（FFT）を使うという事になると思うのですが、FFTについては特に詳しく書きません。プログラム化されたコードを見た場合、FFTだと高速化されたアルゴリズムだけで本質的な部分がわからないので、高速化していないノーマルな離散フーリエ変換（DFT）のプログラムを見て、フーリエ変換の仕組みを調べていきます。
</p>

<p>
オーディオ信号に対してDFTを使うと何ができるかというと、時間単位で並んでいる時間領域のオーディオデータの一部分を切り出して、含まれている周波数ごとの成分に分けた周波数領域のデータに変換する事ができます。逆に、その周波数領域のデータを時間領域のオーディオデータに戻す事もでき、それが逆離散フーリエ変換（IDFT）になります。
</p>

<p>
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="DFT01.jpg" src="http://objective-audio.jp/2010/01/17/DFT01.jpg" width="450" height="500" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></span>
</p>

<p>
離散フーリエ変換というのは、デジタルでサンプリングされたオーディオ信号のような飛び飛びのデータに対して行うフーリエ変換です。いきなり「離散」と出てくると何の事かわからないかもしれませんが、「離散」＝「デジタル」と考えればよいと思います。アナログの「連続」に対して、デジタルの「離散」です。そのDFTを高速化したのがFFTという関係になります。
</p>

<p>
まずは何より使ってみない事にはしょうがないということで、サンプルソースです。
</p>

<pre class="prettyprint">
#include &lt;stdio.h&gt;
#include &lt;math.h&gt;

void DFT(int n, double *real, double *imag)
{
    double tmpReal[n], tmpImag[n];
    
    for (int i = 0; i < n; i++) {
        
        tmpReal[i] = 0.0;
        tmpImag[i] = 0.0;
        
        double d = 2.0 * M_PI * i / n;
        
        for (int j = 0; j < n; j++) {
            
            double phase = d * j;
            
            tmpReal[i] += real[j] * cos(phase);
            tmpImag[i] -= real[j] * sin(phase);
        }
    }
    
    for (int i = 0; i < n; i++) {
        real[i] = tmpReal[i];
        imag[i] = tmpImag[i];
    }
}

int main (int argc, const char * argv[]) {
    
    int n = 16;
    double real[n], imag[n];
    
    double d = 2.0 * M_PI / n;
    
    for (int i = 0; i < n; i++) {
        real[i] = sin(1.0 * i * d); //1Hzのサイン波
        real[i] += sin(3.0 * i * d + M_PI_4); //3Hzのサイン波（1/4πずらし）
        real[i] += sin(5.0 * i * d + M_PI_2); //5Hzのサイン波（1/2πずらし）
        imag[i] = 0.0;
    }
    
    //フーリエ変換
    DFT(n, real, imag);
    
    for (int i = 0; i < n; i++) {
        printf("%dHz %f\n", i, sqrt(real[i] * real[i] + imag[i] * imag[i]));
    }
    
    return 0;
}
</pre>

<p>
Xcodeで実行する場合はCのCommand Line Toolでプロジェクトを作って、main.cを書き換えてください。
</p>

<p>
今回のコードでは、1Hzと3Hzと5Hzのサイン波をいろいろ位相を変えてミックスして元のデータを作ってから変換しています。結果は、
</p>

<pre class="prettyprint">
0Hz 0.000000
1Hz 8.000000
2Hz 0.000000
3Hz 8.000000
4Hz 0.000000
5Hz 8.000000
6Hz 0.000000
7Hz 0.000000
8Hz 0.000000
9Hz 0.000000
10Hz 0.000000
11Hz 8.000000
12Hz 0.000000
13Hz 8.000000
14Hz 0.000000
15Hz 8.000000
</pre>

<p>
と表示されて、1Hzと3Hzと5Hzが含まれているということがわかります。上の周波数の11Hzと13Hzと15Hzにもデータが現れていますが、これは、ナイキスト周波数以上の周波数の音は、ナイキスト周波数を対称に折り返した低い周波数へ現れるということで出てきているものですので、単純に周波数特性を調べるだけなら無視してください（けっして無意味なデータというわけではありませんが...）。
</p>

<p>
コードの説明に入りまして、DFT関数がまさに離散フーリエ変換する関数になります。realに変換したいオーディオデータの配列、imagに同じサイズの空の配列、nに配列のサイズをそれぞれ渡すと、realとimagにフーリエ変換された値が返ってきます。
</p>

<p>
DFTをすると１つの周波数ごとにデータが実部と虚部という２つに分かれて返ってきます。今回のコードではrealが実部、imagが虚部のデータです。実部と虚部は２つでひとつの意味を持ったデータですので、どちらかだけを使うことはあまり無いと思います。main関数の中でやっていますが、周波数特性の振幅を得るという場合はrealとimagをそれぞれ２乗した値の平方根を求めます。
</p>

<p>
DFTして得られる周波数は、DFTに渡すサンプル数の長さを1Hzとして、0からサンプル数-1までの整数倍の周波数です。16サンプルの場合は、0・1・2・3・4・5・6・7・8・9・10・11・12・13・14・15Hzの16個です。ただこれが1
秒を1Hzと考えるときには、たとえば44.1kHzのオーディオの中の64サンプルを変換したという状況だと、0・689・1378...というふうにもっと広い間隔の周波数の並びになります。これはどこを基準にするかで違ってくるというだけの話ですので、このDFTの説明ページでは変換するサンプル数を1Hzとして表現します。
</p>

<p>
とりあえず、DFTができましたというところで１回目は終わりです。次へつづきます。
</p>]]>
        
    </content>
</entry>

<entry>
    <title>Touch the Wave 2 公開されました。</title>
    <link rel="alternate" type="text/html" href="http://objective-audio.jp/2009/12/touch-the-wave-2.html" />
    <id>tag:objective-audio.jp,2009://13.167</id>

    <published>2009-12-05T03:51:44Z</published>
    <updated>2009-12-05T14:11:00Z</updated>

    <summary> Touch the Waveの新バージョン「Touch the Wave 2」...</summary>
    <author>
        <name>Yasoshima</name>
        
    </author>
    
        <category term="Touch the Wave" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://objective-audio.jp/">
        <![CDATA[<p>
Touch the Waveの新バージョン「Touch the Wave 2」が公開されました。
</p>

<p>
諸事情のためTouch the Waveのアップデートではなく、新規アプリです。といっても有料になったわけではなく無料のままです。あくまで諸事情のためです。本当は前バージョンからのプレイリストの引き継ぎの機能を作ってあったのですが、新規アプリのため意味がなくなってしまいました。曲は再びダウンロードし直してください。
</p>

<p>
いちおうアプリ名の「2」はバージョン2ではなくて「2曲同時に再生できるよ」の「2」というつもりです。なので、「2」のバージョン1.0というよくわからないバージョン付けになっています。
</p>

<p>
変更点はいろいろありすぎるので全てリストアップするのはやめますが、一番大きな所は、
</p>

<p>
・２曲同時再生<br />
・MP3やAACをダウンロード可能に<br />
・ピッチの可変範囲が-100％〜+100％に設定可能<br />
</p>

<p>
といったところでしょうか。
</p>

<p>
あと、パフォーマンス調整してiPod touchの第２世代以降だとフリックとかで音が途切れる事がなくなったとか、再生中の２曲にテンポが指定されていればスピードを合わせるのがボタンひとつだけで出来るとかってのもあります。まぁ、いろいろ使ってみてください。
</p>

<p>
appsページの方は作ってありますが、まだ細かい使い方までは書いてありません。余裕ができたらそのうち書きます。
</p>]]>
        
    </content>
</entry>

<entry>
    <title>iPhone Core Audio プログラミング</title>
    <link rel="alternate" type="text/html" href="http://objective-audio.jp/2009/11/iphone-core-audio.html" />
    <id>tag:objective-audio.jp,2009://13.165</id>

    <published>2009-11-17T01:00:00Z</published>
    <updated>2009-11-17T01:56:50Z</updated>

    <summary> ちょっと記事にするには乗り遅れた感がありますが、「iPhone Core Au...</summary>
    <author>
        <name>Yasoshima</name>
        
    </author>
    
        <category term="Core Audio - iPhone" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="プログラミング" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://objective-audio.jp/">
        <![CDATA[<p>
ちょっと記事にするには乗り遅れた感がありますが、「iPhone Core Audio プログラミング」という、iPhoneのオーディオプログラミングに特化した本が発売されています。今はもうだいたいどこの本屋さんいっても置いてありますね。詳しい内容については筆者の永野さんのサイトのページ<a href="http://nagano.monalisa-au.org/?p=979">「iPhone Core Audioプログラミング」(書籍) 発売</a>へ。
</p>

<p>
iPhoneのオーディオのAPIについては、これ一冊に日本語でほぼ全て書いてあります。<big><strong>日本語です！</strong></big>iPhone Dev Centerにも「Core Audio 概要」とか「Audio Session Programming Guide」とかの日本語訳はありますが、Apple純正という安心感はあるものの翻訳なので、ネイティブな日本人が書いた文章というのはやっぱり分かりやすいです。もう僕がiPhoneの開発ネタを書く事もないかなぁなんて思ったり。
</p>

<p>
基本的にはAPIの解説になるので、本の最後の章にアプリのサンプルはいくつかありますが、実際に自分好みのオーディオアプリを作り始めてみると壁にぶち当たると思います（主にパフォーマンスで）。が、まあそれはトライアンドエラーで頑張りましょうってことで。作るアプリの内容とか機種とかによっても引っかかる部分が違いますし。なぜか新しい機種の方が負荷に弱かったりするときもあるんですよねぇ。
</p>

<p>
オーディオのプログラミングっていうと、オーディオの再生とか録音とかシンセサイズとかってところに興味がいってしまいがちだと思いますが、iPhoneに関していえば最も重要なのはAudio Sessionです！ちょっとでもiPhoneでオーディオ鳴らすなら、Chapter4と7は熟読してください！知っていてあえて使わないのと、何となくめんどくさいから読まないで知らずに使えないのとでは大きな差があります。まぁ、App Storeに出さずに自分のデバイスだけで動かせればいいっていうなら話は別ですけどね。他のChapterは気になるところだけピックアップして読めば良いと思います。
</p>

<p>
値段は4,200円と、他の入門書と比べてやや高いですが、それだけの価値はあると思います。僕はオーディオメインでプログラミングを勉強してますが、やっぱりその中でも興味があるところに偏って調べていたりするので、読んでみるといろいろ知らないところがたくさんあります。今後iPhoneのオーディオで、忘れていたり、何か新たに調べたくなったときに、役立ってくれる事は確実です。
</p>]]>
        
    </content>
</entry>

<entry>
    <title>Grand Central Dispatch その７ おまけ</title>
    <link rel="alternate" type="text/html" href="http://objective-audio.jp/2009/11/grand-central-dispatch.html" />
    <id>tag:objective-audio.jp,2009://13.164</id>

    <published>2009-11-01T14:00:00Z</published>
    <updated>2009-11-01T14:30:22Z</updated>

    <summary> さらに今更ながら、ASCII.jpさんの「マルチコア時代の新機軸！ Snow ...</summary>
    <author>
        <name>Yasoshima</name>
        
    </author>
    
        <category term="プログラミング" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="全般 - Mac" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://objective-audio.jp/">
        <![CDATA[<p>
さらに今更ながら、ASCII.jpさんの「<a href="http://ascii.jp/elem/000/000/455/455786/" target="_blank">マルチコア時代の新機軸！ Snow LeopardのGCD</a>」に、わりと一般向けの説明から始まって、コードを使用したプログラマ向けの説明までしているページがありました。とりあえずここらへんで基本知識を得てから、いろいろ試した方が良かったのかも。まあ、今から見ても調べた事の裏付けがとれていいんですけど。あながち間違ってなかったし。
</p>

<p>
その記事を見ていて改めて発見したのは、dispatch_get_main_queueで、メインスレッドで実行されるキューが取得できるという事。なるほど、これがあればperformSelectorOnMainThreadを呼ばなくてもディスパッチで呼び出しが完結できます。前回のタイマーとかはメインキュー使う方が良い気がします。
</p>

<p>
でも、こういった解説記事の中でディスパッチソースにまで触れられているものってあんまり見かけないですね。ディスパッチさえあればアプリの基本的な仕組みが作れてしまう！みたいな。ってことで、ソース系でもうひとつ調べてみました。
</p>

<p>
とりあえずやってみたかったのは、ディスパッチでガンガンバッチ処理的な事をさせておいている途中で、キャンセルしたいって言う事です。すくなくとも僕の認識では、dispatch_asyncでブロックをキューに渡してしまうとキャンセルできない様なので、これをやりたいとおもって見つけたのがディスパッチソースの中のDISPATCH_SOURCE_TYPE_DATA_ADDというやつ。
</p>

<p>
ちょっとこれを使って書いてみたソースがこちら。今回は自分でキャンセルしてみたいので、Cocoa Applicationでプロジェクトを作ってAppDelegateを以下のように変更し、Interface Builderでウィンドウにボタンをひとつ作ってAppDelegateのcancelにつなげてください。
</p>

<pre class="prettyprint">
//
// AppDelegate.h
//

#import &lt;Cocoa/Cocoa.h&gt;

@interface AppDelegate : NSObject <NSApplicationDelegate> {
    NSWindow *window;
    dispatch_source_t _source;
}

@property (assign) IBOutlet NSWindow *window;

- (IBAction)cancel:(id)sender;

@end
</pre>

<pre class="prettyprint">
//
// AppDelegate.m
//

#import "AppDelegate.h"

@implementation AppDelegate

@synthesize window;

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
	
    dispatch_queue_t queue = dispatch_queue_create("test", NULL);
    _source = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, queue);
    
    __block int count = 0;
    
    dispatch_source_set_event_handler(_source, ^{
        count++;
        printf("call %d\n", count);
        usleep(100000);
        dispatch_source_merge_data(_source, 1);
    });
    
    dispatch_source_set_cancel_handler(_source, ^{
        printf("end\n");
        dispatch_release(_source);
        _source = NULL;
        dispatch_release(queue);
        exit(0);
    });
    
    dispatch_source_merge_data(_source, 1);
    dispatch_resume(_source);
}

- (IBAction)cancel:(id)sender
{
    dispatch_source_cancel(_source);
}

@end
</pre>

<p>
実行すると、event handlerのブロックが繰り返し呼ばれてログにカウントが表示されます。キャンセルボタンを押すと終了します。
</p>

<p>
DATA_ADDの使い方としては、dispatch_source_merge_data()の２つ目の引数で1以上の値を与えて呼ぶと、dispatch_source_set_event_handlerで登録したブロックが呼び出されるという感じになります。このサンプルでは、event_handlerのブロックの中から直接merge_dataを呼び出して処理を繰り返すようにしています。
</p>

<p>
merge_dataに0を渡してもブロックが呼ばれない事からも分かるように、たぶん本来はこれで処理自体をするものではなく、<a href="http://www.mikeash.com/?page=pyblog/friday-qa-2009-09-11-intro-to-grand-central-dispatch-part-iii-dispatch-sources.html" target="_blank">こちら</a>のページにのっているように、dispatch_applyとかでやっている処理の進捗の量をmerge_dataの引数で受け取ってインジケータに表示するような用途に使うものだと思われます。
</p>

<p>
まあ、こんな使い方もアリじゃないかなってことで。
</p>]]>
        
    </content>
</entry>

<entry>
    <title>Grand Central Dispatch その６ timer</title>
    <link rel="alternate" type="text/html" href="http://objective-audio.jp/2009/10/grand-central-dispatch-timer.html" />
    <id>tag:objective-audio.jp,2009://13.163</id>

    <published>2009-10-13T14:00:00Z</published>
    <updated>2009-10-13T14:01:51Z</updated>

    <summary> いまさらながら、GCDのサンプルソースはMac Dev Centerにもいろい...</summary>
    <author>
        <name>Yasoshima</name>
        
    </author>
    
        <category term="プログラミング" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="全般 - Mac" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://objective-audio.jp/">
        <![CDATA[<p>
いまさらながら、GCDのサンプルソースはMac Dev Centerにもいろいろありますので参考に。中でも<a href="https://developer.apple.com/mac/library/samplecode/Dispatch_Samples/index.html">Dispatch_Samples</a>なんかはシンプルなサンプルがたくさん集まってますので、最初に見るには良いと思います。
</p>

<p>
今回からはディスパッチの中でもソースというものを見ていこうと思います。前回のエントリにキューとソースは別なんて一度書いてしまいましたが、間違いでソースでもキューは使います。
</p>

<p>
と書いてて、ディスパッチのソースと、ソースコードの区別がわけ分からなくなりそうなので、ディスパッチのソースは「ディスパッチソース」と呼ぶ事にします。勝手に色んな呼び方を作ってしまってすみません。
</p>

<p>
ディスパッチソースの種類にはいろいろありますが、基本的には、何かしら外部からイベントを受け取ったらキューにブロックを渡すというもののようです。以下のようなものがあります。
</p>

<pre class="prettyprint">
DISPATCH_SOURCE_TYPE_DATA_ADD:
DISPATCH_SOURCE_TYPE_DATA_OR:
DISPATCH_SOURCE_TYPE_MACH_SEND
DISPATCH_SOURCE_TYPE_MACH_RECV
DISPATCH_SOURCE_TYPE_PROC
DISPATCH_SOURCE_TYPE_READ
DISPATCH_SOURCE_TYPE_SIGNAL
DISPATCH_SOURCE_TYPE_TIMER
DISPATCH_SOURCE_TYPE_VNODE
DISPATCH_SOURCE_TYPE_WRITE
</pre>

<p>
まあ、ほとんどは自分じゃ使わないなぁと思って調べてなかったりするんで、簡単なそうなタイマーを見ていきます。まずはサンプルソースから。
</p>

<pre class="prettyprint">
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;dispatch/dispatch.h&gt;


int main (int argc, const char * argv[]) {

    dispatch_queue_t queue = dispatch_queue_create("timerQueue", 0);

    //タイマーのソースを作成
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);

    __block int i = 0;

    //イベントを受け取った時に実行されるブロックをソースに設定する
    dispatch_source_set_event_handler(timer, ^{
        printf("%d\n", i);
        i++;
        if (i == 10) dispatch_source_cancel(timer);
    });

    //ソースがキャンセルされてときに実行されるブロックをソースに設定する
    dispatch_source_set_cancel_handler(timer, ^{
        dispatch_release(timer);
        dispatch_release(queue);
        printf("end\n");
        exit(0);
    });

    dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC); //今から１秒後
    uint64_t interval = NSEC_PER_SEC / 5; //0.2秒

    //タイマーを設定する
    dispatch_source_set_timer(timer, start, interval, 0);

    printf("start\n");

    dispatch_resume(timer);

    dispatch_main();

    return 0;
}
</pre>

<p>
実行すると、ログに0から10まで数字が0.2秒おきに出力されて、アプリが終了します。
</p>

<p>
では、コードを上から見ていきます。まずは、タイマーのディスパッチソースを作成しています。ディスパッチソースの作成はdispatch_source_createです。
</p>

<pre class="prettyprint">
dispatch_source_t
dispatch_source_create(dispatch_source_type_t type,
	uintptr_t handle,
	unsigned long mask,
	dispatch_queue_t queue);
</pre>

<p>
ひとつめの引数にはディスパッチソースの種類を渡します。タイマーはDISPATCH_SOURCE_TYPE_TIMERです。２つめの引数のhandleは、ディスパッチソースが動作する元になるものを渡しますが、タイマーは必要ないので0で良いです。３つ目もタイマーでは必要ありませんので、これも0です。最後のqueueには、ディスパッチソースからブロックを渡すキューを設定します。
</p>

<p>
ちなみに、キューはグローバルでもシリアルでも使えますが、グローバルキューだと他の色んなブロックが入っていたら後回しになって影響を受けて実行されるのが遅れやすくなりそうなので、シリアルキューにして完全にセパレートされている方が良いのかなぁと思います。あくまで予測ですけど。
</p>

<p>
dispatch_source_set_event_handlerは、イベントを受け取ったときに呼ばれるブロックを設定します。今回はタイマーですので、タイマーが定期的にイベントを投げてきて、ここのブロックが呼ばれる事になります。
</p>

<p>
dispatch_source_set_cancel_handlerはディスパッチソースがキャンセルされたときに呼ばれるブロックを設定します。基本、タイマーのディスパッチソースやキューを解放します。
</p>

<p>
dispatch_source_set_timerでは、タイマーの開始時間とインターバルを指定します。スタートの時間は、dispatch_timeを使うと今から何秒後みたいな感じで絶対時間のdispatch_time_tが取得できます。インターバルは、１秒がNSEC_PER_SECで定義されていますから、そこから求めるのが良いと思います。
</p>

<p>
で、忘れていけないのは、dispatch_resumeです。ディスパッチソースは作った段階ではsuspend状態ですので、resumeで発動させなければいけません。
</p>

<p>
と、タイマーは以上です。何かオーディオとは直接関係ないGCDをだいぶ引っ張ってしまってますが、やり始めてしまったので仕方が無いということで、少なくとももう一回くらいはやる予定です。
</p>]]>
        
    </content>
</entry>

</feed>
