- Published on
abc.js を使ってみた(再生できるようにしてみた編)
- Authors

- Name
- しお
- https://x.com/sgktmk_com
できたこと
ChatGPT と一緒に、楽譜の表示ができるコンポーネントを作った。
X: 1
T: Twinkle, Twinkle, Little Star
M: 4/4
L: 1/4
K: C
%%textfont Times-Roman 14
Q:1/4=120
V:1
C C G G | A A G2 | F F E E | D D C2 |
G G F F | E E D2 | G G F F | E E D2 |
C C G G | A A G2 | F F E E | D D C2 |
やったこと
このコンポーネントを作って mdx ファイルで使用しただけ。
import { useEffect, useRef } from 'react'
import ABCJS from 'abcjs'
const MusicPlayer = ({ abcNotation }) => {
const sheetRef = useRef(null)
useEffect(() => {
if (sheetRef.current) {
ABCJS.renderAbc(sheetRef.current, abcNotation)
}
}, [abcNotation])
const playMusic = () => {
if (ABCJS.synth.supportsAudio()) {
const visualObj = ABCJS.renderAbc(sheetRef.current, abcNotation)
const synthControl = new ABCJS.synth.SynthController()
synthControl.load('#audio', null, {
displayLoop: true,
displayRestart: true,
displayPlay: true,
displayProgress: true,
displayWarp: true,
})
const createSynth = async () => {
const synth = new ABCJS.synth.CreateSynth()
await synth.init({ visualObj: visualObj[0] })
await synth.prime()
synthControl.setTune(visualObj[0], true)
}
createSynth()
} else {
console.error('Audio is not supported in this browser.')
}
}
return (
<div>
<div ref={sheetRef}></div>
<div id="audio"></div>
<button onClick={playMusic}>Play</button>
</div>
)
}
export default MusicPlayer
以下に詳しく解説していきます。
必要なモジュールのインポート
import { useEffect, useRef } from 'react'
import ABCJS from 'abcjs'
useEffect:MusicPlayerコンポーネントのマウント直後や、更新後に副作用を実行するために使用する。- 今回の例では、楽譜の描画 と オーディオプレイヤーの初期化 が副作用にあたる。
useRef: コンポーネント内で DOM 要素や他の変数を参照し、それを保持するために使用する。
コンポーネント定義
const MusicPlayer = ({ abcNotation }) => {
const sheetRef = useRef(null)
MusicPlayerコンポーネントは、abcNotationというプロパティを受け取ることとする。sheetRefは、楽譜を描画するための DOM 要素を参照するために使用する。
useEffect フック
useEffect(() => {
if (sheetRef.current) {
ABCJS.renderAbc(sheetRef.current, abcNotation)
}
}, [abcNotation])
- このフックは、
abcNotationが変更されるたびに実行される。- 現状はブログ記事からの入力を許容していないので要らないかもしれない。
ABCJS.renderAbcを使用して、sheetRef.currentに楽譜を描画する。
playMusic 関数
const playMusic = () => {
if (ABCJS.synth.supportsAudio()) {
const visualObj = ABCJS.renderAbc(sheetRef.current, abcNotation)
const synthControl = new ABCJS.synth.SynthController()
synthControl.load('#audio', null, {
displayLoop: true,
displayRestart: true,
displayPlay: true,
displayProgress: true,
displayWarp: true,
})
const createSynth = async () => {
const synth = new ABCJS.synth.CreateSynth()
await synth.init({ visualObj: visualObj[0] })
await synth.prime()
synthControl.setTune(visualObj[0], true)
}
createSynth()
} else {
console.error('Audio is not supported in this browser.')
}
}
playMusic()は楽譜を再生するための関数。ABCJS.synth.supportsAudio()でオーディオのサポートを事前に確認して分岐する。ABCJS.renderAbcで楽譜を再度描画する。ABCJS.synth.SynthControllerを使用して、プレイヤーコントロールを作成する。オプションは下記の通り選択できる。
| オプション | デフォルト | 説明 |
|---|---|---|
| displayLoop | false | ループ再生を可能にするかどうか。 |
| displayRestart | false | 最初から再生を可能にするかどうか。 |
| displayPlay | true | 再生ボタンを表示するかどうか。(注:曲が再生中の場合、このボタンは「一時停止」ボタンに変化する。) |
| displayProgress | true | シークバーを表示するかどうか。 |
| displayWarp | false | テンポを表示し、ユーザーがその場でテンポを変更できるようにするかどうか。 |
createSynth関数内でABCJS.synth.CreateSynthを使用してシンセサイザーを初期化し、音楽を再生できるようにする。
JSX のレンダリング
return (
<div>
<div ref={sheetRef}></div>
<div id="audio"></div>
<button onClick={playMusic}>Play</button>
</div>
)
id="audio"のdiv要素がオーディオプレイヤーとして使用される。PlayボタンをクリックするとplayMusic関数が呼び出され、音楽が再生される。