2022年7月14日木曜日

超主観的禅問答のススメ

引っ越しまで1ヶ月切ったのですが、概ね梱包が終わってしまい、逆に「まだ1ヶ月もあるのか」という状態です。

片付けをしてたら、若い頃に書いていたリアル日記のようなもの(大量のA6ノート)が出てきました。

内容は公開しません...というか、思考を整理することだけが目的の日記なので、内容なんて無いようなものですし、もう全部燃えるゴミとして捨ててしまったので私自身、その内容を知る術がありません。今となっては、だいたい何となく「日記書いてたなー」程度のことしか覚えていません。

2004年〜2007年ぐらいの頃、私はインターネットができる機器を携帯電話を含めて全部処分して、情報は紙の本や手紙などの書物からしか得られないようにしていました。

日記は概ねその時代の遺物です。

インターネットからの情報の遮断というと、デジタルネイティブな現代っ子なら考えられないことかもしれませんが、当時も知人から「気でも狂ったのか?」と心配されたりしました。

インターネットというのは有象無象の情報が洪水のように流れていき、その中に身を置いていないと時代から取り残されるのではないかと不安に思うかもしれません。しかし、それら有象無情の情報を得たところで別段賢くなれる訳でもなく、単に思考の選択肢が奪われながら時間を浪費しているということに気づき(誤解し?)、試しに完全な情報遮断をして超主観的禅問答をしてみた感じです。

インターネットを捨てることで、大量の時間が手に入ります。

なので、当時やたらと本を読むようになりました。

読んでいた本は、最初の頃は文庫や新書などの普通の本ですが、最終的にそれらの本だと1日で1冊ぐらいのペースで読んでしまうので、ものすごくお金が掛かります。末期(?)の頃は六法全書、司法試験の参考書、旧約聖書、新約聖書とかを読んで節約していました。当時あまり得意ではなかった英語の本を買って(日本語比で)読めるペースを落としてみたりといった涙ぐましい節約もしていました。

ピアノ教室なんかに通ってみたのも概ねその時期です。

超主観的禅問答の結果、悟りが開けた訳ではないですが、2008年前後でほぼ別人になれたことだけは確かです。

それが良い方向に作用しているのか、悪い方向に作用しているのかは分かりませんが、お金の掛からない「自分探しの旅」のひとつの手段としては割とオススメです。完全リモートワークになった今では難しいですが、有象無象の情報が飛び交う昨今「インターネット捨てたいな〜」という衝動に駆られることがあります。

インターネットを見ないように自制すれば良いのでは?と思われるかもしれませんが、インターネットの魅力は麻薬のようなもので、自制で何とかできるようなものではないので、物理的に情報を遮断するしかありません。卓越したサバイバル能力があれば電気の通ってない山の中や無人島に籠もることがベストです。もやしっ子の私にはそんなスキルはありませんが、インターネット回線や電話の契約を切ることなら簡単にできます。

2022年7月10日日曜日

お気に入りシャッフルと通常シャッフルの仕様差について

現在の東方VGSには「通常シャッフル」と「お気に入りシャッフル」の2種類のシャッフル機能があります。

 通常シャッフル

お気に入りシャッフル

違いは、

  • 通常シャッフル = 全曲を対象にシャッフル
  • お気に入りシャッフル = お気に入り登録した曲のみシャッフル

という点です。

実はこれ以外にも、

  • 通常シャッフル = インタースティシャル広告あり
  • お気に入りシャッフル = 広告なし

という違いがあります。

「広告入れ忘れてない?」と聞かれることがありますが、入れ忘れではなくわざとそうしています。

気にしているのは広告収入よりもエンゲージメントで、今の所、結果的には広告を入れなかったことで得られるエンゲージメントの高さの方が(将来的な)利益向上に結びつく可能性が高いという予測をしています。

もっとも、未来のことなんて予測できる訳が無いし、インタースティシャルは広告単価が高いので常識的に考えれば「入れて当然」ですが。多分、趣味じゃなくて仕事で作っているアプリなら普通に広告を入れていたと思います。

インタースティシャル広告の存在をすっかり忘れていて、入れ忘れた如何にもそれらしい言い訳を考えてみたのですが、こんな感じかな...(流石にこの状態で出してしまって後から広告追加すると燃えそうなのでやめておきませう)

2022年7月9日土曜日

シャッフル再生の並び順保持+αの検討(東方VGS)

東方VGSのユーザーさんからのレビューでシャッフル再生の並び順の保持をして欲しい旨の要望を受けたので検討中です。

https://github.com/suzukiplan/tohovgs4-android/issues/41

ユーザーさんの情報では、Spotifyのシャッフル再生はそんな感じらしいです。

当初私は、Spotifyでは「前回再生時の履歴から再生できる履歴再生みたいな機能があるのかな?」とミスリードしてしまい、Spotifyの履歴機能がどんな感じなのかググって調べてみたのですが、Spotifyの場合、過去の再生履歴を最大50件保持して見ることができるらしいです。

【参考記事】https://muusannitizyou.jp/spotify-log/

この機能を読んでふと、曲ごとの再生回数をローカルで保持して、再生回数の降順でランキング表示する「マイベスト」みたいな機能があると面白そうかも...と思い立ちました。

という訳で、マイベスト機能についても別途検討中です。

https://github.com/suzukiplan/tohovgs4-android/issues/42

他社音楽配信サービスの仕様を眺めるのは面白いです。

だいたいどの音楽配信サービスも私が苦手なサブスクですが、幸い大半のサービスには無料使用期間があるので、各社サービスを限られた無料期間の中で徹底的に研究して、良さそうな機能は更に良くできるように再デザインしつつパクってオマージュしていく手法は筋が良さそうですね。

2022年7月7日木曜日

iOSでn倍速機能をリリース(東方VGS)

東方VGSのiOS版でn倍速再生機能を追加したアップデートを審査提出しました。

実装はこんな感じです。

Androidは追従中です...しばらくお待ち下さい。

倍速設定は「Settings」の「再生速度」で 0.25倍速 〜 2.00倍速の範囲で(0.05刻みで)設定できる仕様にしました。

イチイチ Settings に切り替える操作は野暮ったいので、シークバーに再生速度(xn.nn)のプレビューを表示しつつ、そこをタップすれば Settings へ遷移しなくても再生設定(マスターボリューム & 再生速度)をカスタマイズできるようにしてみました。

要するに、動画サイトと同じようにプレイヤ上で切り替えることができるイメージに近づけました。

デザイン的には同じ設定を複数箇所に分散させるのは宜しくないこと(設定類は原則一元的にすることが望ましい)ですが、倍速再生は動画サイトではお馴染みな機能なので、UIをそれに近い形でデザインしておけば、少ない学習コストで機能を理解して使ってもらえる確率が上がるかなということで。

ただし、東方VGSの倍速再生は動画サイトの倍速再生とは若干異なります。

一般的な動画サイト(YouTubeやニコニコ動画など)の倍速再生だと、倍率を変更すると音程が変わってしまいます。

一方、東方VGSでは音程を一切変えることなく再生速度を変更することができます。

AppleMusicやSpotifyなどの音楽配信サービスでも、もしかするとこういう機能に対する潜在的なニーズはあるかもしれません。(広い括りでみれば音楽も動画と同じコンテンツなので)

ところが、音楽配信サービスだと音程が変わってしまうのは致命的(音楽クリエイターから猛反発を受けそう)なので、理想的には音程を変えずにテンポを変えることができる必要があると思います。

しかし、昨日の日記でも書きましたが、録音済みの音声波形でピッチを変えずにテンポを変えることは困難です。Logic Pro X の VariSpeed という機能で一応できますが完璧ではありませんし、CPU負荷がかなり掛かります。

仮に、音楽も動画と同様、1.5倍速再生されることが常態化してしまえば、恐らく「音程が変わってしまっても良いから倍速対応するぞ!」みたいな(乱暴な)形で実装されていくのかもしれませんが...

ただ、個人的には高速再生してコンテンツをスピーディーに消費するよりも、低速再生でじっくりねっとり楽しんでいただきたいかも。

2022年7月6日水曜日

n倍速再生機能(東方VGS)

東方VGSで倍速再生機能の導入を検討中です。

アプリ版に先立ってCLI(コマンドライン版)に以下の commit で導入しました。

https://github.com/suzukiplan/tohovgs-cli/pull/41/commits/fb5f0216aac60f10d9995de62f02552f8d186470

./tohovgs -t 75 path/to/file.mml

上記のように -t オプションで再生速度のパーセンテージを指定することができます。(上記の例なら 75% の速度で再生)

YouTube や ニコニコ動画 など、動画サイトではお馴染みの機能ですね。

ただし、東方VGS の倍速再生機能は、動画サイトの倍速再生機能と違い、倍率をイジってもピッチ(音程)が変化しません。

動画サイトの場合、2倍速再生すると全ての音が1オクターブ高くなり、0.5倍速で再生すると1オクターブ低くなります。これは、単純に波形データをそのまま伸縮しているために起こります。

ピッチを変えずに再生速度を変化させるには、波形を離散フーリエ変換して音毎の波に分解した後、周波数を変えないようにしてデュレーションを伸縮した後再合成する計算が必要になります。

Cubase Artist/Pro や Logic Pro X などのDAWのオーディオトラックでは、そういった計算方法でピッチを変えずにテンポを変えることができます。ただし、波形を完全に分解することは出来ないので、完全にピッチを変えずに再生速度を変えることができないケースが散見されます。

ピッチを変えずに再生速度を変える一番理想的な方法は、目的のテンポで楽器を演奏し直すことです。

録音された波形データではそれができませんが、ソフトウェア音源トラックの場合、プログラムが毎回譜面データに基づいて楽器をリアルタイムに演奏しているので、テンポを変えるだけでそれを実現できます。

東方VGSはソフトウェア音源方式で音声を出力しているので、ピッチを変えずに再生速度を変えることの方が簡単にできることになります。

この機能を作った目的は、東方Projectにはアップテンポな曲が多いので、コマンドで再生チェックする時にミスノートを探すのが大変なためです。(手軽にテンポを落としてチェックしたかった)

また、この機能がアプリ版でも入れば、東方VGSを使って楽器演奏の練習がしやすくなるかも?と思ったので、アプリ版にも導入する方向で検討中です。

楽器演奏をするとIQ上昇、うつ予防、認知症予防などの効果があるらしいという噂があります。

https://www.lifehacker.jp/article/160718raise_iq/

IQが上がっても多分あまり良いことなんて無いと思いますが、うつ予防や認知症予防ができるかも?というのは中々魅力的ですね。

何ならスクフェス、バンドリ、ダンカグとかでも良いかもしれません。

ただし、音ゲーだとお膳立てが整いすぎていて演奏自体が簡単(※変態譜面をクリアできるかは別問題^^;)なので、リアル楽器よりも達成感がイマイチな気がしないでもないです。私はピアノで初めて平均律クラヴィーア曲集1巻1番のフーガが弾けるようになるまで2〜3ヶ月ぐらい掛かりました...音ゲー勢に分かるように例えると、最高難度の曲をノーツ速度最低でフルコンボするようなイメージ。

最高難度の曲をノーツ速度最低でフルコンボというと絶望感しか湧きませんが、リアル楽器なら何回ミスってもゲームオーバーにならないし、テンポを落として練習することもできるので、根気よく練習すれば割と何とかなります。

という訳で、テンポを落として再生できる機能はもしかするとニーズあるかも?ということで。楽器演奏しなくても、ローテンポで聴くと音がハッキリ全部捉えやすくなるので、音楽の輪郭線がより鮮明になったりします。

2022年7月1日金曜日

お気に入り編集機能を検討中(東方VGS)

先日追加した東方VGSのお気に入り機能ですが、さっそくユーザーから「旧バージョンの頃(マイリスト)の方が使いやすかった」というご指摘をAppStore上のレビューで頂いたので、何がマズかったのかな...と考えてみましたが、お気に入り追加が曲を再生しないとできないので、リストエディット的な用途としては確かに不便かもしれません。

ある程度意図的にそうしてみたのですが、不満が出てしまった以上は改善検討します。

という訳で「お気に入り編集」機能を考え中です。

Favorites ページに【+】ボタンを追加して、

【+】ボタンを押せば纏めて編集できる感じのもを検討中です。

プラスだけでなくマイナスもできるので正確には【±】ですが、初見ユーザーが最初に Favorites ページを開いた時、リストが空っぽの確率が高いので、【+】があれば「あぁ、これで追加できるのか」という感じになり、その時【±】だと一定数「なんじゃこりゃ?」となるリスクがあるかも...ということで【+】にしてみました。

✎でも良いかもしれませんが。



2022年6月30日木曜日

Android版東方VGSでワイヤレスイヤフォンが使えない件の調査状況

ここ数日、Android版の東方VGSがワイヤレスイヤフォンを使うと再生できないという不具合の調査をしています。

https://github.com/suzukiplan/tohovgs4-android/issues/34

現象は モダンUI でのみ発生して RETRO UI では発生しません。

モダンUI と RETRO UI では内部的に音声の再生方法が異なります。

  • モダンUI = AudioTrack
  • RETRO UI = OpenSL/ES

という訳で、AudioTrack の使い方が誤っているのかも?と疑って調査をしたのですが、実装レベルでの誤りは見つかっていません。

「AudioTrackの初期化が失敗している」といった分りやすい事象が起こってくれれば良いのですが、そのような形跡はなく、疑わしいログ出力もありませんでした。

どうやら、ワイヤレスイヤフォンを接続するとAudioTrackが見た目上は正常に動くけど、バッファリングしたデータが勝手に破棄されるような挙動をしているようです。現象発生時の adb logcat を確認したところ、OS の bluetooth インタフェースと思しきものが一時停止(suspend)の状態になっている事が確認できす。

06-29 21:11:18.367  2320  2728 I btif_av : system/bt/btif/src/btif_av.cc:3098 btif_av_stream_suspend: btif_av_stream_suspend
06-29 21:11:18.368  2320  3010 I bt_bta_av: system/bt/bta/av/bta_av_api.cc:281 BTA_AvStop: BTA_AvStop: bta_handle=0x41 suspend=true
06-29 21:11:18.403  2320  3010 I bt_btif_a2dp: system/bt/btif/src/btif_a2dp.cc:131 btif_a2dp_on_suspended: btif_a2dp_on_suspended: ## ON A2DP SUSPENDED ## p_av_suspend=0x6e002963c0
06-29 21:11:18.403  2320  3010 I bt_btif_a2dp_source: system/bt/btif/src/btif_a2dp_source.cc:733 btif_a2dp_source_on_suspended: btif_a2dp_source_on_suspended: state=STATE_RUNNING
06-29 21:11:18.403  2320  3010 I bt_stack: [INFO:a2dp_encoding.cc(503)] ack_stream_suspended: result=SUCCESS_FINISHED
06-29 21:11:18.403  1123  1756 I BTAudioProviderSession: ReportControlStatus - status=SUCCESS for SessionType=A2DP_HARDWARE_OFFLOAD_DATAPATH, bluetooth_audio=0x0200 suspended

多分、アプリ → AudioTrack::write → AudioFlinger → bluetooth I/F → bluetooth earphone という流れで音声ビットストリームが流れていく筈で、suspend になった bluetooth インタフェースが音声ビットストリームを破棄しているから AudioFlinger が永久に stream end を検出できず、その結果 AudioTrack の PlaybackPositionUpdateLister が永久に発火しない(発火しないと音楽の再生が進まない)状況に陥っているのではないかと推理しました。

今回のテストで3000円ぐらいの激安ワイヤレスイヤフォンを調達したので、ハード(ワイヤレスイヤフォン側)の問題かも?と疑って、そのワイヤレスイヤフォンをiPhoneに接続してテストしてみましたが、iPhoneでは全く問題無く再生できました。

なので、ハードではなくソフト(アプリ or OS)側の問題であることは間違いありません。

幸い、OpenSL/ESは問題無く動作するので、モダンUI も RETRO UI と同様、OpenSL/ESを使うようにするという回避策もあるかもしれませんが、OpenSL/ES には別の問題があります。(2016年以前のAndroid版東方VGSでは長い間この問題に悩まされていました...)

OpenSL/ESだと何故か、バックグラウンド再生をすると音飛びが発生する仕様です。これはAndroid 8以降で発生するようになったOS側の仕様変更によるもので、Android 12でもまだ治っていません。(OpenSL/ES自体がマニアックなAPIなので多分治ることは無いと想定しています)

※RETRO UI のバックグラウンド再生を制限しているのはこれが理由です(RETRO UI は C言語で作られている関係で、C言語で使えるオーディオ・インタフェースを使わなければならないため、AudioTrackに置き換えることができません)

念の為、AudioTrack→OpenSL/ESに実装を書き換えてテストもしてみましたが、やはりバックグラウンドの音飛び問題は健在でした...

つまり、OpenSL/ESを使ってしまうと事実上バックグラウンド再生に対応できないため、対応したければAudioTrackを使うしかないというのが実情です。

なお、exo-player という Google が公開しているAndroid用動画再生ライブラリ(OSS)があって、その実装でも AudioTrack が使われています。

exo-player は Android版YouTubeでも使われているので、問題のワイヤレスイヤフォンを使ってAndroid版YouTubeで動作確認をしてみましたが、特に問題無く再生できるようです。

東方VGSとYouTubeの音声再生では、音声ビットストリームのエンコーディング形式に違いがあります。

  • 東方VGS: 22050Hz 16bit mono の raw PCM
  • YouTube: AACなど(動画のコーデックを見て切り替え)

bluetoothの帯域はかなり狭いので、リアルタイムに音声データを通信しようとすると raw PCM だと十分なバッファを確保できません。そのため、AAC等の圧縮形式でデータパケットを流す必要があるのですが、もしかするとAudioTrackはその辺を気にせず raw PCM でそのまま bluetooth にデータを流しているかもしれません。(Androidのベーシック層の設計思想は割とこういうパターンが多いので...)

その場合、AudioTrackのエンコーディングを raw PCM から AAC にして、MediaCodec で AAC エンコードしたデータをwriteしてあげれば何とかなるのかな?(OpenSL/ESの場合、そもそもraw PCM以外 buffer write できない仕様だから、bluetoothへ流す時にOS側でAACなりにエンコードしているから正常に動作している...という推測が成り立ちそうな気がします)

AudioTrackをAPI仕様通りに扱っていて正常に動かないので、本件はOS側の不具合だと言える気がするので、一旦この件の対策はせずにOS側の対策を待つしかないかもしれません。

まぁ、そんなこと言ってたらAndroidでプログラムなんか作れない訳ですが...

APIが必ずしも仕様通りに動くと思ってはならない

という訳で内心は早々にギブアップしたいところではありますが、もう少し粘って調査します。

追記: 無事回避策が見つかったので qiita で詳述してみました。(これで、同じ問題に躓く人が出てきた時、ググれば助かる...かもしれない)


 

合理的ではないものを作りたい

ここ最近、実機版の東方VGSの開発が忙しくて、東方VGSの曲追加が滞っています。 東方VGS(実機版)のデザインを作りながら検討中。基本レトロUIベースですがシークバーはモダンに倣おうかな…とか pic.twitter.com/YOYprlDsYD — SUZUKI PLAN (...