JSFiddle - React, Tailwind, and code Playground

HTML

<audio preload="metadata" src="/worship/audios/header-footer.mp3"></audio>

<audio preload="metadata" src="/worship/audios/body.mp3"></audio>

<audio preload="metadata" src="/worship/audios/background.mp3"></audio>

JavaScript

var processActive = 0;

	$('audio').on('loadedmetadata', function() {

		$(this).attr('data-duration', $(this)[0].duration);

		if ($('audio').eq($('audio').length-1).attr('data-duration') && !processActive) {

			beginProcess();

			processActive = 1;
		}
	});
	

	function beginProcess () {
	 	
	 	// play the intro
		var intro = $('audio').eq(0).clone()[0],

		beginContext = new OfflineAudioContext(2,44100* parseInt($(intro).attr('data-duration')), 44100), // the last param is the sample rate

		begin = beginContext.createMediaElementSource(intro), // Create a MediaElementAudioSourceNode

		beginNodeGain = beginContext.createGain(), // Create a gain node

		finalBuff = [];


		beginNodeGain.gain.setValueAtTime(1.0, parseInt($(intro).attr('data-duration')) - 3); // make the volume high 3 secs before the end

		beginNodeGain.gain.exponentialRampToValueAtTime(0.01, beginContext.length); // reduce the volume to the minimum for the duration of expRampTime - setValTime i.e 3

		// connect the AudioBufferSourceNode to the gainNode and the gainNode to the destination
		begin.connect(beginNodeGain);

		beginNodeGain.connect(beginContext.destination);

		beginContext.startRendering().then(function(buff) {

			finalBuff.push(buff);

			// invoke functions that process the other files
			mergeBody($('audio').eq(1)[0], $('audio').eq(2)[0], finalBuff);

		});
	}

	function mergeBody (body, bg, product) {
		
		var bodContext = new OfflineAudioContext(2, 44100 * parseInt($(body).attr('data-duration')), 44100),

		bgContext = new OfflineAudioContext(2, 44100 * parseInt($(bg).attr('data-duration')), 44100),

		bodBuffNode = bodContext.createMediaElementSource(body),

		bgBuffNode = bgContext.createMediaElementSource(bg),

		// fade in that middle section
		bodGainNode = bodContext.createGain(),

		bgGainNode = bgContext.createGain(),

		smoothTrans =  new Float32Array(2),

		mixArr = [];


		smoothTrans[0] = 1.0;

		smoothTrans[1] = 0.3; // make it flow in the...