我如何捕捉什么按钮被按下的序列,何时
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中找到的。在这段代码中,我只是简单地播放音符,以响应乐器样本上的点击。从内存中,您可以使用. 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播放器"-这首歌大约2m18秒长,磁盘上只有25kb,因为它使用8khz或11khz的8bit单声道样本-还没有设法定义一些声音足够接近他们的算法,所以我只是使用我从中提取的was。
与这个问题最相关的功能应该在playSong2()中找到。这将获得歌曲中每个0.12秒的步骤中每个乐器的当前音符。它对音符进行重新采样,使其更长或更短,以便获得所需的不同音高,然后将数据发送出去,以便与调用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);
}
}
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>
- 滚动然后捕捉到顶部而不是取消捕捉
- 浏览器何时记录历史记录
- 为什么要对define.md和module.exports进行条件检查,以及条件何时通过
- 让javascript知道epub3电子书中何时播放媒体覆盖
- 如何判断何时将dom节点添加到文档中
- 在一个页面中具有多个捕捉绘图和捕捉内容
- “createImageData()”和“new ImageData(()”有何不同
- 如何确定Vue何时完成DOM更新
- Express.js和multer:如何知道文件何时全部上传
- 何时可以;我的用户脚本在Javascript中触发右键单击(上下文菜单)
- jQuery:如何检测用户何时再次滚动到顶部
- 如何在浏览器窗口变大/变小时捕捉元素的宽度
- Google Chrome扩展程序可以检测所有脚本何时加载完成吗
- 点击AngularJS模态窗口捕捉背景事件
- 在Javascript(jquery)中,有没有一种方法可以检测页面锚点何时更改
- 如何通过angular JS映射捕捉SVG圆
- 询问用户何时尝试关闭浏览器选项卡
- 捕捉TAB键按下键向上
- jQuery UI可拖动:自定义捕捉方法
- 我如何捕捉什么按钮被按下的序列,何时