Prompt-Driven Development Journal 0000: Paint and Sound

Last updated: March 17th 2023

Back in December, I was whining on twitter about ChatGPT sucking at generating code. I did expect it to be bad in the first place, since I believe the "Intelligence" part of Artificial Intelligence is a scam.

However, if there's one thing Machine Learning can do is – and get ready for this shocking fact – learning. And it clearly has been learning to code!

So it seems that I am gonna be using this. I will be using it for my crazy music/audio/video-related internal tool development. And I'll be journaling a bit about it. Mostly just showing you the prompts and the code it came up with.

(I've already noticed that non-trivial things require more of a conversation. A back and forth to solve bugs and shit. I will be posting those in future posts.)

(COMMERCIAL INTERRUPTION!: Have you listened to my latest releases? Death metal and grindcore, Dark ambient, Strange EP / History lesson.)

OK let's see today's prompt.

Painting on an HTML <canvas> #

(And playing a sound.)

Prompt:

Can you give me the minimal javascript code needed to 1. Add a CANVAS element to the screen. 2. Allow the user be able to paint multiple lines, erase, and select color, on the canvas? 3. Play one octave of the major scale with a simple tone using A4 (ie. 440hz) for 0.5 seconds whenever the user hits the clear button?

ChatGPT (Mar 14 Version):

// Create the canvas element and append it to the body
const canvas = document.createElement('canvas');
document.body.appendChild(canvas);

// Get the canvas 2D context and set the initial properties
const context = canvas.getContext('2d');
context.lineWidth = 5;
context.lineCap = 'round';
context.strokeStyle = 'black';
context.fillStyle = 'white';

// Add event listeners to detect user input
let isDrawing = false;
let isErasing = false;
let lastX, lastY;
canvas.addEventListener('mousedown', startDrawing);
canvas.addEventListener('mousemove', draw);
canvas.addEventListener('mouseup', stopDrawing);
canvas.addEventListener('mouseout', stopDrawing);
canvas.addEventListener('contextmenu', toggleEraseMode);

// Functions to handle user input
function startDrawing(event) {
  if (event.button !== 0) return;
  isDrawing = true;
  [lastX, lastY] = [event.clientX, event.clientY];
}

function draw(event) {
  if (!isDrawing) return;
  context.strokeStyle = isErasing ? context.fillStyle : document.getElementById('colorPicker').value;
  context.beginPath();
  context.moveTo(lastX, lastY);
  context.lineTo(event.clientX, event.clientY);
  context.stroke();
  [lastX, lastY] = [event.clientX, event.clientY];
}

function stopDrawing() {
  isDrawing = false;
}

function toggleEraseMode(event) {
  event.preventDefault();
  isErasing = !isErasing;
}

// Create the color picker element and append it to the body
const colorPicker = document.createElement('input');
colorPicker.type = 'color';
colorPicker.id = 'colorPicker';
document.body.appendChild(colorPicker);

// Add event listener to update the line color when the color picker value changes
colorPicker.addEventListener('change', () => {
  context.strokeStyle = colorPicker.value;
  context.fillStyle = colorPicker.value === '#ffffff' ? 'black' : 'white';
});

// Create the clear button element and append it to the body
const clearButton = document.createElement('button');
clearButton.textContent = 'Clear';
document.body.appendChild(clearButton);

// Add event listener to clear the canvas when the clear button is clicked and play a tone
clearButton.addEventListener('click', () => {
  context.clearRect(0, 0, canvas.width, canvas.height);
  playTone();
});

// Function to play a tone at 440hz for 0.5 seconds
function playTone() {
  const audioContext = new AudioContext();
  const oscillator = audioContext.createOscillator();
  oscillator.type = 'sine';
  oscillator.connect(audioContext.destination);

  const scale = [1, 9/8, 5/4, 4/3, 3/2, 5/3, 15/8, 2];
  const frequencies = scale.map(ratio => ratio * 440);

  let time = audioContext.currentTime;
  frequencies.forEach(frequency => {
    oscillator.frequency.setValueAtTime(frequency, time);
    time += 0.2;
  });

  oscillator.start();
  oscillator.stop(audioContext.currentTime + 1.0);
}

It works.

Go copy-paste it on codepen.io or something.

Related