# Simulate a very simple woodwind with Lambda (2D fdtd)¶

We simulate a flute-like woodwind to prove that the air escapes the instrument at the first open hole. The shape of the instrument is actually of little importance for this specific experiment.

In [1]:
import lambdasim as l
from IPython.display import *


# Simulation space¶

We draw the walls of our instrument. The instrument will be around 90cm in width. We define alse a source at the left wall (red), and receivers ("microphones") at the first and last hole, as well as at the right opening (blue pixels).

In [2]:
simimg = "walls4.png"
info = l.util.png_info(simimg)
print(info)
Image("./walls4.png")

{'bitdepth': 8, 'interlace': 0, 'planes': 4, 'greyscale': False, 'alpha': True, 'size': (1100, 165)}

Out[2]:
In [18]:
Xpix, Ypix = info['size']
X = 1

s = l.Simulation(resolution=X/Xpix).set_size_in_pixels(Xpix, Ypix)
first_hole_x, first_hole_y = s.pix2coord(360, 100)
x0, _ = s.pix2coord(17, 0)
resfreq = l.acoustics.wavelen2freq(first_hole_x - x0)*0.5

s.wall_from_image(simimg, color=(255,255,255), dist=0.2)

source = s.source_from_array(source_mat, kind='hannsin', amp=0.3, freq=resfreq)

#s.source_point(x0+0.01, first_hole_y, 'hannsin', freq=resfreq, amp=0.3)
#s.source_point(x0+0.01+s.nodesize, first_hole_y+s.nodesize, 'pinknoise', amp=0.1)

print(s)
print("")
print(source)

Adjusting pixel size: Y 165 -> 166
using backend: pyPNG
(181500, 3)
using backend: pyPNG
(181500, 3)
Simulation
----------
nodesize    : 0 mm
samplerate  : 533582 Hz
C           : 343.0 m/s
rho         : 1.204 kg/m3
size        : 1.00 m x 0.15 m
matrix      : 1100 pixels x 166 pixels
num. sources: 22
num. recs.  : 0
num. samples: 0

SourceList
----------
numpoints: 22
freqs    : set([555.0831110227851])
coords   : (16, 85) - (16, 106)



In [19]:
recvpix = l.mask_to_pixels(l.img_to_mask(simimg, (0,0,255), 0.1))
recvpix.sort(key=lambda (x,y):y) # sort by x, then by y
recvpix.sort(key=lambda (x,y):x)
for i, (xpix, ypix) in enumerate(recvpix):
x, y = s.pix2coord(xpix, ypix)


using backend: pyPNG
(181500, 3)


# Write down the simulation, discard the angles¶

In [20]:
print(s.receivers)
s.angmat = None
s.write("ww1")

[(0.32711370262390665, 0.069387755102040802, ''), (0.69567983037370784, 0.068486615425390918, ''), (0.897535117943281, 0.086509408958388531, '')]

Out[20]:
Simulation(samplerate=533582.8, size=(1.0, 0.2), duration=1.000)

# Open the simulation for testing¶

In [21]:
s.opensim()

Calling Lamda as: ['/Applications/Lambda.app/Contents/MacOS/Lambda', '-file', '/Users/em/proj/simulations/woodwind/ww1.sim', '-vis', '-walls', '-contrast', '50']

Out[21]:
<subprocess.Popen at 0x107f23590>

# When done, render the video¶

In [7]:
s.render_video(duration=0.5, contrast=70, fps=60, cmap=2)


# Render the audio to measure phase shifts, interference and rms¶

In [10]:
fut = s.render_wav(duration=0.5, resample=88200, split=True)

In [11]:
fut.result()
# the results are sorted first by Y, then by X. My mistake here, 1st and 2nd receiver are swapped

Calling Lamda as: ['/Applications/Lambda.app/Contents/MacOS/Lambda', '-rce', '-exit', '-file', '/Users/em/proj/simulations/woodwind/ww1.sim', '-iterations', '133566']
saving channel 0 to /Users/em/proj/simulations/woodwind/ww1-recv0-363x77.wav
saving channel 1 to /Users/em/proj/simulations/woodwind/ww1-recv1-772x76.wav
saving channel 2 to /Users/em/proj/simulations/woodwind/ww1-recv2-996x96.wav

Out[11]:
['/Users/em/proj/simulations/woodwind/ww1-recv0-363x77.wav',
'/Users/em/proj/simulations/woodwind/ww1-recv1-772x76.wav',
'/Users/em/proj/simulations/woodwind/ww1-recv2-996x96.wav']

# Plot the results (Sonic Visualizer)¶

The results are ordered from left (top) to right (botton). Here you see that the leftmost hole is by far were most of the emission is taking place, more than 20dB louder than at the right ending of the instrument.

In [12]:
Image("./ww1-rms.png")

Out[12]:

# Phase shift¶

The normalized soundpressure waves show the phase shifting of the wave across the instrument as well as some resonance at the 1/4 lambda and some comb filtering.

In [14]:
Image("./ww1-phase.png")

Out[14]:

# Video rendering¶

In [22]:
HTML("""
<video controls id="ww1">
<source src="https://dl.dropboxusercontent.com/u/264776/web/luftzug/ww1.webm">
<source src="https://dl.dropboxusercontent.com/u/264776/web/luftzug/ww1.mp4">

</video>
<script type='text/javascript'>
document.getElementById('ww1').playbackRate = 2;
document.getElementById('ww1').defaultPlaybackRate = 2;
</script>

""")

Out[22]: