You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I looked over the examples and while all of the kinds of things I want to do are included in one or more examples, the design patterns they use (how the render the ABC, how they set up the synth player, how the handle callbacks, etc.) are so different I just feel very confused.
I started with the simple example of editor and player. I added to the page a set of controls to edit tempo, swing, key (transposition), pitch, instrument, and chords. (It may not currently be possible to alter the reference pitch.) These controls are connected to a callback function called updatePlayerSettings that doesn't actually do anything other than print the values of the controls.
Could someone show me how I can actually alter the player in this callback?
<!DOCTYPE html><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport" content="width=device-width, initial-scale=1.0"><title>Tune Learning App with ABC Editor and Player</title><linkrel="stylesheet" href="https://cdn.jsdelivr.net/npm/sakura.css/css/sakura.css" type="text/css"><linkrel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/abcjs-audio.min.css"><scriptsrc="https://cdn.jsdelivr.net/npm/[email protected]/dist/abcjs-basic-min.min.js"></script></head><style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
.control-group {
margin-bottom: 20px;
}
.slider-container {
display: flex;
align-items: center;
}
.slider-container input[type="range"] {
flex-grow: 1;
margin: 0 10px;
}
#abc-editor {
width: 100%;
height: 200px;
font-family: monospace;
margin-bottom: 20px;
}
#control-values {
white-space: pre-wrap;
font-family: monospace;
background-color: #f0f0f0;
padding: 10px;
border-radius: 5px;
color: black;
}
</style><scriptsrc="abcjs-basic.js"></script></head><body><h1>Tune Learning App</h1><!-- ABC Editor --><textareaid="abc-editor">X:1
T:Tune
M:4/4
L:1/8
K:D
|"D"DFAF|"G"GBdG|"A"cAEC|"D"D4 z4||</textarea><!-- ABC Player --><divid="paper"></div><divid="audio"></div><!-- Controls --><formid="controls"><divid="swing-control"></div><divid="tempo-control"></div><divid="pitch-control"></div><divid="octave-control"></div><divid="key-control"></div><divid="instrument-control"></div><divid="chords-control" class="control-group"><labelfor="play-chords">Play Chords:</label><inputtype="checkbox" id="play-chords" name="play-chords"></div></form><h2>Control Values:</h2><divid="control-values"></div><script>letsynthControl;// Reusable function to create a slider+arrows+entry controlfunctionsliderControl(low,high,small_increment,large_increment,defaultValue,name,has_toggle,initial_toggle=false){name=name.toLowerCase();consttoggle=has_toggle ? `<input type="checkbox" id="${name}-toggle" name="${name}-toggle" ${initial_toggle ? "checked" : ""}>` : "";constsliderHTML=` <div class="control-group"> <label for="${name}">${name.charAt(0).toUpperCase()+name.slice(1)}</label> <div class="slider-container">${toggle} <button type="button" id="${name}-big-dec"><<</button> <button type="button" id="${name}-small-dec"><</button> <input type="range" id="${name}" name="${name}" min="${low}" max="${high}" value="${defaultValue}" ${initial_toggle ? "" : "disabled"}> <button type="button" id="${name}-small-inc">></button> <button type="button" id="${name}-big-inc">>></button> <input type="number" id="${name}-value" min="${low}" max="${high}" value="${defaultValue}" ${initial_toggle ? "" : "disabled"}> </div> </div>`;consttempDiv=document.createElement('div');tempDiv.innerHTML=sliderHTML.trim();returntempDiv.firstChild;}// Add key and instrument selection programmaticallyfunctionaddKeyControl(){constkeys=['C','C#','D','D#','E','F','F#','G','G#','A','A#','B'];constkeyControl=document.createElement('div');keyControl.classList.add('control-group');keyControl.innerHTML=` <label for="key">Key:</label> <select id="key"></select> <button type="button" id="key-down"><</button> <button type="button" id="key-up">></button> `;document.getElementById('key-control').appendChild(keyControl);constkeySelect=document.getElementById('key');keys.forEach(key=>{constoption=document.createElement('option');option.value=key;option.textContent=key;keySelect.appendChild(option);});document.getElementById('key-down').addEventListener('click',function(){constcurrentIndex=keys.indexOf(keySelect.value);if(currentIndex>0){keySelect.value=keys[currentIndex-1];updatePlayerSettings();}});document.getElementById('key-up').addEventListener('click',function(){constcurrentIndex=keys.indexOf(keySelect.value);if(currentIndex<keys.length-1){keySelect.value=keys[currentIndex+1];updatePlayerSettings();}});}functionaddInstrumentControl(){constinstruments=['piano','violin','flute'];constinstrumentControl=document.createElement('div');instrumentControl.classList.add('control-group');instrumentControl.innerHTML=` <label for="instrument">Instrument:</label> <select id="instrument"></select> `;document.getElementById('instrument-control').appendChild(instrumentControl);constinstrumentSelect=document.getElementById('instrument');instruments.forEach(inst=>{constoption=document.createElement('option');option.value=inst;option.textContent=inst.charAt(0).toUpperCase()+inst.slice(1);instrumentSelect.appendChild(option);});instrumentSelect.addEventListener('change',updatePlayerSettings);}// Function to handle all increment and decrement actionsfunctionaddIncrementDecrementEvents(name,slider,stepValues){const{ small, big }=stepValues;constmin=parseInt(slider.min);constmax=parseInt(slider.max);constupdateValue=(step)=>updateControlValue(name,step,min,max);document.getElementById(`${name}-big-dec`).addEventListener('click',()=>updateValue(-big));document.getElementById(`${name}-small-dec`).addEventListener('click',()=>updateValue(-small));document.getElementById(`${name}-small-inc`).addEventListener('click',()=>updateValue(small));document.getElementById(`${name}-big-inc`).addEventListener('click',()=>updateValue(big));}// Function to add event listeners to controlsfunctionaddSliderEvents(name){constslider=document.getElementById(name);constnumberInput=document.getElementById(`${name}-value`);// Sync slider with number inputslider.addEventListener('input',function(){numberInput.value=slider.value;updatePlayerSettings();});numberInput.addEventListener('change',function(){slider.value=numberInput.value;updatePlayerSettings();});// Increment and decrement buttonsaddIncrementDecrementEvents(name,slider,{small: 1,big: 10});// Optional toggle handlingconsttoggle=document.getElementById(`${name}-toggle`);if(toggle){toggle.addEventListener('change',function(){slider.disabled=!this.checked;numberInput.disabled=!this.checked;updatePlayerSettings();});}}// Add sliders to the formdocument.getElementById('swing-control').appendChild(sliderControl(0,100,1,10,0,'Swing',true,false));document.getElementById('tempo-control').appendChild(sliderControl(60,200,1,10,120,'Tempo',false,false));document.getElementById('pitch-control').appendChild(sliderControl(-100,100,1,10,0,'Pitch',false,false));document.getElementById('octave-control').appendChild(sliderControl(-2,2,1,2,0,'Octave',false,false));// Add key and instrument controlsaddKeyControl();addInstrumentControl();document.getElementById('play-chords').addEventListener('change',updatePlayerSettings);// Add events to the sliders['swing','tempo','pitch','octave'].forEach(addSliderEvents);// Generic control value update functionfunctionupdateControlValue(id,step,min,max){constslider=document.getElementById(id);constnumberInput=document.getElementById(`${id}-value`);letnewValue=parseInt(slider.value)+step;newValue=Math.max(min,Math.min(max,newValue));slider.value=newValue;numberInput.value=newValue;updatePlayerSettings();}/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*//* Actual ABCJS Stuff */// Function to update player with values from the UI.// This currently does nothing other than print the values.functionupdatePlayerSettings(){constcontrolValues={swing: document.getElementById('swing').value,tempo: document.getElementById('tempo').value,pitch: document.getElementById('pitch').value,octave: document.getElementById('octave').value,key: document.getElementById('key').value,instrument: document.getElementById('instrument').value,playChords: document.getElementById('play-chords').checked};document.getElementById('control-values').textContent=JSON.stringify(controlValues,null,2);}// ABCJS renderingconstabcEditor=document.getElementById('abc-editor');functionrenderAbc(){constabcOptions={add_classes: true};constvisualObj=ABCJS.renderAbc("paper",abcEditor.value,abcOptions)[0];if(ABCJS.synth.supportsAudio()){if(!synthControl){synthControl=newABCJS.synth.SynthController();synthControl.load("#audio",null,{displayLoop: true,displayPlay: true});}synthControl.setTune(visualObj,false,{qpm: document.getElementById('tempo').value}).then(function(){console.log("Audio loaded");}).catch(function(error){console.warn("Audio problem:",error);});}}// ABC editor change eventabcEditor.addEventListener('input',renderAbc);// Initial ABC renderrenderAbc();// Initial update of control valuesupdatePlayerSettings();</script></body></html>
The text was updated successfully, but these errors were encountered:
I looked over the examples and while all of the kinds of things I want to do are included in one or more examples, the design patterns they use (how the render the ABC, how they set up the synth player, how the handle callbacks, etc.) are so different I just feel very confused.
I started with the simple example of editor and player. I added to the page a set of controls to edit tempo, swing, key (transposition), pitch, instrument, and chords. (It may not currently be possible to alter the reference pitch.) These controls are connected to a callback function called
updatePlayerSettings
that doesn't actually do anything other than print the values of the controls.Could someone show me how I can actually alter the player in this callback?
The text was updated successfully, but these errors were encountered: