S98Player for iPhone 1.0.1 リリースされました

表題の通り、S98Player for iPhone 1.0.1のリリースです。今回は審査にちょっと時間がかかった感じです。

内容は主にバグフィックスです。

  • フェードアウト中に再生を止めて再び再生を開始すると一曲スキップされてしまう問題
  • 一部の曲が再生されずに再生画面のまま固まってしまう問題
  • 一部の曲が曲リストに出てきた瞬間にクラッシュしてしまう問題
  • 再生時間の計算がまれに誤る問題
  • イヤホンが再生中に抜けて自動停止する際に再生ヘッドだけカウントアップし続ける問題

などが修正されています。また、起動直後のスクロールが微妙に早くなっていたりしますが、気づく人はほとんどいないでしょう^^;

上記三番目のバグについては、S98ファイルの途中から再生開始されるように設定しているファイルなどが該当しますので、結構あるかもしれません。

どうぞよろしくお願いします。

S98Player for iPhone 1.0 リリースされました

S98Player for iPhone 1.0がAppStoreからダウンロード出来るようになりました。 ご興味のある方は、こちらのリンクよりAppStoreへどうぞ。

詳細はAppStoreのほうに記載してあります。 また、前回のエントリにもMac版と比べての改善点などが記載されておりますので、よろしければご覧ください。

当初のAppStoreでのレビュー期間を知る、という目標は達成です(笑 結果としては、

  • 8/25未明にバイナリをアップロード
  • 8/28未明にステータスがIn Reviewに
  • 9/1未明にステータスがProcessing for App Store、Ready for Saleに

といった感じでした。

レビューにはS98ファイルが必要と思い、いくつかサーバに上げておいたのですが、レビュアーさんからとおぼしきファイルアクセスがあってから3分後にはステータスがProcessing for App Storeに変わっていました(笑

AppStoreに申請に出す前にそこそこ長い期間プライベートで使っていたのでそこまでバグはでないと思っていましたが、審査中にすでにいくつか見つけてしまいました…。

  • ヘッドホンで視聴中にヘッドホンを(誤って)抜いた場合に音声が停止するが、画面内の再生時間がカウントアップし続けてしまう。
  • ホームボタン二回押し+左画面にスワイプでiPod controlが現れるが、何かの拍子にそのcontrolが見えなくなる(標準のiPod用になってしまう)ことがある。
  • OPM用のS98ファイルに再生できないものがある(のだけど、OPMの仕様など分からないためなんとも…)

あとは、一番最初に立ち上げる時に、スプラッシュスクリーンで止まってしまうことがあるそうです(自分は未確認)。しばらく待っても立ち上がらないときには、一度アプリを終了させてから再度立ち上げてみてください。

最近はS98ファイルも巷で見なくなっていますので、再生できないファイルがあってもうまく対応できないことがあるかもしれません。差し支えない場合にはそのファイルをお渡し頂ければ原因がわかるかもしれません。どうぞよろしくお願いします。

もう少し様子を見てから(その他のバグと、そしてダウンロード数と^^;)、バグフィックス版をリリースしようと思います。

S98Player for iPhoneを申請してみた

S98Playerのダウンロード数から見ても明らかに需要があるとは思えないiPhone版のS98Playerですが、思うところあってAppStoreへ申請しました。

現在ステータスがWaiting for Reviewの段階です。 上のスクリーンショットでは21日に申請となっていますが、その後バグが見つかって自分で再投稿したりしていることもあり、まだ審査は始まっていません。

Mac版と比べて、

  • ファイルリストに曲名や演奏時間などが出る
  • イコライザが使える
  • ループ再生が終了する際にきちんとフェードアウトする
  • OPMも対応している
  • 複数音源を使うデータにも対応している(パン振りは対応してない)

などの点から高機能です(誰も使わないだろうけど)。バックグラウンド再生にも当然ですが対応しています。

また、内部の構造を見なおして無駄をだいぶ省いたので、使用するメモリ量も減りました。

まぁS98ファイルなんて既に巷には出回っていませんから、「S98ナニソレ?」な人には今のところ全く恩恵はないと思います。 ただ、時間に余裕ができたら(来年あたり…?)iPad向けにFM音源用のシーケンサを作ろうと思っています。その保存データをS98ファイルに書き出せれば、S98Playerも多少日の目をみることもあるかな、と。

せっかくciscさんのfmgenがiPhoneでも動くのだから、活用していろいろやってみたいところです。

S98Player Ver. 0.2を作った

4年ほど前にFM音源のサウンドログを再生するアプリを作ったのですが,最近FM音源づいていてちょっとだけコードを修正したので公開します.機能は全く変わっておらず,使い勝手も悪いままですが.

…そして誰も使わないとは思いますが.

修正点は以下の通り.

  • サンプリング周波数を44100Hzから55466Hzに変更.原音に近くなりました.
  • S98v3のヘッダをもう少しきちんと読むように.UTF8,SJIS両方読めます.
  • しかし基本的にOPNAのみの対応….
  • 10.5SDK上でコンパイルしたので10.5以降でしか動かないかも.

OPNへの対応は,サウンドログファイルをもってないのでチェックできないんですよね.ま,基本的に自分用アプリなので問題ないんですけどね(無駄にiPhone向けに移植して一人楽しんでます).

続・FM音源の仕組みを視覚的に理解する

前回のエントリで簡単なFM音源もどきを作ったわけですが、どうも物足りなく感じたため(というか、なんとなく達成感がないというか…)、並列接続も可能な4オペレータ版を作成しました。

そして、オペレータ接続アルゴリズムも8種類から選べるようにしました。

単音しかなりませんが、機能的には、往年のYM-2203音源などと同じ程度のパラメータをいじれます(多少少ないんですが)。

FM音源って?

という方は、是非前エントリをご一読ください。

ダウンロード

となります。

使い方

まぁ、大したことができないのは相変わらずですが…。

右下のプルダウンメニューでアルゴリズムが選べますので、それを選ぶと各オペレータの接続アルゴリズムが変わります。用意した接続アルゴリズムは8種類で、これはYAMAHAのOPN系音源に準じています。

接続アルゴリズムを選ぶと、プルダウンメニューの下に接続の模式図が現れますので、雰囲気はつかめるはずです。

感想

単純な直列だけだと「ふーん」ってな感じでしたが、並列もできるようになるとかなり音が「それっぽい」感じになりました。

最終の出力の手前部分が並列になっているもの(Algorithm 4など)は特に、直列では聞けなかった音が合成されますので、楽しいです。

まとめ

相変わらず実用性皆無のアプリではありますが、往年のYAMAHA製FM音源であるOPN系音源における音色作成くらいは追体験できるのではないかと思います。

気に入った方がいたら、是非アフィリエイトサイトで本でも買ってやってください(笑)

FM音源の仕組みを視覚的に理解する

FM音源って知ってますか? 今じゃ表立って耳にする機会も少ないですが、つい最近まで携帯電話の着メロなんかはこのFM音源を使ってました。

「機械っぽい音」なんていわれるとまぁその通りではあるんですが、往年のNEC製PCなどで使われていたこともあり、独特な音にファンも少なからずいたりします。

このFM音源、「FM (Frequency Modulation)」と名のつく通り「周波数変調」を利用して音を作っているのですが、これがイマイチよく分かりません。いや、Wikipediaの当該ページを見ると波形を導き出す式も載っていますし、それはそれで分かるんですが、その式をいくら見たところで「どんな音がするか」がよく分からない…。

様々なサイトで「周波数変調は、扇風機の前で声を出すとあ”あ”あ”あ”あ”〜〜〜と音が変わるのと同じ原理です」なんて説明されていたりするのですが、この説明は周波数変調がわかっている人にしか理解できないものだと思うのです。

…というわけで、式を見ても分からないなら手を動かせ、ということで、単純なFM音源を鳴らすプログラムを組んでみました。 各オペレータの波形をリアルタイムに表示させて、パラメータをいじるとどのように波形が変わるのかが分かるようにしてみました。

とりあえずお披露目

Cocoaアプリを作りました。何も考えずに作ったのですが、もしかしたらSnow Leopardでしか動かないかもしれません。 ソースも置いておきます。他人に見せるために書いてないので汚くてコメントないですが…。

ま、適当にいじってみてください。大したことはできませんが…。 頭では原理がわかっていても、パラメータをいじると実際に波形が変わるので、見てるだけで(個人的には)楽しいです。 また、パラメータだけだと想像つかなかった音色も、波形を見ればだいぶ想像しやすくなる気がします。

FM音源のキホン

Wikipediaの説明を読むと、FM音源の基本は周波数を変調することだそうですが、どう変調するか、そこがキモのようです。 昔の数学やら物理やらの授業の記憶を掘り返し、頑張って正弦波(sin波)の基本公式を思い出してください(笑)

y = A sin (2 π f t + φ)

ってやつですね(Aは振幅、fが周波数、φが初期位相、tが時間)。

この中でA, f, φが一定であれば普通の正弦波になるわけですが(tだけ時間に合わせて値が変わる)、FM音源は、ここのφの部分も時間に応じて変化させて複雑な音を作り出します。

φをどうやって時間変化させるか

基本的なFM音源の場合、φを、さらに別の正弦波を使って時間変化させます。 これが、キャリアとモジュレータの関係みたいですね。キャリアがメインとなる正弦波を作るオシレータ、モジュレータがキャリアのφを時間変化させるオシレータです。

キャリアとモジュレータの周波数は同じでなくても構いません。 ただ、モジュレータの周波数がキャリアの周波数の整数倍でないと、音がキャリア周波数の高さに聴こえません。 これは、整数倍でないときに

y = A sin (2 π f t + φ)

のsinの中身が、キャリアの1周期ごとに0にならなくなってしまうからです(ちょっと計算してみるとわかります)。

エンベロープジェネレータを使ってさらに変化させる

エンベロープジェネレータの説明はWikipediaなどを読んでいただくとして。 楽器から音が出始めてから終わるまで、音量は一定ではありません。オルガンなどは鍵盤を押した瞬間に最大音量となり、離すと音がプツリと消えますが、ピアノであれば鍵盤を話しても弦が揺れて少しのあいだ音が鳴り続けますし、バイオリンなどは音の出始めがゆっくりです。

FM音源の場合、キャリアに対してエンベロープ変化をつけると、上記のように「オルガンっぽい音の出だし」から「バイオリンっぽい音の出だし」といったように音量を変化させることができます。

しかしさらに複雑なことに、モジュレータの出力に対してもエンベロープジェネレータを使って変化させることができます。 これによって、キャリアから出力される波形が最初は普通の正弦波なんだけどだんだんφが大きくなって違う音になります。つまり、エンベロープジェネレータをモジュレータの出力にかけることによって、音量だけでなく音色まで変化させることができるようになるわけです。

どうやってコーディングしてるか

FM音源のオペレータは、構造体で以下のように定義されています。

struct _FMInfo{
    double isFB;
    int isEnabled;

    double carrierFreq;
    double freqIndex;
    double modIndex;

    double attack;
    double decay;
    double sustain;
    double release;

    int numOfParents;
    FMInfo** parents;
};

そして、ある時間の波形の高さは、以下の関数で計算しています。ほんとに、上記の公式を愚直に計算してます(笑

double fmGetValue(FMInfo* fm, double sec){

    double parentPhase = 0.0;

    for (int i = 0; i < fm->numOfParents; i++){
        parentPhase += fmGetValue(fm->parents[i], sec);
    }

    if (fm->isFB > 0){
        double value = 0.0;
        double beta = M_PI * fm->isFB / 8.0;

        for (int i = 0; i < 20; i++){
            value = sin(2.0 * M_PI * (fm->carrierFreq * fm->freqIndex) * sec + beta * value);
        }

        return fm->modIndex * value * fmGetPower(fm, sec);

    }

    return fm->modIndex * sin(2 * M_PI * (fm->carrierFreq * fm->freqIndex) * sec + parentPhase) * fmGetPower(fm, sec);
}

fmGetPowerという関数はエンベロープジェネレータでの高さを計算する部分です。 今回は、「鍵盤を離した」部分は「音が鳴り始めたら4秒」と決め打ちにしているので、以下のようなコードになっています。

double fmGetPower(FMInfo* fm, double sec){

    double power = 1.0;

    if (sec < fm->attack){
        power = sec / fm->attack;
    }else if (sec < fm->decay + fm->attack) {
        double t = sec - fm->attack;
        double w = (1.0 - fm->sustain) * t / fm->decay;

        power = 1.0 - w;
    }else if( sec < 4){
        power = fm->sustain;
    }else if (sec > 4 && sec < (4 + fm->release)) {
        double t = sec - 4.0;
        power = fm->sustain * (1.0 - t / fm->release);

    }else if (sec >  + fm->release){
        power = 0;
    }

    return power;
}

興味のある方はソース中にあるOperator.hおよびOperator.cをご覧下さい。綺麗ではありませんが、どうなっているかは理解できるのではないかと思います。

オペレータの並列接続

今回のアプリは、キャリアとモジュレータ2つの3オペレータを直列につないだものしか音が出せないのですが、実際には並列接続のものもあります。 並列接続は、いわゆる波形の合成です。周波数をいじるのではなくて、単純に足し算ですね。

上記のコードを読んだ方はお気づきかもしれませんが、コード内では既に並列接続の計算もできるようになっています。ただアプリのUIが複雑になるため、今回はパスしました。暇があったら作るかもしれません。…作らないかもしれません。

まとめ

FM音源の原理はわかっていてもイマイチどういう音が出てくるのか想像できなかったため、簡単なFM音源もどきを実際に作りました。 パラメータをいじって音色を確かめられるだけではなく、波形がリアルタイムに変わることで、パラメータを意図して変化させることも容易になるかもしれません。

今回のアプリではオペレータの並列接続はサポートしていませんが、いつか暇ができたら(そして興味がつづいていたら)実装するかもしれません。 AudioUnitで動く音源を作るのも面白そうですが、そこまでできるかなー。

蛇足

エントリと直接関係ありませんが、右にある本はiPhoneでCoreAudioをいじくるにはとても良い本です。少々値段が高いのですが、iPhone / iPad / iPod touchで音楽をいじるにはこの本は必須だと思います。どうもCoreAudio系はAppleの技術文書が少ないイメージがあり、このように系統だって(それも日本語で!)まとめられた本があるのは助かります。

実はこの本の中にシンプルなFM音源ドラムマシンの実装があり、最初はこれを参考にiPadアプリを作ろうとしていました(オペレータ間の接続をタッチで行ったりできると楽しいなぁ、と)。

ただiPadよりもまずは慣れたMacでやろうということで、ひとまず上記のアプリになりました。また、波形生成のアルゴリズム部分に関しても、オペレータの並列・直列やフィードバックなどを盛り込んだため、異なった実装になっています。

補足

次のエントリに4オペレータ版で並列配置も可能なものを公開しました。よろしければご覧になってください。