TypeScript/React/Tone.jsでダイアトニックコード進行トレーニングアプリを作る #1

先人達が様々な音感トレーニングアプリを作成してくれているが、私が求めているトレーニング内容のものが見つからない。

音楽アプリの開発について調べたところTone.jsというライブラリが便利そうなので、TypeScript/Reactの勉強がてら自作してみることにした。音楽、プログラミングのトレーニングが出来て一石二鳥。

一旦メジャー・マイナーダイアトニックコードの表示・再生までは実装できた。
時間があるときにクイズ形式の機能も作成予定。

実際のアプリは下記URL。
keyと、メジャーかマイナーかを選択するとダイアトニックコード一覧が表示され、再生もできる。音の範囲は1オクターブのみにした。
結構アレなデザインだが、この辺りも今後勉強していければと思う。
https://haaan1234.github.io/DChordApp/

# 使ったもの
**・VScode**
**・TypeScript**
**・Node.js**&nbsp;&nbsp;https://github.com/nodejs/node/blob/main/LICENSE
**・React**&nbsp;&nbsp;Copyright (c) Meta Platforms, Inc. and affiliates.
**・Tone.js**&nbsp;&nbsp;Copyright (c) 2014-2020 Yotam Mann
**・MUI** &nbsp;&nbsp;Copyright © 2024 Material-UI.

# 前提
`create react-app　～ --template typescript`
などでプロジェクト作成まで済んでいること

# 各種インストール
**MUI**
 `yarn add @mui/material @emotion/react @emotion/styled`

 **Tone.js**
 ` yarn add tone`

 # 実装
 初めてTypecript/Reactに触れたが、親コンポーネント・子コンポーネント間のやり取りのイメージを掴むまで苦労した。。パッと作れるようにはなるまでは時間がかかりそう。

 以下、まずは主要なソース全文。クリックで開けます。

<details><summary>App.tsx（親）　画面表示などの主要な処理実施</summary><div>

```ruby:App.tsx
import { useState } from "react"
import { MakeDChords } from "./logic"
import Box from '@mui/material/Box';
import Grid from '@mui/material/Grid';
import React from "react";
import { FormControl, InputLabel, MenuItem, Select, SelectChangeEvent } from "@mui/material";


export default function App() {
import { useState } from "react"
import { MakeDChords } from "./logic"
import Box from '@mui/material/Box';
import Grid from '@mui/material/Grid';
import React from "react";
import { FormControl, InputLabel, MenuItem, Select, SelectChangeEvent } from "@mui/material";


export default function App() {
  //key選択状況を保持
  const [key, setKey] = React.useState(0);
  //keyが選択されたときに処理実行
  const keyChange = (event: SelectChangeEvent) => {
    setKey(Number(event.target.value as string));
  };

  //Maj/min選択状況を保持
  const [Mm, setMm] = React.useState(0);
  //Maj/minが選択されたときに処理実行
  const MmChange = (event: SelectChangeEvent) => {
    setMm(Number(event.target.value as string));
  };

  return (
    <Grid container
      direction="row"
      alignContent="center"
      justifyContent="center"
      sx={{ minHeight: "50vh" }}
    > <Grid item xs={0}>
        <FormControl fullWidth>
          <InputLabel id="key">key</InputLabel>
          <Select
            labelId="key"
            id="key"
            label="key"
            onChange={keyChange}
          >
            <MenuItem value={0}>C</MenuItem>
            <MenuItem value={1}>D♭</MenuItem>
            <MenuItem value={2}>D</MenuItem>
            <MenuItem value={3}>E♭</MenuItem>
            <MenuItem value={4}>E</MenuItem>
            <MenuItem value={5}>F</MenuItem>
            <MenuItem value={6}>G♭</MenuItem>
            <MenuItem value={7}>G</MenuItem>
            <MenuItem value={8}>A♭</MenuItem>
            <MenuItem value={9}>A</MenuItem>
            <MenuItem value={10}>B♭</MenuItem>
            <MenuItem value={11}>B</MenuItem>
          </Select>
        </FormControl>
      </Grid>
      <Grid item xs={0}>
        <FormControl>
          <InputLabel id="Mm">maj/min</InputLabel>
          <Select
            labelId="Mm"
            id="Mm"
            label="Mm"
            onChange={MmChange}  >
            <MenuItem value={0}>maj</MenuItem>
            <MenuItem value={1}>min</MenuItem>
          </Select>
        </FormControl>
        <MakeDChords dkey={key} Mm={Mm} />
      </Grid>
      <Grid item xs={12}>

      </Grid>
    </Grid>
  )
}
```
</div></details>

 <details><summary>logic.tsx（子）　音階などを保持し、ダイアトニックコードを作成する。App.tsxに結果を返す</summary><div>

```ruby:logic.tsx
import styled from "@emotion/styled";
import Button from "@mui/material/Button";
import ButtonGroup from "@mui/material/ButtonGroup";
import React, { MouseEventHandler } from "react"
import * as Tone from 'tone'

//鍵盤音（1オクターブのみ）
const tone = ["C4", "C#4", "D4", "D#4", "E4", "F4", "F#4", "G4", "G#4", "A4", "A#4", "B4", "C4", "C#4", "D4", "D#4", "E4", "F4", "F#4", "G4", "G#4", "A4", "A#4", "B4", "C4", "C#4", "D4", "D#4", "E4", "F4", "F#4", "G4", "G#4", "A4", "A#4", "B4", "C4", "C#4", "D4", "D#4", "E4", "F4", "F#4", "G4", "G#4", "A4", "A#4", "B4"];

//メジャーダイアトニックコード
const MdChords = [
    ["C", "Dm", "Em", "F", "G", "Am", "Bm(♭5)"],
    ["D♭", "E♭m", "Fm", "G♭", "A♭", "B♭m", "Cm(♭5)"],
    ["D", "Em", "F#m", "G", "A", "Bm", "C#m(♭5)"],
    ["E♭", "Fm", "Gm", "A♭", "B♭", "Cm", "Dm(♭5)"],
    ["E", "F#m", "G#m", "A", "B", "C#m", "D#m(♭5)"],
    ["F", "Gm", "Am", "B♭", "C", "Dm", "Em(♭5)"],
    ["G♭", "A♭m", "B♭m", "C♭", "D♭", "E♭m", "Fm(♭5)"],
    ["G", "Am", "Bm", "C", "D", "Em", "F#m(♭5)"],
    ["A♭", "B♭m", "Cm", "D♭", "E♭", "Fm", "Gm(♭5)"],
    ["A", "Bm", "C#m", "D", "E", "F#m", "G#m(♭5)"],
    ["B♭", "Cm", "Dm", "E♭", "F", "Gm", "Am(♭5)"],
    ["B", "C#m", "D#m", "E", "F#", "G#m", "A#m(♭5)"]
]

//マイナーダイアトニックコード
const mDChords = [
    ["Cm", "Dm♭5", "E♭", "Fm", "Gm", "G#", "B♭"],
    ["D♭m", "E♭m♭5", "E", "F#m", "G#m", "A", "B"],
    ["Dm", "Em♭5", "F", "Gm", "Am", "B♭", "C"],
    ["E♭m", "Fm♭5", "F#", "G#m", "B♭m", "B", "C#"],
    ["Em", "F#m♭5", "G", "Am", "Bm", "C", "D"],
    ["Fm", "Gm♭5", "G#", "B♭m", "Cm", "C#", "E♭"],
    ["G♭m", "G#m♭5", "A", "Bm", "C#m", "D", "E"],
    ["Gm", "Am♭5", "B♭", "Cm", "Dm", "E♭", "F"],
    ["A♭m", "B♭m♭5", "B", "C#m", "E♭m", "E", "F#"],
    ["Am", "Bm♭5", "C", "Dm", "Em", "F", "G"],
    ["B♭m", "Cm♭5", "C#", "E♭m", "Fm", "F#", "G#"],
    ["Bm", "C#m♭5", "D", "Em", "F#m", "G", "A"]
]

//全ダイアトニックコード
const dChords: string[][][] = [
    MdChords,
    mDChords
]

type Props = {
    dkey: number,
    Mm: number
}

//音源接続
var synth = new Tone.PolySynth().toMaster();

//ボタン表記が大文字になるのを防ぐ
const TextButton = styled(Button)`
  text-transform: none;
`;


export const MakeDChords = (props: Props) => {
    if (props.Mm === 0) {
        var Ⅰ_chord = [tone[props.dkey], tone[props.dkey + 4], tone[props.dkey + 7]];
        var Ⅱ_Chord = [tone[props.dkey + 2], tone[props.dkey + 5], tone[props.dkey + 9]];
        var Ⅲ_chord = [tone[props.dkey + 4], tone[props.dkey + 7], tone[props.dkey + 11]];
        var Ⅳ_chord = [tone[props.dkey + 5], tone[props.dkey + 9], tone[props.dkey + 12]];
        var Ⅴ_chord = [tone[props.dkey + 7], tone[props.dkey + 11], tone[props.dkey + 14]];
        var Ⅵ_chord = [tone[props.dkey + 9], tone[props.dkey + 12], tone[props.dkey + 16]];
        var Ⅶ_chord = [tone[props.dkey + 11], tone[props.dkey + 14], tone[props.dkey + 17]];

        return (<ButtonGroup size="large" aria-label="Large button group">
            <TextButton key="one" onClick={() => { synth.triggerAttackRelease(Ⅰ_chord, '4n'); }}>{dChords[props.Mm][props.dkey][0]}{"\n"}Ⅰ</TextButton>,
            <TextButton key="two" onClick={() => { synth.triggerAttackRelease(Ⅱ_Chord, '4n'); }}>{dChords[props.Mm][props.dkey][1]}{"\n"}Ⅱ</TextButton>,
            <TextButton key="three" onClick={() => { synth.triggerAttackRelease(Ⅲ_chord, '4n'); }}>{dChords[props.Mm][props.dkey][2]}{"\n"}Ⅲ</TextButton>,
            <TextButton key="four" onClick={() => { synth.triggerAttackRelease(Ⅳ_chord, '4n'); }}>{dChords[props.Mm][props.dkey][3]}{"\n"}Ⅳ</TextButton>,
            <TextButton key="five" onClick={() => { synth.triggerAttackRelease(Ⅴ_chord, '4n'); }}>{dChords[props.Mm][props.dkey][4]}{"\n"}Ⅴ</TextButton>,
            <TextButton key="six" onClick={() => { synth.triggerAttackRelease(Ⅵ_chord, '4n'); }}>{dChords[props.Mm][props.dkey][5]}{"\n"}Ⅵ</TextButton>,
            <TextButton key="seven" onClick={() => { synth.triggerAttackRelease(Ⅶ_chord, '4n'); }}>{dChords[props.Mm][props.dkey][6]}{"\n"}Ⅶ</TextButton>
        </ButtonGroup>
        )
    } else {
        var Ⅰ_chord = [tone[props.dkey], tone[props.dkey + 3], tone[props.dkey + 7]];
        var Ⅱ_Chord = [tone[props.dkey + 2], tone[props.dkey + 5], tone[props.dkey + 8]];
        var Ⅲ_chord = [tone[props.dkey + 3], tone[props.dkey + 7], tone[props.dkey + 10]];
        var Ⅳ_chord = [tone[props.dkey + 5], tone[props.dkey + 8], tone[props.dkey + 12]];
        var Ⅴ_chord = [tone[props.dkey + 7], tone[props.dkey + 10], tone[props.dkey + 14]];
        var Ⅵ_chord = [tone[props.dkey + 8], tone[props.dkey + 12], tone[props.dkey + 15]];
        var Ⅶ_chord = [tone[props.dkey + 10], tone[props.dkey + 14], tone[props.dkey + 17]];

        return (
            <ButtonGroup size="large" aria-label="Large button group">
                <TextButton key="one" onClick={() => { synth.triggerAttackRelease(Ⅰ_chord, '4n'); }}>{dChords[props.Mm][props.dkey][0]}{"\n"}Ⅰ</TextButton>,
                <TextButton key="two" onClick={() => { synth.triggerAttackRelease(Ⅱ_Chord, '4n'); }}>{dChords[props.Mm][props.dkey][1]}{"\n"}Ⅱ</TextButton>,
                <TextButton key="three" onClick={() => { synth.triggerAttackRelease(Ⅲ_chord, '4n'); }}>{dChords[props.Mm][props.dkey][2]}{"\n"}Ⅲ</TextButton>,
                <TextButton key="four" onClick={() => { synth.triggerAttackRelease(Ⅳ_chord, '4n'); }}>{dChords[props.Mm][props.dkey][3]}{"\n"}Ⅳ</TextButton>,
                <TextButton key="five" onClick={() => { synth.triggerAttackRelease(Ⅴ_chord, '4n'); }}>{dChords[props.Mm][props.dkey][4]}{"\n"}Ⅴ</TextButton>,
                <TextButton key="six" onClick={() => { synth.triggerAttackRelease(Ⅵ_chord, '4n'); }}>{dChords[props.Mm][props.dkey][5]}{"\n"}Ⅵ</TextButton>,
                <TextButton key="seven" onClick={() => { synth.triggerAttackRelease(Ⅶ_chord, '4n'); }}>{dChords[props.Mm][props.dkey][6]}{"\n"}Ⅶ</TextButton>
            </ButtonGroup>
        )
    }
}
```

</div></details>

## App.tsx
```ruby:App.tsx
  //key選択状況を保持
  const [key, setKey] = React.useState(0);
  //keyが選択されたときに処理実行
  const keyChange = (event: SelectChangeEvent) => {
    setKey(Number(event.target.value as string));
  };

  //Maj/min選択状況を保持
  const [Mm, setMm] = React.useState(0);
  //Maj/minが選択されたときに処理実行
  const MmChange = (event: SelectChangeEvent) => {
    setMm(Number(event.target.value as string));
  };
```
key（調）とMm（メジャーキーかマイナーキーか）の選択状況を保持し、select状況が変更されるイベントが起きるたびに新しい選択をsetする。
<br>
<br>
```ruby:App.tsx
 return (
    <Grid container
      direction="row"
      alignContent="center"
      justifyContent="center"
      sx={{ minHeight: "50vh" }}
    > <Grid item xs={0}>
        <FormControl fullWidth>
          <InputLabel id="key">key</InputLabel>
          <Select
            labelId="key"
            id="key"
            label="key"
            onChange={keyChange}
          >
            <MenuItem value={0}>C</MenuItem>
            <MenuItem value={1}>D♭</MenuItem>
            <MenuItem value={2}>D</MenuItem>
            <MenuItem value={3}>E♭</MenuItem>
            <MenuItem value={4}>E</MenuItem>
            <MenuItem value={5}>F</MenuItem>
            <MenuItem value={6}>G♭</MenuItem>
            <MenuItem value={7}>G</MenuItem>
            <MenuItem value={8}>A♭</MenuItem>
            <MenuItem value={9}>A</MenuItem>
            <MenuItem value={10}>B♭</MenuItem>
            <MenuItem value={11}>B</MenuItem>
          </Select>
        </FormControl>
      </Grid>
      <Grid item xs={0}>
        <FormControl>
          <InputLabel id="Mm">maj/min</InputLabel>
          <Select
            labelId="Mm"
            id="Mm"
            label="Mm"
            onChange={MmChange}  >
            <MenuItem value={0}>maj</MenuItem>
            <MenuItem value={1}>min</MenuItem>
          </Select>
        </FormControl>
        <MakeDChords dkey={key} Mm={Mm} />
      </Grid>
      <Grid item xs={12}>

      </Grid>
    </Grid>

  )
```

keyとMmのselectボックスを表示している。
 `onChange={keyChange}`
 `onChange={MmChange}`
 でselect状況が更新された際の処理を呼んでいる。
 <br>
  `<MakeDChords dkey={key} Mm={Mm} /> `
  では、logic.tsx（子）に親としてkeyとMmが何を選択されているかのvalueをpropsで送る。

  ## logic.tsx
```ruby:logic.tsx
//鍵盤音（1オクターブのみ）
const tone = ["C4", "C#4", "D4", "D#4", "E4", "F4", "F#4", "G4", "G#4", "A4", "A#4", "B4", "C4", "C#4", "D4", "D#4", "E4", "F4", "F#4", "G4", "G#4", "A4", "A#4", "B4", "C4", "C#4", "D4", "D#4", "E4", "F4", "F#4", "G4", "G#4", "A4", "A#4", "B4", "C4", "C#4", "D4", "D#4", "E4", "F4", "F#4", "G4", "G#4", "A4", "A#4", "B4"];

//メジャーダイアトニックコード
const MdChords = [
    ["C", "Dm", "Em", "F", "G", "Am", "Bm(♭5)"],
    ["D♭", "E♭m", "Fm", "G♭", "A♭", "B♭m", "Cm(♭5)"],
    ["D", "Em", "F#m", "G", "A", "Bm", "C#m(♭5)"],
    ["E♭", "Fm", "Gm", "A♭", "B♭", "Cm", "Dm(♭5)"],
    ["E", "F#m", "G#m", "A", "B", "C#m", "D#m(♭5)"],
    ["F", "Gm", "Am", "B♭", "C", "Dm", "Em(♭5)"],
    ["G♭", "A♭m", "B♭m", "C♭", "D♭", "E♭m", "Fm(♭5)"],
    ["G", "Am", "Bm", "C", "D", "Em", "F#m(♭5)"],
    ["A♭", "B♭m", "Cm", "D♭", "E♭", "Fm", "Gm(♭5)"],
    ["A", "Bm", "C#m", "D", "E", "F#m", "G#m(♭5)"],
    ["B♭", "Cm", "Dm", "E♭", "F", "Gm", "Am(♭5)"],
    ["B", "C#m", "D#m", "E", "F#", "G#m", "A#m(♭5)"]
]

//マイナーダイアトニックコード
const mDChords = [
    ["Cm", "Dm♭5", "E♭", "Fm", "Gm", "G#", "B♭"],
    ["D♭m", "E♭m♭5", "E", "F#m", "G#m", "A", "B"],
    ["Dm", "Em♭5", "F", "Gm", "Am", "B♭", "C"],
    ["E♭m", "Fm♭5", "F#", "G#m", "B♭m", "B", "C#"],
    ["Em", "F#m♭5", "G", "Am", "Bm", "C", "D"],
    ["Fm", "Gm♭5", "G#", "B♭m", "Cm", "C#", "E♭"],
    ["G♭m", "G#m♭5", "A", "Bm", "C#m", "D", "E"],
    ["Gm", "Am♭5", "B♭", "Cm", "Dm", "E♭", "F"],
    ["A♭m", "B♭m♭5", "B", "C#m", "E♭m", "E", "F#"],
    ["Am", "Bm♭5", "C", "Dm", "Em", "F", "G"],
    ["B♭m", "Cm♭5", "C#", "E♭m", "Fm", "F#", "G#"],
    ["Bm", "C#m♭5", "D", "Em", "F#m", "G", "A"]
]

//全ダイアトニックコード
const dChords: string[][][] = [
    MdChords,
    mDChords
]

```
toneにC4～B4の音を繰り返し入れている。
1オクターブ分の鍵盤が横にずっと並んでいると考えればイメージしやすいかも。

ダイアトニックコード名に関してはコードの通りで、配列に入れて管理。
<br>

```ruby:logic.tsx

type Props = {
    dkey: number,
    Mm: number
}

//音源接続
var synth = new Tone.PolySynth().toMaster();

//ボタン表記が大文字になるのを防ぐ
const TextButton = styled(Button)`
  text-transform: none;
`;

```

type Propsで、App.tsx（親）から渡されてくるkeyとMmの型を指定。ここをちゃんと合わせないとエラーになる。

Tone.PolySynth().toMaster()でTone.jsの音を使用する。
今回はコード（和音）なのでPolySynth()を使用

MUIがボタン名の英字を勝手に大文字にしてくるので、スタイル指定用のコード記載。


```ruby:logic.tsx

export const MakeDChords = (props: Props) => {
    if (props.Mm === 0) {
        var Ⅰ_chord = [tone[props.dkey], tone[props.dkey + 4], tone[props.dkey + 7]];
        var Ⅱ_Chord = [tone[props.dkey + 2], tone[props.dkey + 5], tone[props.dkey + 9]];
        var Ⅲ_chord = [tone[props.dkey + 4], tone[props.dkey + 7], tone[props.dkey + 11]];
        var Ⅳ_chord = [tone[props.dkey + 5], tone[props.dkey + 9], tone[props.dkey + 12]];
        var Ⅴ_chord = [tone[props.dkey + 7], tone[props.dkey + 11], tone[props.dkey + 14]];
        var Ⅵ_chord = [tone[props.dkey + 9], tone[props.dkey + 12], tone[props.dkey + 16]];
        var Ⅶ_chord = [tone[props.dkey + 11], tone[props.dkey + 14], tone[props.dkey + 17]];

        return (<ButtonGroup size="large" aria-label="Large button group">
            <TextButton key="one" onClick={() => { synth.triggerAttackRelease(Ⅰ_chord, '4n'); }}>{dChords[props.Mm][props.dkey][0]}{"\n"}Ⅰ</TextButton>,
            <TextButton key="two" onClick={() => { synth.triggerAttackRelease(Ⅱ_Chord, '4n'); }}>{dChords[props.Mm][props.dkey][1]}{"\n"}Ⅱ</TextButton>,
            <TextButton key="three" onClick={() => { synth.triggerAttackRelease(Ⅲ_chord, '4n'); }}>{dChords[props.Mm][props.dkey][2]}{"\n"}Ⅲ</TextButton>,
            <TextButton key="four" onClick={() => { synth.triggerAttackRelease(Ⅳ_chord, '4n'); }}>{dChords[props.Mm][props.dkey][3]}{"\n"}Ⅳ</TextButton>,
            <TextButton key="five" onClick={() => { synth.triggerAttackRelease(Ⅴ_chord, '4n'); }}>{dChords[props.Mm][props.dkey][4]}{"\n"}Ⅴ</TextButton>,
            <TextButton key="six" onClick={() => { synth.triggerAttackRelease(Ⅵ_chord, '4n'); }}>{dChords[props.Mm][props.dkey][5]}{"\n"}Ⅵ</TextButton>,
            <TextButton key="seven" onClick={() => { synth.triggerAttackRelease(Ⅶ_chord, '4n'); }}>{dChords[props.Mm][props.dkey][6]}{"\n"}Ⅶ</TextButton>
        </ButtonGroup>
        )
    } else {
        var Ⅰ_chord = [tone[props.dkey], tone[props.dkey + 3], tone[props.dkey + 7]];
        var Ⅱ_Chord = [tone[props.dkey + 2], tone[props.dkey + 5], tone[props.dkey + 8]];
        var Ⅲ_chord = [tone[props.dkey + 3], tone[props.dkey + 7], tone[props.dkey + 10]];
        var Ⅳ_chord = [tone[props.dkey + 5], tone[props.dkey + 8], tone[props.dkey + 12]];
        var Ⅴ_chord = [tone[props.dkey + 7], tone[props.dkey + 10], tone[props.dkey + 14]];
        var Ⅵ_chord = [tone[props.dkey + 8], tone[props.dkey + 12], tone[props.dkey + 15]];
        var Ⅶ_chord = [tone[props.dkey + 10], tone[props.dkey + 14], tone[props.dkey + 17]];

        return (
            <ButtonGroup size="large" aria-label="Large button group">
                <TextButton key="one" onClick={() => { synth.triggerAttackRelease(Ⅰ_chord, '4n'); }}>{dChords[props.Mm][props.dkey][0]}{"\n"}Ⅰ</TextButton>,
                <TextButton key="two" onClick={() => { synth.triggerAttackRelease(Ⅱ_Chord, '4n'); }}>{dChords[props.Mm][props.dkey][1]}{"\n"}Ⅱ</TextButton>,
                <TextButton key="three" onClick={() => { synth.triggerAttackRelease(Ⅲ_chord, '4n'); }}>{dChords[props.Mm][props.dkey][2]}{"\n"}Ⅲ</TextButton>,
                <TextButton key="four" onClick={() => { synth.triggerAttackRelease(Ⅳ_chord, '4n'); }}>{dChords[props.Mm][props.dkey][3]}{"\n"}Ⅳ</TextButton>,
                <TextButton key="five" onClick={() => { synth.triggerAttackRelease(Ⅴ_chord, '4n'); }}>{dChords[props.Mm][props.dkey][4]}{"\n"}Ⅴ</TextButton>,
                <TextButton key="six" onClick={() => { synth.triggerAttackRelease(Ⅵ_chord, '4n'); }}>{dChords[props.Mm][props.dkey][5]}{"\n"}Ⅵ</TextButton>,
                <TextButton key="seven" onClick={() => { synth.triggerAttackRelease(Ⅶ_chord, '4n'); }}>{dChords[props.Mm][props.dkey][6]}{"\n"}Ⅶ</TextButton>
            </ButtonGroup>
        )
    }
}


```
ここでApp.tsxに結果をreturn
`export const MakeDChords = (props: Props) => {`
`export`で他のファイルにインポートできるよう宣言。
`props: Props`でApp.tsx（親）からのpropsを受け取る。コロンの後のPropsで型指定。
`if (props.Mm === 0) {`でメジャーかマイナーか判定
<br>
`var Ⅰ_chord　～　var Ⅶ_chord`で現在選ばれているkeyを基にtone配列から音を取り出してダイアトニックコードを作成する。ここはプログラムというよりは音楽よりの話。
<br>

`<TextButton key="one" onClick={() => { synth.triggerAttackRelease(Ⅰ_chord, '4n'); }}>{dChords[props.Mm][props.dkey][0]}{"\n"}Ⅰ</TextButton>,`
→`onClick={() => { synth.triggerAttackRelease(Ⅰ_chord, '4n'); }}`でボタンクリックされたときにコードをどのくらいの長さ再生するかを記載。
`{dChords[props.Mm][props.dkey][0]}{"\n"}Ⅰ`でボタン名にダイアトニックコード名を入れる。※{"\n"}は改行

以上。

 # まとめ
 実装としては以上になります。何かのお役に立てたら幸いです。
 
 今後も機能追加したら記事を書いてみようと思う。
 ↓ソース
 https://github.com/haaan1234/DChordApp