iPodライブラリからのファイル書き出し その1

iOS 4.0になってようやくiPodライブラリにある音楽を生のデータとして扱うことができるようになりましたので、その方法をまとめておきたいと思います。ムービーも同じような方法でできるようですが、とりあえずここではオーディオに限定して説明していきます。ちなみにシミュレータにはiPodライブラリがないので試せません。コードは実機で実行してください。

大まかな手順としては以下のような感じです。

① MPMediaItemを取得
② AVURLAssetを生成
③ AVAssetExportSessionを生成
④ Exportを実行

では、やっていきましょう。

① MPMediaItemを取得

MPMediaItemは、iOS3.xのときからありましたのでご存知の方も多いと思いますが、iPodライブラリに中にあるひとつひとつの曲(音楽の場合)の情報をもっているクラスです。これの取得の仕方は、いろいろiPhoneアプリ開発本にもくわしく載っていますので、細かいことはそれらを参考にしていただいた方が良いと思います。

取得の仕方としては、MPMediaPickerControllerを使う方法とMPMediaQueryを使う方法とありますが、今回は簡単に実装できるMPMediaPickerControllerを使ってみます。

では、実際にコードを書いていきたいと思います。Xcodeの新規プロジェクトでWindow Based Applicationを選択し、プロジェクトを作成します。MPMediaPickerControllerを使うのに必要なフレームワークはMediaPlayer.Frameworkですのでインポートします。またあとで必要になるので、AVFoundation.Frameworkもインポートしてください。AppDelegateの中に以下のコードを追加します。

#import <MediaPlayer/MediaPlayer.h>
#import <AVFoundation/AVFoundation.h>

それから、起動するときにMPMediaPickerControllerを表示したいので、以下のコードをapplication:didFinishLaunchingWithOptions:メソッドに追加してください。MPMediaPickerControllerはどうやらUIViewControllerが表示されていないと出せないみたいなので、ダミーでUIViewControllerを作ってからMPMediaPickerControllerを出しています。このへんは適当ですので、あまり参考にしない方が良いかと思います。同期すると消えてしまいますし。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    UIViewController *viewController = [[UIViewController alloc] initWithNibName:nil bundle:nil];
    [window addSubview:viewController.view];
    
    MPMediaPickerController *pickerController = [[MPMediaPickerController alloc] initWithMediaTypes:MPMediaTypeMusic];
    pickerController.delegate = self;
    [viewController presentModalViewController:pickerController animated:NO];
    [pickerController release];
    [window makeKeyAndVisible];
return YES;
}

これでアプリを実行して起動するとMPMediaPickerControllerが表示される状態になっています。

② AVURLAssetを生成

ここからはMPMediaPickerControllerで曲が選択されたあとの処理です。MPMediaPickerControllerのデリゲートに処理を書き込んでいきましょう。

MPMediaItemを取得したら、valueForPropertyにMPMediaItemPropertyAssetURLを渡してNSURLを取得します。ちなみにこのURLはあくまでiPodライブラリの中の場所でしかないので、ここに直接アクセスしようとしても無駄です。AVPlayerなどを使えば再生できたりしますが、AudioFileService系では開くことはできません。まずは、取得したNSURLからAVURLAssetというメディアファイルを表すオブジェクトを生成します。

- (void)mediaPicker:(MPMediaPickerController *)mediaPicker didPickMediaItems:(MPMediaItemCollection *)mediaItemCollection
{
    MPMediaItem *item = [mediaItemCollection.items lastObject];
    NSURL *url = [item valueForProperty:MPMediaItemPropertyAssetURL];
    AVURLAsset *urlAsset = [AVURLAsset URLAssetWithURL:url options:nil];

③ AVAssetExportSessionを生成

次に、AVURLAssetを渡してAVAssetExportSessionを生成します。これが、普通のオーディオファイルに書き出してくれるものです。生成するのはこんな感じです。

AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]
                                           initWithAsset:urlAsset
                                           presetName:AVAssetExportPresetAppleM4A];

この2つ目の引数のpresetNameというのは書き出すときのフォーマットで、オーディオで書き出すpresetNameはこのAVAssetExportPresetAppleM4Aしかないようです。AVAssetExportSessionのexportPresetsCompatibleWithAsset:で使えるものが取得できます。元のファイルのフォーマットをいろいろ変えて試しましたが、AVAssetExportPresetAppleM4Aにした状態では、常にAACの44.1kHz・Low Complexityで書き出されるようです。

AVAssetExportSessionが生成できたら、さらに情報を与えていきます。最低限必要なものは、outputFileTypeとoutputURLです。

exportSession.outputFileType = [[exportSession supportedFileTypes] objectAtIndex:0];
    
NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *filePath = [[docDir stringByAppendingPathComponent:[item valueForProperty:MPMediaItemPropertyTitle]] stringByAppendingPathExtension:@"m4a"];
exportSession.outputURL = [NSURL fileURLWithPath:filePath];

outputURLは書き出す先なので説明は省きます。お好きなところを指定してください。今回はDocumentディレクトリの中にTitleをファイルネームにして書き出しています。

exportSessionに設定できるFileTypeはsupportedFileTypesで取得できます。presetNameをAVAssetExportPresetAppleM4Aにしている場合、supportedFileTypesの中身は「@”com.apple.m4a-audio”」ひとつだけのようでしたので、そのままそれを設定しています。

④ Exportの実行

ここまで準備ができたらあとは書き出しを実行するだけです。書き出しはexportAsynchronouslyWithCompletionHandler:というメソッドで行います。とりあえずコードは以下のような感じ。メソッド名にAsynchronouslyとあるように非同期で実行されます。

    [exportSession exportAsynchronouslyWithCompletionHandler:^{
        
        if (exportSession.status == AVAssetExportSessionStatusCompleted) {
            NSLog(@"export session completed");
        } else {
            NSLog(@"export session error");
        }
        [exportSession release];
    }];
}

書き出しが終了したら、このメソッドで渡したブロックが呼ばれます。exportSessionのstatusプロパティには書き出しが成功したか失敗したかキャンセルされたか等の状態が入ってますので、そのstatusに応じて処理を記述するという感じです。

ブロックの最後には、もうexportSessionが必要なくなったということでreleaseしています。キャンセル処理や進捗を実装する場合等はインスタンス変数とかにexportSessionを保持しておかないといけないと思いますので、releaseのタイミングはうまいことやってください。

以上のコードを実行して曲を選択すると、アプリ内のDocumentディレクトリにファイルがコピーされると思います。File SharingをONにしておけばiTunesからみたりしてコピーされたかどうかが確認できると思います。ただしコピーできないものがあって、DRM付きのファイルはもちろんなのですが、なぜかMP3もコピーしてくれませんでした。また、今回の方法だと自動的にAACに変換されてしまうので、WAVやAIFFなどの非圧縮ファイルをそのままコピーしたい場合などの対応についてはまた次回やります。

BigStopWatch v2.4.1 リリース

BigStopWatchのv2.4.1が公開されました。

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

OpenGL ESのRetina対応

OpenGL ESのRetina対応の方法をちょっとメモしておきます。OpenGL以外のRetina対応については@k_katsumiさんの記事「アプリケーションを iPhone 4 の Retina Display に対応するための方法いろいろ」がとても参考になると思います。というか、この記事を見てOpenGLについては書いてなかったので触発されて書くことにしました。

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

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

glView.contentScaleFactor = [UIScreen mainScreen].scale;

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

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

renderer = [[ES2Renderer alloc] init];
↓
renderer = nil;

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

glTranslatef(0.0f, (GLfloat)(sinf(transY)/2.0f), 0.0f);
↓
glRotatef(transY, 0, 0, 1.0);

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

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

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

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

BigStopWatch v2.4公開されました

BigStopWatchのv2.4が公開されました。ダウンロードはこちらから。

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

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

AVPlayerでムービーを再生する方法

AVFoundationといえばOS3.xではAVAudioPlayerとAVAudioRecorderくらいだったのですが、iOS4.0から一気にいろんなものが増えてます。僕が以前予想していたように、オーディオだけじゃなくて映像関係も扱えるように進化していますね。なんかいろいろありすぎて、かつ自分がAudioUnitでやりたいことを置き換えるようなものじゃなさそうなので基本的にはスルーしているのですが、一番手軽で役に立ちそうだったけどちょっと使い方にハマったAVPlayerを取り上げたいと思います。

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

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

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

AVPlayer *player = <#A configured AVPlayer object#>;
CALayer *superlayer = <#Get a CALayer#>;
AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:player];
[superlayer addSublayer:playerLayer];

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

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

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

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

//
//   AVPlayerView.h
//
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
@interface AVPlayerView : UIView {
}
@end
//
//   AVPlayerView.m
//
#import "AVPlayerView.h"
@implementation AVPlayerView
+ (Class)layerClass
{
    return [AVPlayerLayer class];
}
@end

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

//
//   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;
}

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

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

iOS4.0のオーディオ

iOS4.0がリリースされましたので、個人的に気になった変更点などをまとめておきたいと思います。大々的に告知されていたような目玉機能の羅列ではなく、主にオーディオ周りで気になったところです。

バックグラウンドオーディオ

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

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

appplaysaudio.jpg

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

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

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

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

オーディオカテゴリが厳格になった?

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

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

Accelerate Framework

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

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

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

※以下追記 2010/8/1

iPodライブラリからのファイル書き出しが可能に!

この記事を書いたときに気づいてなかったのですが、iPodライブラリから生のデータとして扱えるファイルに書き出すことができるようになりました。くわしい方法はこちらのエントリへどうぞ。

METRONOME STAR 1.0.1 公開しました

METRONOME STAR v1.0.1がリリースされました。ダウンロードはこちら

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

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

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

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

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

離散フーリエ変換 その3

前回記事を書いてからだいぶ時間が経ってしまって5月にエントリがひとつもないのもさみしいので、書きかけだった記事をアップしておきます。iPadから書き込んでみたいというのもあったので…。

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

位相とは

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

位相 (Wikipedia)

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

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

DFT03_01.jpg

直線位相特性

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

DFT03_03.jpg

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

DFT03_02.jpg

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

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

METRONOME STAR v1.0 公開しました

先月末に予告していたメトロノームアプリがリリースされました。

ダウンロードはこちらから。(iTunesへ飛びます)

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

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