javascript - 如何使用音频元素创建连续的曲调

标签 javascript html audio

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

到目前为止一切正常。然而,在演奏曲调的过程中,所有的声音都是一起演奏的。好像,它们是相互重叠的。我希望在每个声音之后按照最初播放的方式添加暂停。

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



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

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

最佳答案

尝试在 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]);

希望这可以帮助。

关于javascript - 如何使用音频元素创建连续的曲调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48197533/

相关文章:

javascript - 如何在 jQuery 浏览器中安排用户赢得或输掉游戏时播放音频

javascript - 使用 javascript 和 ajax 技术下载/提取网站内容

javascript - 使用 jquery 重新选择所有复选框会导致奇怪的操作

html - 使用 twitter bootstrap,我所有的行加起来应该是 12 行吗?

qt - 使用Qt(QSound)在Symbian上播放WAV文件

HTML5 音频元素侵犯版权?

javascript - 访问者如何通过文本字段向菜单添加选项?

java - 无法在 Chrome 上将大型 html 内容发布到服务器

javascript - 使用alasql将多个json对象导出到xlsx文件

javascript - 从 Controller 输出到 HTML 表单