Breaking a Wine Glass in Python By Detecting the Resonant Frequency

Partager

news image

For 50 days straight between January and March of this year, I wrote a ingenious programming sketch in Python on daily basis.

On day six, I tried to write a program to detect the resonant frequency of a pitcher, and atomize it. As you would also perceive below, my desktop laptop speaker wasn’t somewhat loud ample to interrupt the glass alone.

In today’s submit, I creep via the go of writing a Python program to interrupt wine glasses on inquire of, by detecting their resonant frequency.

Along the formula we’ll 3D print a cone, study about resonant frequencies, and perceive why I wanted an amplifier and compression driver. So, let’s fetch started.

First, the Inspiration

I first seen the video above, which goes into exchange element about how to truly atomize a wine glass with your negate. A few main factors are lined, and Mike Boyd, the creator, hasty touches upon them. He recommends:

  • Having a actual crystal glass
  • Preferring a thinner, longer crystal glass
  • Putting the glass to fetch it to resonate
  • The usage of a spectrum analyzer to search out the resonant frequency of the glass
  • The usage of a straw to visualize when the glass is resonating

With that in direct, it wasn’t unless I tried breaking my third glass that I spotted the very last thing that ensures you after all atomize a pitcher on direct:

  • Having micro abrasions in the glass. It will probably presumably presumably’t be perfectly new and soft.

Without the micro abrasions (either triggered by cleansing the glass with cleansing soap and water or a after all mild sanding), the glass wouldn’t atomize the least bit.

An Aside About How Resonance Works

When Mike Boyd breaks the glass in the above video, he’s the usage of the acoustic resonance of the wine glass.

Crystal wine glasses bear a pure frequency of vibration that you would also hear as soon as you strike them.

Any sounds at this frequency bear the likely to originate the wine glass absorb more vitality than at every other frequency. Our hope is that our program and audio system will generate ample vitality in the glass to interrupt it.

Writing a Prototype Sketch

After seeing the video and being impressed to capture a peep at recreating it, I desired to first fetch a prototype in put.

Would I have the chance to fetch a straw to resonate take care of in that instance video?

Fortunately, my Converse Controlled Flappy Chicken submit already does the sophisticated share of detecting the present pitch frequency from a microphone.

So, hypothetically, placing the wine glass must restful assemble the edifying style tone to interrupt the glass itself.

The usage of the pitch detection code, the counseled thing that is at chance of be left is to play out the pitch frequency detected by a microphone. The code is unassuming ample the usage of Pygame, Music21, and PyAudio:

from threading import Thread
import pygame
import pyaudio
import numpy as np

import time

from rtmidi.midiutil import open_midiinput
from voiceController import q, get_current_note

class MidiInputHandler(object):
    def __init__(self, port, freq):
        self.port = port
        self.base_freq = freq
        self._wallclock = time.time()
        self.freq_vals = [0 for i in vary(6)]

    def __call__(self, tournament, recordsdata=None):
        world currentFrequency
        message, deltatime = tournament
        self._wallclock += deltatime
        print("[%s] @%0.6f %r" % (self.port, self._wallclock, message))
        if message[1] == 16:
            self.freq_vals[0] = (message[2] - sixty two) * .5
        elif message[1] == 17:
            self.freq_vals[1] = (message[2] - sixty two) * .01
        elif message[1] == 18:
            self.freq_vals[2] = (message[2] - sixty two) * .005
        elif message[1] == 19:
            self.freq_vals[3] = (message[2] - sixty two) * .0001 
        elif message[1] == 20:
            self.freq_vals[Four] = (message[2] - sixty two) * .00001
        new_freq = self.base_freq
        for i in vary(6):
            new_freq += self.freq_vals[i]
        currentFrequency = new_freq
        print(new_freq)

port = 1
are trying:
    midiin, port_name = open_midiinput(port)
apart from (EOFError, KeyboardInterrupt):
    exit()

midiSettings = MidiInputHandler(port_name, 940.0)
midiin.set_callback(midiSettings)

pygame.init()

screenWidth, screenHeight = 512, 512
show mask = pygame.direct.set_mode((screenWidth, screenHeight))
clock = pygame.time.Clock()

running = Accurate

titleFont = pygame.font.Font("assets/Bungee-Authorized.ttf", 24)
titleText = titleFont.render("Hit the Glass Gently", Accurate, (0, 128, 0))
titleCurr = titleFont.render("", Accurate, (0, 128, 0))

noteFont = pygame.font.Font("assets/Roboto-Medium.ttf", 55)

t = Thread(target=get_current_note)
t.daemon = Accurate
t.birth()


low_note = ""
high_note = ""
have_low = Unfounded
have_high = Accurate

noteHoldLength = 10  # what number of samples in a row particular person needs to expend a cost
noteHeldCurrently = 0  # take care of discover of how prolonged present payment is held
noteHeld = ""  # string of the present payment

centTolerance = 10  # how remarkable deviance from actual style payment to tolerate


def break_the_internet(frequency, notelength=.1):
    p = pyaudio.PyAudio()

    volume = 0.9     # vary [0.0, 1.0]
    fs = 44100       # sampling payment, Hz, favor to be integer
    length = notelength   # in seconds, would be drift
    f = frequency        # sine frequency, Hz, would be drift

    # generate samples, payment conversion to float32 array
    
    # for paFloat32 sample values favor to be in vary [-1.0, 1.0]
    circulate = p.birth(format=pyaudio.paFloat32,
                channels=1,
                payment=fs,
                output=Accurate)

    # play. Might possibly possibly possibly presumably repeat with various volume values (if finished interactively)
    samples = (np.sin(2*np.pi*np.arange(fs*length)*f/fs)).astype(np.float32)
    circulate.write(volume*samples)
    

newFrequency = 0
breaking = Unfounded
currentFrequency = 0
breaking_zone = Unfounded
super_breaking_zone = Unfounded
noteLength = 5.0

whereas running:
    for tournament in pygame.tournament.fetch():
        if tournament.kind == pygame.QUIT:
            running = Unfounded
        if tournament.kind == pygame.KEYDOWN and tournament.key == pygame.K_q:
            running = Unfounded
        if tournament.kind == pygame.KEYDOWN and tournament.key == pygame.K_SPACE and newFrequency != 0:
            breaking = Accurate
            midiSettings.base_freq = newFrequency
            currentFrequency = newFrequency - 10
        if tournament.kind == pygame.KEYDOWN and tournament.key == pygame.K_s:
            noteLength = 30.0 
            breaking_zone = Accurate
        if tournament.kind == pygame.KEYDOWN and tournament.key == pygame.K_a:
            super_breaking_zone = Accurate
            noteLength = 5.0

    show mask.occupy((0, 0, 0))

    if breaking:
        titleCurr = titleFont.render("Novel Frequency: %f" % currentFrequency, Accurate, 
                                     (128, 128, 0))
    
    # our particular person favor to be singing if there is a cost on the queue
    else:
        if no longer q.empty():
            b = q.fetch()
            pygame.scheme.circle(show mask, (0, 128, 0), 
                               (screenWidth // 2 + (int(b['Cents']) * 2),300),
                               5)

            noteText = noteFont.render(b['Thunder'], Accurate, (0, 128, 0))
            if b['Thunder'] == noteHeldCurrently:
                noteHeld += 1
                if noteHeld == noteHoldLength:
                    titleCurr = titleFont.render("Frequency is: %f" % b['Pitch'].frequency, Accurate, 
                                                 (128, 128, 0))
                    newFrequency = b['Pitch'].frequency
            else:
                noteHeldCurrently = b['Thunder']
                noteHeld = 1
                show mask.blit(noteText, (50, four hundred))

    show mask.blit(titleText, (10,  Eighty))
    show mask.blit(titleCurr, (10, 120))
    pygame.direct.flip()
    clock.tick(30)

    if breaking:
        break_the_internet(currentFrequency, noteLength)

Now, there are some things to payment right here.

One, I relate rtmidi utility in say to dial in the resonant frequency the usage of a Midi controller. This lets me alter the knobs in direct to search out a put the put the straw vibrates basically the most within my wine glass.

Secondly, we relate pyaudio to generate our sine wave of the resonant frequency. We are in a position to even bear dilapidated one other library with more instantaneous suggestions, but this used to be very most sensible to fetch in put.

Now, the formula this scheme works is that you strike the glass, and confidently the voiceController library detects a resonant frequency. The resonant frequency of wine glasses favor to be between 600 – 900 Hz. When you’ve bought that, you press the SPACEBAR, and that begins taking half in that resonant frequency out the audio system.

With this, I used to be in a position to generate the outcomes you perceive from my day-to-day sketch on my desktop laptop audio system.

Alternatively, I wasn’t in a position to interrupt the glass. I had a hunch it used to be because I wasn’t in a position to generate the volume most important.

Bringing in the Giant Weapons

Since I couldn’t fetch my glass to interrupt with my desktop audio system, I started having a peep spherical the procure to perceive how folks bear damaged glass with audio system.

The very most sensible helpful resource I stumbled on used to be from the College of Salford. They suggest the usage of a 2” “compression driver in direct to fetch outcomes. So, I went off to Amazon, and picked up a 2” compression driver.

With this, the counseled thing last used to be to fetch an audio amplifier edifying of using the speaker to an (un)sensible volume. I dilapidated this, and I opinion on the usage of both the amplifier and driver in extra audio projects in the prolonged escape.

In the slay, I desired to bear a stand for the speaker, along with a cone to level of curiosity the vitality of the wave. For this, I dilapidated Blender, along with my Prusa i3 MK2. I printed it in PLA, and it perceived to bear finished the job effectively ample.

With the speaker cone 3D printed, I used to be in the end ready to bear my setup.

It looks something take care of this:

It consists of a Snowball USB microphone, plugged into a laptop laptop. The laptop laptop runs the sketch from above, first waiting to detect a resonant frequency.

You strike the glass, and if the detected resonant frequency is in the zone you’d request (some other time, 600Hz to spherical 900Hz), you press SPACEBAR to birth up taking half in reduction that resonant frequency.

The audio output is attached to an amplifier, and that amplifier is attached to the driver with the 3D printed code. That cone is pointed straight away on the pinnacle of the wine glass, as you seen in the gif in the introduction.

With that, the glass breaks!

Where to Jog From Here

The code, along with the 3D printable cone STL is at Github.

This system that in the end breaks the glass dilapidated in the video is a runt bit various from what I’ve written above. It doesn’t alter with the MIDI controller, because I stumbled on it wasn’t most important in my case to alter the detected frequency. The glass damaged anyways.

When you plan on looking to recreate my experiment, please build on security glasses and ear security.

Ear effort is accumulative, and no longer wearing actual style ear security plan destructive your ears completely. So please don’t fetch that.

And the glass breaks in all locations, so please build on look security too. This conducting is enjoyable, but no longer payment getting severely injured over.

When you’re restful studying Python and Pygame, or you favor a visual introduction to programming, test out my e book, Mark Work with Python. The first three chapters are free.

In the slay, after all be at liberty to half this submit with your buddies. It helps me to proceed making these originate of tutorials.

Learn More

(Visité 3 fois, 1 aujourd'hui)

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *