Я настраиваю веб -страницу, которая будет использоваться барабанщиками для практики шаблонов. функциональный) < /li>
< /ol>
Проблема заключается в синхронизации прокрутки баллов до метронома. На данный момент я использую чисто эмпирические значения, потому что, когда я пытался вычислить расстояния и использовал Settimeout, чтобы прокрутить счет, который я не смог получить удовлетворительный результат. Exemple. < /li>
Вертикальная планка в середине холста является эталонной точкой. Когда примечание достигает этой панели, будет воспроизведен звук, чтобы пользователь мог услышать, какой ударный элемент должен быть воспроизведен и как (Snare Max Vol или Min Vol в этом примере). < /Li>
< /ol>
Сценарий выполняет работу, но является довольно приблизительным. Чтобы сценарий был использован, должна быть очень хорошая синхронизация между метрономом и примечаниями, достигающими справочной панели. class = "lang-html prettyprint-override">
DrumChallenge.com
#div_patterns {
display: inline-block;
margin: 20px;
}
#div_tempo {
display: inline-block;
margin: 20px;
}
#drumscore {
position: relative;
width: 100%;
height: 200px;
}
#drumscore canvas {
position: absolute;
top: 0px;
left: 0px;
}
canvas {
border: 1px solid black;
width: 100%;
height: 200px;
}
Tempo :
Delai :
Timer :
Lancer challenge
document.addEventListener('DOMContentLoaded', () => {
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
const metronome = new Metronome(audioContext);
var Current_Audio = false;
var Challenge_Launched = false;
var Current_Animation = false;
var Timer_Challenge = false;
var Timer_General = false;
var Tempo = 60;
var Delai;
var Distance_Between_Notes = 30;
var General_Timer = 0;
var NextNoteTime = 0;
//
//
//
const LaunchButton = document.getElementById('launch');
LaunchButton.addEventListener('click', function(){
if (Challenge_Launched == false){
CreerChallenge();
Challenge_Launched = true;
const bpm = parseInt(InputTempo.value, 10);
metronome.setTempo(bpm);
metronome.start();
Timer_General = setInterval(SetGeneralTimer, 1000);
NextNoteTime = performance.now();
//drawNotes();
requestAnimationFrame(drawNotes);
} else {
Challenge_Launched = false;
clearTimeout(Timer_Challenge);
clearInterval(Timer_General);
metronome.stop();
//cancelAnimationFrame(Current_Animation);
}
});
//
//
//
function SetTempo(){
Tempo = InputTempo.value;
Delai = (60000 / Tempo).toFixed(2);
document.getElementById('value_tempo').innerHTML = Tempo;
document.getElementById('value_delai').innerHTML = Delai + 'ms';
metronome.setTempo(Tempo);
/*if (Challenge_Launched){
clearTimeout(Timer_Challenge);
//Timer_Challenge = setTimeout(drawNotes, Delai);
}*/
}
//
//
//
const InputTempo = document.getElementById('value_tempo');
InputTempo.addEventListener('blur', function(){
SetTempo()
});
SetTempo()
//
//
//
const drumscore = document.getElementById('drumscore');
//
// Canvas et contexte de la partition
//
const score = document.getElementById('score');
const scorectx = score.getContext('2d');
scorectx.canvas.width = drumscore.offsetWidth;
scorectx.canvas.height = drumscore.offsetHeight;
//
// Canvas et contexte des notes
//
const canvas = document.getElementById('scoreCanvas');
const ctx = canvas.getContext('2d');
ctx.canvas.width = drumscore.offsetWidth;
ctx.canvas.height = drumscore.offsetHeight;
//
// Lignes de la partition
//
const ScoreLines = [60,80,100,120,140];
//
//
//
const Elements = [
{Name: 'Snare', Line: ScoreLines[2]}
];
//
// Patterns
//
const Patterns = [
{
Name: 'Rll',
Element: 'Snare',
Notes: ['R', 'l', 'l'],
Checkbox: false,
Label: false,
Checked: false,
},
{
Name: 'rrL',
Element: 'Snare',
Notes: ['r', 'r', 'L'],
Checkbox: false,
Label: false,
Checked: false,
}
];
//
// Affichage patterns
//
const DivPatterns = document.getElementById('div_patterns');
Patterns.forEach(pattern => {
pattern.Checkbox = document.createElement('input');
pattern.Checkbox.type = "checkbox";
pattern.Label = document.createElement('label')
pattern.Label.htmlFor = pattern.Name;
pattern.Label.appendChild(document.createTextNode(pattern.Name));
DivPatterns.appendChild(pattern.Checkbox);
DivPatterns.appendChild(pattern.Label);
});
//
// Sounds
//
const Sounds = [
{
Element: 'Snare',
Type: 'Normal',
URL: '',
Audio: new Audio('snare_normal.wav')
},
{
Element: 'Snare',
Type: 'Ghost',
Audio: new Audio('snare_ghost.wav')
}
];
//
// Notes à afficher
//
const measures = 20;
const noteWidth = 10;
const noteHeight = 10;
const scrollSpeed = 3;
//
// Main Droite ou Gauche
//
const isAccented = str => str === str.toUpperCase();
const isRightHand = str => str.toUpperCase() === 'R';
//
// Créer le challenge
//
var notes = [];
var current_pattern;
//
// Dessiner la partition
//
function CreerChallenge() {
notes = [];
for (var i=0 ; i {
//ctx.fillRect(note.x, note.y, note.w, note.w);
ctx.beginPath();
ctx.ellipse(note.x, note.y, note.w, note.h, Math.PI, 0, 2 * Math.PI);
ctx.fill();
if (note.x > canvas.width / 2 - 5 && note.x requestAnimationFrame(drawNotes), 1);
}
}
function SetGeneralTimer(){
const startTime = performance.now()
General_Timer++;
document.getElementById('value_timer').innerHTML = General_Timer
const endTime = performance.now()
//console.log(`Started ` + startTime + ' | ' + (endTime - startTime) + ' | ' + General_Timer)
}
drawScore();
});
< /code>
и класс Metronome: < /p>
class Metronome {
constructor(context) {
this.context = context;
this.isPlaying = false;
this.current16thNote = 0;
this.tempo = 60;
this.lookahead = 25.0;
this.scheduleAheadTime = 0.1;
this.nextNoteTime = 0.0;
this.timerID = null;
}
nextNote() {
const secondsPerBeat = 60.0 / this.tempo;
this.nextNoteTime += 0.25 * secondsPerBeat;
this.current16thNote++;
if (this.current16thNote === 16) {
this.current16thNote = 0;
}
}
scheduleNote(beatNumber, time) {
const osc = this.context.createOscillator();
const envelope = this.context.createGain();
osc.frequency.value = (beatNumber % 4 === 0) ? 1000 : 800;
envelope.gain.value = 1;
envelope.gain.exponentialRampToValueAtTime(0.001, time + 0.2);
osc.connect(envelope);
envelope.connect(this.context.destination);
osc.start(time);
osc.stop(time + 0.2);
}
scheduler() {
console.log(this.nextNoteTime);
console.log(this.context.currentTime);
console.log(this.scheduleAheadTime);
while (this.nextNoteTime < this.context.currentTime + this.scheduleAheadTime) {
this.scheduleNote(this.current16thNote, this.nextNoteTime);
this.nextNote();
}
this.timerID = setTimeout(this.scheduler.bind(this), this.lookahead);
}
start() {
if (!this.isPlaying) {
this.isPlaying = true;
this.current16thNote = 0;
this.nextNoteTime = this.context.currentTime;
this.scheduler();
}
}
stop() {
this.isPlaying = false;
clearTimeout(this.timerID);
}
setTempo(newTempo) {
this.tempo = newTempo;
}
}
Подробнее здесь: https://stackoverflow.com/questions/795 ... -scrolling
Синхронизация звука с прокруткой счетов ⇐ Javascript
Форум по Javascript
1744210733
Anonymous
Я настраиваю веб -страницу, которая будет использоваться барабанщиками для практики шаблонов. функциональный) < /li>
< /ol>
Проблема заключается в синхронизации прокрутки баллов до метронома. На данный момент я использую чисто эмпирические значения, потому что, когда я пытался вычислить расстояния и использовал Settimeout, чтобы прокрутить счет, который я не смог получить удовлетворительный результат. Exemple. < /li>
Вертикальная планка в середине холста является эталонной точкой. Когда примечание достигает этой панели, будет воспроизведен звук, чтобы пользователь мог услышать, какой ударный элемент должен быть воспроизведен и как (Snare Max Vol или Min Vol в этом примере). < /Li>
< /ol>
Сценарий выполняет работу, но является довольно приблизительным. Чтобы сценарий был использован, должна быть очень хорошая синхронизация между метрономом и примечаниями, достигающими справочной панели. class = "lang-html prettyprint-override">
DrumChallenge.com
#div_patterns {
display: inline-block;
margin: 20px;
}
#div_tempo {
display: inline-block;
margin: 20px;
}
#drumscore {
position: relative;
width: 100%;
height: 200px;
}
#drumscore canvas {
position: absolute;
top: 0px;
left: 0px;
}
canvas {
border: 1px solid black;
width: 100%;
height: 200px;
}
Tempo :
Delai :
Timer :
Lancer challenge
document.addEventListener('DOMContentLoaded', () => {
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
const metronome = new Metronome(audioContext);
var Current_Audio = false;
var Challenge_Launched = false;
var Current_Animation = false;
var Timer_Challenge = false;
var Timer_General = false;
var Tempo = 60;
var Delai;
var Distance_Between_Notes = 30;
var General_Timer = 0;
var NextNoteTime = 0;
//
//
//
const LaunchButton = document.getElementById('launch');
LaunchButton.addEventListener('click', function(){
if (Challenge_Launched == false){
CreerChallenge();
Challenge_Launched = true;
const bpm = parseInt(InputTempo.value, 10);
metronome.setTempo(bpm);
metronome.start();
Timer_General = setInterval(SetGeneralTimer, 1000);
NextNoteTime = performance.now();
//drawNotes();
requestAnimationFrame(drawNotes);
} else {
Challenge_Launched = false;
clearTimeout(Timer_Challenge);
clearInterval(Timer_General);
metronome.stop();
//cancelAnimationFrame(Current_Animation);
}
});
//
//
//
function SetTempo(){
Tempo = InputTempo.value;
Delai = (60000 / Tempo).toFixed(2);
document.getElementById('value_tempo').innerHTML = Tempo;
document.getElementById('value_delai').innerHTML = Delai + 'ms';
metronome.setTempo(Tempo);
/*if (Challenge_Launched){
clearTimeout(Timer_Challenge);
//Timer_Challenge = setTimeout(drawNotes, Delai);
}*/
}
//
//
//
const InputTempo = document.getElementById('value_tempo');
InputTempo.addEventListener('blur', function(){
SetTempo()
});
SetTempo()
//
//
//
const drumscore = document.getElementById('drumscore');
//
// Canvas et contexte de la partition
//
const score = document.getElementById('score');
const scorectx = score.getContext('2d');
scorectx.canvas.width = drumscore.offsetWidth;
scorectx.canvas.height = drumscore.offsetHeight;
//
// Canvas et contexte des notes
//
const canvas = document.getElementById('scoreCanvas');
const ctx = canvas.getContext('2d');
ctx.canvas.width = drumscore.offsetWidth;
ctx.canvas.height = drumscore.offsetHeight;
//
// Lignes de la partition
//
const ScoreLines = [60,80,100,120,140];
//
//
//
const Elements = [
{Name: 'Snare', Line: ScoreLines[2]}
];
//
// Patterns
//
const Patterns = [
{
Name: 'Rll',
Element: 'Snare',
Notes: ['R', 'l', 'l'],
Checkbox: false,
Label: false,
Checked: false,
},
{
Name: 'rrL',
Element: 'Snare',
Notes: ['r', 'r', 'L'],
Checkbox: false,
Label: false,
Checked: false,
}
];
//
// Affichage patterns
//
const DivPatterns = document.getElementById('div_patterns');
Patterns.forEach(pattern => {
pattern.Checkbox = document.createElement('input');
pattern.Checkbox.type = "checkbox";
pattern.Label = document.createElement('label')
pattern.Label.htmlFor = pattern.Name;
pattern.Label.appendChild(document.createTextNode(pattern.Name));
DivPatterns.appendChild(pattern.Checkbox);
DivPatterns.appendChild(pattern.Label);
});
//
// Sounds
//
const Sounds = [
{
Element: 'Snare',
Type: 'Normal',
URL: '',
Audio: new Audio('snare_normal.wav')
},
{
Element: 'Snare',
Type: 'Ghost',
Audio: new Audio('snare_ghost.wav')
}
];
//
// Notes à afficher
//
const measures = 20;
const noteWidth = 10;
const noteHeight = 10;
const scrollSpeed = 3;
//
// Main Droite ou Gauche
//
const isAccented = str => str === str.toUpperCase();
const isRightHand = str => str.toUpperCase() === 'R';
//
// Créer le challenge
//
var notes = [];
var current_pattern;
//
// Dessiner la partition
//
function CreerChallenge() {
notes = [];
for (var i=0 ; i {
//ctx.fillRect(note.x, note.y, note.w, note.w);
ctx.beginPath();
ctx.ellipse(note.x, note.y, note.w, note.h, Math.PI, 0, 2 * Math.PI);
ctx.fill();
if (note.x > canvas.width / 2 - 5 && note.x requestAnimationFrame(drawNotes), 1);
}
}
function SetGeneralTimer(){
const startTime = performance.now()
General_Timer++;
document.getElementById('value_timer').innerHTML = General_Timer
const endTime = performance.now()
//console.log(`Started ` + startTime + ' | ' + (endTime - startTime) + ' | ' + General_Timer)
}
drawScore();
});
< /code>
и класс Metronome: < /p>
class Metronome {
constructor(context) {
this.context = context;
this.isPlaying = false;
this.current16thNote = 0;
this.tempo = 60;
this.lookahead = 25.0;
this.scheduleAheadTime = 0.1;
this.nextNoteTime = 0.0;
this.timerID = null;
}
nextNote() {
const secondsPerBeat = 60.0 / this.tempo;
this.nextNoteTime += 0.25 * secondsPerBeat;
this.current16thNote++;
if (this.current16thNote === 16) {
this.current16thNote = 0;
}
}
scheduleNote(beatNumber, time) {
const osc = this.context.createOscillator();
const envelope = this.context.createGain();
osc.frequency.value = (beatNumber % 4 === 0) ? 1000 : 800;
envelope.gain.value = 1;
envelope.gain.exponentialRampToValueAtTime(0.001, time + 0.2);
osc.connect(envelope);
envelope.connect(this.context.destination);
osc.start(time);
osc.stop(time + 0.2);
}
scheduler() {
console.log(this.nextNoteTime);
console.log(this.context.currentTime);
console.log(this.scheduleAheadTime);
while (this.nextNoteTime < this.context.currentTime + this.scheduleAheadTime) {
this.scheduleNote(this.current16thNote, this.nextNoteTime);
this.nextNote();
}
this.timerID = setTimeout(this.scheduler.bind(this), this.lookahead);
}
start() {
if (!this.isPlaying) {
this.isPlaying = true;
this.current16thNote = 0;
this.nextNoteTime = this.context.currentTime;
this.scheduler();
}
}
stop() {
this.isPlaying = false;
clearTimeout(this.timerID);
}
setTempo(newTempo) {
this.tempo = newTempo;
}
}
Подробнее здесь: [url]https://stackoverflow.com/questions/79564596/syncing-audio-with-score-scrolling[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия