3D Printed Sound Bites





Introduction: 3D Printed Sound Bites

About: 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 the website and iOS apps and making stuff in our shop. I post new stuff on twit...
After I posted my 3D printed record project, I received an interesting comment from Instructables author rimar2000.  He described an idea he's had for a while about a strip of material that has audio information encoded on it so that it can be played back by quickly sliding a fingernail, credit card, or piece of paper along its surface.  This same basic idea has been implemented in various ways already, here are a few:

talking strip birthday card:

It's even possible to tune rumble strips on a road so that your car turns into a musical instrument as it drives over.  Here is a musical road near MT Fuji, Japan:

another musical road - Lancaster, CA:

The reason rimar2000 suggested this idea to me is because I'd already found a way to convert audio signals into a 3D printable model in my record project.  Using 3D printing it is theoretically possible to convert any piece of audio into a "sound strip," allowing anyone to encode customized messages into this physical format.

I recently found some time to put the code together and print out a few test strips, and unfortunately, I think my process needs a little more refining until it is ready for mass production, but I figured I'd post everything I've started here in case anyone else is interested.  The video below shows the closest I've come so far to reproducing my own voice saying "amanda."  If you know what it's supposed to say, you can kind of make out what's going on here, there are three distinct sections where the sound gets louder - corresponding to the three syllables in the word.

I made this on an Objet Connex500 UV cured resin printer at 300 dpi with 30 micron layers.  It's possible that printing at the max resolution (600dpi with 16 micron layers) might help a little bit, but I haven't had a chance to do it.  It's also possible that other materials or dimensions might help.  I was thinking that tilting the bumps on the surface of the strip so that they are pointing in a 45 degree angle instead of straight up might work better with the angle that the card is hitting them.  If you have any other suggestions please feel free to leave them in the comments.

Step 1: The Code

The main idea behind this project is to take an audio waveform and use it to modulate the height of the surface of a linear strip.  this way, any object passing across the surface will vibrate up and down in the hills and valley of the wave, these vibrations will cause vibrations in the air, which cause us to hear sound.  You will find comments in my code that talk about the specifics of how it works, follow these steps to create your own 3d models:

1.  Download Audacity.

2.  Open an audio file of your choice with Audacity.  Use Effect>Normalize to amplify the signal as much as you can without clipping.  Trim any excess blank space off the beginning an end of the clip, you will want to keep the audio as short as possible.  File>Export this file and save it as a WAV in a folder called "soundBites". 

3.  Download Python 2.5.4.

4.  Copy the Python code below and save it in the soundBites folder, this code converts the information stored in a wav file (audio) into a series of numbers inside a text file (txt).
Copy the file name of the audio file you just saved and paste it into the following line in Python:

             fileName = "your_file_name_here.wav"

Hit Run>RunModule, after a minute or two you will have a .txt file saved in the soundBites folder.

5.  Download Processing.

6.  To export STL from Processing, I used the ModelBuilder Library by Marius Watz.  Download the ModelBuilder library here, I used version 0007a03.

7. Unzip the Modelbuilder library .zip and copy the folder inside called "modelbuilder".  Unzip the processing .zip and go to Processing>modes>java>libraries and paste the "modelbuilder" folder in the "libraries" folder.

8.  Copy the processing sketch below and save it as "soundBites.pde" in the soundBites folder.  You can adjust many parameters in this code: the x/y/z resolution of the printer, the speed that you want to playback, the amplitude of the waves, the thickness of the strip, and more... you can even invert the wave to make it recessed within the strip.
9.  Change the name of the import file in the Processing sketch to match your txt file name:

             String filename = "your_file_name_here.txt";

10.  Hit "Run" in Processing, you should see a file appear in the soundBites folder called "your_file_name.stl", you are now ready for 3d printing.



  • Casting Contest

    Casting Contest
  • Make it Move Contest

    Make it Move Contest
  • Clocks Contest

    Clocks Contest

We have a be nice policy.
Please be positive and constructive.



Thank you very much for sharing this Amanda!
I just have a problem when running the module in Python, it tells me there is invalid syntax and does´t save the .txt file, so I don´t know how to continue...
Any tip on how to fix this? thank you :)


Thanks for your great project

I try to play with it, but i got trouble with python like following:

File "sound.py", line 21, in <module>
frameOneChannel[i] = frameInt[4*i+1]*2**8+frameInt[4*i] #separate channels and store one channel in new list
IndexError: list index out of range

python ver 2.5.4

any one had this issue??


2 replies

It means your file is mono, try using an audio program to add the missing channel, so make your audio file stereo, event if its just the same content on each channel. Here is a way of doing that using audacity which is free:


Thanks! I hit the same issue.

commercial way?
Best regards, and congratulations on your work!

Giaccomo Fontanot, Industrial Designer.

printing square waves is the way to go. Are you interested in pursuing this goal in a more

Hi amandaghassaei. Your work is impressive. I am an Industrial Designer, very interested on this issue. I am retina to figure a way to replicate the talking strips from evades ago. I Have a CNC router, and a LOT of interest to see this working. I believe

The sound-strip idea was used at least as far back as 1955 - I remember an advertising novelty from the Schwinn bicycle company. A ridged red plastic ribbon/strip about 1/8 inch wide was tied to the center of a bicycle-wheel shaped disc (as a resonator). Running your fingernail along the strip clearly played "I like Schwinn bikes." I wonder how this was made - it sure was not computers encoding the speech.


Thank you for this instructables.

I am trying to print some words on different objects and find some applications for signaletic projects. So I want to get the wave of my sound, but without the thickness of the strip.

I have followed all your instructions and the .stl is a 15M file for just one word with 483324 triangles written. to big for my CPU.

Is there a way to just have the curve ?

I have tried to change the thickness and different parameters but I still have a big block with more 400.000 triangles, not just the desired curve.

all the best for your different beautifull project and thank you for your works.


1 reply

change this function:

void drawGrooves(float[] audioData){

int totalSampleNum = audioData.length -1;
float xPosition;
float zPosition;

//draw outer lower edge of groove
for (int sampleNum=0;sampleNum<totalSampleNum;sampleNum++){
if (sampleNum%rateDivisor == 0){
xPosition = speed/samplingRate*sampleNum;//length/sec * sec/samples * sampleNum
zPosition = -depth-amplitude+audioData[sampleNum];
if (invertGroove){
} else {

int lastSampleIndex = 0;
float finalZPosition = 0;
//draw inner lower edge of groove
for (int sampleNum=0;sampleNum<totalSampleNum;sampleNum++){
if (sampleNum%rateDivisor == 0){
xPosition = speed/samplingRate*sampleNum;//length/sec * sec/samples * sampleNum
zPosition = -depth-amplitude+audioData[sampleNum];
if (invertGroove){
finalZPosition = -zPosition;
} else {
finalZPosition = zPosition;
lastSampleIndex = sampleNum;


print("total length: ");
println(" inches");

Very interesting, maybe the combination of lowest amplitude and something to make resonate and amplify like string or membrane would improve. I
If you still didn't found way to get the audiosample value with Processing without the help of the Python script it is very fast easy with the Minim library (already there with the IDE) :

import ddf.minim.*;

Minim minim;
AudioSample sample;
float[] audioDataLeft;
float[] audioDataRight;

void setup() {
minim = new Minim(this);
sample = minim.loadSample("yourFilePathHere");
audioDataLeft = sample.getChannel(BufferedAudio.LEFT);
audioDataRight = sample.getChannel(BufferedAudio.RIGHT);
//etc ... etc ...

etc ...

You'll get the audio data as array of float value between -1 and 1, if I remember well.

1 reply

yeah I messed around with that, but it seems to only give you a small bit of buffered data at a time. I wasn't able to find a way to pull the whole song in. It's possible I just wasn't using it right though

This is a great start. I remember having a balloon with a talking strip attached - the surface of the balloon acted as the "cone" of a speaker, and since the surface was big, the sound was bigger as well - similar to the greeting card example in the first clip where the paper is the transducer changing the mechanical vibrations into airborne sound waves. You may have better luck keeping the substrate of the strip as low-mass (easy to vibrate) as possible, then attach to a passive "amplifier" surface. It was a long time ago, but I think the strip on my balloon was almost like Mylar. I don't see how (with current technology/materials) you could print that fine, but you might be able to make a "negative" that could stamp the pattern into a thinner vibration strip.

Perhaps it's my brain filling in the phonemes between the schwa - short a - schwa pattern, but I'm pretty sure I heard "Amanda" when scraped at 3/4 speed. Not bad for plastic! Certainly better than poor Ranjit Bhatnagar's attempt at a similar "scraper"(http://moonmilk.com/2010/02/08/instrument-a-day-6-wave-scraper/). This makes me wonder though; Perhaps this medium isn't ideal for reproducing the relatively complex waveforms of actual speech (a larynx-produced carrier signal modulated by the mouth), but may prefer sounds that emulate primitive speech synthesis circa 1989 (Square wave carrier clunkily modulated to produce phonemes). Maybe it would be worth a try to print a synthesized vowel cycle (aeiou) modulated from a single carrier of uniform frequency and amplitude (pulse or square perhaps?), even with some simple consonants thrown in (carefully placed noise). I see below that others have suggested how these strips usually work using cleverly placed notches of uniform depth rather than waves of variable amplitude. Possibly a simple carrier signal, with uniform peaks and unmodulated amplitude (only freq & harmonics modulated) would be a better start than cutting the bit depth of an existing live recording. With clearly adjusted harmonics, I feel you'd have more to convey pronunciation. I'm not sure, but maybe it would be worth a try. Either way, excellent experiment!

1 reply

Thanks! That's very generous of you, I wish that this project had come out a little better. You might be right about switching to square waves, but I'm not sure I'll ever have time to try!

Hm, did you run the sound through a low-pass filter before printing the waveforms? I would think that a lot of the higher frequences will just result in noise when converted to geometry.

In fact, if you assume a "read" speed of 26 inch/s and a resolution of 300dpi, that translates to 7800 dots/s, or 3900 grooves/s=3.9kHz. I.e. any frequency higher than 3.9kHz would be impossible to print with just 300dpi. (All that is assuming I remember some fragment of my signal processing course and that I managed to not screw up my numbers anywhere. A tall order, I know...)

Actually, if I were to venture a guess I would think that filtering it down further to just a few distinct frequences using a comb filter may yield even better results.

2 replies

I think the DPI would represent the sample rate though. If 3.9 k is the sample rate (number of grooves), the higest audio frequency you will be able to reproduce is half that or 1.95 k.

(Okay, now I can't stop thinking about this so I better try to get some more of it out of my system)

My idea of using a comb filter may or may not be usable, but here's my thought process behind suggesting it anyway.

Since I wouldn't expect the size of the bumps of the printed strip to actually produce much difference in sound amplitude when dragging an edge over it (I would actually expect having sporadic larger bump would cause the edge to jump and skip over grooves, degrading the sound quality), the geometry would probably work better if it was more like how the musical roads works. That is, a waveform that is essentially digital (low or high) and the sound is produced by the distance between the grooves rather than the varying amplitude of a proper waveform.

My thinking was that by trimming it down to fewer frequencies, it would be result in a waveform with fewer "overlapping" grooves, leading to a cleaner separation between the grooves. But as I said, it was mostly a guess which may be way off. It might be enough to just remove all frequencies below some limit that is way lower than the theoretical maximum above.

1 reply

I think this is on the right track, my next tests are going to be lower amp/lower bit depth. Even 1 bit audio can give some good results, this is a 1 bit david bowie edit:
I think the biggest issue is that I didn't print at 600dpi, I only printed at 300. The difference between 300 and 600 with the 3d printed records was huge

Ooh, how about making your 3d print design match up to a plastic wire tie and use it to play your sound (actually maybe even print something like this). Your sound wave may need to be more saw-tooth like