我有以下問題: 我試圖用javascipt等實現音樂應用程序。 我已經剖析了引擎和UI中的模塊體系結構。我的問題在於引擎模塊。 基本上我有一個主引擎模塊停止多個setTimeout實例
var NoteEngine = (function(){
var that = {},
matrices = [],
beatCount = 1,
globalBPM = 100,
init = function(count){
window.AudioContext = window.AudioContext || window.webkitAudioContext;
context = new AudioContext();
_registerListener();
beatCount = count;
matrices = [
new NoteMatrix("piano", (16 * beatCount), globalBPM),
new NoteMatrix("guitar", (16 * beatCount), globalBPM),
new NoteMatrix("bass", (16 * beatCount), globalBPM),
new NoteMatrix("bell", (16 * beatCount), globalBPM)
];
},
_registerListener = function(){
};
that.init = init;
return that;
})();
一類以加載的聲音和創建的所有行
function NoteMatrix(instrument, colCount, bpm){
var rows = [],
matrixInstrument = instrument,
bufferLoader,
bufferList;
_loadBuffer();
function _loadBuffer(){
var notePaths = _createNoteFilePaths();
bufferLoader = new BufferLoader(
context,
notePaths,
_finishedLoading);
bufferLoader.load();
}
function _createNoteFilePaths(){
var basePath = "res/notes/" + matrixInstrument + "/",
scale = ['C6', 'A5', 'G5', 'E5', 'D5', 'C5', 'A4', 'G4', 'E4', 'D4', 'C4', 'A3', 'G3', 'E3', 'D3', 'C3'],
result = [];
for(var i = 0; i < 16; i++){
result[i] = basePath + scale[i] + ".mp3";
}
return result;
}
function _finishedLoading(buffer){
$("body").trigger("MODULE_FINISHED");
bufferList = buffer;
_createMatrix();
}
function _createMatrix(){
for(var i = 0; i < 16; i++){
rows[i] = new NoteRow(matrixInstrument, colCount, bpm, i, (i*colCount), (((i+1)*colCount) - 1), bufferList[i]);
}
}
}
和另一亞類中,以管理每個儀器的單排
function NoteRow(instrument, loopLength, bpm, row, minID, maxID, buffer){
var noteBuffer = buffer, // Notenklang in Bufferform
gainNode = null, // Hauptknoten für Ausgabe (auch lautstärke)
volume, // Gesamtlautstärke
notes = [], // Enthält alle Notenzustände in der Schleife (taktübergreifend)
rowInstrument = instrument, // Instrumentname in Stringform (für Abgleiche)
timeoutID = null, // Zuständig für Wiederholung/Stop der Schleife
isPlaying = false, // Status ob Schleife spielt oder nicht
current16thNote = 0, // Aktuelle Position in der Schleife
rowBPM = bpm, // Tempo der Schleife
scheduleDelay = 0, // Verzögerung der Wiederholung der Planschleife (in ms)
scheduleAheadTime = 0.1, // Abdeckung der Planschleife (in s)
nextNoteTime = 0.0; // Startzeit der nächsten Note
_init();
_registerListener();
// Initialisiert die Notenreihe
function _init(){
gainNode = context.createGain();
volume = 2.5;
gainNode.gain.value = volume;
for(var i = 0; i < loopLength; i++){
notes[i] = false;
}
}
// Registriert alle Listener für die Notenreihe
function _registerListener(){
$("body").on("CELL_CLICKED", _toggleNote);
$("body").on("PLAY", _play);
$("body").on("STOP", _stop);
$("body").on("VOLUME_CHANGE", _changeVolume);
$("body").on("BPM_CHANGE", _changeBPM);
$("body").on("MUTE", _mute);
$("body").on("RESUME_SOUND", _resumeSound);
$("body").on("REFRESH_ALL", _refresh);
}
// Schaltet eine Note um
function _toggleNote(event, data){
if(data.instrument == rowInstrument && (data.id >= minID && data.id <= maxID)){
console.log(data);
notes[data.id - minID] = !notes[data.id - minID];
}
}
function _play(){
current16thNote = 0;
nextNoteTime = context.currentTime;
_startScheduler();
}
function _stop(){
clearTimeout(timeoutId);
}
function _handlePlayback(){
isPlaying = !isPlaying;
if(isPlaying) {
current16thNote = 0;
nextNoteTime = context.currentTime;
_startScheduler();
}else{
clearTimeout(timeoutId);
}
}
// Schaltet die Notenreihe stumm
function _mute(){
gainNode.gain.value = 0;
}
// Stellt die ursprüngliche Lautstärke der Notenreihe wieder her
function _resumeSound(){
gainNode.gain.value = volume;
}
// Setzt die Notenreihe zurück
function _refresh(){
for(var i = 0; i < notes.length; i++){
notes[i] = false;
}
}
// Ändert die Lautstärke der Notenreihe
function _changeVolume(event, data){
volume = data/20;
gainNode.gain.value = volume;
}
// Ändert das Tempo der Notenreihe
function _changeBPM(event, data){
rowBPM = data;
}
// Startet die Playback Schleife, die immer wieder abprüft,
// ob im vorgelegten Zeitraum eine Note abgespielt werden soll
function _startScheduler(){
while (nextNoteTime < context.currentTime + scheduleAheadTime) {
_scheduleNote(current16thNote, nextNoteTime);
_nextNote();
}
timeoutId = setTimeout(_startScheduler, scheduleDelay);
}
// Spielt die Note und aktiviert die entsprechende Animation
function _scheduleNote(beatPosition, time){
if(notes[beatPosition]){
var voice = context.createBufferSource();
voice.buffer = noteBuffer;
voice.connect(gainNode);
gainNode.connect(context.destination);
voice.start(time);
$("#" + (minID + beatPosition)).addClass("animation");
setTimeout(function(){
$("#" + (minID + beatPosition)).removeClass("animation");
}, 100);
}
}
// Verschiebt die Position der Schleife nach vorne
// Abhängig vom Tempo legt es auch das Interval zur nächsten Note fest
function _nextNote(){
var secondsPerBeat = 60.0/rowBPM;
nextNoteTime += 0.25 * secondsPerBeat;
current16thNote++;
if (current16thNote == loopLength) {
current16thNote = 0;
}
}
}
我的問題在於NoteRows。您可能會看到來自NoteRow類的對象使用特定筆記管理特定樂器中的整行。一切正常,除非我無法用clearTimeout停止播放循環。有什麼建議? (可能不會改變整個架構)
我們能看到整個動物的某個地方嗎? – Flint 2015-04-04 19:53:12
我不認爲這很重要,因爲在這個問題上,用戶界面和引擎不依賴於彼此。在http://132.199.139.24/~krm22840/Note16/index.html – sixeco 2015-04-04 20:28:19
有一個較舊的版本(不幸的是,有任何音樂功能)讓我quess,莫? ; P – Igle 2015-04-04 20:45:57