如何使用音频元素创建连续音乐

时间:2018-01-10 23:04:48

标签: javascript html5 audio

我正在尝试根据Do Re Mi等键制作一个简单的钢琴。我的想法是,每个声音(Do Re Mi ..)将对应于按键事件播放。我按照按键选择的顺序收集数组中的每个有效音频元素。之后,一旦用户按下“播放”按钮,所有声音将作为曲调一起播放。

到目前为止,情况正常。但是,在曲调播放期间,所有声音都在一起播放。似乎,它们彼此重叠。我希望在每个声音之后添加暂停,就像它们最初播放的方式一样。

  

Ex:做(2s暂停),Re(没有暂停)Re,(1s暂停)Mi,Do(3s暂停),....

我尝试使用睡眠功能添加暂停,但它无效。在我的控制台输出中,正确打印数组元素(收集音频元素和相应的暂停),并且也正确地暂停,但是在音频播放期间不保持暂停。很感谢任何形式的帮助。这是我的代码,

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);
    }
   }

1 个答案:

答案 0 :(得分:0)

尝试在setInterval之外声明一个等于0的变量,假设为var noteIndex = 0。在setInterval内播放第一个音符:tune[noteIndex],然后递增noteIndex

所以你的代码应该是这样的:

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]);

希望这有帮助。