[英]How do I capture a sequence of what button was pressed and when?
我發現很難理解javascript的工作原理,特別是在編寫自己的代碼時,因此我請一個朋友幫我,並為我提供了類似的東西。
var curtime = new Date();
delaytime = curtime.getTime() - previoustime.getTime();
previoustime.setTime( curtime.getTime());
temparray = new Array;
temparray.push( name );
temparray.push( delaytime );
recording.push( temparray);
但我似乎無法掌握如何將其鏈接到我的按鈕並將其保存到數組中的概念。 我希望能夠使用此記錄的信息來准確播放用戶輸入的內容,但一次只能執行一次。
如果有人可以幫助我進入下一個階段,那將不勝感激,因為我迷上了javascript。
好玩的問題。 考慮以下事實: 對於任何給定事件 ,每個元素可能觸發多個事件處理程序 。 這意味着什么? 您可以將(a)可以“實際”工作的功能附加到按鈕上,也可以將(b)記帳功能附加到兩者上。 (盡管,不能保證它們被調用的順序-不需要按照添加的順序被調用-這可能已經改變,大約6個月內我沒看過)
另外,由於我已經使用.addEventListener附加了事件處理程序,因此this
關鍵字首先引用觸發事件的html元素。 -這就是為什么我可以將單個“通用”功能附加到所有按鈕以從中提取任何必要的信息的原因。
因此,您只需要將兩個功能都附加到您要為其記錄信息的任何元素。 這是一個簡單的例子。 希望能幫助到你。
<!doctype html>
<html>
<head>
<script>
function onBtn1(evt)
{
alert('you pressed button 1');
}
function onBtn2(evt)
{
alert('btn2');
}
function onBtn3(evt)
{
alert('pressed btn 3');
}
function onShowRecordsBtn(evt)
{
var i, n = eventList.length;
var tgt = byId('outputTgt');
var msg = '';
for (i=0; i<n; i++)
{
// all entries except the first one must be preceded with a new-line
if (i != 0)
msg += "<br>";
// show the id and time of each clicked button
msg += "ID: " + eventList[i].elemId + " - Time: " + eventList[i].time;
}
tgt.innerHTML = msg;
}
// declare an empty array to hold the list of events.
var eventList = [];
function saveBtnPressInfo(evt)
{
var curRecord = { time: new Date(), elemId: this.id};
// same as preceding line of code
// var curRecord = { time: null, elemId: null};
// curRecord.time = new Date();
// curRecord.elemId = this.id;
eventList.push(curRecord);
}
window.addEventListener('load', onPageLoaded, false);
function byId(e){return document.getElementById(e);}
function onPageLoaded(evt)
{
// add the (unique) event handlers to the buttons
byId('btn1').addEventListener('click', onBtn1, false);
byId('btn2').addEventListener('click', onBtn2, false);
byId('btn3').addEventListener('click', onBtn3, false);
// add the event to the showEvents 'button' - I made it an inut element so that it doesn't get
// found when we get a list of all <button> elements on the page. (I don't want to know when the user asked for button-press stats)
byId('showRecordsBtn').addEventListener('click', onShowRecordsBtn, false);
// add the record-keeping function to each of the buttons
var btnList = document.getElementsByTagName('button');
var i, n = btnList.length;
for (i=0; i<n; i++)
{
btnList[i].addEventListener('click', saveBtnPressInfo, false);
}
}
</script>
<style>
</style>
</head>
<body>
<button id='btn1'>Button 1</button>
<button id='btn2'>Button 2</button>
<button id='btn3'>Button 3</button>
<hr>
<input id='showRecordsBtn' type='button' value='Show btn-click activity'/>
<div id='outputTgt'></div>
</body>
</html>
編輯:
這是一些使用Voxel Bukkake中的(instrument)synth的代碼。 在此代碼中,我只是演奏音符以響應對樂器樣本的單擊。 從內存中,您可以使用.noteOn的參數來指定調用和發出聲音之間的毫秒數。
<!DOCTYPE html>
<html>
<head>
<script>
function byId(e){return document.getElementById(e);}
function newEl(tag){return document.createElement(tag);}
function newTxt(txt){return document.createTextNode(txt);}
function toggleClass(element, newStr)
{
index=element.className.indexOf(newStr);
if ( index == -1)
element.className += ' '+newStr;
else
{
if (index != 0)
newStr = ' '+newStr;
element.className = element.className.replace(newStr, '');
}
}
function forEachNode(nodeList, func)
{
var i, n = nodeList.length;
for (i=0; i<n; i++)
{
func(nodeList[i], i, nodeList);
}
}
var current_time = 0;
function Instrument(attack, delay, sustain, release, sustainTime, cutoff, resonance, lfoFreq, lfoAmp, detuneSquare, detuneSaw, squareVol, sawVol, noiseVol)
{
// volume envelope
this.A = attack;
this.D = delay;
this.S = sustain;
this.R = release;
this.sustainTime = sustainTime;
this.cutoff = cutoff;
this.resonance = resonance;
this.lfo_freq = lfoFreq;
this.lfo_amp = lfoAmp;
this.square_detune = detuneSquare;
this.saw_detune = detuneSaw;
this.square_vol = squareVol;
this.saw_vol = sawVol;
this.noise_vol = noiseVol;
}
function Voice(pitch, pos, ins, vol, active)
{
this.pitch = pitch;
this.pos = pos; // position in samples from the beginning
this.ins = ins; // instrument
this.vol = vol;
this.xn = [0,0,0];//[1.0,1.0,1.0];
this.yn = [0,0,0];//[1.0,1.0,1.0];
this.active = 0; // 0 = inactive, (not 0) = active
}
function synth(v, len, mix_buf)
{
current_time = 100;
var ins = v.ins;
//var pitch_sine = v->pitch * ins->sine_detune;
var pitch_square = v.pitch * ins.square_detune;
var pitch_saw = v.pitch * ins.saw_detune;
var vol, res, t;
var i;
var invSAMPLE_RATE = 1 / 44100;
var periodo_square = 1.0/pitch_square;
v.pos = 0;
for (i=0; i<len; i++)
{
res=0;
t = (v.pos+i)*invSAMPLE_RATE;
// t >>= 0;
// First add the oscillators
// Sine
//res = ins->sine_vol * msin(DOSPI*pitch_sine*t);
// Square
if ( (t % periodo_square) > (periodo_square/2.0))
res += ins.square_vol;
else
res -= ins.square_vol;
// Saw
res += ins.saw_vol * ( ( (t*pitch_saw)% 2.0) - 1.0);
// Noise
res += ins.noise_vol * (2.0*whitenoise()-1.0) ;
// We now apply the ADSR
vol = getAmp(ins, t);
res *= vol;
// We estimate the value of applying cutoff LFO
var cutoff, lfo_freq;
if (ins.lfo_freq < 0)
{
lfo_freq = -ins.lfo_freq;
t = current_time;
}
else
{
lfo_freq = ins.lfo_freq;
}
var DOSPI = 6.2831853071795862;
cutoff= ins.cutoff + ins.lfo_amp * Math.cos(DOSPI * lfo_freq * t);
var r = ins.resonance;
// Calculate filter coefficients
var c, c2,a1,a2,b1,b2;
//We extract some calculations that are redundant in HP and LP
var PI_samplerate = 0.000071237928652829774;
var param_tan = PI_samplerate * cutoff;
if (cutoff > 0.0) // Low-pass
{
c = 1.0 / Math.tan(param_tan);
c2 = c*c;
a1 = 1.0 / ( 1.0 + r * c + c2);
a2 = 2.0 * a1;
b1 = 2.0 * ( 1.0 - c2) * a1;
}
else // High-pass
{
c = Math.tan(-param_tan);
c2 = c*c;
a1 = 1.0 / ( 1.0 + r * c + c2);
a2 = -2*a1;
b1 = 2.0 * ( c2 - 1.0) * a1;
}
b2 = ( 1.0 - r * c + c2) * a1;
v.yn[0] = (a1*res) + (a2*v.xn[1]) + (a1*v.xn[2]) - (b1*v.yn[1]) - (b2*v.yn[2]);
v.xn[2]=v.xn[1];
v.xn[1]=res;
v.yn[2]=v.yn[1];
v.yn[1]=v.yn[0];
// From here already filtering res
mix_buf[i] += v.yn[0] * v.vol;
}
v.pos+=len;
if (vol > 0.0)
return 1;
return 0;
}
// Returns the value of time pos ADSR
// Linear interpolation
// function getAmp(instrument, pos)
function getAmp(i, pos)
{
var A = i.A/100 + 0.00001;
if (pos <= A)
return (pos/A);
pos -= A;
var D = i.D / 100;
var S = i.S / 100;
if (pos <= D)
return (1.0 - (pos * (1 - S)) / D);
pos -= D;
var sustain_time = i.sustainTime/100;
if (pos <= sustain_time)
return S;
pos -= sustain_time;
var R = i.R/100;
if (pos < R)
return S - S * (pos/R);
else
return 0;
}
function whitenoise()
{
return Math.random();
}
////============================================================
window.addEventListener('load', mInit, false);
var context;
function mInit()
{
context = new webkitAudioContext();
var hihat = new Instrument( 1,5,15,50,0, -12000,1.1, 1.500,8000, 1.0,0.5, 0.5,0.3, 1.2);
var drum = new Instrument( 1,15,40,5,0, 20, 1.0, 1.0, 200, 1.5,1.0, 1.0,0.5, 2.4);
var low = new Instrument( 1,15,40,5,0, 800,1.0, -0.500,-600, 1.0,1.0,0.4,0.7, 0.0);
var organ = new Instrument(50,30,45,100,20, -1150,1.0, -8.333,-950, 0.501,1.0, 0.5,0.7, 0.0);
var lead = new Instrument( 0,10,50,40,20, 900,1.0, 1.500, 900, 0.5,1.0, 0.8,0.4, 0.0);
var simon = new Instrument(10,10,50,75,70, 800,0.25, 1.500,700, 0.8,0.8, 0.5,0.5, 0.0);
//function Insrument(attack, delay, sustain, release, sustainTime, cutoff, resonance, lfoFreq, lfoAmp, detuneSquare, detuneSaw, squareVol, sawVol, noiseVol)
var start = new Date();
addPlayableGraph(hihat);
// addPlayableGraph(drum);
// addPlayableGraph(low);
addPlayableGraph(organ);
addPlayableGraph(lead);
addPlayableGraph(simon);
var end = new Date();
var diff = end-start;
start = newTxt('Calculation Time: ' + diff + 'ms');
document.body.appendChild(start);
var coords = newEl('div');
coords.setAttribute('id', 'coords');
document.body.appendChild(coords);
}
function addPlayableGraph(instrument)
{
var note = 43;
var pitch = 440.0 * Math.pow(2.0, (note-45.0)/12.0);
var pos = 0;
var vol = 0.4;
var active = 1.0;
var voice = new Voice(pitch, pos, instrument, vol, active);
var buffer = [];
var i, n=4410 * (20);
for (i=0; i<n; i++)
buffer[i] = 0.0;
voice.active = synth(voice, n, buffer);
var canvas = newEl('canvas');
canvas.height = 96;
canvas.width = 1024;
document.body.appendChild(canvas);
drawFloatArray(buffer, canvas);
canvas.mBuffer = buffer;
canvas.onclick = function() { playSound(this.mBuffer, 44100, 100); };
canvas.onmousemove =
function(e)
{
e = e || event;
var str = 'Pos: ' + (e.clientX/canvas.width)*2000 + ',' + e.clientY;
byId('coords').innerText = str;
}
return canvas;
}
function drawFloatArray(samples, canvas)
{
var i, n = samples.length;
var dur = (n / 44100 * 1000)>>0;
canvas.title = 'Duration: ' + dur / 1000.0 + 's';
var width=canvas.width,height=canvas.height;
var ctx = canvas.getContext('2d');
ctx.strokeStyle = 'yellow';
ctx.fillStyle = '#303030';
ctx.fillRect(0,0,width,height);
ctx.moveTo(0,height/2);
ctx.beginPath();
for (i=0; i<n; i++)
{
x = (i*width) / n;
y = (samples[i]*height/2)+height/2;
ctx.lineTo(x, y);
}
ctx.stroke();
ctx.closePath();
}
function playSound(buffer, freq, vol) // buffer, 44100, 0-100
{
var mBuffer = context.createBuffer(1, buffer.length, freq);
var dataBuffer = mBuffer.getChannelData(0);
var soundBuffer = buffer;
var i, n = buffer.length;
for (i=0;i<n;i++)
dataBuffer[i] = soundBuffer[i];
var node = context.createBufferSource();
node.buffer = mBuffer;
node.gain.value = 0.5 * vol/100.0;
node.connect(context.destination);
node.noteOn(0);
}
</script>
<style>
</style>
</head>
<body>
</body>
</html>
最后,您可以查看http://www.iquilezles.org/apps/soundtoy/,了解一種使用“簡單”數學方程式進行儀器定義的方法。 但尤其是萌-尋找允許單個公式(樂器)產生不同音高的代碼(如果需要)
您可能只需要使用.noteOn的參數來播放已經擁有的mp3。 不能記住我是否演奏過這樣的加載聲音,或者只是生成了東西。
即,很多有趣的,瀏覽器生成的內容。
可以采用兩種基本的回放方法。 您可以計算出每個音符之間的延遲,然后依次播放每個音符,等待每個音符之間的時間間隔,然后再使用noteOn(0)播放下一個音符。 這將消耗最少的內存,但會阻止同時啟動多個音符。
另一種方法是確定從回放開始到每個單獨音符的時間,然后在聲音輸出開始之前提示它們。 您需要更多的內存,但是我發現它是一種更直觀的方法。 您也可以同時開出一堆音符-例如,需要和弦。
我在此代碼中采用了第二種方法。 您需要提供自己的聲音樣本(共6個),並且必須通過localhost運行它,而不僅僅是從文件夾中雙擊它。 我認為這是因為我使用AJAX加載了示例。
樣本來自“ chiptune.xm”,如以下代碼所示: https : //forum.tuts4you.com/files/file/184-snd-keygen-template-code-walker/ (需要注冊)您可以提取帶有(amiga)個“ mod播放器”中的任何一個的樣本-這首歌長約2m18s,磁盤上只有25kb,因為它使用8bit或11khz左右的8bit單聲道樣本-未能定義聲音盡管它們在算法上還足夠接近它們,所以我只使用從中提取的WAV。
與該問題最相關的功能應該在playSong2()中找到。 這會在歌曲的每個0.12秒步長獲取每種樂器的當前音符。 在發出要排隊等待播放音符的數據之前,它將對音符進行更長或更短的重新采樣,以獲得所需的不同音高。 無論如何,我現在很忙,希望我所能做的一點工作對您有所幫助。 :)
玩得開心!
<!DOCTYPE html>
<html>
<head>
<script>
function byId(e){return document.getElementById(e);}
function newEl(tag){return document.createElement(tag);}
function newTxt(txt){return document.createTextNode(txt);}
function toggleClass(element, newStr)
{
index=element.className.indexOf(newStr);
if ( index == -1)
element.className += ' '+newStr;
else
{
if (index != 0)
newStr = ' '+newStr;
element.className = element.className.replace(newStr, '');
}
}
function forEachNode(nodeList, func)
{
var i, n = nodeList.length;
for (i=0; i<n; i++)
{
func(nodeList[i], i, nodeList);
}
}
window.addEventListener('load', mInit, false);
var guitar1, tmpContext;
var instruments = [];
function mInit()
{
instruments.push(new sampledSound('audio/st88gbass.wav'));
instruments.push(new sampledSound('audio/st03church.wav'));
instruments.push(new sampledSound('audio/st88snare13.wav'));
instruments.push(new sampledSound('audio/st03bastrumma.wav'));
instruments.push(new sampledSound('audio/st03bassdrum6.wav'));
instruments.push(new sampledSound('audio/st03guitar7.wav'));
// instruments.forEach( function(elem){elem.canvas.addEventListener('click', mClick2, false);} );
/*
var rawSnd = new rawSound('audio/salida.raw.bin');
*/
tmpContext = new webkitAudioContext();
}
function getFreq(noteNum)
{
var pitch = 440.0 * Math.pow(2.0, (noteNum-45.0)/12.0);
return pitch;
}
function mClick2()
{
// function playSamples(floatArray, startTime)
// function reSample(srcArray, origNote, newNote)
var origNote = 36, newNote = 35;
var newSamples;
//var samples = this.mBuffer.getChannelData(0);
var curTime = tmpContext.currentTime;
newSamples = reSample(this.sampledSound.mBuffer.getChannelData(0), origNote, newNote);
playSamples(newSamples, curTime + 0.3);
}
function mClick()
{
var origNote = 36;
var newNote = 37;
var k = getFreq(origNote) / getFreq(newNote); //c4Hz / a3Hz;
var srcBuffer = this.sampledSound.mBuffer;
var srcSamples = srcBuffer.getChannelData(0);
// alert('continue to play note D4 - ' + k + ' * the # of samples');
var srcX, srcY, srcWidth, dstX, dstWidth, dstY;
var srcX, srcDx;
var dstSamples = new Float32Array();
dstWidth = (srcSamples.length * k) >> 0;
srcWidth = srcSamples.length;
for (dstX=0; dstX<dstWidth; dstX++)
{
srcX = ((dstX / dstWidth) * srcWidth) >> 0;
srcY = srcSamples[srcX];
dstSamples[dstX] = srcY;
}
// alert("Source samples (" + c4Hz + 'hz): ' + srcSamples.length + '\n'
// +"Dest samples (" + d4Hz + 'hz): ' + dstSamples.length);
tmpBuffer = tmpContext.createBuffer(1, dstWidth, 44100);
var datBuf = tmpBuffer.getChannelData(0);
var inBuf = dstSamples;
var i, n = dstWidth;
// datBuf = inBuf;
for (i=0; i<n; i++)
datBuf[i] = inBuf[i];
var node = tmpContext.createBufferSource();
node.buffer = tmpBuffer;
var volume = 100;
node.gain.value = 0.5 * volume/100.0;
node.connect(tmpContext.destination);
var startTime=tmpContext.currentTime;//+0.100;
node.noteOn(startTime + 0.30);
}
var patterns =
// all patterns use the organ track
[
// 0, 0, 5, 6, 6, 2, 2, 1, 1, 6, 6, 2, 2, 1, 1
[0,1,2,3], [0,1,2,3], [1,2,3,4], [1,2,3,5], [1,2,3,5], [1,2,3,6], [1,2,3,6], [1,2,3,7], [1,2,3,7], [1,2,3,5], [1,2,3,5], [1,2,3,6], [1,2,3,6], [1,2,3,7], [1,2,3,7],
// 6
[1,2,3,5], [1,2,3,4]
]
// 0,0,5,6,6,2,2,1,1,6,6,2,2,1,1,6,5,3,
var tracks =
[
// 1 - organ track
[
[31,0x82],[ 0,0x00],[ 0,0x00],[ 0,0x00],[ 0,0x00],[ 0,0x00],[ 0,0x00],[ 0,0x00],
[ 0,0x00],[ 0,0x00],[ 0,0x00],[ 0,0x00],[31,0x82],[ 0,0x00],[ 0,0x00],[ 0,0x00],
[ 0,0x00],[ 0,0x00],[ 0,0x00],[ 0,0x00],[ 0,0x00],[ 0,0x00],[ 0,0x00],[ 0,0x00],
[31,0x82],[ 0,0x00],[ 0,0x00],[ 0,0x00],[ 0,0x00],[ 0,0x00],[ 0,0x00],[ 0,0x00],
[29,0x82],[ 0,0x00],[ 0,0x00],[ 0,0x00],[ 0,0x00],[ 0,0x00],[ 0,0x00],[ 0,0x00],
[ 0,0x00],[ 0,0x00],[ 0,0x00],[29,0x82],[ 0,0x00],[ 0,0x00],[ 0,0x00],[ 0,0x00],
[ 0,0x00],[ 0,0x00],[ 0,0x00],[ 0,0x00],[ 0,0x00],[ 0,0x00],[ 0,0x00],[ 0,0x00],
[29,0x82],[ 0,0x00],[ 0,0x00],[ 0,0x00],[ 0,0x00],[ 0,0x00],[ 0,0x00],[ 0,0x00]
],
// 2 - bass drum
[
[38,1],[0,0],[0,0],[0,0],[36,1],[0,0],[38,1],[0,0],
[0,0],[0,0],[36,1],[0,0],[38,1],[0,0],[41,1],[0,0],
[0,0],[0,0],[41,1],[0,0],[0,0],[0,0],[41,1],[0,0],
[40,1],[0,0],[38,1],[0,0],[36,1],[0,0],[38,1],[0,0],
[38,1],[0,0],[0,0],[0,0],[36,1],[0,0],[38,1],[0,0],
[0,0],[0,0],[36,1],[0,0],[38,1],[0,0],[41,1],[0,0],
[0,0],[0,0],[41,1],[0,0],[0,0],[0,0],[41,1],[0,0],
[40,1],[0,0],[38,1],[0,0],[36,1],[0,0],[38,1],[0,0]
],
// 3 - bastruma and basdrumb
[
[43,4],[0,0],[47,5],[0,0],[41,3],[0,0],[47,5],[0,0],
[43,4],[0,0],[47,5],[0,0],[41,3],[0,0],[47,5],[0,0],
[43,4],[0,0],[47,5],[0,0],[41,3],[0,0],[47,5],[0,0],
[43,4],[0,0],[47,5],[0,0],[41,3],[0,0],[47,5],[0,0],
[43,4],[0,0],[47,5],[0,0],[41,3],[0,0],[47,5],[0,0],
[43,4],[0,0],[47,5],[0,0],[41,3],[0,0],[47,5],[0,0],
[43,4],[0,0],[47,5],[0,0],[41,3],[0,0],[47,5],[0,0],
[43,4],[0,0],[47,5],[0,0],[41,3],[41,3],[41,3],[41,3]
],
// 4 - guitar7
[
[43,0x06],[0,0],[38,0x86],[0,0],[41,0x86],[0,0],[47,0x46],[0,0],
[43,0x46],[0,0],[38,0x46],[0,0],[41,0x46],[0,0],[47,0x46],[0,0],
[43,0x46],[0,0],[47,0x46],[0,0],[41,0x46],[0,0],[47,0x46],[0,0],
[41,0x06],[0,0],[41,0x46],[0,0],[40,0x46],[0,0],[40,0x46],[0,0],
[38,0x06],[0,0],[33,0x86],[0,0],[38,0x46],[0,0],[33,0x46],[0,0],
[38,0x46],[0,0],[33,0x46],[0,0],[38,0x46],[0,0],[33,0x46],[0,0],
[38,0x46],[0,0],[33,0x46],[0,0],[38,0x46],[0,0],[33,0x46],[0,0],
[38,0x26],[0,0],[33,0x26],[0,0],[38,0x26],[0,0],[33,0x26],[0,0]
],
// 5 - guitar7
[
[43,0x06],[0,0],[38,0x86],[0,0],[43,0x46],[0,0],[38,0x46],[0,0],
[43,0x46],[0,0],[38,0x46],[0,0],[43,0x46],[0,0],[38,0x46],[0,0],
[43,0x06],[0,0],[38,0x86],[0,0],[43,0x46],[0,0],[38,0x46],[0,0],
[41,0x06],[0,0],[41,0x86],[0,0],[41,0x46],[0,0],[41,0x46],[0,0],
[41,0x06],[0,0],[45,0x86],[0,0],[41,0x46],[0,0],[45,0x46],[0,0],
[41,0x46],[0,0],[45,0x46],[0,0],[41,0x46],[0,0],[45,0x46],[0,0],
[38,0x06],[0,0],[33,0x86],[0,0],[38,0x06],[0,0],[45,0x86],[0,0],
[38,0x46],[0,0],[45,0x46],[0,0],[38,0x06],[0,0],[45,0x46],[0,0]
],
//
// 6 - guitar7
[
[38,0x06],[0,0],[33,0x86],[0,0],[36,0x06],[0,0],[38,0x06],[0,0],
[33,0x86],[0,0],[36,0x06],[0,0],[38,0x06],[0,0],[41,0x06],[0,0],
[36,0x86],[0,0],[41,0x06],[0,0],[36,0x86],[0,0],[41,0x06],[0,0],
[40,0x06],[0,0],[38,0x06],[0,0],[36,0x06],[0,0],[38,0x06],[0,0],
[38,0x06],[0,0],[33,0x86],[0,0],[36,0x06],[0,0],[38,0x06],[0,0],
[33,0x86],[0,0],[36,0x06],[0,0],[38,0x06],[0,0],[41,0x06],[0,0],
[36,0x86],[0,0],[41,0x06],[0,0],[36,0x86],[0,0],[41,0x06],[0,0],
[40,0x06],[0,0],[38,0x06],[0,0],[36,0x06],[0,0],[38,0x06],[0,0]
],
//
// 6 - guitar7
[
[43,0x06],[0,0],[43,0x86],[0,0],[38,0x46],[0,0],[43,0x46],[0,0],
[43,0x06],[0,0],[43,0x86],[0,0],[43,0x06],[0,0],[38,0x06],[0,0],
[43,0x86],[0,0],[38,0x46],[0,0],[43,0x46],[0,0],[38,0x06],[0,0],
[41,0x06],[0,0],[43,0x06],[0,0],[43,0x86],[0,0],[41,0x06],[0,0],
[41,0x86],[0,0],[45,0x46],[0,0],[41,0x46],[0,0],[41,0x06],[0,0],
[40,0x06],[0,0],[38,0x06],[0,0],[43,0x46],[0,0],[41,0x06],[0,0],
[41,0x86],[0,0],[45,0x46],[0,0],[41,0x46],[0,0],[45,0x46],[0,0],
[41,0x46],[0,0],[45,0x26],[0,0],[41,0x26],[0,0],[45,0x26],[0,0]
]
//
];
var rowTime = 0.12;
function playSong()
{
var numTracks = tracks.length;
var numRows = tracks[0].length;
var curRow, curTrack, curNote;
var startTime = tmpContext.currentTime + 1.0;
var newSamples;
for (curTrack=0; curTrack<numTracks; curTrack++)
{
for (curRow=0; curRow<numRows; curRow++)
{
curNote = tracks[curTrack][curRow];
if (curNote[0] != 0)
{
newSamples = new Float32Array();
newSamples = reSample( instruments[curNote[1]-1].mBuffer.getChannelData(0), 36, curNote[0]);
playSamples(newSamples, curRow * rowTime + startTime);
}
}
}
alert('numTracks: ' + numTracks + ' - numRows: ' + numRows);
}
//patterns
function playSong2()
{
var nPatterns = patterns.length;
var curPattern, patternIndex, nTracks, nRows, songRow, startTime, newSamples;
var rowTime = 0.12;
var startTime = tmpContext.currentTime + 1.0;
var curVol, curInstr;
for (patternIndex=0; patternIndex<nPatterns; patternIndex++)
{
curPattern = patterns[patternIndex];
nTracks = curPattern.length;
songRow = patternIndex * 64;
console.log(curPattern);
for (trackIndex=0; trackIndex<nTracks; trackIndex++)
{
if (curPattern[trackIndex] != 0)
{
curTrack = tracks[ curPattern[trackIndex] - 1 ];
nRows = curTrack.length;
for (rowIndex=0; rowIndex<nRows; rowIndex++)
{
curNote = curTrack[rowIndex];
if (curNote[0] != 0)
{
// var nt = newTxt('play note');
// document.body.appendChild(nt);
curVol = curNote[1] >> 4;
curInstr = (curNote[1] & 0xF) - 1;
newSamples = new Float32Array();
newSamples = reSample( instruments[curInstr].mBuffer.getChannelData(0), 36, curNote[0]);
if (curVol == 0)
playSamples(newSamples, ((songRow+rowIndex) * rowTime) + startTime);
else
playSamples(newSamples, ((songRow+rowIndex) * rowTime) + startTime, (curVol * 100) / 0x0f );
}
}
}
}
}
}
// volume is optional, range is 0..100. If not specified, 100 is used;
function playSamples(floatArray, startTime, volume)
{
var tmpBuffer = tmpContext.createBuffer(1, floatArray.length, 44100);
var datBuf = tmpBuffer.getChannelData(0);
var inBuf = floatArray;
var i, n = inBuf.length;
// datBuf = inBuf;
for (i=0; i<n; i++)
datBuf[i] = inBuf[i];
var node = tmpContext.createBufferSource();
node.buffer = tmpBuffer;
if (volume === undefined)
var volume = 100;
node.gain.value = 0.5 * volume/100.0;
node.connect(tmpContext.destination);
// var startTime=tmpContext.currentTime;//+0.100;
node.noteOn(startTime);
}
function reSample(srcArray, origNote, newNote)
{
var k = getFreq(origNote) / getFreq(newNote);
var srcWidth = srcArray.length;
var dstWidth = (srcWidth * k) >> 0;
var newSamples = new Float32Array(dstWidth);
var dstX, srcX, srcY;
for (dstX=0; dstX<dstWidth; dstX++)
{
srcX = ((dstX / dstWidth) * srcWidth) >> 0;
srcY = srcArray[srcX];
newSamples[dstX] = srcY;
}
return newSamples;
}
/* ---------------------------------------------------------------------------------------------- */
function rawSound(sndSampleUrl, canvas)
{
this.mContext = new webkitAudioContext();
this.request = new XMLHttpRequest();
this.request.open('GET', sndSampleUrl, true);
this.request.responseType = 'arraybuffer';
this.mBuffer = [];
var canvas = newEl('canvas'); //byId('output');
canvas.width = 500;
canvas.height = 100;
canvas.sampledSound = this;
document.body.appendChild(canvas);
canvas.onclick = function(){ this.sampledSound.play(); };
// Decode asynchronously
var me = this;
this.request.onload =
function(e)
{
me.mBuffer = new Int16Array(this.response);
tmpBuffer = new Int16Array(this.response);
me.convertedBuffer = [];
var i, n = tmpBuffer.length;
for (i=0; i<n; i++)
{
me.convertedBuffer[i] = tmpBuffer[i] / 32768;
}
me.mBuffer = me.mContext.createBuffer(1, n, 44100);
// var msg = newTxt('Retrieved ' + sndSampleUrl + '(' + me.request.response.byteLength + ' bytes)');
// document.body.appendChild(msg);
// document.body.appendChild(newEl('br'));
// var msg = newTxt('Samples: ' + tmpBuffer.length + ', Secs: ' + ( (((tmpBuffer.length/44100)*1000)>>0)/1000));
// document.body.appendChild(msg);
drawFloatArray(me.convertedBuffer, canvas);
//me.mContext.decodeAudioData(me.request.response, function(buffer) {me.mBuffer = buffer;me.drawSound(canvas);}, onErrorFn);
// alert('Retrieved ' + sndSampleUrl + '(' + me.request.response.byteLength + ' bytes)' );
}
this.request.send();
}
rawSound.prototype.play = function()
{
var dataBuffer = this.mBuffer.getChannelData(0);
var soundBuffer = this.convertedBuffer;
var i, n = soundBuffer.length;
for (i=0; i<n; i++)
dataBuffer[i] = soundBuffer[i];
var node = this.mContext.createBufferSource();
node.buffer = this.mBuffer;
node.gain.value = 0.5 * this.mVolume/100.0;
node.connect(this.mContext.destination);
node.noteOn(0);
}
function drawFloatArray(samples, canvas)
{
var i, n = samples.length;
var dur = (n / 44100 * 1000)>>0;
canvas.title = 'Duration: ' + dur / 1000.0 + 's';
var width=canvas.width,height=canvas.height;
var ctx = canvas.getContext('2d');
ctx.strokeStyle = 'yellow';
ctx.fillStyle = '#303030';
ctx.fillRect(0,0,width,height);
ctx.moveTo(0,height/2);
ctx.beginPath();
for (i=0; i<n; i++)
{
x = (i*width) / n;
y = (samples[i]*height/2)+height/2;
ctx.lineTo(x, y);
}
ctx.stroke();
ctx.closePath();
}
function sampledSound(sndSampleUrl, canvas)
{
this.request = new XMLHttpRequest();
this.request.open('GET', sndSampleUrl, true);
this.request.responseType = 'arraybuffer';
this.mBuffer = [];
this.mContext = new webkitAudioContext();
this.loaded = false;
var canvas = newEl('canvas'); //byId('output');
canvas.width = 500;
canvas.height = 100;
canvas.sampledSound = this;
this.canvas = canvas;
document.body.appendChild(canvas);
canvas.onclick = function(){ this.sampledSound.play(); };
// Decode asynchronously
var me = this;
this.request.onload = function(){me.mContext.decodeAudioData(me.request.response, function(buffer) {me.mBuffer = buffer;me.drawSound(canvas);me.loaded=true;}, onErrorFn);}
this.request.send();
}
sampledSound.prototype.play = function()
{
var source = this.mContext.createBufferSource();
source.buffer = this.mBuffer; //bufferList[soundIndex];
source.connect(this.mContext.destination);
source.noteOn(0);
}
sampledSound.prototype.drawSound = function(canvas)
{
// var msg = 'Canvas size: ' + canvas.width + 'x' + canvas.height + 'px';
// msg += "\n - " + this.mBuffer.duration + ' seconds';
// alert(msg);
var dur = (this.mBuffer.duration * 1000)>>0;
canvas.title = 'Duration: ' + dur / 1000.0 + 's';
canvas.width = (dur/1000 * 512)>>0;
canvas.style.width = (dur/1000 * 512)>>0 + 'px';
var width=canvas.width, height=canvas.height;
var x,y, i, n = this.mBuffer.length;
var ctx = canvas.getContext('2d');
var samples = this.mBuffer.getChannelData(0);
ctx.strokeStyle = 'yellow';
ctx.fillStyle = '#303030';
ctx.fillRect(0,0,width,height);
ctx.moveTo(0,height/2);
ctx.beginPath();
for (i=0; i<n; i++)
{
x = (i*width)/n;
y = (samples[i]*height/2)+height/2;
ctx.lineTo(x, y);
}
ctx.stroke();
ctx.closePath();
}
function onErrorFn()
{
alert('f#@ker');
}
</script>
<style>
canvas
{
/* width: 250px; */
height: 100px;
padding: 4px;
}
</style>
</head>
<body>
<button onclick='playSong2();'>playSong</button>
</body>
</html>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.