Tone.jsを使えば音楽知識ゼロの私でも簡単に作曲して遊べた！


# 注意

**Tone.jsを初めてさわってみました、間違いなどありましたらご指摘お願いします:bow:**
**また、題名にある通り私は音楽の知識は全くありません、そんな人でも `Tone.js` を使えば簡単に作曲っぽいことができるということで勘弁してください:bow:**

また、[この記事内のコードは全てこちらに同じのを用意](https://github.com/okumurakengo/00016_tone)してあります

# 参考

- [Tonejs/Tone.js - github](https://github.com/Tonejs/Tone.js)
- [ブラウザを誰でも簡単に扱える楽器にしてみた - Qiita](https://qiita.com/comorebi_notes/items/56e41f3ddc228597450d)
- [Tone.jsを使ってテキストからメロディを鳴らしてみた - Qiita](https://qiita.com/hiroki-pf/items/54433d0f8d8492c9c5b8)

---

# 作曲してみた!

といっても、適当に音を羅列したようなものです:bow:

<blockquote class="twitter-tweet" data-lang="en"><p lang="ja" dir="ltr">超簡単にだけど、人生初作曲 <a href="https://t.co/AMLRWRQARm">pic.twitter.com/AMLRWRQARm</a></p>&mdash; 奥村健吾 (@okumurakengo) <a href="https://twitter.com/okumurakengo/status/1114791492260855809?ref_src=twsrc%5Etfw">April 7, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

[コードはこちらにも用意しました](https://github.com/okumurakengo/00016_tone/blob/master/src/index.js)

# Installation

Tone.jsインストール

```bash
npm install tone
```


# 自分が作曲したコード

```html:index.html
<input type="button" value="play!">
```

```js:index.js
import Tone from "tone";

const synth = new Tone.Synth().toMaster();

// note:ドレミなどの音階を指定
// dur:「4n」->「♩」(四分音符)、「8n」->「♪」(八分音符)
// nullだと休符
const data = [
  { note: "E4", dur: "8n" },
  { note: "F4", dur: "4n" },
  [{ note: "G4", dur: "8n" }, { note: "G4", dur: "8n" }],
  { note: "G4", dur: "4n" },

  { note: "E4", dur: "8n" },
  [{ note: "G4", dur: "8n" }, { note: "C5", dur: "8n" }],
  { note: "C5", dur: "8n" },
  [{ note: "C5", dur: "8n" }, { note: "D5", dur: "2n" }],

  null,
  { note: "E5", dur: "8n" },
  { note: "E5", dur: "8n" },
  { note: "D5", dur: "2n" },

  null,
  [{ note: "C5", dur: "8n" },{ note: "A4", dur: "8n" }],
  [{ note: "C5", dur: "2n" },{ note: "C5", dur: "2n" }],
];

const seq = new Tone.Sequence((time, { note, dur }) => {
    synth.triggerAttackRelease(note, dur, time);
}, data, "4n").start(0);
seq.loop = false;
Tone.Transport.bpm.value = 150; // テンポ

document.querySelector("[type=button]").addEventListener("click", e => {
    Tone.Transport.start();
});
```

# Tone.js

私が勉強したことをまとめす、間違ってたらご指摘お願いします:bow:

## Hello Tone

音を出してみます

```js:hello-tone.js
import Tone from "tone";

const synth = new Tone.Synth().toMaster();

document.querySelector("[type=button]").addEventListener("click", e => {
    synth.triggerAttackRelease("C4", "8n"); // 8分音符「♪」の、「ド」を弾く
});
```

<blockquote class="twitter-tweet" data-lang="en"><p lang="und" dir="ltr"><a href="https://t.co/M9uKkPUZ7e">pic.twitter.com/M9uKkPUZ7e</a></p>&mdash; 奥村健吾 (@okumurakengo) <a href="https://twitter.com/okumurakengo/status/1114816548051415040?ref_src=twsrc%5Etfw">April 7, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## TypeScript

参考

- [Tonejs/TypeScript - github](https://github.com/Tonejs/TypeScript)

TypeScriptでも動かせました

```bash
npm i typescript git://github.com/Tonejs/TypeScript.git
```

```ts:ts-index.ts
import * as Tone from "tone";

const synth: Tone.Synth = new Tone.Synth().toMaster();

document.querySelector("[type=button]").addEventListener("click", e => {
    synth.triggerAttackRelease("C4", "8n");
});
```

- [自分で試したコード](https://github.com/okumurakengo/00016_tone/blob/master/src/ts-index.ts)

<blockquote class="twitter-tweet" data-lang="en"><p lang="und" dir="ltr"><a href="https://t.co/J5IWppWnla">pic.twitter.com/J5IWppWnla</a></p>&mdash; 奥村健吾 (@okumurakengo) <a href="https://twitter.com/okumurakengo/status/1114840517584404480?ref_src=twsrc%5Etfw">April 7, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


## `C4` とは?

音楽の初心者のためここでつまづきました。

以下のサイトを見るととても参考になりました

- [音階周波数](https://tomari.org/main/java/oto.html)

参考サイトそのまま流用した表です:bow:

| 鍵盤番号 | 音階名 | 音階名 | |
|:--|:--|:--|:--|
| 1 | ラ | A0 |  |
| 2 |    | A#0 |  |
| 3 | シ | B0 |  |
| 4 | ド | C1 |  |
| 5 |  | C#1 |  |
| 6 | レ | D1 |  |
| 7 |  | D#1 |  |
| 8 | ミ | E1 |  |
| 9 | ファ | F1 |  |
| 10 | |  F#1 |  |
| 11 | ソ | G1 |  |
| 12 | |  G#1 |  |
| 13 | ラ | A1 |  |
| 14 | |  A#1 |  |
| 15 | シ | B1 |  |
| 16 | ド | C2 |  |
| 17 | |  C#2 |  |
| 18 | レ | D2 |  |
| 19 | |  D#2 |  |
| 20 | ミ | E2 |  |
| 21 | ファ | F2 |  |
| 22 | |  F#2 |  |
| 23 | ソ | G2 |  |
| 24 | | G#2 |  |
| 25 | ラ  | A2 |  |
| 26 | | A#2 |  |
| 27 | シ  | B2 |  |
| 28 | ド  | C3 |  |
| 29 | | C#3 |  |
| 30 | レ  | D3 |  |
| 31 | | D#3 |  |
| 32 | ミ  | E3 |  |
| 33 | ファ  | F3 |  |
| 34 | | F#3 |  |
| 35 | ソ  | G3 |  |
| 36 | | G#3 |  |
| 37 | ラ  | A3 |  |
| 38 | | A#3 |  |
| 39 | シ  | B3 |  |
| 40 | ド  | C4 | **C4** を指定するとここを鳴らしてくれる |
| 41 | | C#4 |  |
| 42 | レ  | D4 |  |
| 43 | | D#4 |  |
| 44 | ミ  | E4 |  |
| 45 | ファ  | F |  |
| 46 | | F#4 |  |
| 47 | ソ  | G4 |  |
| 48 | | G#4 |  |
| 49 | ラ  | A4 |  |
| 50 | | A#4 |  |
| 51 | シ  | B4 |  |
| 52 | ド  | C5 |  |
| 53 | | C#5 |  |
| 54 | レ  | D5 |  |
| 55 | | D#5 |  |
| 56 | ミ  | E5 |  |
| 57 | ファ  | F5 |  |
| 58 | | F#5 |  |
| 59 | ソ  | G5 |  |
| 60 | | G#5 |  |
| 61 | ラ  | A5 |  |
| 62 | | A#5 |  |
| 63 | シ  | B5 |  |
| 64 | ド | C6 |  |
| 65 |  | C#6 |  |
| 66 | レ | D6 |  |
| 67 |  | D#6 |  |
| 68 | ミ | E6 |  |
| 69 | ファ | F6 |  |
| 70 |  | F#6 |  |
| 71 | ソ | G6 |  |
| 72 |  | G#6 |  |
| 73 | ラ | A6 |  |
| 74 |  | A#6 |  |
| 75 | シ | B6 |  |
| 76 | ド | C7 |  |
| 77 |  | C#7 |  |
| 78 | レ | D7 |  |
| 79 |  | D#7 |  |
| 80 | ミ | E7 |  |
| 81 | ファ | F7 |  |
| 82 |  | F#7 |  |
| 83 | ソ | G7 |  |
| 84 |  | G#7 |  |
| 85 | ラ | A7 |  |
| 86 |  | A#7 |  |
| 87 | シ | B7 |  |
| 88 | ド | C8 |

C4〜B4を設定することでドレミファソラシと音を出すことができました

```js:cdefgab.js
import Tone from "tone";

const synth = new Tone.Synth().toMaster();

document.body.insertAdjacentHTML("afterbegin", `
    <input type="button" value="ド" id="c">
    <input type="button" value="レ" id="d">
    <input type="button" value="ミ" id="e">
    <input type="button" value="ファ" id="f">
    <input type="button" value="ソ" id="g">
    <input type="button" value="ラ" id="a">
    <input type="button" value="シ" id="b">
    <br>
    <input type="button" value="ド#" id="cs">
`);
c.addEventListener("click", e => synth.triggerAttackRelease("C4", "8n"));
d.addEventListener("click", e => synth.triggerAttackRelease("D4", "8n"));
e.addEventListener("click", e => synth.triggerAttackRelease("E4", "8n"));
f.addEventListener("click", e => synth.triggerAttackRelease("F4", "8n"));
g.addEventListener("click", e => synth.triggerAttackRelease("G4", "8n"));
a.addEventListener("click", e => synth.triggerAttackRelease("A4", "8n"));
b.addEventListener("click", e => synth.triggerAttackRelease("B4", "8n"));
cs.addEventListener("click", e => synth.triggerAttackRelease("C#4", "8n"));
```

<blockquote class="twitter-tweet" data-lang="en"><p lang="und" dir="ltr"><a href="https://t.co/Hi9oGOyxDH">pic.twitter.com/Hi9oGOyxDH</a></p>&mdash; 奥村健吾 (@okumurakengo) <a href="https://twitter.com/okumurakengo/status/1114824250047619072?ref_src=twsrc%5Etfw">April 7, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


## `8分音符` とは?

音楽の初心者のためここでもつまづきました。


以下のサイトを見るととても参考になりました

- [音符の長さ(音価) - 楽譜の読み方 - リガラボ](http://lab.rygasound.com/navi/%E9%9F%B3%E7%AC%A6%E3%81%AE%E9%95%B7%E3%81%95%E9%9F%B3%E4%BE%A1/)
- [付点・3連符・リズム - 楽譜の読み方 - リガラボ](http://lab.rygasound.com/navi/%E4%BB%98%E7%82%B9-3%E9%80%A3%E7%AC%A6-%E3%83%AA%E3%82%BA%E3%83%A0/)

![新規プロジェクト.png](https://qiita-image-store.s3.amazonaws.com/0/142910/990d4b99-18cc-32ba-216b-6896ec1ee78a.png)

参考サイト引用です

> 一番上にあるのがすべての音符の基礎となる、一番長い全音符（ぜんおんぷ）です。その全音符を主として、そこから音符の長さを2分割していきます。

> 全音符が1だとすると、その半分が2分音符(にぶおんぷ)、2分音符の半分が4分音符(しぶおんぷ)。つまり、4分音符は全音符の4分の1ということになります。

実際に音を鳴らすと違いがよくわかりました

```js:note.js
import Tone from "tone";

const synth = new Tone.Synth().toMaster();

document.body.insertAdjacentHTML("afterbegin", `
    <input type="button" value="全音符" id="note">
    <input type="button" value="2分音符" id="halfNote">
    <input type="button" value="4分音符" id="quarterNote">
    <input type="button" value="8分音符" id="eighthNote">
    <input type="button" value="16分音符" id="sixteen">
`);
note.addEventListener("click", e => synth.triggerAttackRelease("C4", "1n"));
halfNote.addEventListener("click", e => synth.triggerAttackRelease("C4", "2n"));
quarterNote.addEventListener("click", e => synth.triggerAttackRelease("C4", "4n"));
eighthNote.addEventListener("click", e => synth.triggerAttackRelease("C4", "8n"));
sixteen.addEventListener("click", e => synth.triggerAttackRelease("C4", "16n"));
```

<blockquote class="twitter-tweet" data-lang="en"><p lang="und" dir="ltr"><a href="https://t.co/X6Vf95YZ10">pic.twitter.com/X6Vf95YZ10</a></p>&mdash; 奥村健吾 (@okumurakengo) <a href="https://twitter.com/okumurakengo/status/1114834263784939521?ref_src=twsrc%5Etfw">April 7, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


## 繰り返し実行する

```js:loops.js
import Tone from "tone";

const synth = new Tone.Synth().toMaster();

const notes = [
    "C4", "E4", "G4",
    "C5", "E5", "G5",
];
let index = 0;

Tone.Transport.scheduleRepeat(time => {
    let note = notes[index % notes.length];
    synth.triggerAttackRelease(note, "8n", time);
    index++;
}, "8n");

document.querySelector("[type=button]").addEventListener("click", e => {
    Tone.Transport.start();

    setTimeout(() => {
        Tone.Transport.stop();
    }, 5000);
});
```

<blockquote class="twitter-tweet" data-lang="en"><p lang="und" dir="ltr"><a href="https://t.co/ujGQfyGPlu">pic.twitter.com/ujGQfyGPlu</a></p>&mdash; 奥村健吾 (@okumurakengo) <a href="https://twitter.com/okumurakengo/status/1114843222474276864?ref_src=twsrc%5Etfw">April 7, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## 順に音を鳴らす

```js:sequence.js
import Tone from "tone";

var synth = new Tone.Synth().toMaster();
var seq = new Tone.Sequence((time, note) => {
    synth.triggerAttackRelease(note, "4n", time);
}, ["C4", "E4", "G4", "B4", "D5"], "4n").start(0);
seq.loop = false;

document.querySelector("[type=button]").addEventListener("click", e => {
    Tone.Transport.start();
});
```

<blockquote class="twitter-tweet" data-lang="en"><p lang="und" dir="ltr"><a href="https://t.co/nJKu2YTWSp">pic.twitter.com/nJKu2YTWSp</a></p>&mdash; 奥村健吾 (@okumurakengo) <a href="https://twitter.com/okumurakengo/status/1114847740331061249?ref_src=twsrc%5Etfw">April 7, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


# 簡単に作曲することができたチュートリアル

こちらの参考サイトが素晴らしかったのでそのままやらせていただきました
音楽の知識がない私が試したという内容ですので、誤りがありましたらご指摘お願いします:bow:
**本当に素晴らしいので、私の記事はみなくても、こちらの参考ページだけでもみていただければと:muscle:**

- [作曲のしかた #1.メロディーの作り方 | 一夜漬け音楽理論](https://riron.sitefactory.info/0401.html)

> まずは音階を無視して音符の長さだけを考えて適当に1小節作ってみます。
> 例えば「タン タン タ タ タン」という至って普通のリズムです。

```js
import Tone from "tone";

const synth = new Tone.Synth().toMaster();

const data = [
    { note: "E4", dur: "4n" },
    { note: "E4", dur: "4n" },
    [{ note: "E4", dur: "8n" }, { note: "E4", dur: "8n" }],
    { note: "E4", dur: "4n" },
];

const seq = new Tone.Sequence((time, { note, dur }) => {
    synth.triggerAttackRelease(note, dur, time);
}, data, "4n").start(0);
seq.loop = false;

document.querySelector("[type=button]").addEventListener("click", e => {
    Tone.Transport.start();
});
```

<blockquote class="twitter-tweet" data-lang="en"><p lang="und" dir="ltr"><a href="https://t.co/AuR9XaTWfm">pic.twitter.com/AuR9XaTWfm</a></p>&mdash; 奥村健吾 (@okumurakengo) <a href="https://twitter.com/okumurakengo/status/1114850019327139840?ref_src=twsrc%5Etfw">April 7, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


> 次はそのメロディーに音階を付けていきます。
> 別に凝った事をする必要はありませんので簡単に付けていきましょう。

```js
const data = [
    { note: "E4", dur: "4n" },
    { note: "E4", dur: "4n" },
    [{ note: "E4", dur: "8n" }, { note: "F4", dur: "8n" }],
    { note: "G4", dur: "4n" },
];

const seq = new Tone.Sequence((time, { note, dur }) => {
    synth.triggerAttackRelease(note, dur, time);
}, data, "4n").start(0);
```

<blockquote class="twitter-tweet" data-lang="en"><p lang="und" dir="ltr"><a href="https://t.co/FtrM3ssenP">pic.twitter.com/FtrM3ssenP</a></p>&mdash; 奥村健吾 (@okumurakengo) <a href="https://twitter.com/okumurakengo/status/1114850496127176704?ref_src=twsrc%5Etfw">April 7, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

> これで1小節のメロディーが出来ました。
> 次はそのメロディーを4回くり返して聴いてみます。

```js
const data = [
    { note: "E4", dur: "4n" },
    { note: "E4", dur: "4n" },
    [{ note: "E4", dur: "8n" }, { note: "F4", dur: "8n" }],
    { note: "G4", dur: "4n" },

    { note: "E4", dur: "4n" },
    { note: "E4", dur: "4n" },
    [{ note: "E4", dur: "8n" }, { note: "F4", dur: "8n" }],
    { note: "G4", dur: "4n" },

    { note: "E4", dur: "4n" },
    { note: "E4", dur: "4n" },
    [{ note: "E4", dur: "8n" }, { note: "F4", dur: "8n" }],
    { note: "G4", dur: "4n" },

    { note: "E4", dur: "4n" },
    { note: "E4", dur: "4n" },
    [{ note: "E4", dur: "8n" }, { note: "F4", dur: "8n" }],
    { note: "G4", dur: "4n" },
];

const seq = new Tone.Sequence((time, { note, dur }) => {
    synth.triggerAttackRelease(note, dur, time);
}, data, "4n").start(0);
```

<blockquote class="twitter-tweet" data-lang="en"><p lang="und" dir="ltr"><a href="https://t.co/3W0mkeMm2R">pic.twitter.com/3W0mkeMm2R</a></p>&mdash; 奥村健吾 (@okumurakengo) <a href="https://twitter.com/okumurakengo/status/1114851133581742080?ref_src=twsrc%5Etfw">April 7, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


> 4 回目を変えたくなりませんか？
> というわけで4小節目を変えてみます。

```js
const data = [
    { note: "E4", dur: "4n" },
    { note: "E4", dur: "4n" },
    [{ note: "E4", dur: "8n" }, { note: "F4", dur: "8n" }],
    { note: "G4", dur: "4n" },

    { note: "E4", dur: "4n" },
    { note: "E4", dur: "4n" },
    [{ note: "E4", dur: "8n" }, { note: "F4", dur: "8n" }],
    { note: "G4", dur: "4n" },

    { note: "E4", dur: "4n" },
    { note: "E4", dur: "4n" },
    [{ note: "E4", dur: "8n" }, { note: "F4", dur: "8n" }],
    [{ note: "G4", dur: "8n" }, { note: "C5", dur: "2n" }],
];

const seq = new Tone.Sequence((time, { note, dur }) => {
    synth.triggerAttackRelease(note, dur, time);
}, data, "4n").start(0);
```

<blockquote class="twitter-tweet" data-lang="en"><p lang="und" dir="ltr"><a href="https://t.co/lawPQcXvcx">pic.twitter.com/lawPQcXvcx</a></p>&mdash; 奥村健吾 (@okumurakengo) <a href="https://twitter.com/okumurakengo/status/1114852598077480960?ref_src=twsrc%5Etfw">April 7, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

> これだけで急にメロディーっぽくなりますね。
> 次は2小節目を変えてみましょうか。
> 4小節目をちょっと変化させた形です。

```js
const data = [
    { note: "E4", dur: "4n" },
    { note: "E4", dur: "4n" },
    [{ note: "E4", dur: "8n" }, { note: "F4", dur: "8n" }],
    [{ note: "G4", dur: "8n" }, { note: "C5", dur: "2n" }],

    null,
    [null, { note: "D5", dur: "8n" }],
    { note: "C5", dur: "2n" },
    null,

    { note: "E4", dur: "4n" },
    { note: "E4", dur: "4n" },
    [{ note: "E4", dur: "8n" }, { note: "F4", dur: "8n" }],
    [{ note: "G4", dur: "8n" }, { note: "C5", dur: "2n" }],
];

const seq = new Tone.Sequence((time, { note, dur }) => {
    synth.triggerAttackRelease(note, dur, time);
}, data, "4n").start(0);
```

<blockquote class="twitter-tweet" data-lang="en"><p lang="und" dir="ltr"><a href="https://t.co/0xRQ6BAD9F">pic.twitter.com/0xRQ6BAD9F</a></p>&mdash; 奥村健吾 (@okumurakengo) <a href="https://twitter.com/okumurakengo/status/1114853902006927362?ref_src=twsrc%5Etfw">April 7, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


> なかなか良い感じになりました。
> さらに3小節目を変えてみます。

```js
const data = [
    { note: "E4", dur: "4n" },
    { note: "E4", dur: "4n" },
    [{ note: "E4", dur: "8n" }, { note: "F4", dur: "8n" }],
    [{ note: "G4", dur: "8n" }, { note: "C5", dur: "2n" }],

    null,
    [null, { note: "D5", dur: "8n" }],
    { note: "C5", dur: "2n" },
    null,

    { note: "B4", dur: "4n" },
    { note: "B4", dur: "4n" },
    [{ note: "B4", dur: "8n" }, { note: "A4", dur: "8n" }],
    [{ note: "B4", dur: "8n" }, { note: "C5", dur: "2n" }],
];

const seq = new Tone.Sequence((time, { note, dur }) => {
    synth.triggerAttackRelease(note, dur, time);
}, data, "4n").start(0);
```

<blockquote class="twitter-tweet" data-lang="en"><p lang="und" dir="ltr"><a href="https://t.co/Pj5xEZrcdq">pic.twitter.com/Pj5xEZrcdq</a></p>&mdash; 奥村健吾 (@okumurakengo) <a href="https://twitter.com/okumurakengo/status/1114855729075122176?ref_src=twsrc%5Etfw">April 7, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

> 全体的に見て細かい修正をして完成。

```js
const data = [
    { note: "E4", dur: "2n" },
    null,
    [{ note: "E4", dur: "8n" }, { note: "F4", dur: "8n" }],
    [{ note: "G4", dur: "8n" }, { note: "C5", dur: "2n" }],

    null,
    [null, { note: "D5", dur: "8n" }],
    { note: "C5", dur: "2n" },
    null,

    null,
    { note: "B4", dur: "4n" },
    [{ note: "B4", dur: "8n" }, { note: "A4", dur: "8n" }],
    [{ note: "B4", dur: "8n" }, { note: "C5", dur: "2n" }],
];

const seq = new Tone.Sequence((time, { note, dur }) => {
    synth.triggerAttackRelease(note, dur, time);
}, data, "4n").start(0);
seq.loop = false;
Tone.Transport.bpm.value = 150;
```

<blockquote class="twitter-tweet" data-lang="en"><p lang="und" dir="ltr"><a href="https://t.co/9TMgHzrMrw">pic.twitter.com/9TMgHzrMrw</a></p>&mdash; 奥村健吾 (@okumurakengo) <a href="https://twitter.com/okumurakengo/status/1114857505929064448?ref_src=twsrc%5Etfw">April 7, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

本当に素晴らしい解説でした、ありがとうございました:bow:

# 作成した曲をダウンロードする

参考

- [Tone.js & CodePen Part 07: Recording Tone in an Audio File - youtube](https://www.youtube.com/watch?v=VHCv3waFkRo&t=24s)

参考サイトのまんまですが、こちらも共有させていただきます!

```index.html
    <input type="button" value="play!">
    <audio controls></audio>
```

```js:download.js
import Tone from "tone";

const audio = document.querySelector("audio");
const synth = new Tone.Synth().toMaster();
const actx  = Tone.context;
const dest  = actx.createMediaStreamDestination();
const recorder = new MediaRecorder(dest.stream);

synth.connect(dest);

const chunks = [];

const notes = "CDEFGAB".split("").map(n=>`${n}4`);
let note = 0;
Tone.Transport.scheduleRepeat(time => {
    if (note === 0) {
        recorder.start();
    }
    if (note > notes.length) {
        synth.triggerRelease(time);
        recorder.stop();
        Tone.Transport.stop();
    } else {
        synth.triggerAttack(notes[note], time);
    }
    note++;
}, "4n");

recorder.ondataavailable = evt => chunks.push(evt.data);
recorder.onstop = evt => {
    let blob = new Blob(chunks, { type: "audio/ogg: codecs=opus" })
    audio.src = URL.createObjectURL(blob);
};

document.querySelector("[type=button]").addEventListener("click", e => {
    Tone.Transport.start();
});
```

<blockquote class="twitter-tweet" data-lang="en"><p lang="und" dir="ltr"><a href="https://t.co/rAZ8L09RgP">pic.twitter.com/rAZ8L09RgP</a></p>&mdash; 奥村健吾 (@okumurakengo) <a href="https://twitter.com/okumurakengo/status/1114862794526973952?ref_src=twsrc%5Etfw">April 7, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

audioタグにblob形式で保存して、ブラウザの機能でダウンロードするということのようです

![image.png](https://qiita-image-store.s3.amazonaws.com/0/142910/e1dba2c6-4313-574c-d1b8-01225f9231cf.png)

---

最後まで読んでいただいてありがとうございましたm(_ _)m