# Generate editable drawing of audio waveform from audio file in p5js?

**URL:** <https://discourse.processing.org/t/generate-editable-drawing-of-audio-waveform-from-audio-file-in-p5js/29926>\
**Category:** Libraries\
**Created:** [May 7, 2021, 12:38am UTC](https://discourse.processing.org/t/generate-editable-drawing-of-audio-waveform-from-audio-file-in-p5js/29926 "2021-05-07T00:38:45Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Gershy13](https://avatars.discourse-cdn.com/v4/letter/g/a183cd/32.png) [@Gershy13](https://discourse.processing.org/u/Gershy13)\
**Post date:** [May 7, 2021, 12:38am UTC](https://discourse.processing.org/t/generate-editable-drawing-of-audio-waveform-from-audio-file-in-p5js/29926/1 "2021-05-07T00:38:45Z")

</div>

Can anyone help me? Im trying to draw a audio waveform of an mp3 file in p5js. Essentially like what you would see on the track in a DAW like LogicPro/Audacity/Adobe Audition. I want the full track to be generated as a drawing, but all at once instead of in realtime while the audio is playing. Is this possible?

Any tips would be appreciated!

Thanks  
Gersh

---

<div class="post-metadata">

**Author:** ![KumuPaul](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/kumupaul/32/13072_2.png) [@KumuPaul](https://discourse.processing.org/u/KumuPaul)\
**Post date:** [May 7, 2021, 9:21am UTC](https://discourse.processing.org/t/generate-editable-drawing-of-audio-waveform-from-audio-file-in-p5js/29926/2 "2021-05-07T09:21:41Z")

</div>

There is a popular library for dealing with sound, audio inputs, and sound files in p5.js: [p5.sound](https://p5js.org/reference/#/libraries/p5.sound). Unfortunately it doesn’t have great support for analyzing audio buffers that aren’t actually being played (as far as I can tell). However, the `p5.SoundFile` class has an undocumented property `buffer` which is an [`AudioBuffer`](https://developer.mozilla.org/en-US/docs/Web/API/AudioBuffer), and that class (which is a standard class provided by the browser) allows you to get the raw amplitude data for each channel in an audio buffer. This can then be analyzed to render amplitude or frequency information. Here’s a simple example:

```javascript
function audioViz(p) {
	let audioFileSelector;
	let audioFile;
	let leftChannelData;
	let rightChannelData;

	p.setup = function() {
		p.createCanvas(400, 400);
		audioFileSelector = p.createFileInput(loadaudioFile);
		audioFileSelector.position(0, 0);
		p.textAlign(p.CENTER, p.CENTER);
		p.noLoop();
	}

	p.draw = function() {
		p.background('lightgray');
		p.noFill();
		p.stroke('red');
		p.strokeWeight(1);
		let loading = true;
		if (leftChannelData) {
			renderChannel(leftChannelData, 0);
			loading = false;
		}
		if (rightChannelData) {
			renderChannel(rightChannelData, p.height);
			loading = false;
		}
		if (loading) {
			p.noStroke();
			p.fill('red');
			p.text('Waiting/Loading..', p.width / 2, p.height / 2);
		}
	}
	
	function renderChannel(data, peakHeight) {
		// values per pixel
		let resolution = p.int(p.max(1, p.round(data.length / p.width)));
		
		// Normalize our graph based on the peak amplitude of this channel
		let maxAmp;
		for (let i = 0; i < data.length; i++) {
			if (maxAmp === undefined || p.abs(data[i]) > maxAmp) {
				maxAmp = data[i];
			}
		}
		
		let x = 0;
		let sum = 0;
		p.beginShape();
		for (let i = 0; i < data.length; i++) {
			// Compute an average for each set of values
			sum += p.abs(data[i]);
			
			if (i % resolution == 0) {
				p.vertex(
					x++,
					// map the average amplitude to range from the center of the canvas to
					// either the top or bottom depending on the channel
					p.map(sum / resolution, 0, maxAmp, p.height / 2, peakHeight));
				sum = 0;
			}
		}
		p.endShape();
	}

	function loadaudioFile(file) {
		audioFile =
			p.loadSound(
				file.data,
				() => {
					// This gets the raw amplitude data for the channel, this is an array
					// of values between -1 and 1
					leftChannelData = audioFile.buffer.getChannelData(0);
					rightChannelData =
						audioFile.buffer.numberOfChannels > 1 ?
						  audioFile.buffer.getChannelData(1) :
							undefined;
					p.redraw();
				},
				e => console.error(e)
			);
	}
}

new p5(audioViz);

```

Here’s the [runnable sketch](https://openprocessing.org/sketch/1188146).

---

<div class="post-metadata">

**Author:** ![Gershy13](https://avatars.discourse-cdn.com/v4/letter/g/a183cd/32.png) [@Gershy13](https://discourse.processing.org/u/Gershy13)\
**Post date:** [May 7, 2021, 1:20pm UTC](https://discourse.processing.org/t/generate-editable-drawing-of-audio-waveform-from-audio-file-in-p5js/29926/3 "2021-05-07T13:20:19Z")

</div>

Would it be possible to tweak this to change the way it looks on user input? Or is it only drawn once? For instance a slider that changes the amplitude of the waveform, or change the color in realtime etc.  
Also is it possible to make the visual output more pleasing? Ive seen some people make a waveform from rectangle bars and i think that looks better than the vertex lines? Would it be possible to do that with this code?

---

<div class="post-metadata">

**Author:** ![KumuPaul](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/kumupaul/32/13072_2.png) [@KumuPaul](https://discourse.processing.org/u/KumuPaul)\
**Post date:** [May 7, 2021, 5:38pm UTC](https://discourse.processing.org/t/generate-editable-drawing-of-audio-waveform-from-audio-file-in-p5js/29926/4 "2021-05-07T17:38:26Z")

</div>

> [@Gershy13](#):
>
> Would it be possible to tweak this to change the way it looks…

Of course it is possible. This example is just meant to demonstrate the use of loadSound/buffer/getChannelData to get audio file data. I chose to use a beginShape/vertex/endShape to render the data because it was simple. You can use whatever approach you want.

I suggest you read this example carefully and read the documentation for any methods you aren’t familiar with. If there are specific things you still don’t understand, feel free to ask.

However if you’re asking me to make a bunch of tweaks to this example to make it look precisely how you want… that’s gonna be a no 🎣

---

<div class="post-metadata">

**Author:** ![micuat](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/micuat/32/19407_2.png) [@micuat](https://discourse.processing.org/u/micuat)\
**Post date:** [May 7, 2021, 6:10pm UTC](https://discourse.processing.org/t/generate-editable-drawing-of-audio-waveform-from-audio-file-in-p5js/29926/5 "2021-05-07T18:10:19Z")

</div>

just to add - programming takes time. Fortunately or unfortunately we are used to commercial software with polished user interfaces but that took years and numerous programmers to do it. If you start coding something like that by yourself, be patient and embrace small steps. You may not make Ableton 10 in a week but at first they started with a very small team  
[https://roberthenke.com/technology/ableton\_live.html](https://roberthenke.com/technology/ableton_live.html)

---

<div class="post-metadata">

**Author:** ![Gershy13](https://avatars.discourse-cdn.com/v4/letter/g/a183cd/32.png) [@Gershy13](https://discourse.processing.org/u/Gershy13)\
**Post date:** [May 8, 2021, 6:17pm UTC](https://discourse.processing.org/t/generate-editable-drawing-of-audio-waveform-from-audio-file-in-p5js/29926/6 "2021-05-08T18:17:55Z")

</div>

Hi yes thanks, thats what i wanted to know, im still relatively new to p5js so was wondering if it could be done, wasnt asking for you to do it for me…

I do have one more question tho, although it is unrelated to this topic, would best practice be asking here or asking in a new post?

---

<div class="post-metadata">

**Author:** ![KumuPaul](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/kumupaul/32/13072_2.png) [@KumuPaul](https://discourse.processing.org/u/KumuPaul)\
**Post date:** [May 9, 2021, 1:21am UTC](https://discourse.processing.org/t/generate-editable-drawing-of-audio-waveform-from-audio-file-in-p5js/29926/7 "2021-05-09T01:21:55Z")

</div>

Great! If it’s unrelated you should definitely make a new post, you’ll get better visibility that way.

---

<div class="post-metadata">

**Author:** ![Gershy13](https://avatars.discourse-cdn.com/v4/letter/g/a183cd/32.png) [@Gershy13](https://discourse.processing.org/u/Gershy13)\
**Post date:** [May 9, 2021, 12:22pm UTC](https://discourse.processing.org/t/generate-editable-drawing-of-audio-waveform-from-audio-file-in-p5js/29926/8 "2021-05-09T12:22:12Z")

</div>

Thanks, ill do that.
