9
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ElixirでTone.jsを使ってみました 〜Webでピコピコ鳴らす〜

Last updated at Posted at 2025-12-21

Elixirでも手軽に音を鳴らしたいです
今回はTone.jsを使います

Tone.jsの公式の説明では
「Tone.js は、ブラウザ上でインタラクティブな音楽を作成するための Web Audio フレームワークです。」

ざっくりTone.jsができること

  • シンセサイザー
    • FMSynth
    • AMSynth
    • NoiseSynth
    • Synth
  • エフェクト
    • LFO
    • リバーブ
      など、上記は一部で省略してます、下記で確認できます

完成イメージ

前提

  • LiveViewのhookを使ったことがある
  • mix phx.newでプロジェクト作成済

Tone.jsインストール

$ cd assets
$ npm i tone

コードを書く

Hook

assets/js/tonex.js
import * as Tone from "tone"

Tonex = {
  mounted() {
    this.synth = new Tone.Synth().toDestination();

    this.handleEvent("play_note", ({note, duration}) => {
      this.synth.triggerAttackRelease(note, duration);
    })
  }
}

export default Tonex;

説明

  • this.synth = new Tone.Synth().toDestination(); でシンセを初期化
  • this.handleEvent("play_note", ({note, duration}) => はElixirからの受付をする
    • this.synth.triggerAttackRelease(note, duration); でシンセの音を鳴らす

これは、公式のサンプルHello ToneをElixirで使えるようにラップしました

公式のサンプルHello Tone
//create a synth and connect it to the main output (your speakers)
const synth = new Tone.Synth().toDestination();

//play a middle 'C' for the duration of an 8th note
synth.triggerAttackRelease("C4", "8n");

操作画面

lib/live_tone_web/live/tone_live.ex
defmodule LiveToneWeb.ToneLive do
  use LiveToneWeb, :live_view

  def mount(_params, _session, socket) do
    base_notes = ~w"C D E F G A B"

    notes =
      1..7
      |> Enum.map(fn r -> Enum.map(base_notes, fn x -> "#{x}#{r}" end) end)
      |> List.flatten()

    socket =
      assign(socket, notes: notes)

    {:ok, socket}
  end

  def render(assigns) do
    ~H"""
    <Layouts.app flash={@flash}>
    <div id="audio-container" phx-hook="Tonex" class="w-[350px]">
      <button
          :for={note <- @notes}
          phx-click="play"
          phx-value-note={note}
          class="btn w-[50px]"
        >{note}</button>
    </div>
    </Layouts.app>
    """
  end

  def handle_event("play", %{"note" => note}, socket) do
    {:noreply, play_note(socket, note)}
  end

  def play_note(socket, note) do
    push_event(socket, "play_note", %{note: note, duration: "8n"})
  end
end

説明

  • mount
    • 鳴らす音のノートを定美
      • base_notes ノートを定美 ドレミファソラシ(CDEFGAB)
      • notes 7オクターブ分定義 C1〜B7
  • render
    • ボタンをC1〜B7を作成
    • phx-click="play"でdef handle_event("play"と関連付けする
  • handle_event("play", %{"note" => note}, socket)
    • ボタンを押したときplay_note(socket, note)を呼ぶ
  • play_note(socket, note)
    • tonex.jsのthis.handleEvent("play_note", ({note, duration}) => { を実行
      • つまり、ここでTone.jsの機能を実行できる

ElixirでTone.jsを使うことができました
このコラムでは、Tone.jsの基礎の部分のみ使ってます
Tone.jsのAPIをHookに定義すると、さらにいろいろな表現ができます

ソース

9
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?