JSFiddle - React, Tailwind, and code Playground

by Ben Gillbanks

JavaScript

// Function to play a note using Web Audio API
function playNote(note, duration = 1, type = 'sine') {

	// Create an AudioContext
	const audioCtx = new (window.AudioContext || window.webkitAudioContext)();

	// Create an oscillator
	const oscillator = audioCtx.createOscillator();
    
    const frequency = getFrequency(note);
    console.log('frequency', frequency);

	// Set the oscillator frequency and type
	oscillator.frequency.setValueAtTime(frequency, audioCtx.currentTime);
	oscillator.type = type;

	// Create a gain node to control the volume
	const gainNode = audioCtx.createGain();

	// Connect the oscillator to the gain node and the gain node to the destination (speakers)
	oscillator.connect(gainNode);
	gainNode.connect(audioCtx.destination);

	// Start the oscillator
	oscillator.start();

	// Stop the oscillator after the specified duration
	setTimeout(() => {
		oscillator.stop();
		audioCtx.close(); // Close the audio context to free resources
	}, duration * 1000); // Convert duration to milliseconds
    
}


// Function to calculate frequency of a piano note
function getFrequency(note) {
	const A4 = 440;
	const semitoneRatio = Math.pow(2, 1/12);
	const noteMap = {
		'C': -9,
		'C#': -8,
		'D': -7,
		'D#': -6,
		'E': -5,
		'F': -4,
		'F#': -3,
		'G': -2,
		'G#': -1,
		'A': 0,
		'A#': 1,
		'B': 2
	};

	const octave = parseInt(note.slice(-1), 10);
	const key = note.slice(0, -1);

	const semitoneDistance = noteMap[key] + (octave - 4) * 12;

	return A4 * Math.pow(semitoneRatio, semitoneDistance);
}

// Example usage
playNote('C4', 1, 'square');
setTimeout( 
() => playNote('D4', 1, 'square'), 
1000 
);