質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

Q&A

解決済

3回答

3358閲覧

簡易ピアノを作って音階を鳴らしたい

toloveru83

総合スコア15

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

0グッド

0クリップ

投稿2019/07/22 12:13

編集2019/07/29 01:56

前提・実現したいこと

HTMLとJavascriptで音階当てゲームを作っています。
現在、実装しようとしている機能は、クイズ開始前に各音の確認をするために
クリック、又はキーボードで音を鳴らす仕組みです。

発生している問題・エラーメッセージ

Google Chromeで動作確認を行っているのですが、鍵盤のキーボードをクリックしても音が鳴りません。 Chromeの検証ツールで確認したところ、下記エラーが表示されましたが、対処方法が分かりません。 Uncaught TypeError: Failed to set the 'value' property on 'AudioParam': The provided float value is non-finite. 「指定された値(value)は有限ではない(無限)。」

該当のソースコード

HTML

1<!DOCTYPE html> 2<html> 3<head> 4<meta charset="UTF-8"> 5<title>音当てゲーム</title> 6<script></script> 7</head> 8<body onload="init()"> 9<p>音当てゲーム</p> 10<input type="button" id="test" value="テスト" onclick="testGame()"> 11<input type="button" id="start" value="スタート" onclick="initGame()"> 12<input type="button" id="stop" value="ストップ" onclick="stop2Game()"> 13<input type="button" value="ドレミを表示" onclick="showKeyboard()"> 14【第<span id="qNo">1</span>問:<span id="memo">白鍵のみ</span>】 15<span id="message"></span> 16<hr> 17volume:<input type="range" id="volume" value="0.5" min="0" max="1" 18step="0.1" onchange="setVolume()"> 19<span id="volumeText">[0.5]</span> 20<div id="piano"></div> 21</body> 22</html>

JavaScript

1var audioContext = new AudioContext(); //オーディオコンテキスト 2var oscillator = new Array(); 3var gain = new Array(); 4var gainNode; //Gainノード 5var qNo,answer,cnt,total; //問題番号、解答、正解数 6var status; //ステータス(wait/qustion/answer) 7var startTime,timer1,timer2; 8var minNotoNo = 72; 9 10var doremi = ["ド","ド#","レ","レ#","ミ","ファ","ファ#","ソ","ソ#","ラ","ラ#","シ"]; 11 12var keyboard = ["Z","S","X","D","C","V","G","B","H","N","J","M"]; 13 14function init(){ 15 16for(var i=0;i<keyboard.length;i++){ 17 var notoNo; 18 19 notoNo = i+minNotoNo; 20 21var key = document.createElement("button"); 22key.id = "key_" + i; 23key.onclick = hitKey; 24key.onmousedown = mouseKeyDown; 25key.onmouseup = mouseKeyUp; 26key.onmouseleave = mouseKeyUp; 27 28 29if(doremi[notoNo%12].indexOf("#") > 0){ 30 //黒鍵 31 key.classList.add("black"); 32 }else{ 33 //白鍵 34 key.classList.add("white"); 35 var baseKey = document.createElement("div"); 36 } 37 //ベースの鍵盤に追加 38 baseKey.appendChild(key); 39 //ベースの鍵盤をピアノに追加 40 document.getElementById("piano").appendChild(baseKey); 41 42 testGame(notoNo); 43 } 44 45 //Gainノードの作成 46 gainNode = audioContext.createGain(); 47 setVolume(); 48} 49 50function testGame(notoNo){ 51var audioContext = new AudioContext(); 52 53 oscillator[notoNo] = audioContext.createOscillator(); 54 gain[notoNo] = audioContext.createGain(); 55 56 var f = 440*Math.pow(2,(notoNo-69)/12); 57 58 //接続 59 oscillator[notoNo].connect(gain[notoNo]); 60 gain[notoNo].connect(audioContext.destination); 61 62 //周波数、ボリューム(無音)をセット 63 oscillator[notoNo].frequency.value = f; 64 gain[notoNo].gain.value = 0; 65 66 //無音で鳴らす 67 oscillator[notoNo].start(); 68 } 69 const eventName = typeof document.ontouchend !== 'undefined' ? 'touchend' : 'mouseup'; 70 document.addEventListener(eventName, initAudioContext); 71 function initAudioContext(){ 72 document.removeEventListener(eventName, initAudioContext); 73 // wake up AudioContext 74 audioContext.resume(); 75 } 76 77 78 function mouseKeyDown(event){ 79 //鍵盤のノートナンバー(4文字目以降の文字列)を取得 80 var notoNo = event.target.id.substr(4); 81 //音を鳴らす 82 playKey(notoNo); 83 } 84 85 function mouseKeyUp(event){ 86 //鍵盤のノートナンバー(4文字目以降の文字列)を取得 87 var notoNo = event.target.id.substr(4); 88 //音を止める 89 stopKey(notoNo); 90 } 91 92 document.onkeydown = function(event){ 93 //キーに割り当てられているショートカットをキャンセル 94 event.preventDefault(); 95 //押されたキーボードと対応する音を鳴らす 96 for(var i=0;i<keyboard.length;i++){ 97 if(event.key == keyboard[i].toLowerCase()) playKey(i+minNotoNo); 98 } 99 } 100 101 document.onkeyup = function(event){ 102 //放されたキーボードと対応する音を止める 103 for(var i=0;i<keyboard.length;i++){ 104 if(event.key == keyboard[i].toLowerCase()) stopKey(i+minNotoNo); 105 } 106 } 107 108 function playKey(notoNo){ 109 //音を鳴らす(ボリュームを上げる) 110 gain.value = document.getElementById("volume").value; 111 //押されている鍵盤にstrikeクラスを追加 112 document.getElementById("key_" + notoNo).classList.add("strike"); 113 } 114 115 function stopKey(notoNo){ 116 //無音にする 117 gain.value = 0; 118 //放された鍵盤からstrikeクラスを削除 119 document.getElementById("key_" + notoNo).classList.remove("strike"); 120 } 121 122function hitKey(event){ 123 if(status == "question"){ 124 //解答 125 cnt++; 126 status = "answer"; 127 //音階の生成 128 var noteNo = Number(event.target.id.split("_")[1]) + 72; 129 event.target.classList.add("red"); 130 //音階をセット 131 sound(noteNo); 132 } 133} 134 135function sound(noteNo){ 136 //oscillatorノードの作成 137 var oscillatorNode = audioContext.createOscillator(); 138 var f = 440 * Math.pow(2,(noteNo-69) / 12); 139 oscillatorNode.frequency.setValueAtTime(f,audioContext.currentTime); 140 //ノードの接続 141 oscillatorNode.connect(gainNode); 142 gainNode.connect(audioContext.destination); 143 //0.2秒間再生 144 oscillatorNode.start(audioContext.currentTime); 145 oscillatorNode.stop(audioContext.currentTime + 0.2); 146 if(status == "answer")oscillatorNode.onended = checkNote; 147} 148 149function setVolume(){ 150 //ボリュームをセット 151 var volume = document.getElementById("volume").value; 152 gainNode.gain.setValueAtTime(volume,audioContext.currentTime); 153 document.getElementById("volumeText").innerHTML = "[" + volume + "]"; 154} 155 156 157 158function checkNote(){ 159 //解答チェック 160 var message,key; 161 for(var i=0;i<doremi.length;i++){ 162 key = document.getElementById("key_" + i); 163 if(key.classList.contains("red")){ 164 if(key.id.split("_")[1] == answer){ 165 message = "正解![" + doremi[answer] + "]"; 166 if(cnt == 1)total++; 167 //5秒後に次の問題を表示 168 timer2 = setTimeout(function(){ 169 qNo++; 170 //次の問題/終了 171 if(qNo < 11){ 172 startGame(); 173 }else{ 174 stopGame(); 175 } 176 },5000); 177 }else{ 178 message = "不正解!!"; 179 status = "question"; 180 } 181 key.classList.remove("red"); 182 document.getElementById("message").innerText = message; 183 } 184 } 185} 186 187function initGame(){ 188 //初期化 189 total = 0; 190 qNo = 1; 191 //開始 192 document.getElementById("start").disabled = true; 193 startGame(); 194} 195 196function startGame(){ 197 //開始 198 cnt = 0; 199 status = "wait"; 200 document.getElementById("qNo").innerText = qNo; 201 document.getElementById("memo").innerText = "白鍵のみ"; 202 if(qNo > 5){ 203 document.getElementById("memo").innerText = "白鍵+黒鍵"; 204 } 205 startTime = Date.now(); 206 timer1 = setInterval(countTime,100); 207} 208 209function stop2Game(){ 210 //終了 211 status = "wait"; 212 var message = "終了 (正解数:" + total + "/" + qNo + ")" 213 document.getElementById("message").innerText = message; 214 document.getElementById("start").disabled = false; 215} 216 217function stopGame(){ 218 //終了 219 status = "wait"; 220 var message = "終了 (正解数:" + total + "/10)" 221 document.getElementById("message").innerText = message; 222 document.getElementById("start").disabled = false; 223} 224 225function countTime(){ 226 //カウントダウン 227 var time = 3 - Math.floor((Date.now() - startTime)/1000); 228 document.getElementById("message").innerHTML = "<b>" + time + "</b>"; 229 //問題 230 if(time == 0){ 231 status = "question"; 232 clearInterval(timer1); 233 document.getElementById("message").innerText = ""; 234 answer = Math.floor(Math.random() * 12); 235 //白鍵のみ調整 236 if((qNo < 6)&&(doremi[answer].indexOf("#") > 0)) answer++; 237 sound(answer + 72); 238 } 239} 240 241function showKeyboard(){ 242 var notoNo,keyText; 243 for(var i=0;i<doremi.length;i++){ 244 notoNo = i+minNotoNo; 245 keyText = "<div id='text"+notoNo+"'>"+doremi[notoNo%12]+"</div>"; 246 document.getElementById("key_" + i).innerHTML = keyText; 247 } 248}

CSS

1#piano {margin-top: 10px;} 2#piano div { 3 position: relative; 4 width: 80px; 5 height: 400px; 6 float: left; 7} 8#piano button {position: absolute;} 9.white{ 10 background-color: white; 11 top: 0px; 12 width: 80px; 13 height: 400px; 14 border-radius: 20px; 15 z-index: 0; 16} 17.black{ 18 background-color: black; 19 top: 0px; 20 left: 50px; 21 width: 60px; 22 height: 240px; 23 border-radius: 20px; 24 z-index: 1; 25} 26button div{ 27 position: absolute; 28 bottom: 0px; 29 left: 0px; 30 width: 100px; 31 font-size: 20px; 32} 33white div {color: black;} 34black div {color: gray;} 35.red{background-color: red;} 36.strike{background-color: yellow;} 37#memo {color: #0000CC;} 38#message {color: #CC0000;}

試したこと

エラーの該当箇所「oscillator[notoNo].frequency.value = f;」
(69行目)から変数のスペルミス等確認していますがよくわかりません。

補足情報(FW/ツールのバージョンなど)

Google Chrome最新バージョン:75.0.3770.142(Official Build) (64 ビット)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Res

2019/07/28 13:03

JS、CSS、HTMLごとにソースコードを分けていただくと分かりやすいです
toloveru83

2019/07/28 14:02

ご依頼ありがとうございます。 ソースコードの方分けさせていただきました。
Res

2019/07/28 22:16

cssの部分に<style>タグはいりませんよ。(始めと終わり)
toloveru83

2019/07/29 01:57

ご指摘ありがとうございます。 修正しました。
Res

2019/07/29 02:04

ありがとうございます。
guest

回答3

0

Javascript Web Audio API error: Failed to set the 'value' property on 'AudioParam': The provided float value is non-finite

isFinite() を使い、有限かどうか確かめてからセットすればいいようです。

投稿2019/07/28 14:11

Zuishin

総合スコア28660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

Uncaught TypeError: Failed to set the 'value' property on 'AudioParam': The provided float value is non-finite.

valueに有限じゃないfloatの値 (つまり無限) が渡っているとのことです。(ほぼ直訳)

投稿2019/07/22 12:27

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

ボタンにつけている hitKey ですが、event.target.id を見ているため子の div の id を取得してしまっているようです。
currentTarget を使うようにしてみてください。
https://developer.mozilla.org/ja/docs/Web/API/Event/currentTarget

投稿2019/07/29 01:52

x_x

総合スコア13749

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問