Example code for minim sound library

Hi.

Does any body have an example piece of code for allowing computer microphone input using the minim library on the python platform? I am trying to build a sound reactive drawing tool but am not able to find and example mic input code anywhere…

Thank you in advance!!

1 Like
add_library('minim')

def setup():
    global mic
    minim = Minim(this)
    mic = minim.getLineIn()
    
def draw():
    background(0)
    circle(width/2, height/2, mic.left.get(0)*100)
2 Likes

add_library(‘minim’)
mic = None

def setup():
global mic
size(800,800)
background(0)

minim = Minim(this)
mic = minim.getLineIn()

def draw():
fill(25,25,25)
circle(width/2, height/2, mic.left.get(0)*100)
print(mic.left.get(0))

I tried your code. And this. Nothing. Wow, I’m really struggling to get this microphone thing going. I’m trying not to get too disheartened.

Are you running macOS Catalina?

1 Like

I would also try Processing Foundation’s Sound library (I hope Catalina problems won’t hinder you).

def setup():
    size(600, 600)  
    global input, loudness, waveform, samples
    source = AudioIn(this, 0)
    source.start()
    loudness = Amplitude(this)
    loudness.input(source)
    samples = 60
    waveform = Waveform(this, samples)
    waveform.input(source)

def draw():
    background(0) 
    volume = loudness.analyze()
    for i, w in enumerate(waveform.analyze()):
        fill(128)
        rect(i * 10, 300, 10, 300 * w)        
    s = int(map(volume, 0, 0.5, 10, 100))
    fill(255)
    ellipse(300, 300, s, s)

1 Like

Yep I am on Catalina 10.15.4

Hey Alex. The code you posted there is for the Sound library?

I have been having issues with at on Catalina. Neither it or the Minim example code that tabreturn posted are working for me.

1 Like

Yes, it is using ‘normal’ Sound library :frowning:
Maybe you could try to emulate a Linux box using VirtualBox.org and this OVA file:
https://drive.google.com/file/d/1mJExrCPgrwlOpSgFHQ56oJbEUGfuySKg/view

This is a Catalina issue – Processing, regardless of the mode or code, cannot access your mic. According to the GitHub thread, you can resolve the issue by launching Processing from the Terminal.

Launch Processing via the Terminal, switch to Java mode, then test an example (File > Examples > Sound > IO > AudioInput). If it works in Java mode, it should work in Python mode too. Either way, this will help pinpoint the problem.

Unfortunately I cannot test this because I have no access to a Catalina machine right now.

2 Likes

@tabreturn @villares Thanks guys.

I have managed to get it working on a different operating system. And I’m going to use the Sound Library to try and put this thing together.

I would like to create a toggle switch with my key board to turn the mic (and amp.analzye() for the effects) on and off with a small ellipse that changes from red to green in the bottom corner when the mic is active… Ideally I would have this done with the space bar.

This is what I have so far in terms of a switch. From what I can gather I might need to create a global variable that is initially set to off eg mic_switch = False? Then have this change to True with the keyPressed() function. I am not sure what part of the mic = AudioIn(this)/mic.start() command I can convert into a boolean to have switched?

def setup():
    size(1000, 800)
    background(250)
    
def draw():

    if mousePressed:
        noStroke()
        fill(random(0,height),random(0,152),203)
        ellipse(mouseX, mouseY, 10, 10)
    
    
def keyPressed():

    if key == 'e':
        noStroke()
        fill(43, 250, 99)
        ellipse(950, 750, 20, 20)
    else:
        noStroke() 
        fill(250, 43, 60)
        ellipse(950, 750, 20, 20)
2 Likes

Glad to hear you’re making some progress!

Yes, you can use a global variable. Here’s some code to illustrate:

add_library('sound')
mic_on = True  # global variable for mic state 

def setup():
    global mic, amp
    size(500, 500)
    mic = AudioIn(this, 0)
    mic.start()
    amp = Amplitude(this)
    amp.input(mic)

def draw():
    background('#FFFFFF')
    if mic_on:
        # things to do when the mic is on
        fill('#00FF00')
        circle(450, 450, 20)
        diameter = map(amp.analyze(), 0, 1, 10, width)
        circle(width/2, height/2, diameter)
    else:
        # things to do when the mic is off
        fill('#FF0000')
        circle(450, 450, 20)

def keyPressed():
    global mic_on
    if key == ' ':  # detect space key
        mic_on = not mic_on  # invert boolean
3 Likes

@tabreturn this is amazing thank you. Things are coming together despite the system difficulties - the windows comp I am using keeps crashing…

Where I’m at right now… I’m not sure what the best way of taking the information on the screen that is drawn when the mic is off, and using the variable taken from the amp.analyze and effecting the whole image.

I have been able to iterate over all of the pixels and change the colour of them (but not have them change back when the mic is off). And I figured that the translate() would have the screen moving around (When I used the translate with your code I have had the ellipse moving, but only towards the bottom right of the window). But I’m not sure how to combine the amp.analyze date with the translate() and apply it to the whole drawing…

Do I have to have a defined object to apply the translate() to or can I apply it to everything that is on the window?

Thank you again!

1 Like

The translate() function applies to everything beneath it. Note, however, that if translate() is called within draw(), the transformation is reset when the loop begins again.

I’m unclear on what you’re asking here. It sounds like you’re loading in an image and manipulating the pixel values using the mic. But I don’t know what the goal is. You say, “but [moving] only towards the bottom right of the window”. How do you want to move things? Up and down? In circles? Shrink and grow? …

Hmm maybe it won’t work as there isn’t necessarily an object beneath it. Unless there is a way of indicating for it to apply to the whole image?

The idea is to be able to draw on the screen with the mouse when the mic is off, then when the mic is turned on, translate would apply to everything that has been drawn on the window, with the degree of movement coming from the amp.analyze. I would like to have things move in all directions randomly with the degree of movement coming from the mic input. Does this make sense?

What is the mouse drawing? Circles, squares, lines, pixels? It sounds like each circle/square/line/pixel will move about independently? What algorithm will you use to guide them – a random walk, something that employs vectors? When you say degree of movement, is degree a reference to angle or quantity?

I have too many questions. I think you’ll need to provide some diagrams before I can answer any of this.

To combine what we have put together so far. This is the guts of what I am trying to achieve…

add_library('sound')
mic_on = False 

def setup():
    
    global mic, amp
    size(800, 800)
    background(250)

    #sound input and analysis 
    mic = AudioIn(this, 0)   
    mic.start()
    amp = Amplitude(this)     
    amp.input(mic)
    
def draw():
    global mic_on
    
    if mic_on:
        
        # variable coming from the volume of the mic information
        # which is applied to the transformation when the mic is ON
        sound_variable = map(amp.analyze(), 0, 1, 10, 255)

        
        
        noStroke()       #EFX on indicator  
        fill('#00FF00')
        circle(750, 750, 20)
        fill("#183CC6")
        textSize(20)
        text("EFX", 680, 758)
    
    else: 
        
        # drawing tool with the mouse
        if mousePressed:
            fill(random(0, height), random(0, width), 100)
            ellipse(mouseX, mouseY, 15,15)
            
        noStroke()     #EFX off indicator 
        fill('#FF0000')
        circle(750, 750, 20)
        fill("#183CC6")
        textSize(20)
        text("EFX", 680, 758)
                 
    
def keyPressed():
    global mic_on
    
    if key == ' ':  
        mic_on = not mic_on  # invert the mic state

    if mic_on == False and key == 'c': #clear the drawing surface
        background(250)

And yes exactly random walk, the degree being quantity, or distance moved in conjunction with the amp sound_variable variable. I want to add a colour change with mouse position but that can come afterwards.

1 Like

It’s probably best to store the circles you draw in a list. As you draw new circles, you append them to that list. Each frame, you loop through the list to render the circles.

Here’s a demo for you to riff off –

def setup():
    size(800, 800)

circles = []

def draw():
    global circles
    background('#FFFFFF')

    if mousePressed:
        '''
        create a new circle
        (you could also use a list-in-a-list instead of a dictionary-in-a-list)
        ''' 
        circ = {
          'x' : mouseX, 
          'y' : mouseY, 
          'fill' : color(random(255), random(255), random(255))
        }
        # add the new circle to the list
        circles.append(circ)
    
    # render the list of circles
    for circ in circles:
        fill(circ['fill'])
        circle(circ['x'], circ['y'], 15)
        
    if keyPressed:
        # press any key to randomly move the circles
        for circ in circles:
            circ['x'] += random(-5, 5)
            circ['y'] += random(-5, 5)
2 Likes

Amazing. I’ve managed to get it all together and working, Colour input from the keyboard and the circle movement hooked up to the mic, with the on/off switch making things happen! It works!

3 Likes

It was so close! I had everything working then tried to add a couple more keyboard commands and something changed. I want to be able to clear the welcome info and change the colour of the circles in the dict to the background colour with ‘c’ but now it seems that these actions are taking place when ever a key is pressed, regardless of if the button was ‘c’ or not. This is what I have in the key board functions. Any idea why the screen is clearing and the circles turning white every time I press any of the allocated keys?

def brush_colour():
    global pen_colour
    
    if keyPressed and key == 'r':   # pen colour key input
        pen_colour = "#FF3131"
    if keyPressed and key == 'g':
        pen_colour = "#33C945" 
    if keyPressed and key == 'b':
        pen_colour = "#318CFF"
    if keyPressed and key == 's':
        pen_colour = color(random(255), random(255), random(255))

def keyPressed():
    global mic_on
   
    if key == ' ':                # detect space key
        mic_on = not mic_on       # invert mic state

    if key == ENTER or RETURN:    # clears the welcome information
        background(255)

    if mic_on == False and key == 'c' or 'C': # sets the circle fill to white and clears the drawing
        for circ in circles:
            circ['fill'] = color(255)