<?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-02-07T08:09:26Z</updated>
    <subtitle>MacとiPhoneでオーディオプログラミング</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type Pro 4.22-ja</generator>

<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>

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

    <published>2009-10-04T10:00:00Z</published>
    <updated>2009-10-11T15:08:45Z</updated>

    <summary> ディスパッチまだまだ続きます。でも、処理の高速化ってことを考えると、GCDより...</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よりOpenCLのほうが効果的なんじゃないかって気がしてきました。まあ、Airでしか試してないからだと思いますけど。
</p>

<p>
ディスパッチはいままでの並列処理の方法と比べるとシンプルで簡単だ、なんて書かれていたりしますけど、どうやらセマフォは欠かせないようで、ディスパッチにもあります。
</p>

<p>
先にあれこれ書くのがめんどくさくなってきたので、とりあえずサンプルコードから。
</p>

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

int main (int argc, const char * argv[]) {
    
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_t group = dispatch_group_create();
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
    
    for (int i = 0; i &lt; 10; i++) {
        dispatch_group_async(group, queue, ^{
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            //クリティカルセクション開始
            printf("start %d\n", (int)i);
            usleep(10000);
            printf("end %d\n", (int)i);
            //クリティカルセクション終了
            dispatch_semaphore_signal(semaphore);
        });
    }
    
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    
    dispatch_release(semaphore);
    dispatch_release(group);
    
    return 0;
}
</pre>

<p>
ディスパッチのセマフォの使い方としてはまず、dispatch_semaphore_createでセマフォのオブジェクトdispatch_semaphore_tを作ります。引数にはセマフォの旗の数を指定できます。0だと一回も進入できなくなってしまいますので1以上を指定します。
</p>

<p>
そして、クリティカルセクションをdispatch_semaphore_wait〜dispatch_semaphore_signalで囲みます。それぞれ引数にセマフォオブジェクトを渡します。waitでは進入できない時に待つ時間を指定できて、DISPATCH_TIME_FOREVERなら永久に待ちます。
</p>

<p>
サンプルコードを実行すると、クリティカルセクション開始〜終了としているところは同時に実行されず、printfでstartとendがセットで0から9まで順番に出力されます。もし、セマフォ関連の関数を排除したら、startのあとにスリープさせていますので、startが10個出力された後に、endが10個出力されるはずです。
</p>

<p>
という感じで、ディスパッチのキューに直接ブロックを渡す関係は以上で終わりです。ちなみに、キューにブロックを渡してしまうと後からキャンセルが出来なかったりしますのでご注意を。
</p>

<p>
その処理のキャンセルとかも含めて、ディスパッチにはソースって仕組みも用意されていますので、次回以降見ていこうと思います。
</p>]]>
        
    </content>
</entry>

<entry>
    <title>CoreAudio その３〜５改 AudioObjectでのプロパティ取得・設定</title>
    <link rel="alternate" type="text/html" href="http://objective-audio.jp/2009/09/coreaudio-audioobject.html" />
    <id>tag:objective-audio.jp,2009://13.161</id>

    <published>2009-09-27T12:00:00Z</published>
    <updated>2009-09-27T17:08:01Z</updated>

    <summary> Mac OS X 10.6 Snow Leopardから、AudioHardw...</summary>
    <author>
        <name>Yasoshima</name>
        
    </author>
    
        <category term="Core Audio - Mac" 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 OS X 10.6 Snow Leopardから、AudioHardware〜とかAudioDevice〜とかAudioStream〜とかのGet・Set系がことごとくDEPRECATEDになってしまいました。
</p>

<p>
僕の認識では、もともとAudioObject〜があって、そのコンビニエンスメソッドとしてAudioDeviceとかの関数があると思っていたのですけど、どうやら歴史的には逆だったようです。ヘッダをよく見てみたら、AudioObject系はわりと最近の10.4から増えてたんですね。
</p>

<p>
あと、AudioUnitがiPhoneと同じようにAudioComponentにいきなり変わっててびっくり。iPhoneで慣れ親しんでいたとはいえ、もちょっと緩やかに移行してくれてもいいんじゃないすかね。
</p>

<p>
プロパティの定数系も結構Deprecatedしてます。でも、これはXcodeで警告を出してくれないので注意が必要です。ヘッダのコメントに"Some Day Be Deprecated"なんてこっそりかかれてます。Device系だとkAudioDevicePropertyDeviceNameから始まるところとかです。10.7になっていきなりエラー出まくりなんて事のないようにしっかりチェックしておきましょう。
</p>

<p>
ということで、取得・設定系をAudioObjectを使ってやってみたいと思います。
</p>

<p>
AudioObjectでオーディオ情報の取得・設定をするにはAudioObjectGetPropertyDataやAudioObjectSetPropertyDataという関数を使います。これはいままでAudioHardware〜やAudioDevice〜など別々の関数でやっていたオーディオ情報の取得や設定を、ひとつでまかなえるものです。プロパティのサイズを調べるのにも、AudioObjectGetPropertyDataSizeという関数で行う事になります。
</p>

<p>
たとえば、プロパティの取得する関数はこんな感じで定義されています。
</p>

<pre class="prettyprint">extern OSStatus
AudioObjectGetPropertyData(AudioObjectID inObjectID,
                           const AudioObjectPropertyAddress* inAddress,
                           UInt32 inQualifierDataSize,
                           const void* inQualifierData,
                           UInt32* ioDataSize,
                           void* outData) 

</pre>

<p>
最初のAudioObjectIDというのはAudioDeviceIDやAudioStreamIDをそのまま渡します。前の記事の<a href="http://objective-audio.jp/2008/04/core-audio-3-audioobjectid.html">その３</a>でも説明しましたが、AudioDeviceIDもAudioStreamIDもAudioObjectIDをtypedefしているだけのもので、つまり全てAudioObjectIDです（リファレンス的にAudioDeviceなどはAudioObjectのサブクラスってことらしい）。AudioHardware〜系の関数をつかっていたプロパティのときはkAudioObjectSystemObjectを渡します。
</p>

<p>
ちょっとひとつ飛ばしまして、inQualifierDataSizeとinQualifierDataは、サンプルで使っているものが無かったのでよくわかりません。基本0とNULLで大丈夫なようです。もしかしたらまだ機能していないかもしれません。ioDataSizeとoutDataは取得するプロパティのサイズと受け取るメモリ領域で、前と同じです。
</p>

<p>
で、新しく出てきたAudioObjectPropertyAddressは、
</p>

<pre class="prettyprint">struct  AudioObjectPropertyAddress
{
    AudioObjectPropertySelector mSelector;
    AudioObjectPropertyScope    mScope;
    AudioObjectPropertyElement  mElement;
};
typedef struct AudioObjectPropertyAddress   AudioObjectPropertyAddress;
</pre>

<p>
と定義されてます。プロパティの場所を特定するのに必要なものを集めたって感じですかね。
</p>

<p>
Selectorは〜PropertyIDの事です。なんでかセレクタって名前になってます。Scopeは、まあほとんどの場合はkAudioObjectPropertyScopeGlobalで、Deviceなどの入出力部分のときはInputとかOutputとかで指定したりって感じです。Elementは基本kAudioObjectPropertyElementMaster（= 0）でOKだと思います（これ以外指定するパターンがすぐに見つけられなかった。Channel的なところで0以外を使うのでは）。
</p>

<p>
では、サンプルソースです。Xcodeで新規プロジェクト→Command Line Tool→Foundationでプロジェクトを作成して、CoreAudio.Frameworkを追加して、main.mを以下のソースに差し替えてください。走らせると、デフォルトになっているオーディオデバイスの名前を表示して、サンプルレートを設定可能な中で変更します。
</p>

<pre class="prettyprint">#import &lt;Foundation/Foundation.h&gt;
#import &lt;CoreAudio/CoreAudio.h&gt;

int main (int argc, const char * argv[]) {
    
    AudioDeviceID devID;
    UInt32 size;
    AudioObjectPropertyAddress address;
    AudioValueRange *sampleRates;
    CFStringRef deviceName = NULL;
	
    //デフォルトのアウトプットに設定されているオーディオデバイスを取得する
    address.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
    address.mScope = kAudioObjectPropertyScopeGlobal;
    address.mElement = kAudioObjectPropertyElementMaster;
    size = sizeof(devID);
    
    AudioObjectGetPropertyData(kAudioObjectSystemObject, &address, 0, NULL, &size, &devID);
    
    //アウトプットの名前を取得する
    address.mSelector = kAudioObjectPropertyName;
    size = sizeof(deviceName);
    
    AudioObjectGetPropertyData(devID, &address, 0, NULL, &size, &deviceName);
    
    //アウトプットのデバイスが対応しているサンプルレートを取得する
    address.mSelector = kAudioDevicePropertyAvailableNominalSampleRates;
    AudioObjectGetPropertyDataSize(devID, &address, 0, NULL, &size);
    
    UInt32 numOfSampleRates = size / sizeof(AudioValueRange);
    sampleRates = calloc(numOfSampleRates, sizeof(AudioValueRange));
    
    AudioObjectGetPropertyData(devID, &address, 0, NULL, &size, sampleRates);
    
    //現在のサンプルレートを取得する
    Float64 currentSampleRate;
    address.mSelector = kAudioDevicePropertyNominalSampleRate;
    size = sizeof(Float64);
    
    AudioObjectGetPropertyData(devID, &address, 0, NULL, &size, &currentSampleRate);
    
    //サンプルレートを別のにする
    int currentIndex = 0;
    for (int i = 0; i < numOfSampleRates; i++) {
        if (sampleRates[i].mMinimum == currentSampleRate) {
            currentIndex = i;
            break;
        }
    }
    
    int newIndex = currentIndex + 1;
    if (newIndex >= numOfSampleRates) newIndex = 0;
    
    //サンプルレートを設定する
    Float64 newSampleRate = sampleRates[newIndex].mMinimum;
    size = sizeof(Float64);
    
    AudioObjectSetPropertyData(devID, &address, 0, NULL, size, &newSampleRate);
    
    NSLog(@"device name = %@", deviceName);
    NSLog(@"new samplerate = %f", newSampleRate);
    
    free(sampleRates);
    CFRelease(deviceName);
    
    return 0;
}
</pre>

<p>
あ、そういえばwhenって無いなぁ。
</p>]]>
        
    </content>
</entry>

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

    <published>2009-09-20T15:12:19Z</published>
    <updated>2009-09-27T17:08:44Z</updated>

    <summary> 前回紹介したdispatch_applyはブロックの処理が終わるまで待ってくれ...</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>
前回紹介したdispatch_applyはブロックの処理が終わるまで待ってくれていましたが、dispatch_asyncは別スレッドで処理されてしまうので、どの順番で処理されるのかも分からない状態でブロックを処理させっぱなしになってしまいます。
</p>

<p>
グループというのを使えば、asyncで処理する複数のブロックをひとつのグループにまとめて、それらのブロック全部が終わったタイミングを受け取る事が出来ます。
</p>

<p>
まず、グループを作る関数がこれです。
</p>

<pre class="prettyprint">dispatch_group_t dispatch_group_create(void);
</pre>

<p>
次に、グループで処理させたいブロックを渡すのがdispatch_group_asyncです。グループはasyncオンリーでsyncはありません。
</p>

<pre class="prettyprint">void
dispatch_group_async(dispatch_group_t group,
	dispatch_queue_t queue,
	dispatch_block_t block);
</pre>

<p>
そして、グループの処理全部が終わったら呼ばれるブロックを設定するのがdispatch_group_notifyです。基本的に、グループ自体や、グループ内共通で使ったメモリ領域などを解放するのに使うようです。どこかに通知するのにも使えると思います。
</p>

<pre class="prettyprint">void
dispatch_group_notify(dispatch_group_t group,
	dispatch_queue_t queue,
	dispatch_block_t block);
</pre>

<p>
カレントスレッドで処理の終わりを待つ必要があれば、待たせることもできます。dispatch_group_waitです。どれだけ待つのかを指定できます。DISPATCH_TIME_FOREVERという定数をtimeoutに渡せば、いつまでも待ちます。
</p>

<pre class="prettyprint">long
dispatch_group_wait(dispatch_group_t group, dispatch_time_t timeout);
</pre>

<p>
なお、waitで待っても待たなくても、notifyで設定したブロックが呼ばれるのは別スレッドのようです。
</p>

<p>
といったところで、サンプルソースです。
</p>

<pre class="prettyprint">#include &lt;stdio.h&gt;
#include &lt;dispatch/dispatch.h&gt;
int main (int argc, const char * argv[]) {
    
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_t group = dispatch_group_create();
    
    __block int sum = 0;
    
    for (int i = 0; i &lt; 10; i++) {
        dispatch_group_async(group, queue, ^{
            printf("+%d\n", i);
            sum += i;
        });
    }
    
    dispatch_group_notify(group, queue, ^{
        dispatch_release(group);
    });
    
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    
    printf("sum = %d\n", sum);
    
    return 0;
}</pre>

<p>
前回のapplyと同じような処理をさせています。waitが無ければ、おそらくsumは0で終わってしまうと思いますが、waitで待っている事でちゃんと45と答えが出ます。
</p>

<p>
waitの代わりにdispatch_main()にしておいてnotifyのブロックの中でsumを見れば、そこでも45となっていて、ちゃんとasyncで渡したブロックが全て実行された後に呼ばれる事が分かると思います。
</p>

<p>
ちなみに、notifyのブロックが呼ばれる前にasyncで新たなブロックを同じグループに入れると、その新しいブロックも終わってからnotifyのブロックが呼ばれます。が、、notifyのタイミングが新たなブロックの前か後かどちらでくるか分からなくなってしまうので、やらない方が良いと思います。
</p>]]>
        
    </content>
</entry>

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

    <published>2009-09-15T12:41:35Z</published>
    <updated>2009-09-27T17:09:12Z</updated>

    <summary> 前回のコードのように同じ処理をforループでキューに渡すようなとき、それ専用の...</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>
前回のコードのように同じ処理をforループでキューに渡すようなとき、それ専用の関数がディスパッチには既に用意されています。dispatch_applyです。
</p>

<pre class="prettyprint">void
dispatch_apply(size_t iterations, dispatch_queue_t queue, void (^block)(size_t));
</pre>

<p>
iterationsの数だけブロックをキューに渡して処理させます。ブロックはsize_tの引数を一つだけ持ち、よくあるforループと同じように０から１ずつ増やした値が渡されます。
</p>

<p>
まあ、実際に動かしてみればわかるってことで、サンプルコードです。
</p>

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

int main (int argc, const char * argv[]) {
    
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    __block int sum = 0;
    
    dispatch_apply(10, queue, ^(size_t i){
        sum += i;
    });
    
    printf("sum = %d\n", sum); // sumは45になる
    
    return 0;
}
</pre>

<p>
これを実行すると、0から9までがsumに足されて45になります。
</p>

<p>
dispatch_applyはグローバルキューに渡していても、ちゃんと全てのブロックが処理されるのを待ちますので、dispatch_main()が無くてもアプリが終了する前に全て足された答えが出ます。ですが、sync的に順番に処理されている訳ではなく、並列に処理はされています。ただ、asyncと同じという訳でもなく、applyでは、呼び出したスレッドと別スレッドを組み合わせて並列にブロックが実行されているようです（asyncは別スレッドだけ）。
</p>

<p>
ブロックの途中でスリープさせたりとかして試してみると、applyでは同時に２つまでしか処理されません（試したのがMacBook Airでコアが２つだから？）。asyncだといくらでも同時に実行されてしまいます。このあたりは、使い道の違いって感じですかね。
</p>

<p>
短いですが、今回はこの辺で。次回はgroupでも。
</p>]]>
        
    </content>
</entry>

<entry>
    <title>Grand Central Dispatch その２ Queue</title>
    <link rel="alternate" type="text/html" href="http://objective-audio.jp/2009/09/grand-central-dispatch-queue.html" />
    <id>tag:objective-audio.jp,2009://13.157</id>

    <published>2009-09-13T11:19:08Z</published>
    <updated>2009-09-27T17:09:55Z</updated>

    <summary> Queueを作る ディスパッチの基本的な使い方は、処理したいコードをブロックや...</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[
<h3>
Queueを作る
</h3>

<p>
ディスパッチの基本的な使い方は、処理したいコードをブロックや関数で用意しておいて、キューにそのブロックや関数を渡すという流れになります。
</p>

<p>
ディスパッチのキューには２種類あります。アプリ（OS？）に最初から一つ用意されているグローバルキューと、自分で作るキューです。グローバルキューは並列に処理できますが、自分で作るキュー（以後シリアルキューと書いて区別します）は入れていった順番に直列でしか処理できません。
</p>

<p>
キューはdispatch_queue_tという型のオブジェクトで表されます。ディスパッチのオブジェクトは他にもいくつかありますが、それは次回以降に後回しにします。
</p>

<p>
グローバルキューを取得するにはこの関数を使います。
</p>

<pre class="prettyprint">dispatch_queue_t
dispatch_get_global_queue(long priority, unsigned long flags);
</pre>

<p>
一つ目の引数にはキューが処理される優先度を指定します。普通はDISPATCH_QUEUE_PRIORITY_DEFAULTを指定すれば良いと思います。DEFAULT以外にもHIGHとLOWがあります。HIGHの処理が全て終わってからDEFAULT、DEFAULTが全て終わってからLOWという順番で処理されていくようです。２つ目の引数はヘッダを見るとReserved for future useとなっていて今は何も意味しないので、0を入れておけば良いです。
</p>

<p>
シリアルキューはこの関数で作ります。
</p>

<pre class="prettyprint">dispatch_queue_t
dispatch_queue_create(const char *label, dispatch_queue_attr_t attr);
</pre>

<p>
一つ目の引数はキューに付けられるラベルで、サンプルを見る限り逆DNS記法が推奨されているようです。でも、同じラベルでふたつキューを作っても、同じキューが返されるという事は無く、別のキューが作られるようです。２つ目の引数はこれまたヘッダにUnusedなんて書かれていて、こちらはNULLでも入れておけば良いようです。
</p>

<p>
なお、Carbonに慣れ親しんでいる方はお分かりかと思いますが、関数名にcreateとついているのでdispatch_queue_createで作ったキューは使い終わったら解放しなければいけません。それを行うのはdispatch_releaseです。
</p>

<pre class="prettyprint">dispatch_release(queue);
</pre>

<p>
使うかどうか分かりませんが、リテインカウントをあげる事も出来ます。
</p>

<pre class="prettyprint">dispatch_retain(queue);
</pre>

<p>
これらretainとreleaseはキュー以外のオブジェクトにも使います。
</p>

<h3>
Queueに処理を渡す
</h3>

<p>
キューを取得できたら、ブロックを渡して処理をさせます。キューを使って処理を開始させる関数はいろいろありますが、まず基本的な２つを見てみます。こんなかんじで定義されています。
</p>

<pre class="prettyprint">void
dispatch_async(dispatch_queue_t queue, dispatch_block_t block);

void
dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
</pre>

<p>
ayncは非同期でバラバラに、syncは同期で順番に、キューにブロックを処理をさせようとする関数です。と説明すると、キューにも同じような用途で２種類あるのに何で関数がまた同じように２種類分かれているんだと思ってしまうのですが、ちょっと役割が違います。
</p>

<p>
ブロックが処理されるスレッドを調べてみると、asyncは呼び出し元のスレッドとは別のスレッドでブロックを処理させ、syncは呼び出し元と同じスレッドで処理をさせるようです。
</p>

<p>
実際の挙動としては、グローバルキューにasyncでブロックを渡すと別スレッドで並列に実行されますが、syncで渡すと現在のスレッドをつかうのでそのまま直列に実行されます。シリアルキューにsyncで渡せばもちろんそのまま直列に実行ですが、asyncで渡すと入れていった順番に別スレッドで実行されます。
</p>

<p>
グローバルキュー＋syncの組み合わせはありえないって気がするんですが、もしかしたら想像もつかない用途があるかもしれません。まあ、他にもディスパッチ用の関数はたくさんあるんで意味が無さそうな組み合わせはいろいろ出てくると思います。
</p>

<p>
それと、ここでつかえるブロックは返り値も引数もなしのブロックです。</p>

<h3>
実行してみる
</h3>

<p>
なんか説明が長くなってきたので、実際にディスパッチを使ってみます。ディスパッチを使うには&lt;dispatch/dispatch.h&gt;をincludeしないといけないのですが、Objective-Cで使う場合はFoundationに既に含まれているので何も気にしなくても使えます。</p>

<p>
では、サンプルのソースコードです。単純にディスパッチを試すためC言語だけで組んであります。新規プロジェクトをCommand Line ToolのTypeをCで作成して、main.cを以下のコードに差し替えてください。あっ、もちろんSnow LeopardのXcode3.2で。
</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 gQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    dispatch_async(gQueue, ^{
        
        dispatch_queue_t sQueue = dispatch_queue_create("jp.objective-audio.sample1", NULL);
        
        for (int i = 0; i &lt; 10; i++) {
            dispatch_sync(sQueue, ^{
                printf("block %d\n", i);
            });
        }
        
        dispatch_release(sQueue);
        
        printf("finish\n");
        exit(0);
    });
    
    dispatch_main();
    
    return 0;
}
</pre>

<p>
dispatch_asyncで非同期で実行するブロックの中でシリアルキューを作って、１０回ほどdispatch_syncでブロックを実行させています。その処理が終わったら"finish"と表示してアプリ終了です。
</p>

<p>
ブロックの記述は、わざわざ宣言とかしなくても、こんなかんじで関数の中に直接書けちゃいます。
</p>

<p>
最後のdispatch_main()というのはメインスレッドを休止させるもので、これを使わないとdispatch_asyncでグローバルキューにブロックを実行させる前にアプリがreturn 0で終了してしまいます。NSApplicationMain()かCFRunLoopRun()が走っている場合には必要ありません、というかdispatch_main()を呼び出すと固まります。
</p>

<p>
キューの種類を入れ替えてみたり、syncとasyncを入れ替えてみたりすると、どんな感じで動作するか分かるかと思います。asyncのところをsyncにするとdispatch_main()が無くてもちゃんと全部実行されますし。逆にsyncのところをasyncにすると、ブロックの処理が別スレッドに行ってしまうので、実行される前に"finish"となります。
</p>

<p>
とりあえず今回は以上です。asyncやsync以外にもディスパッチでブロックを実行させる関数があるので、また次回見ていきます。
</p>]]>
        
    </content>
</entry>

<entry>
    <title>やっぱりiPhone nanoがいい</title>
    <link rel="alternate" type="text/html" href="http://objective-audio.jp/2009/09/iphone-nano.html" />
    <id>tag:objective-audio.jp,2009://13.158</id>

    <published>2009-09-10T12:30:01Z</published>
    <updated>2009-09-10T12:34:23Z</updated>

    <summary> iPod touchの第３世代が発表された！8GBは１万円台だ！って思ってあや...</summary>
    <author>
        <name>Yasoshima</name>
        
    </author>
    
        <category term="雑記" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://objective-audio.jp/">
        <![CDATA[<p>
iPod touchの第３世代が発表された！8GBは１万円台だ！って思ってあやうく勢いで買っちゃうところでした。8GBは第２世代のままだったんですね。
</p>

<p>
iPhone 3GSはスルーしてますが、第３世代のiPod touchはいずれ買うと思います。でも、アプリ開発してなければ断然iPod nanoですね、なんたってラジオ付きですから。ラジオとカメラとナイキとおまけの音楽プレーヤで、持ち歩きデバイスとしてはあと電話がつけば言う事無いです。
</p>

<p>
アプリが入れられなくても、タッチディスプレイじゃなくても、小さいだけで結構需要があると思うんですけどね。iPhoneでかすぎでヤボッタイです。すくなくともiPod touchなみに薄くなってほしい。
</p>]]>
        
    </content>
</entry>

<entry>
    <title>Grand Central Dispatch その１ Block</title>
    <link rel="alternate" type="text/html" href="http://objective-audio.jp/2009/09/grand-central-dispatch-block.html" />
    <id>tag:objective-audio.jp,2009://13.156</id>

    <published>2009-09-09T14:01:49Z</published>
    <updated>2009-09-27T17:11:10Z</updated>

    <summary> Grand Central Dispatchについて日本語で丁寧に詳しく説明し...</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>
Grand Central Dispatchについて日本語で丁寧に詳しく説明してくれるサイトはないかなぁと待っていたのですが、待っている間にひととおり自分なりに調べ終えてしまったので、まとめて書いておきます。まちがいに気がついたらご指摘していただけるとうれしいです。
</p>

<p>
Grand Central Dispatch（以下ディスパッチ。リファレンスとか関数名とかGrand Centralって全然ついていなくてDispatchだけですしね。）とはなんぞやというと、Snow Leopardから導入された並列処理のAPIです。並列処理といえばLeopardではNSOperationというObjective-CのAPIが導入されましたが、ディスパッチはC言語のAPIとして用意されていて、システムに近い低レベルなところで使えるものです。
</p>

<p>
あれこれ試した印象で言うと、コアが２つしかないCPUのMacでたいした事の無い処理をなんでもかんでもディスパッチで並列にしても、ディスパッチのオーバーヘッドが大きくて逆に遅くなってしまうので、どこで使うかってのはよく考えた方が良さそうです。Mac Proみたいにコアがたくさんあると効果が大きいんだろうなぁと思います。
</p>

<h3>
Blockの構文
</h3>

<p>
ディスパッチでは一つ一つの処理をブロックという単位でキューに渡して処理を実行します。ブロックの代わりに関数を使う事も出来るのですが、あえてディスパッチ用にC言語を拡張して用意しているくらいですので、ブロックを使うというのが正当な使い方だと思います。
</p>

<p>
ブロックは変数に入れておく事ができ、ブロック名をname1とname2とすると宣言はこうなります。
</p>

<pre class="prettyprint">void (^name1)(void); //返り値なし、引数なし
int (^name2)(float, int); //返り値int、引数floatとint
</pre>

<p>
名前の頭にキャレット（^）を付けます。で、これらへ代入をするのはこうなります。
</p>

<pre class="prettyprint">name1 = ^{
    //ブロックの処理を記述
};

name2 = ^(float f, int i) {
    //ブロックの処理を記述
    return (int)f + i;
};
</pre>

<p>
ブロック本体は、キャレット（^）、引数、その後にブレース（{}）で囲んで記述します。name1のように引数がvoidなら省略できます。なお、name2のように返り値があったり、引数が２つ以上のブロックはディスパッチでは使いません。ディスパッチ以外のところで、関数にするほどじゃないけど、あるていどコードをまとめたいってときには使えると思います。
</p>

<p>
ブロックは関数と違って、メソッドや関数の中に置けます。関数のような感じで外にも置けます。
</p>

<p>
呼び出す時は関数と一緒です。
</p>

<pre class="prettyprint">name1();
name2(3.0, 5); //返りは8
</pre>

<br />

<h3>
ブロック変数
</h3>

<p>
ディスパッチでブロックを使うときには返り値が無いとなると、処理結果を得るためにはどうするかって事なんですが、そのひとつにブロック変数というのがあります。たとえば、以下のようなコード。
</p>

<pre class="prettyprint">#import &lt;Foundation/Foundation.h&gt;

int y = 0;

int main (int argc, const char * argv[]) {
    
    int x = 0;
    
    void (^inc)(void) = ^{
        x++; //エラー
        y++;
    };
    
    inc();
    
    printf("x = %d / y = %d\n", x, y);
    
    return 0;
}
</pre>

<p>
これはx++のところでエラーが出てコンパイルが通りません。
</p>

<p>
ブロック内では、グローバル変数には自由にアクセスできますが、関数内のブロック外にあるローカル変数は、そのままでは読み込めるだけで書き込みは出来ません。ディスパッチでブロックを処理するときには、呼び出した関数とは別のスレッドで処理される場合があるので（というかそれがディスパッチを使う目的）、関数が終わったら消えてしまうローカル変数には戻せないという事だと思います。</p>

<p>
ローカル変数に書き込むには__blockという修飾子をつけます。こうすることで、その変数が使われるブロックがすべて終わるまで保持されるようです。
</p>

<pre class="prettyprint">
#import &lt;Foundation/Foundation.h&gt;

int y = 0;

int main (int argc, const char * argv[]) {
    
    __block int x = 0;
    
    void (^inc)(void) = ^{
        x++;
        y++;
    };
    
    inc();
    
    printf("x = %d / y = %d\n", x, y); // x = 1、y = 1
    
    return 0;
}
</pre>

<p>
とりあえずブロックはこんなところで、次回は実際にディスパッチを使ってみます。
</p>]]>
        
    </content>
</entry>

<entry>
    <title>５匹のSnow Leopard</title>
    <link rel="alternate" type="text/html" href="http://objective-audio.jp/2009/09/snow-leopard.html" />
    <id>tag:objective-audio.jp,2009://13.155</id>

    <published>2009-09-01T22:54:15Z</published>
    <updated>2009-09-02T20:50:07Z</updated>

    <summary> Snow Leopardのファミリーパックに多く含まれているとおぼしき不良ロッ...</summary>
    <author>
        <name>Yasoshima</name>
        
    </author>
    
        <category term="雑記" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://objective-audio.jp/">
        <![CDATA[<p>
Snow Leopardのファミリーパックに多く含まれているとおぼしき不良ロットのインストーラディスクに見事当たってしまいました。発売日が発表されてすぐWebのApple Storeで注文をして、せっかく当日に届いたというのに、結局、最初にインストールを開始してから終了まで５日もかかってしまいました。
</p>

<p>
ちなみにApple Storeから送られてきた代替のものがこちら。
</p>

<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="SnowLeopard5.jpg" src="http://objective-audio.jp/2009/09/02/SnowLeopard5.jpg" width="640" height="480" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></span>

<p>
Apple Storeからのメールによると、「ファミリーパックのご注文の急増に伴い、一時的な製品の供給不足が発生しております」とのことで、シングルユーザーが５枚送られてくる事になったそうな。
</p>

<p>
でもきっと、注文の急増なんかじゃなくて、不良品の多いファミリーパックを出荷停止しているとか、５枚送っとけばどれかは大丈夫だろうとかって気がします。まあいちおう金額的に言えば、シングルユーザー５個からファミリーパック１個の値段を引いて（3,300 × 5 - 5,600）で10,900円の得って感じになりますね。うちのMacは３台しか（も？）無いので、あまった２パッケージを売りさばけば、それだけでモトが取れてしまいます。やりませんけど。
</p>

<p>
とりあえず、開発用のMacBook AirをSnow Leopardにアップグレードしました。Grand Central Dispatchが気になってたんですよねぇ。まだ、DevCenterのリファレンスをチラ見しただけなので、実際にいじくれるこれからが楽しみです。オーディオ処理に役立ちそうですしね。Open CLの方はどうなんですかね、iPhoneで使えるといいとは思うんですが。
</p>

<p>
ちなみにMacBook Airの人がOSインストールする時は、ハードディスクにインストーラをコピー（復元）して、そっからインストールしたほうが良いです。Time machineにバックアップしたドライブも一緒につなげて移行アシスタントまで一気にいけちゃいます。リモートインストールだと時間がかかるのはもちろんのこと、Super Driveからの場合でも、外付けのUSBハードディスクに繋ぎ変えないといけませんから。やりかたはMacPeopleに載ってますよ、と。
</p>]]>
        
    </content>
</entry>

<entry>
    <title>本に載ってます</title>
    <link rel="alternate" type="text/html" href="http://objective-audio.jp/2009/08/post-16.html" />
    <id>tag:objective-audio.jp,2009://13.154</id>

    <published>2009-08-11T15:12:35Z</published>
    <updated>2009-08-12T13:20:37Z</updated>

    <summary> 昨日８月１１日発売（たぶん）の「iPhone これは使える!アプリ&amp;ツールガイ...</summary>
    <author>
        <name>Yasoshima</name>
        
    </author>
    
        <category term="BigStopWatch" 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 これは使える!アプリ&ツールガイド OS3.0&3GS」に、BigStopWatchが後ろの方にささやかに載ってます。
</p>

<p>
今回初めて事前に掲載の連絡をいただけたので、前もって記事の内容を見させてもらったりしました。BigStopWatchはあまりそんなことないですけど、本とかブログとか、iPhoneアプリ関係けっこう間違って紹介されてたりしたなぁと思いまして。Touch the Waveは以前ブログとか見て回ったときには惨敗でしたし。
</p>

<p>
この本の表紙がすごく地味で、なおかつ目立たないところに載っているので、ダウンロード数にはあまり反映されなさそうです。AppStoreでリリース日を更新する方が効果が大きそうです。
</p>

<p>
ところで本で思ったのですが、出版社さんには、OS3.0公開になってから時代遅れなOS2.xのiPhone SDK解説本なんて出さずに、「iPhone SDK マガジン」みたいなの毎月出して欲しいんですよねぇ。あるいは「Objective-C マガジン」とか。Mac中心のプログラミング雑誌だったら、いろんなもの混在でいいんですけど。
</p>]]>
        
    </content>
</entry>

</feed>
