首页 > 解决方案 > 将播放列表添加到 Tone.js 音频播放器

问题描述

简短版:我正在构建一个具有播放列表功能的音频播放器。播放器可以工作,但播放列表按钮不会更改最初提供的 URL。

长版:我使用 Tone.js 的 GrainPlayer(*) 播放由多个 mp3 组成的歌曲。播放器本身(包括播放和停止按钮)工作正常,但仅适用于最初为变量 melodyURL 和 percussionURL 提供的 URL。

我还包括了在歌曲之间切换的播放列表按钮,因此更改了 melodyURL 和打击乐 URL 的 URL。但是新的 URL 没有分配给 GrainPlayer。

我错过了什么?任何帮助表示赞赏。

提前致谢,

乔治

*) GrainPlayer,因为我还必须在不影响音高的情况下调整播放速率。

<button id="btn-play">PLAY</button>
<button id="btn-stop" style="display:none">STOP</button>

<ul id="playlist">
    <li><button data-melody="funk_melody.mp3" data-perc="funk_percussion.mp3" >Funk Song</button></li>
    <li><button data-melody="rock_melody.mp3" data-perc="rock_percussion.mp3" >Rock Song</button></li>
</ul>
    
<script src="Tone.js"></script>
<script>    
    let melodyURL = "funk_melody.mp3"
    let percussionURL = "funk_percussion.mp3"
        
    const player = {
        melody: new Tone.GrainPlayer({ 
            url: melodyURL, 
        }),
        percussion: new Tone.GrainPlayer({ 
            url: percussionURL, 
        }),
    }
    player.melody.toDestination()
    player.percussion.toDestination()
        
    
    //  PLAYLIST BUTTONS (Don't work! Don't reasign file URLs)
    
    const playList = document.getElementById('playlist')
    const playlistItems = playlist.querySelectorAll('li')
        
    for (playlistItem of playlistItems) {
        const itemButton = playlistItem.querySelector('button')
        itemButton.addEventListener('click', async () => {
            melodyURL       = itemButton.dataset.melody
            percussionURL   = itemButton.dataset.percussion
        }
    }
    
    
    //  PLAY / STOP BUTTONS
        
    document.getElementById("btn-play").addEventListener('click', async () => {
        Tone.loaded().then(() => {
            player.melody.start()
            player.percussion.start()
            document.getElementById("btn-play").style.display = 'none'
            document.getElementById("btn-stop").style.display = 'inline'
        })
    })
        
    document.getElementById("btn-stop").addEventListener('click', async () => {
        player.melody.stop()
        player.percussion.stop()
        document.getElementById("btn-play").style.display = 'inline'
        document.getElementById("btn-stop").style.display = 'none'
    })
</script>

标签: javascripttone.js

解决方案


我找到了解决问题的方法:为 URL 重新分配变量是不够的。播放列表按钮之后还必须重新分配播放器。

//  PLAYLIST BUTTONS (Now working!)

const playList = document.getElementById('playlist')
const playlistItems = playlist.querySelectorAll('li')
    
for (playlistItem of playlistItems) {
    const itemButton = playlistItem.querySelector('button')
    itemButton.addEventListener('click', async () => {

        // NEW: stop previous player
        player.melody.stop()
        player.percussion.stop()

        melodyURL       = itemButton.dataset.melody
        percussionURL   = itemButton.dataset.percussion

        // NEW: reasign player 
        player = {
            melody: new Tone.GrainPlayer({ url: melodyURL }).toDestination(),
            percussion: new Tone.GrainPlayer({ url: percussionURL }).toDestination,
        }

        player.melody.start()
        player.percussion.start()
    }
}

推荐阅读