自 2022 年 6 月 6 日星期一以來,這一直讓我發瘋,我真的希望有人能告訴我我做錯了什么。
我有一臺使用 Web Audio API 用 Ja??vaScript 撰寫的音樂機器(作為愛好/學習經驗),我正在嘗試做一些非常簡單的事情:- 通過用戶界面更新變數值,然后使用變數的新值參考陣列索引。
用英語講!用戶應該能夠通過 UI 上的滑塊更改八度。
我所擁有的是:
- 用于設定值的滑塊
- 保存滑塊值的變數
- 一個物件字面量陣列,其中包含保存音符頻率的鍵/值對(每個物件都保存一個八度音階)
- 已編程的鍵盤鍵“Y”
應該發生什么:
- 按鍵盤鍵“Y”彈奏一個音符
- 一個音符應該以特定的八度演奏
- 移動滑塊應該改變變數的值
- 變數的值應該用于參考陣列的索引
- 按“Y”鍵應該以不同的八度播放一個音符(或回傳未定義)
實際發生了什么:
- 按鍵盤鍵“Y”播放音符
- 移動滑塊會改變變數的值
- 再次按“Y”鍵以相同的八度演奏相同的音符
- 用戶設定的變數的當前值沒有被用來參考特定的陣列索引
我的音樂機器的代碼很粗,所以我設法重現了我在下面的代碼中遇到的問題,我寧愿通過這樣做我能夠看到出了什么問題,但是,唉不!:o(
為簡潔起見,包含刻度的陣列只有四個索引,0 和 1 應該回傳 undefined,索引 2 應該回傳440,索引 2 應該回傳880
// get the range slider and label from the document
const slider = document.getElementById("slider");
const labelVal = document.getElementById("label");
// var to hold the value of the slider
// We'll use this as the index value later
let oct = 2;
// add an event listener to the slider
window.addEventListener("change", handelChange, false);
// the change event handler
function handelChange(event) {
// set the value of var oct to the slider value
oct = parseFloat(slider.value);
console.log("oct Value:", oct);
// set the label content to equal value of `oct`
labelVal.innerHTML = oct;
return oct;
}
// Create the audio context
const actx = new AudioContext();
// function to call `function createOsc(freq)`
function playNote(freq) {
ceateOsc(freq);
}
// function to create an audio graph that
// starts and stops the oscillator
function ceateOsc(freq) {
// create the audio nodes
const osc = actx.createOscillator();
const vol = actx.createGain();
// set the nodes' values
osc.frequency.value = freq;
vol.gain.value = 0.1;
// connect the nodes to the audio context destintion
osc.connect(vol).connect(actx.destination);
// start & stop the oscillator
osc.start();
osc.stop(actx.currentTime 1);
}
// array of objects holding musical note frequencies
let scale = [{}, // return undefined
{}, // return undefined
{
A: 440, // return 440
},
{
A: 880, // return 880
},
];
// map keyboard to notes using var `oct`
// for the index number of array `scale`
const notes = {
// scale[0].A should undefined
// scale[1].A should undefined
// scale[2].A should return 440
// scale[3].A should return 880
y: scale[oct].A,
};
// ************* Listen For Keyboard Input START ************ \\
window.addEventListener("keydown", keydownHandler, false);
function keydownHandler(event) {
const key = event.key;
const freq = notes[key];
console.log("keydown event: oct val =", oct, "frequency =", freq);
// if our notes object has this keyboard key defined
// play the note:
if (freq) {
playNote(freq);
} else {
console.log("Only key 'Y' can play a note");
}
}
// ************* Listen For Keyboard Input END ************ \\
<h3>Test To Set Index Via User Interface</h3>
<p>Press key 'Y' to play note 'A'</p>
<p>Set slider to value 2 or 3 to change the octave</p>
<p>
<!-- Range input: value to be used as the index number -->
<input type="range" id="slider" min="0" max="3" value="2" /><label id="label" for="setOctave">2</label
>
</p>
我試過的:
- 如果我像這樣手動設定索引:
scale[3].A鍵'Y'播放音符A @ 880hz - 如果我像這樣手動設定索引:
scale[2].A鍵“Y”播放音符 A @ 440hz - 如果我像這樣手動設定索引:
scale[0].A鍵'Y'回傳undefined
oct此外,如果我手動設定 var鍵 'Y'的初始值,則回傳正確的音符/八度。
我console.log(oct)在代碼中的各個點都包含了,包括點,keydown在每個點我們可以看到的值oct等于滑塊的值。實際上, 的值oct實際上是用于更新向用戶顯示的 UI '滑塊文本值',但是,oct此時代碼中的當前值并未被使用scale[oct].A
我在這里遺漏了一些完全明顯的東西,還是發生了一些我不知道的事情?
我非常感謝對此的任何反饋。
謝謝。
uj5u.com熱心網友回復:
初始化notes時, 的值oct僅在創建物件時訪問一次。后續更改oct不會對“y”屬性的值產生任何影響。
解決此問題的一種選擇是將“y”的值設定為 getter 函式:
const notes = {
// scale[0].A should undefined
// scale[1].A should undefined
// scale[2].A should return 440
// scale[3].A should return 880
get y() { return scale[oct].A; }
};
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/488755.html
標籤:javascript 数组 目的 网络音频 api
