Wednesday, August 17, 2016

Minim 14. balance Example

A Balance UGen can change the magnitude of left or right channel in a stereo signal.


We use a LFO and Sine Oscillator as well.


# Ex14.pyde
# Based on Java File in Examples: balanceExample.pde

'''
balanceExample is an example of using the Balance UGen
inside an instrument. It is important to note that
Balance works specifically on stereo signals. It is
not the same as Pan, which takes a mono signal and
places it in a stereo field. Balance works by simply
attenuating either the left or right channel of a
stereo signal based on what the balance is set to.
Negative balance values will attenuate the left channel
and positive balance values attentuate the right channel.
For more information about Minim and additional features,
visit http://code.compartmental.net/minim/
author: Damien Di Fede
'''

add_library('minim')

out = None

# Every instrument must implement the Instrument interface
# so playNote() can call the instrument's methods.
class ToneInstrument(Instrument):
    # declare our oscillators. sineOsc is used for the
    # sounding tone and lFOOsc is used to control the
    # value of Balance
    def __init__(self, frequency, amplitude, lfoFrequency,
                 lfoAmplitude):
        self.sineOsc = Oscil(frequency, amplitude,
                            Waves.SINE)
        self.lFOOsc = Oscil(lfoFrequency, lfoAmplitude,
                            Waves.SINE)
        # Balance takes the value of the Balance as an
        # argument. 0 would result in no change in the
        # signal fed into it
        # negative values will attenuate the left channel
        # and positive values will attenuate the right
        # channel
        self.balance = Balance(0.5)
        # patch our LFO to the balance control of Balance
        self.lFOOsc.patch(self.balance.balance)
        # patch our oscillator to the balance and into the
        # damp
        self.sineOsc.patch(self.balance)
        
    def noteOn(self,dur):
        # every instrument must have a noteOn(float)
        # method to start sounding we simply patch
        # our balance to output. This is better than
        # simply turning the volume up because
        # it means we don't actually have to do any
        # processing until we are meant to be heard.
        self.balance.patch(out)
        
    def noteOff(self):
        # every instrument must have a noteOff() method
        self.balance.unpatch(out)

def setup():
    # initalize the drawing window
    global out
    size(512, 200)
    # initalize the minim object and output
    minim = Minim(this)
    # note that we must ask for a stereo output
    # because balance does not work with mono output.
    out = minim.getLineOut(Minim.STEREO, 1024)
    # pause time when adding a bunch of notes at once
    out.pauseNotes()
    # make an instance of my instrument and ask the
    # output to play it
    # arguments are: oscillator frequency, oscillator
    # amplitude, lfo for the balance frequency, lfo
    # for the balance amplitude
    myNote = ToneInstrument(200.0, 0.3, 0.5, 1.0)
    # play this instrument on the output.
    # arguments are: how many seconds from now to
    # play the note, and how long to play the note for
    out.playNote(0.0, 8.0, myNote)
    # make another instance of my instrument
    myNote = ToneInstrument(415.3, 0.3, 1.0, 1.0)
    out.playNote(2.0, 0.5, myNote)
    myNote = ToneInstrument(415.3, 0.3, 2.0, 1.0)
    out.playNote(3.5, 0.5, myNote)
    myNote = ToneInstrument(415.3, 0.3, 3.0, 1.0)
    out.playNote(5.0, 0.5, myNote)
    myNote = ToneInstrument(830.6, 0.3, 5.0, 1.0)
    out.playNote(6.5, 1.5, myNote)
    # resume time after a bunch of notes are added
    # at once
    out.resumeNotes()
    
# draw is run many times
def draw():
    # erase the window to black
    background(0)
    # draw using a white stroke
    stroke(255)
    # draw the waveforms
    for i in range(out.bufferSize() - 1):
        # find the x position of each buffer value
        x1  =  map(i, 0, out.bufferSize(), 0, width)
        x2  =  map(i+1, 0, out.bufferSize(), 0, width)
        # draw a line from one buffer position to the next
        # for both channels
        line(x1, 50 + out.left.get(i)*50,
             x2, 50 + out.left.get(i+1)*50)
        line(x1, 150 + out.right.get(i)*50,
             x2, 150 + out.right.get(i+1)*50)

This is the output:


Minim 13. set Loop Points

For the AudioPlayer object we may set the beginning and ending points.


A left-click sets the beginning and right-click sets the ending point. We also have to give initial values for loopBegin and loopEnd since they are needed in draw().


# Ex13.pyde
# Based on Java File in Examples: setLoopPoints.pde

'''
This sketch demonstrates how to use setLoopPoints
using an AudioPlayer. Left-click with the mouse
to set the start point of the loop and right-click
to set the end point of the loop. You will likely
find there to be a break during loops while the code
seeks from the beginning of the file to the start
of the loop. This seek time can become quite
noticable if you are using an mp3 file because it
will need to decode as it seeks.
'''

add_library('minim')

snip = None
loopBegin = 0
loopEnd = 1000

def setup():
    size(512, 200)
    global snip
    minim = Minim(this)
    snip = minim.loadFile("groove.mp3", 2048)
    
def draw():
    background(0)
    fill(255)
    text("Loop Count: %d" % snip.loopCount(), 5, 20)
    text("Looping: %s" % snip.isLooping(), 5, 40)
    text("Playing: %s" % snip.isPlaying(), 5, 60)
    p = snip.position()
    l = snip.length()
    text("Position: %d" % p, 5, 80)
    text("Length: %d" % l, 5, 100)
    x = map(p, 0, l, 0, width)
    stroke(255)
    line(x, height/2 - 50, x, height/2 + 50)
    lbx = map(loopBegin, 0, snip.length(), 0, width)
    lex = map(loopEnd, 0, snip.length(), 0, width)
    stroke(0, 255, 0)
    line(lbx, 0, lbx, height)
    stroke(255, 0, 0)
    line(lex, 0, lex, height)
    
        
def mousePressed():
    global loopEnd, loopBegin
    ms = int(map(mouseX, 0, width, 0, snip.length()))
    if mouseButton == RIGHT:
        snip.setLoopPoints(loopBegin, ms)
        loopEnd = ms
    else:
        snip.setLoopPoints(ms, loopEnd)
        loopBegin = ms

def keyPressed():
    snip.loop(2) 

This is the output:


Minim 12. rewind

We can use the rewind() method of an AudioPlayer to point the audio to beginning.


Pressing any key will rewind the AudioPlayer object.


# Ex12.pyde
# Based on Java File in Examples: rewind.pde

'''
This sketch demonstrates how to use the rewind method
of a Playable class. The class used here is AudioPlayer,
but you can also rewind an AudioSnippet. Rewinding a
Playable sets the position to zero, the beginning.
Rewinding doesn't change the play state of a Playable,
so if it is playing or looping when you rewind, it will
continue to play or loop after you rewind it. Press 'r'
to rewind the player.
'''

add_library('minim')

groove = None

def setup():
    size(512, 200)
    global groove
    minim = Minim(this)
    groove = minim.loadFile("groove.mp3", 2048)
    groove.loop()
    
def draw():
    background(0)
    stroke(255)
    for i in range(groove.bufferSize()-1):
        line(i, 50 + groove.left.get(i)*50, 
             i+1, 50 + groove.left.get(i+1)*50 )
        line(i, 150 + groove.right.get(i)*50,
             i+1, 150 + groove.right.get(i+1)*50)
    posx = map(groove.position(), 0, groove.length(),
               0, width)
    stroke(0,200,0)
    line(posx, 0, posx, height)
    stroke(255)
    text("Press any key to rewind.", 10, 20)
    
def keyPressed():
    groove.rewind()     

This is the output:


Minim 11. pause

This sketch demonstrates the pause() method of AudioPlayer.


By pressing any key, so keyPressed() is called, we can pause() or loop().


# Ex11.pyde
# Based on Java File in Examples: pause.pde

'''
This sketch demonstrates how to use the pause method of a
Playable class. The class used here is AudioPlayer, but
you can also pause an AudioSnippet. Pausing a Playable
causes it to cease playback but not change position, so
that when you resume playback it will start from where
you last paused it. Press 'p' to pause the player.
'''

add_library('minim')

groove = None

def setup():
    size(512, 200)
    global groove
    minim = Minim(this)
    groove = minim.loadFile("groove.mp3", 2048)
    groove.loop()
    
def draw():
    background(0)
    stroke(255)
    for i in range(groove.bufferSize()-1):
        line(i, 50 + groove.left.get(i)*50, 
             i+1, 50 + groove.left.get(i+1)*50 )
        line(i, 150 + groove.right.get(i)*50,
             i+1, 150 + groove.right.get(i+1)*50)
        
def keyPressed():
    if groove.isPlaying():
        groove.pause()
    else:
        groove.loop()

This is the output:


Minim 10. loop Num

We can enter a number on the keyboard for the number of loops.


We create a tuple t with three values returned by 3 methods of AudioPlayer object, for use in the text() expression.


# Ex10.pyde
# Based on Java File in Examples: loopNum.pde

'''
This sketch demonstrates how to use the loop method of
a Playable class. The class used here is AudioPlayer,
but you can also loop an AudioSnippet. When you call
loop(int) it will make the Playable loop for the number
of times you specify. So, loop(3) will loop the recording
three times, which will result in the recording being
played 4 times. This may seem odd, but it is consistent
with the behavior of a JavaSound Clip. If you want to
make it stop looping you can call play() and it will
finish the current loop and then stop. Press any of the
number keys to make the player loop that many times.
Text will be displayed on the screen indicating your
most recent choice.
'''

add_library('minim')

groove = None

def setup():
    size(600, 200)
    global groove
    minim = Minim(this)
    groove = minim.loadFile("groove.mp3", 2048)
    textFont(createFont("Verdana", 18))
    
def draw():
    background(0)
    stroke(255)
    for i in range(groove.bufferSize()-1):
        line(i, 50 + groove.left.get(i)*50, 
             i+1, 50 + groove.left.get(i+1)*50 )
        line(i, 150 + groove.right.get(i)*50,
             i+1, 150 + groove.right.get(i+1)*50)
    t = (groove.loopCount(), groove.isPlaying(),
         groove.isLooping())
    s1 = 'The player has %d loops left  '
    s2 = 'Is playing: %s  '
    s3 = 'Is looping: %s'
    s = s1 + s2 + s3
    text(s % t, 5, 25)
        
def keyPressed():
    loopcount = int(key)
    if loopcount>0 and loopcount<10:
        groove.loop(loopcount)

This is the output:


Minim 9. loop

This program demonstrates the loop() method of a AudioPlayer object, once '1' is pressed.


The file 'groove.mp3' has to be in the data directory of the sketch.


# Ex9.pyde
# Based on Java File in Examples: loop.pde

'''
This sketch demonstrates how to use the loop
method of a Playable class. The class used
here is AudioPlayer, but you can also loop
an AudioSnippet. When you call loop() it will
make the Playable playback in an infinite loop.
If you want to make it stop looping you can
call play() and it will finish the current loop
and then stop. Press 'l' to start the player
looping.
'''

add_library('minim')

groove = None

def setup():
    size(512, 200)
    global groove
    minim = Minim(this)
    groove = minim.loadFile("groove.mp3", 2048)
    
def draw():
    background(0)
    stroke(255)
    for i in range(groove.bufferSize()-1):
        line(i, 50 + groove.left.get(i)*50, 
             i+1, 50 + groove.left.get(i+1)*50 )
        line(i, 150 + groove.right.get(i)*50,
             i+1, 150 + groove.right.get(i+1)*50)
        
def keyPressed():
    if key == 'l': groove.loop()

This is the output:


Tuesday, August 16, 2016

Minim 8. Trigger A Sample

We have kick and snare files in our data folder. They are loaded into two AudioSample objects. The objects have to be global so they will remain in memory for the draw function.


The kick or snare sounds are triggered by the trigger() method, and here they are triggered when a key is pressed: 's' (for snare) or 'k' (for kick).


# Ex8.pyde
# Based on Java File in Examples: TriggerASample.pde

'''
This sketch demonstrates how to use the loadSample
method of Minim. The loadSample method allows you
to specify the sample you want to load with a
String and optionally specify what you want the
buffer size of the returned AudioSample to be.
Minim is able to load wav files, au files, aif
files, snd files, and mp3 files. When you call
loadSample, if you just specify the filename it
will try to load the sample from the data folder
of your sketch. However, you can also specify an
absolute path (such as "C:\foo\bar\thing.wav")
and the file will be loaded from that location
(keep in mind that won't work from an applet). 
You can also specify a URL, such as "http://
www.mysite.com/mp3/song.mp3", but keep in mind
that if you run the sketch as an applet you may
run in to security restrictions if the applet is
not on the same domain as the file you want to
load. You can get around the restriction by
signing all of the jars in the applet.
An AudioSample is a special kind of file playback
that allows you to repeatedly trigger an audio
file. It does this by keeping the entire file in
an internal buffer and then keeping a list of
trigger points. AudioSample supports up to 20
overlapping triggers, which should be plenty for
short sounds. It is not advised that you use this
class for long sounds, like entire songs, for
example, because the entire file is kept in memory.
Use 'k' and 's' to trigger a kick drum sample and
a snare sample, respectively. You will see their
waveforms drawn when they are played back. For more
information about Minim and additional features, 
visit http://code.compartmental.net/minim/
'''

add_library('minim')

kick = None
snare = None

def setup():
    size(512, 200)
    global kick, snare
    minim = Minim(this)
    kick = minim.loadSample("BD.mp3", 512)
    # An AudioSample will spawn its own audio processing
    # Thread, and since audio processing works by
    # generating one buffer of samples at a time, we can
    # specify how big we want that buffer to be in the
    # call to loadSample. Above, we requested a buffer
    # size of 512 because this will make the triggering
    # of the samples sound more responsive. On some
    # systems, this might be too small and the audio
    # will sound corrupted, in that case, you can just
    # increase the buffer size.
    # if a file doesn't exist, loadSample will return null
    if kick == None:
        print "Didn't get kick!"
    # load SD.wav from the data folder
    snare = minim.loadSample("SD.wav", 512)
    if snare == None:
       print "Didn't get snare!"
    
def draw():
    background(0)
    stroke(255)
    # use the mix buffers to draw the waveforms
    for i in range(kick.bufferSize()-1):
        x1 = map(i, 0, kick.bufferSize(), 0, width)
        x2 = map(i+1, 0, kick.bufferSize(), 0, width)
        line( x1, 50 - kick.mix.get(i)*50, 
             x2, 50 - kick.mix.get(i+1)*50 )
        line( x1, 150 - snare.mix.get(i)*50,
             x2, 150 - snare.mix.get(i+1)*50)
        
def keyPressed():
    if key == 's': snare.trigger()
    if key == 'k': kick.trigger()

This is the output when the snare is triggered: