Wolfram Computation Meets Knowledge

Spellbound Valentines: DIY Art from 3D-Printed Sound

An original gift can make people feel much warmer, especially in the icy weather affecting so many places this winter—including our headquarters. Valentine’s Day is a good excuse to get a little creative in the art of gift making. And for me, “getting creative” long ago became synonymous with programing in the Wolfram Language. It is that medium that compels me to treat programming as art, where one can improvise, easily pulling magical rabbits out of a hat.

So what shall we make? I think the best gift is a DIY one—especially if it says a lot without even making a sound. Below you see a 3D-printed silver earring in the shape of a sound wave recorded while a person is saying “I love you.”

I love you

Image courtesy of bza.biz.
This original idea comes from the artist David Bizer at bza.biz. You can send a recording of your voice to his studio, and they can design several types of jewelry based on a visualization of the sound wave. David was also kind enough to provide a detailed DIY tutorial for one of these pieces of jewelry.

This inspired me to do a little exploration into sound forms and 3D printing. We start from a sound recording. And because the word “valentine” also means “gift,” there is more than one meaning if you 3D-print the word and then say, while giving it to your loved one, “Here is my valentine for you.” I thought that in my case it would be symbolic to make Mathematica say “Valentine” to all our readers:

Speak ["Valentine"]

Download the audio file.

I recorded it with another instance of Mathematica with a nifty built-in Sound Recorder:

Sound Recorder

Which can be run as:

SystemDialogInput ["RecordSound"]

Once SystemDialogInput gets the data, it automatically produces an interface, which you can see above, that can be assigned to a variable I called “raw.” This “raw” data needs to be brushed up a bit. There are usually long, silent moments at the beginning and the end of an audio recording due to time spent pressing recording interface buttons. Deletion of these moments can be automated. The underlying structure of the sound player interface is a list of real values in the range {-1, 1} :

Short[InputForm[raw], 3]

Where the last number 32,000 is the sampling rate. Here are a few ways to automatically crop silent background moments. One approach is based on Split, a function that can take a condition to isolate low-magnitude values in data.

data = Flatten[Split[raw[[1, 1, 1]], # < .05 &][[2 ;; -2]]]; Sound@SampledSoundList[data, 32000]

The other method is based on ImageCrop, which is a built-in image processing algorithm to crop off extra background from images. The trick is turning sound data temporarily to a two-pixel-wide image, cropping, and getting the data back. Results are similar.

data = ImageData[ImageCrop[Image[{#, #} &@raw[[1, 1, 1]]]]][[1]]; Sound[SampledSoundList[data, 32000]]

Imagine we would like to 3D-print a shape reminiscent of the sound representation shown in the player interface. If we look carefully, this shape is not entirely symmetric with respect to the horizontal axis:


If we choose to neglect this asymmetry, one simple way is to pick the part that is above or below the horizontal axis and work only with it. We could approximate the outer shape by a sort of envelope curve and rotate that curve around the horizontal axis to get a symmetric 3D shape. The envelope is easily built by partitioning data in non-overlapping intervals and finding a maximum point in each such interval. How detailed the envelope is depends on the size of the partitioning bins.


There are a few ways to rotate the envelope around the horizontal axis, for example, we could use Interpolation and RevolutionPlot3D. But for better control of smoothness of shape, I decided to go with BSplineFunction, which can produce surfaces and high-dimensional manifolds. To better understand it, let’s consider a simple curve case. Here is a smooth spline through our envelope points.

Simple curve case

I dropped a few end points to make the pendant’s ends look nicer. We also re-scaled the dataset in space. Our shape was spreading horizontally by thousands of units and vertically by two units. With the Wolfram Language, it’s easy to visualize by just changing the AspectRatio option for graphics, but in a 3D printer we will get a thin, overstretched object. Above we re-scaled the envelope to be about 30 units long and 10 wide—a size appropriate for a small piece of jewelry, perhaps a pendant if the unit is one millimeter.

Now we will place data points in 3D space and rotate the whole dataset six times with a Pi/6 increment around the horizontal axis to complete half of a full rotation. Then we will use the BSplineFunction for a smooth surface.

Place data points in 3D space

I explicitly specified the option SplineClosed so you would know how to produce closed surfaces in a specific direction, if need be. I decided to leave my surface fully open and make half a circular pendant in order for you to see how the option PlotStyle -> Thickness[x] influences the appearance of the surface. First of all, the option Thickness must be applied to any open surface for a 3D printer to process the data properly. But also the physical wall thickness is an important characteristic for 3D printers and 3D-printing websites like Shapeways to test the object for this criteria. Generally, too-thin walls cannot be printed due to 3D printer and/or printing material limitations. Thickness expands surfaces in both directions—inward and outward. The image clearly shows that, because red control points are now sunk inside the thick surface. In the case of a thin surface, the points are usually located outside the surface.

To deliver our object to the printing devices or services, we need to export it to STL format. The Wolfram Language supports this and quite a few other 3D formats. We need to be careful that the resulting shape is smooth enough, but is not overpopulated with unnecessary polygons, because that will make its byte size large and generally difficult to process for printing. For this we will explicitly specify the option PlotPoints to control the fineness of the mesh separately along and around the pendant. For better control and smoothness, we set MaxRecursion -> 0 to prevent automated recursive subdivisions. Note how RegionFunction is used to make a hole in the pendant for a ring, link, thread, chain, or similar connector.

pendant = ParametricPlot3D

The object is ready to be exported to STL. We could import it back into Mathematica to see if it’s OK, but it’s also good to view it in some other modeling/printing software to ensure compatibility and faultiness. I will use the popular and free tool MeshLab:

Export["pendant.stl", pendant];

This is a magnified version of a real object that is supposed to be three centimeters long. Now perhaps you can see another reason I decided to go with half of a full rotation. Viewed in the cross section, the cut wall outlines the vividly original sound wave shape. I also tested out the STL file by uploading it to the Shapeways site, which tests 3D objects for their capacity to be 3D-printed in various materials. For example, this specific 30-millimeter-long piece passed the test on wall thickness to be printable in raw bronze or silver.

It’s also possible to preview an STL object as if it were made of a specific material using the Texture functionality. One way to go about it is to find an image with an approximate color palette that you’d like to apply to the object. Let’s import from Wikipedia this historical bronze medal from the 1980 Olympic Games in Moscow…

1980 Olympic Games bronze medal

…and select a small, more or less uniform region, but still with enough of a rich color palette to represent realistic bronze. We will texture-map it onto every polygon of our STL object. Note that VertexTextureCoordinates are randomly rotated to improve the realism of the texture by reducing its obvious repetitiveness:

texture = ImageCrop[i, 200 {1, 1}]

plo = Import["pendant.stl", "PolygonObjects"];

Animated gif

If you are interested in exploring more about 3D printing with the Wolfram Language, check out other Wolfram users’ work, for example, Henry Segerman or George W. Hart. For an excellent source on 3D-printing tips and tricks (such as surface normals, water-tightness, verification tools, splines, NURBS, etc.), I refer you to our free online video: Scan, Convert, and Print: Playing with 3D Objects in Mathematica. See the attached notebook below for the complete code, and feel free to experiment with voices, messages, and jewelry types. I’m sure in no time you’ll come up with your own artistic ideas. No matter how much programing you know, if you got to this point, you have already “spoken” a little bit of the Wolfram Language. And I hope it will help you to get creative, productive, or even romantic, and spend your holidays with a few original ideas. Happy Valentine’s Day!

Download this post as a Computable Document Format (CDF) file.


Join the discussion

!Please enter your comment (at least 5 characters).

!Please enter your name.

!Please enter a valid email address.


  1. We’ve got some nice feedback from our users, including beautiful renderings by Michael Hale of spoken names. Take a look at the images, let us know what you think: http://goo.gl/vij6xJ

  2. This is a great idea for 3d jewelry, capturing the sound of love, beautiful.

  3. Its not my first time to go to see this site, i am visiting this web page
    dailly and obtain good facts from here all the time.

  4. The point was to remind readers about Speak[…] functionality. I am aware of native OS functionality – but thank you for bringing it out – other folks can make use of it.

  5. Yes it is absolutely possible with Mathematica home edition.