ステレオ音声再生実験
はじめに
IEに備わっている音楽演奏・音声再生機能(BGSOUNDオブジェクト)の動作試験です。ページを開くとシラネーヨ(ならびにモナー)のステレオ音声が再生されます。ヘッドホンで聴くと,あたかもシラネーヨが目の前を通りすぎたり,突然近づいてきたりする‥‥ハズなのですが,まだ試行錯誤の段階なもので,そのような錯覚を覚えるほど完成度は高くありません。時折,音声に「プチプチ」っていう雑音が入って耳障りなのですが,今後改善できるかどうか分りません。
この動的コンテンツはInternet Explorerでなければ実行できません。
注意事項
- 音声が出ないときは,音の鳴るアプリケーション(“Windows Media Player”など)が動作していないか確認してください。もし動作しているならそのアプリケーションを終了させて,このウェブページを開き直して(リロードして)ください。
- ボタン操作のタイミングによって,以後マウス操作ができなくなることがあります。そんなときはバックスペースキーを押してください。
- Windows2000のIE5.5で動作確認しております。
- 長時間視聴すると“は○じん”になるかもしれません。お気をつけください。
コンソールの使い方
- 音声選択: 再生する音声ファイルを選択します。
- 操作:「連続再生」ボタンを押すと,音声を繰り返し再生します。「停止」ボタンを押すと停止します。
- バランス: 音声のバランス(左右のスピーカのどちらに音声を寄せるか)を調整します。「左」,「中央」,「右」を押すと任意にバランスが切り替わります。「≪」,「≫」はバランスを微調整するボタンです。「自動」を選択しているときは,あらかじめ決められた周期でバランスが遷移します。
- 音量:音量をセットします。「最小」は無音。「最大」は通常の音量です(スピーカが張り裂けんばかりの大音量にはなりません)。「自動」を選択しているときは,あらかじめ決められた周期で音量が遷移します。
- メタ情報:BGSOUNDオブジェクトの情報が表示されます。
音声ファイルの説明
- [MP3] シラネーヨ
「シラネーヨ」の声です。この音声は,私の声を元に音声処理装置で加工したものです。 - [MP3] マターリしよーヨ
上と同じ「シラネーヨ」の声です。「第2回音声伝送実験」で公開した音声ファイルと同一です。 - [MP3] オマエモナー
「モナー」の声です。ふしぎ少女風(なぞ)にしてみました。
※音声ファイルの容量はどれも30kバイト程度と小さいのですが,ネットワークの状態によってロードに時間が掛かったり,失敗したりすることがあるかもしれません。
技術資料
使用ツール:Microsoft Visual J++ 6.0
<HTML> <HEAD> <META NAME="GENERATOR" Content="Microsoft Visual Studio 98"> <META HTTP-EQUIV="Content-Type" content="text/html"> <bgsound id=sound> <script><!-- function SoundDecorator(target) { this.target = target; this.src; } SoundDecorator.prototype.PAN_LEFT = -10000; SoundDecorator.prototype.PAN_CENTER = 0; SoundDecorator.prototype.PAN_RIGHT = +10000; SoundDecorator.prototype.VOLUME_MAX = 0; SoundDecorator.prototype.VOLUME_MIN = -10000; SoundDecorator.prototype.setPan = function (val) { switch (val) { case 'center': this.target.balance = this.PAN_CENTER; break; case 'right': this.target.balance = this.PAN_RIGHT; break; case 'left': this.target.balance = this.PAN_LEFT; break; default: if (typeof val == 'number') { this.target.balance = val; } break; } } SoundDecorator.prototype.getPan = function () { return this.target.balance; } SoundDecorator.prototype.setVolume = function (val) { this.target.volume = val; } SoundDecorator.prototype.getVolume = function () { return this.target.volume; } SoundDecorator.prototype.setSrc = function (src) { this.src = src; } SoundDecorator.prototype.getSrc = function () { return this.src; } SoundDecorator.prototype.play = function () { if (arguments.length == 1) { this.setSrc(arguments[0]); } this.target.loop = 1; this.target.src = this.src; } SoundDecorator.prototype.repeat = function () { if (arguments.length == 1) { this.setSrc(arguments[0]); } this.target.loop = -1; this.target.src = this.src; } SoundDecorator.prototype.stop = function () { this.target.src = null; } SoundDecorator.prototype.toString = function () { return "properties={" + "src=\"" + this.target.src + '"' + "," + "loop=" + this.target.loop + "," + "volume=" + this.target.volume + "," + "balance=" + this.target.balance + "}"; } //////// var sd = new SoundDecorator(sound); var demo1ID = null, demo2ID = null; function setDemo1(op) { if (demo1ID != null) { clearInterval(demo1ID); demo1ID = null; sd.setPan(sd.PAN_CENTER); panPanel.disabled = false; } if (op) { var demo = new function (sdecorator) { this.sound = sdecorator; this.array = new Array(); this.index = 0; var i = 0; var step = 500; for (var pan = -5000; pan <= 5000; pan += step) { this.array[i ++] = pan; } for (var pan = 5000; pan >= -5000; pan -= step) { this.array[i ++] = pan; } this.exec = function () { this.sound.setPan(this.array[this.index]); this.index = (this.index + 1) % this.array.length; } } (sd); // 無名オブジェクトのコンストラクタの引数 var functor = function () { demo.exec(); } demo1ID = setInterval(functor, 400); panPanel.disabled = true; } } function setDemo2(op) { if (demo2ID != null) { clearInterval(demo2ID); demo2ID = null; volumePanel.disabled = false; } if (op) { var demo = new function (sdecorator) { this.sound = sdecorator; this.array = new Array(); this.index = 0; var i = 0; var step = 500; for (var pan = -5000; pan <= 0; pan += step) { this.array[i ++] = pan; } for (var pan = 0; pan >= -5000; pan -= step) { this.array[i ++] = pan; } this.exec = function () { this.sound.setVolume(this.array[this.index]); this.index = (this.index + 1) % this.array.length; } } (sd); var functor = function () { demo.exec(); } demo2ID = setInterval(functor, 400); volumePanel.disabled = true; } } function selectSource(filename) { sd.setSrc(filename); sd.repeat(); } //////// function update() { function updatePanIndicator() { var currentPan = sd.getPan(); var leftValue, rightValue; if (currentPan == sd.PAN_CENTER) { leftValue = 0; rightValue = 0; } else { if (currentPan < sd.PAN_CENTER) { leftValue = 0; rightValue = -currentPan / 100; } else { leftValue = currentPan / 100; rightValue = 0; } } console.panIndicator.value = "" +"L = -" +leftValue + "db" +"," +"R = -" +rightValue + "db"; var isLeft = (currentPan <= sd.PAN_LEFT); var isRight = (currentPan >= sd.PAN_RIGHT); var isCenter = (currentPan == sd.PAN_CENTER); console.leftPanButton.disabled = isLeft; console.leftShiftPanButton.disabled = isLeft; console.centerPanButton.disabled = isCenter; console.rightShiftPanButton.disabled = isRight; console.rightPanButton.disabled = isRight; } function updateVolumeIndicator() { var currentVolume = sd.getVolume(); console.volumeIndicator.value = currentVolume / 100 + "db"; var isMaximum = (currentVolume >= sd.VOLUME_MAX); var isMinimum = (currentVolume <= sd.VOLUME_MIN); console.decVolumeButton.disabled = isMinimum; console.incVolumeButton.disabled = isMaximum; console.minimizeVolumeButton.disabled = isMinimum; console.maximizeVolumeButton.disabled = isMaximum; } updatePanIndicator(); updateVolumeIndicator(); console.detailField.value = sd; } function init() { console.demo1switch.checked = true; console.demo2switch.checked = true; setDemo1(console.demo1switch.checked); setDemo2(console.demo2switch.checked); selectSource(console.fileSelector.value); //// setInterval(function () {update();}, 250); } window.onload = init; //--></script> </HEAD> <BODY> <form id=console style="border:solid;border-color:#c60;background-color:#fc9;padding-left:20px"> <div style="color:white;margin-left:-20px;background-color:#f90;font-weight:bold">コンソール</div> <div style="margin-top:10px"> 音声選択 <select id=fileSelector onchange="selectSource(this.value)"> <option value="au-shiraneyo-9788364805.mp3" selected>( ´ー`) シラネーヨ <option value="au-mattari-9779724812.mp3">( ´ー`) マターリしよーヨ <option value="au-omaemona-9788364795.mp3">( ´∀`) オマエモナー </select> </div> <div style="margin-top:10px"> 操作 <input type=button value="連続再生" id=playButton onclick="sd.repeat()"> <input type=button value="停止" id=stopButton onclick="sd.stop()"> </div> <div style="margin-top:10px"> バランス<br> <input type=checkbox id=demo1switch onclick="setDemo1(this.checked)">自動<br> <div id=panPanel style="margin-left:5px"> <input type=button value="左" id=leftPanButton onclick="sd.setPan(sd.PAN_LEFT)"> <input type=button value="中央" id=centerPanButton onclick="sd.setPan(sd.PAN_CENTER)"> <input type=button value="右" id=rightPanButton onclick="sd.setPan(sd.PAN_RIGHT)"> <input type=button value="≪" id=leftShiftPanButton onclick="sd.setPan(sd.getPan() - 250)"> <input type=button value="≫" id=rightShiftPanButton onclick="sd.setPan(sd.getPan() + 250)"> <input type=text id=panIndicator disabled size=25> </div> </div> <div style="margin-top:10px"> 音量<br> <input type=checkbox id=demo2switch onclick="setDemo2(this.checked)">自動<br> <div id=volumePanel style="margin-left:5px"> <input type=button value="最小" id=minimizeVolumeButton onclick="sd.setVolume(sd.VOLUME_MIN)"> <input type=button value="最大" id=maximizeVolumeButton onclick="sd.setVolume(sd.VOLUME_MAX)"> <input type=button value=" - " id=decVolumeButton onclick="sd.setVolume(sd.getVolume() - 250)"> <input type=button value=" + " id=incVolumeButton onclick="sd.setVolume(sd.getVolume() + 250)"> <input type=text id=volumeIndicator disabled> </div> </div> <div style="margin-top:10px"> メタ情報<br> <textarea cols=60 rows=4 id=detailField wrap=virtual disabled></textarea> </div> </form> </BODY> </HTML>