Home How to create continuous tunes with audio elements
Reply: 1

How to create continuous tunes with audio elements

sandy
1#
sandy Published in 2018-01-10 23:04:48Z

I am trying to make a simple piano based on Do Re Mi etc keys. My idea is, each sound (Do Re Mi..) will be played corresponding to the keypress event. I am collecting each valid audio element in an array in the order they are chosen by keypress. Later, once user will press the "play" button, all the sounds will be played together as a tune.

Things are working fine so far. However, during the tune playing all the sounds are played together. Seems like, they are overlapped with each other. I want the pause to be added after each sound the way they were initially played.

Ex : Do (2s pause), Re(no Pause)Re, (1s pause)Mi, Do(3s pause),....

I tried to add pause with a sleep function but it is not working. In my console output the array elements (where the audio elements and corresponding pauses are collected) are printed correctly and the pause is also taken correctly however, during the audio play the pause is not maintained. Any help is very much appreciated. Here is my code,

HTML

<!DOCTYPE html>
   <head>
    <title>do-re-mi keyboard</title>
    <link type="text/css" href="style.css" rel="stylesheet"/>
   </head>
   <body>
    <div id="main-div">
        <h1>Let's create some awesome music ....</h1>
        <div class="keys">
            <div data-key="68" class="musicKey"><p>D</p><span>(Do)</span></div>
            <div data-key="82" class="musicKey"><p>R</p><span>(Re)</span></div>
            <div data-key="77" class="musicKey"><p>M</p><span>(Mi)</span></div>
            <div data-key="70" class="musicKey"><p>F</p><span>(Fa)</span></div>
            <div data-key="83" class="musicKey"><p>S</p><span>(So)</span></div>
            <div data-key="76" class="musicKey"><p>L</p><span>(La)</span></div>
            <div data-key="84" class="musicKey"><p>T</p><span>(Ti)</span></div>
            <button id="playTune">Play</button>
            <button id="refresh">Refresh</button>
        </div>

    </div> <!--main div ends -->
    <audio data-key="68" src="audio/do.mp3" type="audio/mpeg"></audio>
    <audio data-key="82" src="audio/re.mp3" type="audio/mpeg"></audio>
    <audio data-key="77" src="audio/mi.mp3" type="audio/mpeg"></audio>
    <audio data-key="70" src="audio/fa.mp3" type="audio/mpeg"></audio>
    <audio data-key="83" src="audio/so.mp3" type="audio/mpeg"></audio>
    <audio data-key="76" src="audio/la.mp3" type="audio/mpeg"></audio>
    <audio data-key="84" src="audio/ti.mp3" type="audio/mpeg"></audio>

    <script src="soundBox.js" type="text/javascript"></script>
   </body>

</html> 

CSS

body{
    margin:0;
}

#main-div{

    height:100vh;
    width:100%;
    background-color: #ffffcc;
    background:url('image/sand.jpg');
}

h1{
    text-align: center;
    margin-top:0;
    padding-top: 50px;
    font-family: 'Rouge Script', cursive; 
    font-size: 40px; font-weight:bolder; 
    line-height: 48px; margin: 0 0 20px;
    color: #e65c00;
    text-shadow: 1px 1px 2px #803300; 
}

.keys{
    height: 200px;
    width:700px;
    position:absolute;
    top:50%;
    left:50%;
    background-color:yellow;
    transform:translate(-50%,-50%);
    align-items: center;
}

.musicKey{
    height : 80px;
    width:80px;
    border-radius: 10px;
    background-color:red;
    margin-top:60px;
    margin-left:10px;
    margin-right:10px;
    float:left;
    align-items:center;
   /* box-shadow: inset -3px -5px 2px 1px #515151;*/
    text-align:center;
    transition:all 0.07s;
}

.musicKey span{
    text-align:center;
    font-size: medium;
    padding-top:30px;
}

.musicKeyPressed{
    transform:scale(1.1);
    border-color:black;
    box-shadow: 3px 1px 1px 1px #515151;
}

#playTune{
    float:right;
    height:40px;
    width:80px;
    background-color:gray;
    margin:10px;
}

#refresh{

    float:right;
    height:40px;
    width:80px;
    background-color:green;
    margin:10px;

}

JavaScript

document.addEventListener("keydown",playMusic);

let keyArr = document.querySelectorAll(".musicKey");

var audioKeyProp = {};
var tune = [];
var keyCount =0;
var start =0;
var oldStart =0;

function sleepFunc(time) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e7; i++) {
    if ((new Date().getTime() - start) > time){
      break;
    }
  }
}

document.getElementById("refresh").addEventListener("click",function(){
    tune = [];
    start =0;
    oldStart =0;
    keyCount =0;
});

document.getElementById("playTune").addEventListener("click",function(){

    //console.log("tune array = " + tune);
    if(tune.length > 0)
    {
        tune.forEach(function(item){
           // console.log("tune item = "+ item);
            if(typeof(item) === "number")
            {
                sleepFunc(item);
            }
            else
            {
                item.play();
                item.currentTime=0;
            }

            });
    }

});

keyArr.forEach(function(item){

    let tempVal = item.getAttribute('data-key');
    audioKeyProp[tempVal] = document.querySelector(`audio[data-key="${tempVal}"]`);
});

function backToOriginalPosition(e)
{
    if(e.propertyName !== "transform") return;
    this.classList.remove("musicKeyPressed");
}

function playMusic(event)
{
    var pressedKey = event.keyCode;
    var timeElapse = 0;
    start = new Date().getTime();

    if(keyCount >= 1)
    {
        timeElapse = start - oldStart;
    }

    var keyDiv = document.querySelector(`div[data-key="${pressedKey}"]`);
    var audioElement = audioKeyProp[pressedKey];

    if(audioElement && keyDiv)
    {
        console.log("duration= " + audioElement.duration);
        oldStart = start;
        keyCount++;
        tune.push(timeElapse);
        tune.push(audioElement);

        audioElement.currentTime =0;
        audioElement.play();
        keyDiv.classList.add("musicKeyPressed");
        keyDiv.addEventListener("transitionend",backToOriginalPosition);
    }
   }
Omer
2#
Omer Reply to 2018-01-11 10:41:53Z

Try declaring a variable outside a setInterval which will be equal to 0, let's say var noteIndex = 0. Inside the setInterval play the first note: tune[noteIndex] and then increment noteIndex.

So your code should be something like that:

var tune = [];                      //Set tunes to play
var pause = [];                     //Set tunes breaks
var noteIndex = 0;

var playNotes = setInterval(function(){
    tune[noteIndex].play();
    noteIndex++;
    if (noteIndex > tune.length) {  //Stop the interval if all notes are played.
        noteIndex = 0;              //Reset 'noteIndex' for next use.
        break;
    }
}, pause[noteIndex]);

Hope this helps.

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.33355 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO