マンネリ化した誕生日会にobnizでハッピーバースデーをかけてみたら子供は目をキラキラさせていた

## 誕生日の祝い方ってマンネリ化しませんか？
誕生日は飾りつけして、プレゼントとケーキを準備して楽しくお祝いしてきました:birthday:
今年は何が欲しい？と聞いてもゲーム以外欲しいものはない息子。
よし！私が広げてた電子部品に興味津々の息子にobnizでハッピーバースデーを流してお祝いしよう:blush:


## 実装した結果
息子はまだ入力できないため、LINEでは音声入力ボタンを押して入力してもらいました:grin:
実は動画を撮る前に何度も練習しました。息子がその他のことを口走ったりして、設定している「今日は俺の誕生日」だけ入力するのは難しかったです:sweat_smile:
また、obnizのスピーカーの調子が悪いこともあり、途中で飛んでしまうことがありました。

しかし、曲が流れると「すごーい」と喜んでくれました！
お母さんが作れるって自分もできるかもしれないという気持ちにも繋がり良いと思いました。

https://twitter.com/yuko6891/status/1655136118868971520?s=20

## 環境
obniz
スピーカー
Node-RED
LINE Bot

## 設計
![スクリーンショット 2023-05-05 15.46.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3310538/240be4ab-3d5f-e84b-7071-0012456c99ee.png)

```json:JSON
[{"id":"3600bd5cae59f6fa","type":"Webhook","z":"53fdf1e902d9d3a6","name":"","url":"/webhook","x":60,"y":100,"wires":[["10364338e96384ae"]]},{"id":"2860efecca4335db","type":"ReplyMessage","z":"53fdf1e902d9d3a6","name":"","replyMessage":"","x":600,"y":80,"wires":[]},{"id":"10364338e96384ae","type":"switch","z":"53fdf1e902d9d3a6","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"今日は俺の誕生日","vt":"str"},{"t":"neq","v":"今日は俺の誕生日","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":210,"y":100,"wires":[["56c37ed269bae941","59e7180f8ed1f95e"],["0f041e36f6a8adf4"]]},{"id":"0f041e36f6a8adf4","type":"template","z":"53fdf1e902d9d3a6","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"「今日は俺の誕生日」とはなしかけてね🎁\n","output":"str","x":380,"y":140,"wires":[["2860efecca4335db"]]},{"id":"bd44a0c60f354ed1","type":"BloadcastMessage","z":"53fdf1e902d9d3a6","name":"","x":610,"y":40,"wires":[[]]},{"id":"56c37ed269bae941","type":"template","z":"53fdf1e902d9d3a6","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"おめでとうございます🎉","output":"str","x":380,"y":40,"wires":[["bd44a0c60f354ed1"]]},{"id":"59e7180f8ed1f95e","type":"obniz-function","z":"53fdf1e902d9d3a6","obniz":"eef8a30a8f48b90b","name":"","code":"// 任意の秒数待つことができる関数\n// 参考: https://qiita.com/suin/items/99aa8641d06b5f819656\nconst sleep = (msec) => new Promise(res => setTimeout(res, msec));\n\nobniz.display.clear(); // 画面を消去\n\n// ソ↓\nobnizParts.Speaker.play(1567.982); await sleep(400); obnizParts.Speaker.stop(); await sleep(200);\n// ソ↓\nobnizParts.Speaker.play(1567.982); await sleep(400); obnizParts.Speaker.stop();\n// ラ↓\nobnizParts.Speaker.play(1760.000); await sleep(400); obnizParts.Speaker.stop(); await sleep(200);\n// ソ↓\nobnizParts.Speaker.play(1567.982); await sleep(400); obnizParts.Speaker.stop();\n// ド↓\nobnizParts.Speaker.play(2093.005); await sleep(300); obnizParts.Speaker.stop(); await sleep(400);\n// シ↓\nobnizParts.Speaker.play(1975.533); await sleep(300); obnizParts.Speaker.stop(); await sleep(400);\n\n// ソ↓2回目\nobnizParts.Speaker.play(1567.982); await sleep(400); obnizParts.Speaker.stop(); await sleep(200);\n// ソ↓\nobnizParts.Speaker.play(1567.982); await sleep(400); obnizParts.Speaker.stop();\n// ラ↓\nobnizParts.Speaker.play(1760.000); await sleep(400); obnizParts.Speaker.stop(); await sleep(200);\n// ソ↓\nobnizParts.Speaker.play(1567.982); await sleep(400); obnizParts.Speaker.stop();\n// レ↓\nobnizParts.Speaker.play(2349.318); await sleep(300); obnizParts.Speaker.stop(); await sleep(400);\n// ド↓\nobnizParts.Speaker.play(2093.005); await sleep(300); obnizParts.Speaker.stop(); await sleep(400);\n\n// ソ(G6)↓\nobnizParts.Speaker.play(1567.982); await sleep(400); obnizParts.Speaker.stop(); await sleep(200);\n// ソ(G6)↓\nobnizParts.Speaker.play(1567.982); await sleep(400); obnizParts.Speaker.stop();\n// ソ(G7)↓\nobnizParts.Speaker.play(3135.963); await sleep(400); obnizParts.Speaker.stop(); await sleep(200);\n// ミ↓\nobnizParts.Speaker.play(2637.020); await sleep(400); obnizParts.Speaker.stop();\n// ド↓\nobnizParts.Speaker.play(2217.461); await sleep(300); obnizParts.Speaker.stop(); await sleep(400);\n// シ↓\nobnizParts.Speaker.play(1975.533); await sleep(300); obnizParts.Speaker.stop(); await sleep(400);\n// ラ↓\nobnizParts.Speaker.play(1760.000); await sleep(300); obnizParts.Speaker.stop(); await sleep(400);\n\n// ファ↓\nobnizParts.Speaker.play(2793.826); await sleep(400); obnizParts.Speaker.stop(); await sleep(200);\n// ファ↓\nobnizParts.Speaker.play(2793.826); await sleep(400); obnizParts.Speaker.stop();\n// ミ↓\nobnizParts.Speaker.play(2637.020); await sleep(400); obnizParts.Speaker.stop(); await sleep(200);\n// ド↓\nobnizParts.Speaker.play(2093.005); await sleep(400); obnizParts.Speaker.stop();\n// レ↓\nobnizParts.Speaker.play(2349.318); await sleep(300); obnizParts.Speaker.stop(); await sleep(400);\n// ド↓\nobnizParts.Speaker.play(2093.005); await sleep(300); obnizParts.Speaker.stop();","x":400,"y":80,"wires":[["2860efecca4335db"]]},{"id":"eef8a30a8f48b90b","type":"obniz","obnizId":"","deviceType":"obnizboard1y","name":"","accessToken":"","code":"obniz.display.clear(); // 画面を消去\nobnizParts.Speaker = obniz.wired(\"Speaker\", { signal: 0, gnd: 1 });"}]
```
### 音の設定
音はこちらのサイトから周波数をとりました。

https://tomari.org/main/java/oto.html


今回はG6の高い音のソを選びました。周波数は、（1567.982）だと分かるのでこちらを設定します。
![スクリーンショット 2023-05-07 18.32.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3310538/de61e78e-6340-5e6d-b9ee-dde0b44d39d1.png)

以下、一部抜粋してきました。
ハッピーバースデー（ソソラソ） トューユー（ドーシー）
```javascript
// ソ↓
obnizParts.Speaker.play(1567.982); await sleep(400); obnizParts.Speaker.stop(); await sleep(200);
// ソ↓
obnizParts.Speaker.play(1567.982); await sleep(400); obnizParts.Speaker.stop();
// ラ↓
obnizParts.Speaker.play(1760.000); await sleep(400); obnizParts.Speaker.stop(); await sleep(200);
// ソ↓
obnizParts.Speaker.play(1567.982); await sleep(400); obnizParts.Speaker.stop();
// ド↓
obnizParts.Speaker.play(2093.005); await sleep(300); obnizParts.Speaker.stop(); await sleep(400);
// シ↓
obnizParts.Speaker.play(1975.533); await sleep(300); obnizParts.Speaker.stop(); await sleep(400);
```

## 参考にした記事

https://qiita.com/ped-yui123/items/b85d6f1fc59853307f3c