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

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

新規登録して質問してみよう
ただいま回答率
85.35%
Web Audio

Web Audioは、音声を処理・合成するためのWebアプリケーション向けJavaScript APIです。HTML5から導入されました。オーディオソースの選択、エフェクト・ビジュアライゼーションの追加、パンニングなど特殊効果の適用など多くの機能を持ちます。

JavaScript

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

HTML

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

Q&A

解決済

1回答

1366閲覧

WebAudioで読み込んだ音が出ない

cl_

総合スコア9

Web Audio

Web Audioは、音声を処理・合成するためのWebアプリケーション向けJavaScript APIです。HTML5から導入されました。オーディオソースの選択、エフェクト・ビジュアライゼーションの追加、パンニングなど特殊効果の適用など多くの機能を持ちます。

JavaScript

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

HTML

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

0グッド

1クリップ

投稿2020/03/17 00:00

WebAudioで読み込んだ音声ファイルから立体音響を作ろうとしています。Three.jsと関連づけてこちらに3Dテキストが音を出しながら迫りくるようにしたいです。

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

数秒のwavファイルを読みこんでやろうとしたら、音がしません。

(なし)

下記該当のソースコードで

JavaScript

1 fetchAsAudioBuffer(ctx, 'Myaudio.wav', function(audioBuffer) { 2 instrument = audioBuffer; 3 console.log(instrument); 4 });

で関数の外へaudioBufferのデータを渡す方法がわかりません。

該当のソースコード

JavaScript

1'use strict'; 2 3{ 4 let scene; 5 let text; 6 let light; 7 let ambient; 8 let camera; 9 let renderer; 10 let controls; 11 let loader; 12 let textPositionZ = 0; 13 const stage = document.getElementById('stage'); 14 const fontSize = 4; 15 16 17// Detect if the audio context is supported. 18 window.AudioContext = ( 19 window.AudioContext || 20 window.webkitAudioContext || 21 null 22 ); 23 24 if (!AudioContext) { 25 throw new Error("AudioContext not supported!"); 26 } 27 28 29 30 function onResize() { 31 const width = window.innerWidth; 32 const height = window.innerHeight-30; 33 34 // rendererのサイズ調整 35 renderer.setPixelRatio(window.devicePixelRatio); 36 renderer.setSize(width, height); 37 38 // cameraのアスペクト比をただす 39 camera.aspect = width / height; 40 camera.updateProjectionMatrix(); 41 } 42 43 44 45 // scene 46 scene = new THREE.Scene(); 47 48 // mesh 49 loader = new THREE.FontLoader(); 50 loader.load('js/helvetiker_regular.typeface.json', function(font) { 51 createText(font); 52 }); 53 function createText(font) { 54 text = new THREE.Mesh( 55 new THREE.TextGeometry('https://URL.com', { 56 font: font, 57 size: fontSize, 58 height: 0.001 59 }), 60 new THREE.MeshLambertMaterial({ color: 0xff5836, side: THREE.DoubleSide }) 61 ); 62 text.position.set(0, 0, 90); 63 scene.add(text); 64 // return text; 65 } 66 67 // light 68 light = new THREE.DirectionalLight(0xffffff, 1); 69 light.position.set(0, 0, 30); 70 scene.add(light); 71 ambient = new THREE.AmbientLight(0x404040); 72 scene.add(ambient); 73 74 // camera 75 camera = new THREE.PerspectiveCamera(135, window.innerWidth / window.innerHeight-30, 0.01, 130); 76 camera.position.set(0, 0, 220); 77 camera.lookAt(scene.position); 78 79 // controls 80 stage.addEventListener('click', () => { 81 if (textPositionZ === 0) { 82 textPositionZ = 1; 83 }else { 84 textPositionZ = 0; 85 } 86 // WebAudio 87 const ctx = new AudioContext(); 88 const panner = ctx.createPanner(); 89 const gain = ctx.createGain(); 90 const sound = {}; 91 let instrument; // 読み込んだAudioBufferを格納するやつ 92 fetchAsAudioBuffer(ctx, 'Myaudio.wav', function(audioBuffer) { 93 instrument = audioBuffer; 94 console.log(instrument); // <- 中身あり 95 }); 96 sound.volume = ctx.createGain(); 97 sound.panner = ctx.createPanner(); 98 99 synth(ctx, ctx.currentTime, instrument, sound.volume); 100 sound.volume.connect(sound.panner); 101 sound.panner.connect(gain); 102 gain.connect(ctx.destination); 103 104 function fetchAsAudioBuffer(audioContext, url, callback) { 105 const xhr = new XMLHttpRequest(); 106 107 xhr.open('GET', url, true); 108 xhr.responseType = 'arraybuffer'; // ArrayBuffer指定 109 xhr.onload = function() { 110 console.log(xhr.response) // <- 中身あり 111 if (xhr.response) { 112 audioContext.decodeAudioData(xhr.response).then(callback); 113 } 114 }; 115 116 xhr.send(); 117 } 118 119 function synth(audioContext, t0, audioBuffer, nextNode) { 120 const bufferSource = audioContext.createBufferSource(); 121 console.log(audioBuffer); // <- **undefined**! 122 bufferSource.buffer = audioBuffer; 123 bufferSource.start(t0); 124 bufferSource.loop = true; 125 bufferSource.connect(nextNode); 126 } 127 128 function render() { 129 requestAnimationFrame(render); 130 text.position.z += textPositionZ; 131 text.updateMatrixWorld(); 132 camera.updateMatrixWorld(); 133 const newTx = new THREE.Vector3(); 134 const cam = new THREE.Vector3(); 135 newTx.setFromMatrixPosition(text.matrixWorld); 136 cam.setFromMatrixPosition(camera.matrixWorld); 137 138 sound.panner.setPosition(newTx.x, newTx.y, newTx.z); 139 ctx.listener.setPosition(cam.x, cam.y, cam.z); 140 renderer.render(scene, camera); 141 } 142 143 render(); 144 }); 145 146 // renderer 147 renderer = new THREE.WebGLRenderer({ antialias: true }); 148 onResize(); 149 window.addEventListener('resize', onResize); 150 renderer.setClearColor(0xffffff); 151 stage.appendChild(renderer.domElement); 152 153}

試したこと

  • 音声ファイルの長さを1秒、7秒に変更 → 同じ
  • 音源をaudioContext.createOscillator()で作ったsin波に変更 → 立体的に音が鳴る

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

ローカル開発環境の構築[macOS編]
の通りに構築した環境上で

html

1<!DOCTYPE html> 2<html lang="ja"> 3<head> 4 <meta charset="utf-8" name="viewport" content="width=device-width, initial-scale=1"/> 5 <style> 6 body { 7 margin: 0; 8 overflow: hidden; 9 } 10 11 </style> 12 <title>Voice</title> 13</head> 14<body> 15 <div id="stage">Click Please!</div> 16 <script src="js/three.min.js"></script> 17 <script src="js/OrbitControls.js"></script> 18 <script>(該当のソースコード)</script> 19</body> 20</html> 21

を実行
音声ファイルは上記コードのファイルと同じ階層に配置

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

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

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

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

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

guest

回答1

0

ベストアンサー

#原因

変数instrumentAudioBufferのオブジェクトが入る想定となっていますが、この変数instrumentAudioBufferのオブジェクトが代入されるタイミングは、fetchAsAudioBuffer関数による非同期のコールバック関数が呼ばれたあとになります。

そのため、fetchAsAudioBuffer関数を呼び出した直後では、変数instrumentにはAudioBufferオブジェクトは代入されておらず、内容はundefinedのままです。この状態のまま、fetchAsAudioBuffer関数よりあとのプログラムの実行が継続されます。

これにより、

js

1synth(ctx, ctx.currentTime, instrument, sound.volume);

が実行されるタイミングで、synth関数の第3引数でundefinedが渡され、意図しない結果となっていると思われます。

コールバック関数が呼び出されるイメージ

対処方法

fetchAsAudioBuffer関数に渡しているコールバック関数が実行されるタイミングでAudioBufferが得られているので、このタイミングでsynth関数を呼び出すことで、とりあえずの対処ができそうです。

synth関数の第4引数に、AudioContext.createGain()で得られたGainNodeのオブジェクトを渡しているので、fetchAsAudioBuffer関数を呼び出す前に、GainNodeのオブジェクトを得ておく必要があります。

JavaScript

1 () 2 : 3const sound = {}; 4let instrument; 5sound.volume = ctx.createGain(); // 先に sound.volume の GainNode を作っておく 6fetchAsAudioBuffer(ctx, 'Myaudio.wav', function(audioBuffer) { 7 instrument = audioBuffer; 8 synth(ctx, ctx.currentTime, instrument, sound.volume); 9}); 10 : 11 ()

投稿2020/03/17 00:18

編集2020/03/17 00:36
mozukichi

総合スコア57

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

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

cl_

2020/03/17 06:52

そうでした!ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問