ブラウザで動く波形編集アプリをReactで作った

1 min読了の目安(約1700字TECH技術記事 2

リンク

以下のURLから登録不要で起動できます。

https://fono.app

目指したもの

誰でも直感的に操作がわかる波形編集アプリ。

機能

  • 複数ファイルのインポート、結合
  • フェード
  • クリップごとの音量調整
  • クリップの分割・長さの調整
  • コンプレッサー
  • EQ
  • リバーブ
  • VUメーター
  • wavファイルでのエクスポート

技術スタック

  • Typescript
  • React
  • styled-components
  • zustand
  • Tone.js
  • Netlify

Reactとかstyled-componentsについて言うことは特に無いので、zustandとTone.jsのみ所感を書きます。

zustand - 状態管理ライブラリ

zustand はreduxのような状態管理ライブラリです。ただreduxと比べて以下のような特徴があります。

  • fluxアーキテクチャのような縛りがなく、ボイラープレートコードが少ない。
  • ストアはただのグローバルオブジェクトみたいなイメージで、なんでも放り込める(それが良いかは別として)。
  • selectorはredux同様で柔軟に書ける。
  • Providerで囲む必要がない。

シンプルに、サクッとグローバルステートを管理するぶんにはかなり便利に感じます。それでいてselectorや購読を使いこなせばパフォーマンスチューニングもしっかりできる。

ただ、そうとうに柔軟なことができてしまうので、大人数で大規模な開発をする場合は向かないかもしれません。

Tone.js

Tone.js には全面的にお世話になっています。

Webアプリでオーディオを扱う以上、WebAudioAPIを使うことになるわけですが、Tone.jsはさらに高レベルのAPIを提供してくれます。

たとえば、生のWebAudioAPIでは AudioContext の持つクロックを使用して音源の再生タイミングをスケジューリングするんですが、これはコンテクスト作成時からひたすら加算されていく時間に過ぎません。音楽的な「拍」の概念はありません。

Tone.jsの Transport はその無機的なクロックをいい感じにラッピングして、音楽的なタイミングでの再生をサポートしてくれます。リピートや、音源を途中から再生したときの処理もよしなにしてくれます。

ただ一点引っかかったのは、3バンドイコライザの実装である EQ3 の音質がかなりアレだということです。githubのissueとしても挙がっていましたが、全バンドを0にしていてもカットオフ周波数あたりが相当に削れているようです。メンテナによると仕様らしいので、僕の使い方がどこか間違っていたのか・・・? FonoではBiquad Filterを使って自前の実装をしています。

TODO

波形のレンダリング

オーディオ波形はcanvasに描画しています。wavesurferの実装を参考にしたんですが、パフォーマンス不足によりズームやクリップ長の変更時にガクガクします。別にjavascriptの限界というわけではなく、他の波形編集アプリを触ってみるとスムースに動いているので、ここは改善したいです。

エフェクト

エフェクトの種類もそうですが、範囲指定で適用できるようにしたいですね。

タイムラインの表示

拡大・縮小してもつねに1秒単位で刻まれているのをなんとかしたい。