A few months back, I wrote about how I used a 3D printer to transform any mp3 into a physical record.  Though all the documentation for that project is available here, and the 3D models could potentially be printed through an online fabrication service, I knew that the barrier to entry for normal people interested in trying out the process themselves was prohibitively high.  With this project I wanted to try to extend the idea of digitally fabricated records to use relatively common and affordable machines and materials so that (hopefully) more people can participate, experiment, and actually use all this documentation I've been writing.

These records were cut on an Epilog 120 Watt Legend EXT to a theoretical precision of 1200dpi (the kerf of the cut and some tricks I used to avoid crashing the laser cutter dropped the actual precision down by ~1/6).  The audio on the records has a bit depth between 4-5 (typical mp3 audio is 16 bit) and a sampling rate up to about 4.5kHz (mp3 is 44.1kHz).  So far I've successfully cut audio on wood (figs 1-2), acrylic (figs 3-4), and paper (figs 5-6), and I'm sure there are many more materials that would work.  I wrote the Processing sketch that generates the record cutting paths so that it can be modified for any song, material, cutting machine, record size, and turntable speed (skip ahead to download the code and learn how to make your own records).

You should also note that in this Instructable I'll demonstrate specifically how I used a laser cutter for this process, but the cutting files I'm using are standard vector graphics in a PDF format, so they can be extended to many other digital fabrication tools. For example, I'm curious to see if it's possible to use a CNC mill or a CNC razor blade paper cutter with my cutting files (a group of people were able to cut out some sine waves on paper using a Cameo in this Instructable).

Below are some of my final results, read on to see how they were made and how you can make your own.

Joy Division - Love Will Tear Us Apart on clear acrylic (download vector files):

Radiohead - Idioteque on wood (download vector files):

The Velvet Underground and Nico - Femme Fatale on maple (download vector files):

Step 1: How Does a Record Work?

I've explained a bit about how a record works and the scale of vinyl microgrooves in my 3d printed record project.  The main difference between these laser cut records and my 3d printed records is the axis that the grooves are cut on.  Since I can't control the power of the laser while it is cutting a vector path, the laser cut records are cut laterally on the surface of the material.  This means that the needle only vibrates in the plane parallel to platter of the turntable.  The 3d printed records are "cut" vertically, meaning the needle vibrates in the plane perpendicular to the platter.  I chose to modulate the grooves vertically for the 3d printed records because the vertical axis is the most precise axis on the machine (resolution of 16 microns).

Stereo (2 channel) vinyl records are cut both vertically and laterally, this way it's possible for two isolated channels of audio to fit into one groove.  Mono vinyls are cut laterally only, this is because the vertical cuts can become distorted, especially if you try to increase the amplitude of your waveform to increase the dynamic range of the sound.  Although I didn't really have a choice in the matter, it's better to to cut a mono groove laterally.

To give you an idea of the size of the grooves on a modern record, check out the image above from Chris Supranowitz, a researcher at The Institute of Optics at the University of Rochester.  This is a close up image of a vinyl record, taken with an electron microscope.  The dark objects in the grooves are tiny particles of dust.  The laser cutter cannot make such precise cuts because the width of the beam is too large, so the grooves on my records are about 1-2 orders of magnitude larger in every dimension than these grooves.
<p>hi amanda, hi community</p><p>attached you see two screenshots from the same .pdf. the more complete looking one is preview/acrobat the smaller one comes from illustrator. anybody? solutions or explainations? </p><p>hugs</p><p>cc</p>
<p>Hey,</p><p>Just wanted to pin this comment to the top since lots of people are running into it. the problem is that illustrator doesn't like to import so much data at once, so it cuts it off. You need to break your data into smaller chunks to import.</p><p>If you look at the processing code:</p><p><a href="https://github.com/amandaghassaei/LaserCutRecord/blob/master/LaserCutRecord.pde">https://github.com/amandaghassaei/LaserCutRecord/b...</a></p><p>there's a variable called </p><p><strong>numGroovesPerFile</strong></p><p>lower this number so that you export more files with fewer grooves on each (maybe 7 is a good place to start, but you may need to go lower). Once you make the chunks of data small enough, you will be able to import the files into illustrator without loosing anything.</p><p>Hope that helps!</p>
hi amanda, <br><br>thanks a lot. i reuced the numgroovesperfile down to 5. it worked now. couldn&acute;t believe it. thanks for pointing out the importance of it.<br><br>will post the results here soon.
<p>This is an amazing project, cant wait to try it. I cant find any mention of it, but how long does it take to laser one record?</p>
<p>Hi Amanda, (in regards to the laser cut record project) I'm having some trouble because when I send the files to be cut on the laser cutter, the laser cutter messes up. Is there any reason why this is happening?</p><p>Thank you.</p><p>Kind regards</p>
You'll have to be a little more specific, what does "messes up" mean? Can you upload a photo?
Sure, sorry I'll attach the photos. I did two test runs with the velvet underground song, the first one (black record) was fine up until the end when stopped following the vector paths. The second test was with the white-ish material, the laser cutter didn't even cut the circle right from the start. Pictures are attached :)
<p>did you end up getting it to work?</p>
<p>Yes I got it working! Thank you so much, I look forward to more instructables from you!</p>
Sure, sorry heres two test ones I ran. The first one came out the way it should until it got to the end and thats the black record. The white-ish record just messed up from the start, it wouldn't cut the circle properly.
<p>wow I've never seen this before. what model is the lase cutter? Maybe try increasing the number </p><p>minDist </p><p>to 8 or 9 and see if that does anything. It's at the top of this file:</p><p><a href="https://github.com/amandaghassaei/LaserCutRecord/blob/master/LaserCutRecord.pde">https://github.com/amandaghassaei/LaserCutRecord/b...</a></p><p>that will space out individual points on the vector path a little more. I found that if they were too close together my laser would just stop. The behavior you're seeing is very strange, but maybe related.</p>
<p>I got it to work!!! (digitally anyways)</p><p>This is amazing. Now my laser cutter just has to be delivered...</p><p>Here are the first 3 min of &quot;The General&quot; by Dispatch</p>
<p>cool, hope it works!</p>
I'm having a bit of an issue running the processing sketch. <br> <br>Processing crashes when I load the split strings into this array. My .txt file is 43mb. Which seems gigantic for a plain text. But at 44100 x 180~ sec. I guess that makes some sense. <br> <br>it's this line that causes the sketch to run out of memory. I've changed my processing prefs to allocate 512MB but it still crashes. I suppose I'm confused, or not doing something right, as no one else has posted this issue... <br> <br> float audioData[] = float(split(rawDataString,',')); //separated by commas <br> <br>any thoughts?
<p>Having the same issue with roughly the same size txt file, the original song was 3.10 minutes long. Can anyone give me any tips on what i'm doing wrong?</p>
<p>can you post the text file? click on "add images" when you leave a comment, it will let you upload a file.</p>
<p>interesting, I haven't seen that one before. can you upload your txt file? (use the "add images" button)</p>
<p>Does anyone have any suggestions for making a straight line (instead of a circular record shape) with this? </p>
<p>Just put in an empty sound file, that should work. The sound waves are made by the &quot;wiggles&quot; so anything with no sound would just be a regular curve.</p>
<p>Oh, no, sorry for the confusion - I meant, I'd like to take the audio and plot it along a straight line, rather than curved as a record..Is it possible to do that with this Processing code? I'm not very good with equations..</p>
<p>put this code and the attached files in the same folder and run it in processing. You'll probably want to play around with xScale depending on how fast you want to read the audio.</p><p>import processing.pdf.*;<br><br>//parameters<br>String filename = "casbah.txt";//generate a txt file of your waveform using python wav to txt, and copy the file name here<br>float samplingRate = 44100;//sampling rate of incoming audio<br>float dpi = 1200.0;//dpi of cutter<br>int cutterWidth = 100;//width of laser cutter bed in inches<br>int cutterHeight = 5;//height of laser cutter bed in inches<br>float amplitude = 5.0;//in pixels<br><br>float xScale = 1.0;//in pixels<br><br>void setup(){<br> <br> float[] songData = processAudioData();<br> <br> float scaleNum = 72.0;//scale factor of vectors (default 72 dpi)<br> amplitude = amplitude/dpi*scaleNum;<br> xScale = xScale/dpi*scaleNum;<br> <br> size(int(cutterWidth*scaleNum),int(cutterHeight*scaleNum));<br> <br> <br> //change extension of file name<br> int dotPos = filename.lastIndexOf(".");<br> if (dotPos &gt; 0)<br> filename = filename.substring(0, dotPos);<br> <br> <br> float x = 0;<br> <br> beginRecord(PDF, filename + ".pdf");//save as PDF<br> background(255);//white background<br> noFill();//don't fill loops<br> strokeWeight(0.001);//hairline width<br> <br> beginShape();<br> int i;<br> for (i=0;i&lt;songData.length;i++){<br> x = i*xScale;<br> if (x &gt; cutterWidth*scaleNum) break;<br> vertex(x,cutterHeight/2*scaleNum + amplitude*songData[i]);<br> }<br> <br> println("sample " + i + " of " + songData.length);<br> println(i/float(songData.length)*songData.length/samplingRate + " seconds of " + songData.length/samplingRate + " fit on this pdf");<br> <br> endShape();<br> endRecord();<br> <br> exit();<br> <br> //tell me when it's over<br> println("Finished.");<br><br>}<br><br>float[] processAudioData(){<br> <br> //get data out of txt file<br> String rawData[] = loadStrings(filename);<br> String rawDataString = rawData[0];<br> float audioData[] = float(split(rawDataString,','));//separated by commas<br> <br> //normalize audio data to given bitdepth<br> //first find max val<br> float maxval = 0;<br> for(int i=0;i&lt;audioData.length;i++){<br> if (abs(audioData[i])&gt;maxval){<br> maxval = abs(audioData[i]);<br> }<br> }<br> //normalize amplitude to max val<br> for(int i=0;i&lt;audioData.length;i++){<br> audioData[i]*=amplitude/maxval;<br> }<br> <br> return audioData;<br>}</p>
<p>just added it to the repo too:</p><p>https://github.com/amandaghassaei/LaserCutRecord/blob/master/LinearRecord.pde</p>
<p>Oh Wait did you mean a line that isn't curved at all? This guy printed this with a laser engraver, so if you don't have a laser engraver, you can't cut or etch anything. A laser printer can easily engrave a straight line, usually all you have to do is draw a straight line on a computer, adjust the print settings and print it to the engraver</p>
<p>No, I mean I'd like to take the audio signal modulation and print it in consecutive lines, rather than curving the grooves around a record shaped disc.I have a laser engraver. </p>
<p>Like this - except spec'd for record player groove size. </p>
<p>Hi Amanda, I just sent you an e-mail regarding a film shoot inquiry. Can you please check your gmail and let me know what you think? Thank you~</p>
<p>hi amanda!<br><br>i have the same problem with the pdf files not matching properly. The preview and the acrobat reader/pro show me the exact turns and geometries. but when opening in an vector editing program such as illustrator or rhino a certain part doesn&acute;t show up. so the bit&acute;s don&acute;t fit. can you tell why?! and what to do? thanks a lot and much respect for this incredibly easy and understable manual! </p>
<p>Hi Amanda, I've run the code through Python 2.5.4 and it is saying there is a syntax error. Here is the code I'm running:</p><p>import wave</p><p>import math</p><p>import struct</p><p>bitDepth = 8#target bitDepth</p><p>frate = 44100#target frame rate</p><p>fileName = &quot;FemmeMono.wav&quot;#file to be imported (change this)</p><p>#read file and get data</p><p>w = wave.open(fileName, 'r')</p><p>numframes = w.getnframes()</p><p>frame = w.readframes(numframes)#w.getnframes()</p><p>frameInt = map(ord, list(frame))#turn into array</p><p>#separate left and right channels and merge bytes</p><p>frameOneChannel = [0]*numframes#initialize list of one channel of wave</p><p>for i in range(numframes):</p><p> frameOneChannel[i] = frameInt[4*i+1]*2**8+frameInt[4*i]#separate channels and store one channel in new list</p><p> if frameOneChannel[i] &gt; 2**15:</p><p> frameOneChannel[i] = (frameOneChannel[i]-2**16)</p><p> elif frameOneChannel[i] == 2**15:</p><p> frameOneChannel[i] = 0</p><p> else:</p><p> frameOneChannel[i] = frameOneChannel[i]</p><p>#convert to string</p><p>audioStr = ''</p><p>for i in range(numframes):</p><p> audioStr += str(frameOneChannel[i])</p><p> audioStr += &quot;,&quot;#separate elements with comma</p><p>fileName = fileName[:-3]#remove .wav extension</p><p>text_file = open(fileName+&quot;txt&quot;, &quot;w&quot;)</p><p>text_file.write(&quot;%s&quot;%audioStr)</p><p>text_file.close()</p>
<p>does it say what line?</p>
Thank you for your reply! I fixed the problem, how thick was the wood that you used for the record?
<p>doesn't really matter, I used 1/8 to 1/4". as long as it's pretty flat and stays flat it should be ok.</p>
<p>I keep getting unterminated string constant</p>
<p>are you missing a closing double quote on your filename variable?</p>
<p>which line? and what version of processing?</p>
<p>For the 3d printed version, have you tried printing a blank record and then recording onto it as a baseline for potential audio quality? If so, how did it turn out?</p><p>Have you tried any additional materials since? Perhaps wax? I'm looking into replicating old edison wax tubes as a side project. :)</p>
<p>I've thought about that, but the geometry of the streaks that cause the noise is different on every print, so I think you would only add more noise by trying to correct for it. I'm going to do a text in a few weeks milling a record, on brass I think.</p>
<p>Awesome.. Will be great for personal records. :)</p>
<p>Hi , I thought I was original changing the diamond tool by a Laser one to cut the viny!!!.....I am subscribed to &quot;INSTRUCABLES&quot; and decide to look here for a transducer sound-mechanical.....and I ve found &quot;my&quot; Idea hahaha......Ideas are on air ....ok Congratulations.<br><br>However I am involved in laser cutting /gravure of surface for automation in machines , these grooves must be read by an electronic eye , we move to the laser a year ago ( we use tu use Copper and cnc with diamond tool), in our experience you can get great results with engraving Polyimide ( warning: Not Polyamide) ....is Thermoset and stands high temperature , and the cut is very very precise and without the tipycal deformation of thermoplastics at High temperature, , the scrap is just a fine powder that you can remove with a brush, colors in the market are ambar and Black.</p>
<p>im getting an error on python:</p><p>Traceback (most recent call last):</p><p> File &quot;/Users/eidtecnico/Downloads/LASER RECORDS/LaserCutRecord-master/LaserCutRecord/wavtotext.py&quot;, line 26, in &lt;module&gt;</p><p> frameOneChannel[i] = frameInt[4*i+1]*2**8+frameInt[4*i]#separate channels and store one channel in new list</p><p>TypeError: 'map' object is not subscriptable</p><p>&gt;&gt;&gt; </p>
<p>did you put the audio file in the same folder as the python script?</p>
<p>Hello! I'm also getting the same problem when I run the file in Python 3.4.1. When I run the file in Python 2.7.8 it says </p><p>Traceback (most recent call last):</p><p> File &quot;/Users/flaviawilson/Desktop/UNIVERSITY/CCDN244 Expanded Photographics/Project Two - Lomo/LaserCutRecord-master/wavtotext.py&quot;, line 26, in &lt;module&gt;</p><p> frameOneChannel[i] = frameInt[4*i+1]*2**8+frameInt[4*i]#separate channels and store one channel in new list</p><p>IndexError: list index out of range</p><p>Do you have any ideas? The audio file is definitely in the same folder as the python script. Sorry to be a bother, I'm new to python but super excited about this instructable! You've done an awesome job, thanks so much :)</p>
<p>Figured out the problem - I'd already converted the audio track to mono, so the python code was getting confused because it was thinking the track was in stereo.</p><p>Also the code does only seem to work in 2.5.4, but I might be wrong.</p>
<p>Thanks! Stereo Mono issue solved it. </p>
<p>cool, yeah I haven't tested other versions.</p>
<p>use 2.5.4. I tried using other python releases as well and they didnt work</p>
<p>I am confused on step 10 what do I rename in processing?</p>
<p>if your text file was called mySong.txt then you should change the line to:</p><p><strong>String filename = "mySong.txt";</strong></p>
<p>the name of your song, the text file to import.</p>
<p>hi there - when you say the track length must be 3:10 is this minutes or hours? many thanks! stephen</p>

About This Instructable


481 favorites


Bio: I'm a grad student at the Center for Bits and Atoms at MIT Media Lab. Before that I worked at Instructables, writing code for ... More »
More by amandaghassaei: OTCA Metapixel - Conway's Game of Life "9 Degrees of Freedom" IMU Twitter Controlled Pet Feeder
Add instructable to: