将播放列表添加到 Tone.js 个音频播放器

Add Playlist to Tone.js Audio Player

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

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

提供的 URLs

我还添加了用于在歌曲之间切换的播放列表按钮,因此更改了 URL 旋律 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>

我找到了问题的解决方案:为 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()
    }
}