How to create a musical melody generator using HTML, CSS and JavaScript
Do you love music and want to make your own songs? Do you want to learn how to use artificial intelligence (AI) to create melodies that sound amazing and unique? If so, this tutorial is for you!
Introduction
In this tutorial, you will learn how to create a web app that can generate musical melodies using generative AI. Generative AI is a branch of artificial intelligence that can create new content, such as images, text, music, etc., based on some input or parameters. You will use the Web Audio API, which is a JavaScript interface that allows you to manipulate and process audio in the browser. You will also use some HTML and CSS to create a simple user interface for your web app.
What you will need
To follow this tutorial, you will need:
- A text editor, such as Visual Studio Code, Atom, or Sublime Text
- A web browser, such as Chrome, Firefox, or Safari
- A basic knowledge of HTML, CSS and JavaScript
Before we get into it, here's a preview of how our musical melody generator will look:
...and now for the fun part.
Step 1: Create the HTML file
First, create a new folder for your project and name it melody-generator
. Inside this folder, create a new file and name it index.html
. This will be the main HTML file for your app. Open this file in your text editor and add the following code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Melody Generator</title>
<!-- Link to the CSS file -->
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>Melody Generator</h1>
<p>This app can generate musical melodies
using generative AI and the Web Audio API.</p>
<!-- Create a form to get the user input -->
<form id="melody-form">
<label for="scale">Scale:</label>
<select id="scale" name="scale">
<option value="major">Major</option>
<option value="minor">Minor</option>
<option value="pentatonic">Pentatonic</option>
<option value="blues">Blues</option>
</select>
<label id="tempo-label" for="tempo">Tempo:</label>
<input id="tempo" name="tempo" type="range" min="60" max="180" value="120">
<label id="length-label" for="length">Length:</label>
<input id="length" name="length" type="range" min="4" max="16" value="8">
<button id="generate-button" type="button">Generate</button>
</form>
<!-- Create a div to display the generated melody -->
<div id="melody-display"></div>
<!-- Link to the JavaScript file -->
<script src="script.js"></script>
</body>
</html>
This code creates a basic HTML structure for your app, with a title, a paragraph, a form, and a div. The form contains three inputs: a select for the scale, a number for the tempo, and a number for the length.
- Scale: The scale is the set of notes that the melody will use.
- Tempo: The tempo is the speed of the melody in beats per minute.
- Length: The length is the number of notes in the melody.
The form also has a button to generate the melody. The div will be used to display the generated melody as text and play it as audio. The code also links to two external files: a CSS file for the style and a JavaScript file for the logic.
Step 2: Create the CSS file
Next, create a new file in the same folder and name it style.css
. This will be the CSS file for your app. Open this file in your text editor and add the following code:
/* Set the font family and size for the whole document */
* {
box-sizing: border-box;
font-family: Arial, sans-serif;
}
body {
background-color: #f0f0f0;
}
/* Center the title and the paragraph */
h1, p {
text-align: center;
}
/* Style the form */
#melody-form {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin: 10px;
}
/* Style the labels and the inputs */
label {
font-weight: bold;
margin: 16px 5px 5px 5px;
width: 150px;
}
input, select {
margin: 5px;
width: 150px;
width: 150px;
height: 30px;
border: 2px solid #4a47a3;
border-radius: 5px;
outline: none;
padding: 5px;
}
/* Style the button */
#generate-button {
margin: 16px;
padding: 10px;
width: 150px;
background-color: #4a47a3;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
/* Style the div */
#melody-display {
display: flex;
flex-direction: column;
align-items: center;
margin: 20px;
}
This code adds some basic style to your app, such as the font, the colors, the margins, and the alignment. You can modify this code as you like to customize the appearance of your app.
Our melody generator will look like this on smaller screens:
Step 3: Create the JavaScript file
Finally, create a new file in the same folder and name it script.js
. This will be the JavaScript file for your app. Open this file in your text editor and add the following code:
// Get the elements from the HTML file
const scaleSelect = document.getElementById("scale");
const tempoInput = document.getElementById("tempo");
const lengthInput = document.getElementById("length");
const generateButton = document.getElementById("generate-button");
const melodyDisplay = document.getElementById("melody-display");
const tempoLabel = document.getElementById("tempo-label");
const lengthLabel = document.getElementById("length-label");
// Set the initial values for the range sliders
tempoLabel.innerHTML = "Tempo: " + tempoInput.value;
lengthLabel.innerHTML = "Length: " + lengthInput.value;
// Define some constants for the notes and the frequencies
const NOTES = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];
const FREQUENCIES = [261.63, 277.18, 293.66, 311.13, 329.63, 349.23, 369.99, 392.00, 415.30, 440.00, 466.16, 493.88];
// Define some constants for the scales and the intervals
const SCALES = {
major: [0, 2, 4, 5, 7, 9, 11],
minor: [0, 2, 3, 5, 7, 8, 10],
pentatonic: [0, 2, 4, 7, 9],
blues: [0, 3, 5, 6, 7, 10]
};
// Define a constant for the duration of each note in seconds
const DURATION = 0.5;
// Create a new AudioContext object to use the Web Audio API
const audioContext = new AudioContext();
// Define a function to generate a random integer between a min and a max value
function randomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
// Define a function to generate a random melody based on the user input
function generateMelody() {
// Get the user input from the form
const scale = scaleSelect.value;
const tempo = tempoInput.value;
const length = lengthInput.value;
// Initialize an empty array to store the melody
const melody = [];
// Loop for the number of notes in the melody
for (let i = 0; i < length; i++) {
// Generate a random index from the scale
const index = randomInt(0, SCALES[scale].length - 1);
// Get the note and the frequency from the index
const note = NOTES[SCALES[scale][index]];
const frequency = FREQUENCIES[SCALES[scale][index]];
// Push the note and the frequency to the melody array
melody.push({note, frequency});
}
// Return the melody array
return melody;
}
// Define a function to display the melody as text and play it as audio
function displayMelody(melody) {
// Initialize an empty string to store the melody as text
let melodyText = "";
// Loop through the melody array
for (let i = 0; i < melody.length; i++) {
// Get the note and the frequency from the array
const note = melody[i].note;
const frequency = melody[i].frequency;
// Append the note to the melody text
melodyText += note + " ";
// Create a new OscillatorNode object to generate a sound wave
const oscillator = audioContext.createOscillator();
// Set the type and the frequency of the oscillator
oscillator.type = "sine";
oscillator.frequency.value = frequency;
// Connect the oscillator to the destination (the speakers)
oscillator.connect(audioContext.destination);
// Start the oscillator at the current time plus the duration times the index
oscillator.start(audioContext.currentTime + DURATION * i);
// Stop the oscillator at the current time plus the duration times the index plus one
oscillator.stop(audioContext.currentTime + DURATION * (i + 1));
}
// Set the innerHTML of the melody display element to the melody text
melodyDisplay.innerHTML = melodyText;
}
// Add an event listener to the generate button to call the generate and display functions
generateButton.addEventListener("click", function() {
// Generate a random melody
const melody = generateMelody();
// Display the melody
displayMelody(melody);
});
// Add an event listener to the tempo range slider and display the chosen value on the label
tempoInput.addEventListener("change", ()=>{
tempoLabel.innerHTML = "Tempo: " + tempoInput.value;
});
// Add an event listener to the length slider and display the length of the melody on the label
lengthInput.addEventListener("change", ()=>{
lengthLabel.innerHTML = "Length: " + lengthInput.value;
});
This code adds the logic to your app, using the Web Audio API and some generative AI techniques. The code first gets the elements from the HTML file and defines some constants for the notes, the frequencies, the scales, and the duration. Then, it defines a function to generate a random melody based on the user input, using a random integer function and an array of intervals for each scale.
Conclusion
In this tutorial, you have learned how to create a musical melody generator using HTML, CSS, and JavaScript. You have used the Web Audio API to manipulate audio in the browser, and you have also explored some aspects of generative AI, such as randomness and creativity. You have also created a simple and responsive user interface for your project using HTML and CSS.
You can further improve your project by adding more features, such as:
- Allowing the user to choose different types of sounds, such as piano, guitar, or synth.
- Allowing the user to save, download, or share their melodies.
- Applying some music theory rules or patterns to generate more harmonious or interesting melodies.
You might also want check out our tutorial on how to create a music player, which focuses more on how to use the audio element to play audio files.
We hope you have enjoyed this tutorial and learned something helpful.