Title

music-cover

HTML

<!-- HTML -->
<div class="music-wrapper" data-songs="Don't Swallow The Cap,Loafers,Welcome To The Family" data-music_dir="music" data-image_dir="images"> 
	<div class="music-info">
		<h4 id="title">Title</h4>
		<div class="progress-wrapper">
			<div class="progress"></div>
			<canvas id="audio_visual" height="500" width="500"></canvas>
		</div>
	</div>

	<audio src="music/Don't Swallow The Cap.mp3" id="audio"></audio>

	<div class="img-wrapper">
		<img src="images/Don't Swallow The Cap.jpg" alt="music-cover" id="cover">
	</div>

	<div class="navigation">
		<button id="previous" class="action-btn">
			<i class="fas fa-backward"></i>
		</button>
		<button id="play" class="action-btn action-btn-big">
			<i class="fas fa-play "></i>
		</button>
		<button id="next" class="action-btn">
			<i class="fas fa-forward"></i>
		</button>
	</div>
</div>
The main music wrapper has a dataset called songs.
It's a string based array of song names with a comma acting as a delimiter.
// JS
const songs = musicWrapper.dataset.songs.split(',')

There's also the data tags music_dir and image_dir.
These contain the directory to search when looking for the mp3s and jpgs.
This happens in the loadSong function.
// JS
function loadSong(song) {
	title.innerText = song
	audio.src = `${musicDir}/${song}.mp3`
	cover.src = `${imageDir}/${song}.jpg`
}

music-info is a relatively simple group.
The only real notable things are the div class progress and the canvas with id audio_visual.
progress is the progress bar updated in the audio listed later.
The canvas tagged audio_visual is the waveform visualiser seen underneath the progress bar.

audio is simply the audio context for the player.
It uses multiple event listeners.
// JS
audio.addEventListener('timeupdate', (e) => {...
audio.addEventListener('ended', () => {...
audio.addEventListener('pause', () => {pauseSong()})
audio.addEventListener('play', () => {playSong()})

I believe the img-wrapper and navigation are pretty self explanatory.