Exemple #1
0
class DragFilter(Filter):
    def init(self):
        self.osc = Oscillator(freq=1)
        self.osc2 = Oscillator(freq=5, zero=True, phase=20)
        self.amplitude = 0
        self.add_parameter(name="amplitude", min=10, max=60)

    def compute(self, frame):
        f = cv.cvtColor(cv.medianBlur(frame, 3), cv.COLOR_BGR2GRAY)
        mask = cv.adaptiveThreshold(f, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C,
                                    cv.THRESH_BINARY, 17, 4)
        invert_mask = 255 - mask

        source = cv.bitwise_and(frame, frame, mask=invert_mask)
        lfo = self.osc2.next()
        self.osc.freq = lfo * 5
        o = self.osc.next()
        # print(self.amplitude)
        self.M = np.float32([[1, 0, self.amplitude], [0, 1, self.amplitude]])

        acc = cv.addWeighted(
            self._previous,
            0.9,
            cv.warpAffine(source, self.M, (self.cols, self.rows)),
            1,
            0.0,
        )
        self._previous = acc
        # invert_frame = cv.bitwise_not(frame)
        # acc = cv.bitwise_or(acc, cv.bitwise_and(invert_frame, invert_frame, mask=invert_mask))

        return acc
Exemple #2
0
    def __init__(self):
        # config
        app_title = "Oscbar"
        interval = 2  # seconds per calibration step

        # initial oscillator settings
        self.wave_type = "sine_wave"
        self.amplitude = 0.5
        self.frequency = 440
        self.store_wave = None
        self.store_freq = None

        # object instances
        self.app = rumps.App(app_title, icon=APP_ICON)
        self.oct_timer = rumps.Timer(
            lambda sender, factor=2, max_freq=880, title='Octave Walk': self.
            advance_frequency(sender, factor, max_freq, title),
            interval)
        self.oct_thirds_timer = rumps.Timer(
            lambda sender, factor=(2**(1 / 3)), max_freq=880, title
            ='Octave Walk  â…“': self.advance_frequency(
                sender, factor, max_freq, title),
            interval)
        self.osc = Oscillator(self.wave_type, self.amplitude, self.frequency)

        # set up menu
        self.build_menu()
        self.osc_ready_menu()
Exemple #3
0
def main(
    ramp_start=START,
    ramp_end=START + RISE,
    ramp_seconds=RISE * 60,
    feel=90,
    osc_multiplier=3,
    active_seceonds=2,
    inactive_seconds_min=2,
    inactive_seconds_max=10,
):
    ramp = Ramp(ramp_start, ramp_end, ramp_seconds)
    seq = Sequence()
    time_osc = Oscillator(inactive_seconds_min, inactive_seconds_max, 120)

    with commander() as cmd:
        cmd.set_power('H')
        cmd.set_mode(Mode.CONTINUOUS)
        cmd.set_feel(feel)

        while True:
            base_level = ramp.get_value() + osc_multiplier * seq.get_value()

            cmd.set_level('A', base_level)
            sleep(active_seceonds)
            cmd.set_level('A', 0)

            # inactive_seconds = randint(inactive_seconds_min, inactive_seconds_max)
            inactive_seconds = time_osc.get_value()
            sleep(inactive_seconds)
def plot_theta_vs_theta_dash():
    pendulum = Oscillator(alpha=0.8, radius=1)
    time_steps = 400
    time_max = 10.0
    plt.axes(xlim=(-0.1, 0.1), ylim=(-0.25, 0.25))
    trajectory = pendulum.get_trajectory(time_max, time_steps)
    theta = [position for position, velocity in trajectory]
    theta_dash = [velocity for position, velocity in trajectory]
    plt.plot(theta, theta_dash, "b")
def plot_underdamped_pendulum():
    pendulum = Oscillator(alpha=0.8, radius=1)
    time_steps = 400
    time_max = 10.0
    time = numpy.linspace(0, time_max, time_steps + 1)
    plt.axes(xlim=(0, 10), ylim=(-0.2, 0.2))
    trajectory = pendulum.get_trajectory(time_max, time_steps)
    theta = [position for position, velocity in trajectory]
    plt.plot(time, theta, "r")
Exemple #6
0
	def initAudio(self):
		""" Inits the two oscillators and their channels. """

		#guide tone
		self.guide_osc = Oscillator('sine', self.guide, BUFFER_SIZE)
		self.guide_ch = pygame.mixer.Channel(0)
		self.guide_ch.set_volume(0.9/2.0)

		#adjustable (the knob one), starts at same freq
		self.osc = Oscillator('sine', self.pitch, BUFFER_SIZE)
		self.osc_ch = pygame.mixer.Channel(1)
		self.osc_ch.set_volume(0.9/2.0)
Exemple #7
0
    def initAudio(self):
        """ Inits the two oscillators and their channels. """

        #guide tone
        self.guide_osc = Oscillator('sine', self.guide, BUFFER_SIZE)
        self.guide_ch = pygame.mixer.Channel(0)
        self.guide_ch.set_volume(0.9 / 2.0)

        #adjustable (the knob one), starts at same freq
        self.osc = Oscillator('sine', self.pitch, BUFFER_SIZE)
        self.osc_ch = pygame.mixer.Channel(1)
        self.osc_ch.set_volume(0.9 / 2.0)
    def __init__(self,
                no_of_voices=2,
                no_of_bass_voices=1,
                waveform="sine",
                samplerate=None,
                transposition_factor=1.0,
                attack_time=0.01,
                decay_time=0.01,
                after_decay_level=1.0,
                release_time=1.0,
                bass_attack_time=0.01,
                bass_decay_time=0.01,
                bass_after_decay_level=1.0,
                bass_release_time=1.0,
                bass_transposition_factor=1.0,
                volume=0.3):
        self.no_of_voices = no_of_voices
        self.no_of_bass_voices = no_of_bass_voices
        self.current_voice_index = 0
        self.current_bass_voice_index = 0
        self.samplerate = samplerate

        self.oscillators = [Oscillator(waveform=waveform, \
                            dt=1.0/self.samplerate, frequency=100.0) \
                            for i in range(self.no_of_voices)]
        self.bass_oscillators = [Oscillator(waveform=waveform, \
                                dt=1.0/self.samplerate, frequency=100.0) \
                                for i in range(self.no_of_bass_voices)]


        self.transposition_factor = transposition_factor
        self.bass_transposition_factor = bass_transposition_factor

        self.envelopes = [envelope.Envelope(attack_time=attack_time, \
                          decay_time=decay_time, \
                          after_decay_level=after_decay_level, \
                          release_time=release_time,
                          dt=1.0/self.samplerate) \
                          for i in range(self.no_of_voices)]
        self.bass_envelopes = [envelope.Envelope(attack_time=bass_attack_time, \
                               decay_time=bass_decay_time,\
                               after_decay_level=bass_after_decay_level,\
                               release_time=bass_release_time,
                               dt=1.0/self.samplerate) \
                               for i in range(self.no_of_bass_voices)]
        self.start_envelope = False
        self.release_envelope = False
        self.start_bass_envelope = False
        self.release_bass_envelope = False
        self.is_recording = False
        self.recorded_wave = []
        self.volume = volume
Exemple #9
0
    def to_pcm_audio(self):

        oscillator = Oscillator(self._frequency, self._phase)
        envelope = Envelope()
        for point in self._amplitude_envelope_points:
            envelope.add_point(point)

        samples = oscillator.get_output(self._sample_times)
        samples *= envelope.get_output(self._sample_times)

        if self._base_pcm_audio:
            samples += self._base_pcm_audio.samples

        return PcmAudio(self._reference_pcm_audio.sampling_rate, samples)
class Crawler(object):
    """
    Attraction
    
    A class to describe a thing in our world, has vectors for position, 
    velocity, and acceleration.
    Also includes scalar values for mass, maximum velocity, and elasticity.
    """

    def __init__(self):
        self.acc = PVector()
        self.vel = PVector(random(-1, 1), random(-1, 1))
        self.loc = PVector(random(width), random(height))
        self.mass = random(8, 16)
        self.osc = Oscillator(self.mass*2)

    def applyForce(self, force):
        f = force.get()
        f.div(self.mass)
        self.acc.add(f)

    def update(self):
        
        # Method to update position
        self.vel.add(self.acc)
        self.loc.add(self.vel)
        
        # Multiplying by 0 sets the all the components to 0
        self.acc.mult(0)

        self.osc.update(self.vel.mag()/10)

    def display(self):
        # Method to display
        angle = self.vel.heading2D()
        
        pushMatrix()
        translate(self.loc.x, self.loc.y)
        rotate(angle)
        
        ellipseMode(CENTER)
        stroke(0)
        fill(175, 100)
        ellipse(0, 0, self.mass*2, self.mass*2)

        self.osc.display(self.loc)
        
        popMatrix()
Exemple #11
0
class Crawler(object):
    """
    Attraction
    
    A class to describe a thing in our world, has vectors for position, 
    velocity, and acceleration.
    Also includes scalar values for mass, maximum velocity, and elasticity.
    """
    def __init__(self):
        self.acc = PVector()
        self.vel = PVector(random(-1, 1), random(-1, 1))
        self.loc = PVector(random(width), random(height))
        self.mass = random(8, 16)
        self.osc = Oscillator(self.mass * 2)

    def applyForce(self, force):
        f = force.get()
        f.div(self.mass)
        self.acc.add(f)

    def update(self):

        # Method to update position
        self.vel.add(self.acc)
        self.loc.add(self.vel)

        # Multiplying by 0 sets the all the components to 0
        self.acc.mult(0)

        self.osc.update(self.vel.mag() / 10)

    def display(self):
        # Method to display
        angle = self.vel.heading2D()

        pushMatrix()
        translate(self.loc.x, self.loc.y)
        rotate(angle)

        ellipseMode(CENTER)
        stroke(0)
        fill(175, 100)
        ellipse(0, 0, self.mass * 2, self.mass * 2)

        self.osc.display(self.loc)

        popMatrix()
Exemple #12
0
def main():

    ndim = 2
    np.random.seed(3)

    tf = 25
    nsteps = 1000
    u_init = [0, 0]
    noise = Noise([0, tf])
    oscil = Oscillator(noise, tf, nsteps, u_init)
    my_map = BlackBox(map_def, args=(oscil, ))

    n_init = 4
    n_iter = 80

    mean, cov = np.zeros(ndim), np.ones(ndim)
    domain = [[-6, 6]] * ndim
    inputs = GaussianInputs(domain, mean, cov)
    X = inputs.draw_samples(n_init, "lhs")
    Y = my_map.evaluate(X)

    o = OptimalDesign(X,
                      Y,
                      my_map,
                      inputs,
                      fix_noise=True,
                      noise_var=0.0,
                      normalize_Y=True)
    m_list = o.optimize(n_iter,
                        acquisition="US",
                        num_restarts=10,
                        parallel_restarts=True)

    # Compute true pdf
    filename = "map_samples{:d}D.txt".format(ndim)
    try:
        smpl = np.genfromtxt(filename)
        pts = smpl[:, 0:-1]
        yy = smpl[:, -1]
    except:
        pts = inputs.draw_samples(n_samples=100, sample_method="grd")
        yy = my_map.evaluate(pts, parallel=True, include_noise=False)
        np.savetxt(filename, np.column_stack((pts, yy)))
    pdf = custom_KDE(yy, weights=inputs.pdf(pts))

    for ii in np.arange(0, n_iter + 1, 10):
        pb, pp, pm = model_pdf(m_list[ii], inputs, pts=pts)
        plot_pdf(pdf,
                 pb, [pm, pp],
                 filename="pdfs%.4d.pdf" % (ii),
                 xticks=[-3, 0, 3],
                 yticks=[-8, -3, 2])
        plot_smp(m_list[ii],
                 inputs,
                 n_init,
                 filename="smps%.4d.pdf" % (ii),
                 xticks=[-6, 0, 6],
                 yticks=[-5, 0, 5],
                 cmapticks=[-2, -1, 0, 1, 2])
Exemple #13
0
def main(
    ramp_start=START,
    ramp_end=START + RISE,
    ramp_seconds=RISE * 60,
    warn_adjustment=2,
    feel=80,
    warn_seconds=3,
    bang_adjustment_min=10,
    bang_adjustment_max=20,
    active_seconds=1,
    inactive_seconds_min=10,
    inactive_seconds_max=30,
):
    ramp = Ramp(ramp_start, ramp_end, ramp_seconds)
    seq = Sequence()
    time_osc = Oscillator(inactive_seconds_min, inactive_seconds_max, 120)
    bang_adjustment = bang_adjustment_min

    with commander() as cmd:
        cmd.set_mode(Mode.CONTINUOUS)
        cmd.set_power('H')
        cmd.set_feel(feel)

        while True:
            active_level = ramp.get_value()
            warn_level = active_level // warn_adjustment

            if randint(1, 6) == 1:
                # bang
                active_level += bang_adjustment
                bang_adjustment = min(bang_adjustment + 1, bang_adjustment_max)

            cmd.set_level('A', warn_level)
            sleep(warn_seconds)
            cmd.set_level('A', active_level)
            sleep(active_seconds)
            cmd.set_level('A', 0)

            # inactive_seconds = randint(inactive_seconds_min, inactive_seconds_max)
            inactive_seconds = time_osc.get_value()
            sleep(inactive_seconds)
Exemple #14
0
def main():
    dev = OpenClDevice()
    dev.build('oscillator.cl')

    length_sec = 3.0
    n_instances = 256  # larger values cause mysterious behavior that smells like corrupted memory or instances modifying each other's memory
    local_size = 64  # must divide n_instances, and my video card prefers it to be at least 32
    sample_freq = 44100.0
    n_samples = int(length_sec * sample_freq)

    a = instruments.violin_envelope()
    vib = vibrato.generate(290, 3, 3, 6, 0.4, [3, 5, 4, 1], [1, 8, 4, 1])
    partials = []
    for i in range(len(a)):
        n = i + 1  # n=1 for fundamental
        p = Partial(
            vib,
            Pie.from_string("0 0,0.2 0.5 c ; , 2 1 ; , 3 0"))  # gradual onset
        p = copy.deepcopy(p).scale_f(n).scale_a(a[i])
        partials.append(p)

    # resp = lambda f:1.0 # no filtering
    # resp = lambda f:instruments.log_comb_response(f)
    resp = lambda f: instruments.fisher_response(f)
    for partial in partials:
        partial.filter(resp)

    osc = Oscillator(
        {
            'n_samples': n_samples,
            'n_instances': n_instances,
            't0': 0.0,
            'dt': 1 / sample_freq
        }, partials)

    if False:
        print("graphing...")
        #attack_envelope.graph("a.png",0,3,100)
        partials[10].a.graph("a.png", 0, 3, 100)
        print("...done")

    timer_start = time.perf_counter()
    osc.run(dev, local_size)
    timer_end = time.perf_counter()

    print("return code=", osc.error_code())
    if osc.error_code() != 0:
        sys.exit(" ******* exiting with an error **********")
    print("wall-lock time for computation = ",
          (timer_end - timer_start) * 1000, "ms")

    write_file('a.wav', osc.y(), n_samples, sample_freq)
Exemple #15
0
def main(
    ramp_start=START,
    ramp_end=START + RISE,
    ramp_seconds=RISE * 60,
    feel=80,
    speed=65,
    osc_max=10,
    osc_period_seconds=120,
    step_seconds=5,
):
    ramp = Ramp(ramp_start, ramp_end, ramp_seconds)
    osc = Oscillator(0, osc_max, osc_period_seconds)

    with commander() as cmd:
        cmd.set_mode(Mode.WATERFALL)
        cmd.set_power('H')
        cmd.set_speed(speed)
        cmd.set_feel(feel)

        while True:
            base_level = ramp.get_value() + osc.get_value()

            cmd.set_level('A', base_level)
            sleep(step_seconds)
Exemple #16
0
def main(
    ramp_start=START,
    ramp_end=START + RISE,
    ramp_seconds=RISE * 60,
    warn_adjustment=10,
    feel=80,
    speed=90,
    warn_seconds=3,
    osc_multiplier=2,
    active_seconds=5,
    inactive_seconds_min=5,
    inactive_seconds_max=15,
):
    ramp = Ramp(ramp_start, ramp_end, ramp_seconds)
    seq = Sequence()
    time_osc = Oscillator(inactive_seconds_min, inactive_seconds_max, 120)

    with commander() as cmd:
        cmd.set_power('H')
        cmd.set_mode(Mode.PULSE)
        cmd.set_feel(feel)
        cmd.set_speed(speed)

        while True:
            base_level = ramp.get_value() + osc_multiplier * seq.get_value()
            warn_level = base_level - warn_adjustment

            cmd.set_level('A', warn_level)
            sleep(warn_seconds)
            cmd.set_level('A', base_level)
            sleep(active_seconds)
            cmd.set_level('A', 0)

            # inactive_seconds = randint(inactive_seconds_min, inactive_seconds_max)
            inactive_seconds = time_osc.get_value()
            sleep(inactive_seconds)
    def scene(self):
        spaceships_guns = [(10, 0), (gol.nx_c - 46, gol.ny_c - 9)]
        for i in range(len(spaceships_guns)):
            spaceship_guns = SpaceshipGuns(spaceships_guns[i][0],
                                           spaceships_guns[i][1])
            if (i % 2) == 1:
                spaceship_guns.rot90(2)
            gol.seed(spaceship_guns, spaceship_guns.pos_x,
                     spaceship_guns.pos_y)

        oscillators = [(gol.nx_c - 27, 10), (10, gol.ny_c - 27)]
        for i in oscillators:
            oscilltor = Oscillator(i[0], i[1])
            gol.seed(oscilltor, oscilltor.pos_x, oscilltor.pos_y)

        sticks = [(5, 10), (5, 20), (gol.nx_c - 6, gol.ny_c - 11),
                  (gol.nx_c - 6, gol.ny_c - 21)]
        for i in sticks:
            stick = Stick(i[0], i[1])
            gol.seed(stick, stick.pos_x, stick.pos_y)

        spaceships = [Spaceship(40, 80)]
        spaceships[0].rot90()
        gol.seed(spaceships[0], spaceships[0].pos_x, spaceships[0].pos_y)
Exemple #18
0
 def test_amplitude_decreases_when_friction_present(self):
     oscillator = Oscillator(alpha=1.0, radius=1.0)
     self.assertTrue(
         oscillator.state[0] > oscillator.get_trajectory(10.0, 500)[-1][0])
 def __init__(self):
     self.acc = PVector()
     self.vel = PVector(random(-1, 1), random(-1, 1))
     self.loc = PVector(random(width), random(height))
     self.mass = random(8, 16)
     self.osc = Oscillator(self.mass*2)
spike_gen_in_dn_id = 2
ei_rate = 1  # probability of an excitatory synapse between any pair of excitatory and inhibitory neurons
ie_rate = 1  # probability of an inhibitory synapse between any pair of excitatory and inhibitory neurons
nids_exc = range(exc_offset, num_exc + exc_offset)
nids_inh = range(inh_offset, num_inh + inh_offset)

# init a network generator
net_gen = n.NetworkGenerator()

# create spikegens
spikegen_input_up = Neuron(chip_id, core_id_exc, spike_gen_in_up_id, True)
spikegen_input_dn = Neuron(chip_id, core_id_exc, spike_gen_in_dn_id, True)

oscillator = Oscillator(net_gen,
                        spikegen_input_up,
                        spikegen_input_dn,
                        exc_offset,
                        inh_offset,
                        osc_input_rate=120)

nids_exc, nids_inh, spike_gen_osc_id = oscillator.get_ids()

# print network
net_gen.print_network()
# make a dynapse1config using the network
new_config = net_gen.make_dynapse1_configuration()
# apply the configuration
model.apply_configuration(new_config)

# get the global neuron IDs of the neurons
monitored_global_nids_exc = [
    ut.get_global_id(chip_id, core_id_exc, nid_exc) for nid_exc in nids_exc
import math

from matplotlib import animation
from matplotlib import pyplot as plt

from oscillator import Oscillator

fig = plt.figure()
ax = plt.axes(xlim=(-0.1, 0.1), ylim=(-0.2, 1))

pendulum_bob, = ax.plot([], [], lw=2, marker='o', color="r", markersize=30)
pendulum_rod, = ax.plot([], [], lw=2, color="black")

time_steps = 400
time_max = 10.0
pendulum = Oscillator()

trajectory = pendulum.get_trajectory(time_max, time_steps)
y = [position for position, velocity in trajectory]
x_coord = [math.sin(position) for position, velocity in trajectory]
y_coord = [(1 - math.cos(position)) for position, velocity in trajectory]


def init():
    pendulum_bob.set_data([], [])
    plt.title("Damped Pendulum Motion")
    plt.xlabel("X", fontsize=13, family='monospace')
    plt.ylabel("Y", fontsize=13, family='monospace')
    return pendulum_bob,

Exemple #22
0
class Game:
	""" The main game class. This deals with two oscillators, of which one is adjustable.
		The diffrence between those frequencies are measured and compared to the wanted interval.
		Margin of errors is given i cents.

	 """
	screen = None
	center = None #screen center
	instructions = None #instructions surface
	interval = None #interval surface
	result = None # surface for result displaying


	path = None #for resources

	#GUI elements
	knob = None
	knob_rect = None
	plate = None

	running = False #state check

	intevals = None #interval array
	guide_osc = None # guide note oscillator
	guide = None # guide_osc frequency
	osc = None # user ajustable oscillator
	guide_ch = None #Audio channel
	osc_ch = None #Audio channel
	pitch = None # osc frequency


	steps = 1 # number of musical notes. Level one starts at an octave
	prev_steps = [] #stores old game settings
	max_freq = 0 # 4 x base oscillator frequency (two octaves)
	min_freq = 0 # bace oscillator frequency

	level = 1 #level

	pause = False # pausing main loop

	practise = False
	tuner = None

	acceptable_off = 10 # how many cents off for a corrects answer?


	def __init__(self, gradient, path):
		""" 
			gradient: A gradient object to act as background
			path: path to images

		"""
		self.screen = gradient
		self.center = self.screen.get_rect().center

		self.path = path

		# interval class
		self.intervals = Interval()

		self.instr_str = 'UP AND DOWN ARROWS COARSE TUNE. USE LEFT AND RIGHT FOR FINE ADJUSTMENT'
		self.conf_str = 'PRESS ENTER TO CONFIRM'

		self.setLevel(self.level)

		self.initGUI()
		#self.initAudio()

	def initGUI(self):
		""" Inits the graphical components """

		#clear background
		self.screen.clear()
		self.screen.draw()

		#knob image
		img = pygame.image.load(self.path + 'knob.png')

		#plates
		self.plate = pygame.image.load(self.path + 'rust.png')

		self.knob = Knob(img)
		self.knob.set_plate(self.plate)
		#self.knob.set_shadow((-6,-4), 150, 25)
		knb_center = self.knob.get_rect().center
		self.knob = (self.knob, (self.center[0]-knb_center[0], self.center[1]-knb_center[1])) # also stores knob.rect at blit time		
		
		self.center = self.screen.get_rect().center

		#"back" 
		back_img = pygame.image.load(self.path + 'back.png')
		back_pos = (30,30)
		#tuple width the image and it's position and a third element containting elements Rect.
		self.back = (back_img, (30,30), self.screen.blit(back_img, back_pos))

		#arrow
		arrow_img = pygame.image.load(self.path + 'arrow.png')
		self.arrow = (arrow_img, (self.center[0] - arrow_img.get_width()/2, 104)) 

		#instructions, texts
		instrs = ['UP', 'DOWN', 'FINE UP', 'FINE DOWN', 'PRESS ENTER TO CONFIRM']
		font = pygame.font.Font(self.path + 'Actor-Regular.ttf', 10)

		#instructions, key images
		key_images = pygame.Surface((184, 69), pygame.SRCALPHA, 32) #collecting those images in a surface, for flexible positioning.
		key_images_cp = key_images.get_rect().center

		img = pygame.image.load(self.path + 'key.png')
		up = pygame.transform.rotozoom(img, 90, 1)
		key_images.blit(up, (key_images_cp[0] - up.get_size()[0]/2, 0)) #up arrow
		key_images.blit(font.render(instrs[0], True, BLACK), (key_images_cp[0] - font.size(instrs[0])[0]/2, 9)) #up text
		key_images.blit(font.render(instrs[3], True, BLACK), (0, key_images_cp[1] - font.size(instrs[3])[1]/2)) #left text
		left = pygame.transform.rotozoom(img, 180, 1)
		key_images.blit(left, (font.size(instrs[3])[0] + 5, key_images_cp[1] - left.get_size()[1]/2)) #left arrow
		right = img
		key_images.blit(right, (key_images.get_width() - font.size(instrs[3])[0] - 5 - right.get_size()[0], key_images_cp[1] - right.get_size()[1]/2)) #right arrow (reflects left)
		key_images.blit(font.render(instrs[2], True, BLACK), (key_images.get_width() - font.size(instrs[3])[0] + 5 - right.get_size()[0], key_images_cp[1] - font.size(instrs[2])[1]/2)) #right text
		key_images.blit(font.render(instrs[1], True, BLACK), (key_images_cp[0] - font.size(instrs[1])[0]/2, 44)) #down text
		down = pygame.transform.rotozoom(img, 270, 1)
		key_images.blit(down, (key_images_cp[0] - down.get_size()[0]/2, 69 - down.get_size()[1])) #up arrow

		#public parent container for instructions
		self.instructions = pygame.Surface((self.screen.get_width(), 115), pygame.SRCALPHA, 32)
		self.instructions.blit(key_images, (self.instructions.get_rect().center[0] - key_images_cp[0], 0))
		self.instructions.blit(font.render(instrs[4], True, BLACK),(self.instructions.get_rect().center[0] - font.size(instrs[4])[0]/2, key_images.get_height() + 20))


	def initAudio(self):
		""" Inits the two oscillators and their channels. """

		#guide tone
		self.guide_osc = Oscillator('sine', self.guide, BUFFER_SIZE)
		self.guide_ch = pygame.mixer.Channel(0)
		self.guide_ch.set_volume(0.9/2.0)

		#adjustable (the knob one), starts at same freq
		self.osc = Oscillator('sine', self.pitch, BUFFER_SIZE)
		self.osc_ch = pygame.mixer.Channel(1)
		self.osc_ch.set_volume(0.9/2.0)

	def setLevel(self, level):
		""" inits different levels """

		lowest_freq = 220 # low limit
		# for use in levels > 4
		rand_guide = self.stepToFreq(random.randint(0, 12), 220) # 220Hz < 440Hz in perfect notes.

		if level == 1:
			self.guide = 440
			self.steps = 0
			self.pitch = self.stepToFreq(1, self.guide)

		elif level == 2:
			self.guide = 440
			self.steps = 12
			self.pitch = self.stepToFreq(11, self.guide)

		elif level == 3:
			self.guide = 440
			self.steps = 7
			self.pitch = self.stepToFreq(6, self.guide)

		elif level == 4:
			self.guide = rand_guide
			self.steps = 5
			init_rand = random.randint(0, 11)
			self.pitch = self.stepToFreq(init_rand, self.guide)

		elif level == 5:
			self.guide = rand_guide
			self.steps = self.randExclude(self.prev_steps + [5], 0,12)
			init_rand = random.randint(0, 11)
			self.pitch = self.stepToFreq(11, self.guide)

		elif level == 6:
			self.guide = rand_guide
			self.steps = self.randExclude(self.prev_steps + [6])
			init_rand = random.randint(0, 24)
			self.pitch = self.stepToFreq(11, self.guide)

		elif level >= 7:
			self.guide = rand_guide
			self.steps = random.randint(0,24) # whole range
			init_rand = random.randint(0, 24)
			self.pitch = self.stepToFreq(11, self.guide)

		else:
			return False

		self.prev_steps.append(self.steps) #store, for unique intervals the first 6 levels
		
		# set min/max frequencies
		self.max_freq = self.guide * 4 # maximum frequency
		self.min_freq = self.guide - 20# minimum frequency 
		
		#set interval text
		self.setIntervalText()

	def setIntervalText(self):
		""" Text to display the wanted interval """
		font = pygame.font.Font(pygame.font.get_default_font(), 18)
		img = font.render(self.intervals.at(self.steps), True, BLACK)
		#interval surface gets made every time function is called, this is done during pauses in main loop. The inefficiency should not be a problem.
		self.interval = pygame.Surface((self.screen.get_width(), font.get_height()), SRCALPHA, 32)
		self.interval.blit(img, (self.center[0] - img.get_width()/2, 0))



	def draw(self):
		""" draw screen """

		self.back = (self.back[0], self.back[1], self.screen.blit(self.back[0], self.back[1]))
		self.screen.blit(self.arrow[0], self.arrow[1])

		self.screen.blit(self.knob[0], self.knob[1])

		if not self.pause:
			self.screen.blit(self.interval, (0, 70))
			self.screen.blit(self.instructions, (0, 285))

		#practise mode?
		if self.practise is True:
			#display tuner
			goal = self.stepToFreq(self.steps, self.guide_osc.frequency())
			cents = self.hertzToCents(goal, self.pitch)
			self.tuner.update(cents)
			self.screen.blit(self.tuner, (self.center[0]-self.tuner.center[0], 20))

		self.screen.draw()

	def updateChannels(self):
		""" update audio queues """
		if self.guide_ch.get_queue() == None:
			self.guide_ch.queue(self.guide_osc.samples())

		if self.osc_ch.get_queue() == None:
			self.osc_ch.queue(self.osc.samples())

	def set_practise(self, on=True):
		""" Turn practise mode on/off """
		self.practise = on
		self.tuner = Tuner(self.path) #initiats at practise on, and stays.

	def message(self):
		""" Checks current frequency (at the adjustable oscillator)
			and sets a message to user
		"""
		font = pygame.font.Font(pygame.font.get_default_font(), 18)

		goal = self.stepToFreq(self.steps, self.guide_osc.frequency())
		cents = self.hertzToCents(goal, self.pitch)

		self.screen.clear()

		if cents < 0: off = 'flat'
		elif cents > 0: off = 'sharp'

		msg = ''

		#ok?
		if cents > -self.acceptable_off and cents < self.acceptable_off:
			self.level += 1;
			self.setLevel(self.level)
			self.guide_osc.set_frequency(self.guide)

			msg = 'Well done! Just ' + str(round(cents,1)) + ' cents ' + off + '.'
		else:
			msg = str(round(cents,1)) + ' cents ' + off + '. Try again'

		if round(cents,1) == 0:
			msg = 'Amazing! Right on the spot!'

		#display message
		img = font.render(msg.upper(), True, BLACK)
		self.screen.blit(img, (self.center[0] - img.get_width()/2, 70))

		#instruction message
		cont = 'PRESS ANY KEY TO CONTINUE.'
		font = pygame.font.Font(self.path + 'Actor-Regular.ttf', 10)
		self.screen.blit(font.render(cont, True, BLACK),(self.center[0] - font.size(cont)[0]/2, self.screen.get_height() - font.size(cont)[1] - 13))

		self.draw()

	def run(self):
		""" main game loop.
			Always starts from level 1, and reinits the oscillators/audio channels 
		"""

		if self.running:
			return False
		self.running = True
		degrees = 0
		self.setLevel(1) # start from level 1 again
		self.initAudio() # init audio here for fresh oscillators

		clock = pygame.time.Clock()

		while self.running:
			
			if not self.pause:
				#start with checking each channels audio queue
				self.updateChannels()
				self.screen.clear()

				mx,my = pygame.mouse.get_pos()
				keystate = pygame.key.get_pressed()

				#fast increase frequency
				if keystate[K_UP]:
					if self.pitch < self.max_freq:
						self.pitch += 1.6#*= 1.01
						#self.pitch *= 1.01
						degrees += 1.3
						self.knob[0].rotate(degrees)

				#fast decrease frequency
				elif keystate[K_DOWN]:
					if self.pitch > self.min_freq:
						self.pitch -= 1.6#/= 1.01
						#self.pitch /= 1.01
						degrees -= 1.3
						self.knob[0].rotate(degrees)

				#slow decrease frequency
				elif keystate[K_LEFT]:
					if self.pitch > self.min_freq:
						self.pitch -=  0.1
						degrees -= 0.2
						self.knob[0].rotate(degrees)

				#slow increase frequency
				elif keystate[K_RIGHT]:
					if self.pitch < self.max_freq:
						self.pitch += 0.1
						degrees += 0.2
						self.knob[0].rotate(degrees)

				self.osc.set_frequency(self.pitch)
				

			for e in pygame.event.get():
				if e.type == QUIT:
					self.running = False

				elif e.type == MOUSEBUTTONDOWN:
					#check back button
					if self.back[2].collidepoint(e.pos):
						self.running = False

				elif e.type == KEYUP:
					#unpause
					if self.pause:
						self.pause = False
						break
					elif e.key == K_RETURN:
						self.pause = True
						self.message()
						
			if not self.pause:
				#redraw screen
				self.draw()
			clock.tick(60)


		self.running = False
		return True


	#helpers
	def hertzToCents(self, a, b):
		try:
			return 1200 * math.log((b/float(a)), 2)
		except Exception as e:
			print e
			return 0

	def posToDeg(self, pos): #not used
		""" Returns a positions degree from windows center """
		degree = math.degrees(math.atan2(self.center[1]-pos[1], self.center[0]-pos[0])) + 180
		if degree == 360.0:
			degree = 0
		return round(degree)

	def randExclude(self, seq, low=0, high=24):
		""" returns a random integer

			seq: numbers to exclude (list)
			low: lowest int
			high: highest int
		"""
		rand = 0
		while rand in seq:
			rand = random.randint(low, high)
		return rand

	def stepToFreq(self, step, frequency=False):
		""" returns a frequncy scale or a new frequency

			step: number of keys
			frequency: from frequency
		"""
		if not frequency:
			return math.pow(2, step/12.0)

		return frequency * math.pow(2, step/12.0)

	def freqToNote(self, freq): #not used
		""" Code for determining note name from frequency value.
			Code is written for equal temperament and A=440.
			Notes are displayed according to sharps. This can be overrided easily by changing the array definition below.

			Written by Firat Civaner (for mathlab)
			http://www.mathworks.com/matlabcentral/fileexchange/35330-frequency-to-note/content/freq2note.m


			return: A tuple with  a string with notename + octave and frequency offset in cents
		"""

		A4 = 440
		notenames = ['C' , 'C#', 'D' , 'D#' , 'E' , 'F' , 'F#', 'G' , 'G#' , 'A' , 'A#' , 'B' ]

		centdif = round( 1200 * math.log(freq/A4)/math.log(2))

		notedif = round(centdif/100)
		if centdif % 100 > 50:
			notedif = notedif + 1

		error = centdif-notedif*100
		notenumber = notedif + 9 + 12*4 #count of half tones starting from C0.

		octavenumber = round((notenumber)/12)
		place = int(round(notenumber % 12 + 1))
		if place < 0 or place > len(notenames)-1:
			print place
			return 'error'
		try:
			return (notenames[place]+str(octavenumber), error)
		except:
			return 'Error. Could not identify note'
Exemple #23
0
class Game:
    """ The main game class. This deals with two oscillators, of which one is adjustable.
		The diffrence between those frequencies are measured and compared to the wanted interval.
		Margin of errors is given i cents.

	 """
    screen = None
    center = None  #screen center
    instructions = None  #instructions surface
    interval = None  #interval surface
    result = None  # surface for result displaying

    path = None  #for resources

    #GUI elements
    knob = None
    knob_rect = None
    plate = None

    running = False  #state check

    intevals = None  #interval array
    guide_osc = None  # guide note oscillator
    guide = None  # guide_osc frequency
    osc = None  # user ajustable oscillator
    guide_ch = None  #Audio channel
    osc_ch = None  #Audio channel
    pitch = None  # osc frequency

    steps = 1  # number of musical notes. Level one starts at an octave
    prev_steps = []  #stores old game settings
    max_freq = 0  # 4 x base oscillator frequency (two octaves)
    min_freq = 0  # bace oscillator frequency

    level = 1  #level

    pause = False  # pausing main loop

    practise = False
    tuner = None

    acceptable_off = 10  # how many cents off for a corrects answer?

    def __init__(self, gradient, path):
        """ 
			gradient: A gradient object to act as background
			path: path to images

		"""
        self.screen = gradient
        self.center = self.screen.get_rect().center

        self.path = path

        # interval class
        self.intervals = Interval()

        self.instr_str = 'UP AND DOWN ARROWS COARSE TUNE. USE LEFT AND RIGHT FOR FINE ADJUSTMENT'
        self.conf_str = 'PRESS ENTER TO CONFIRM'

        self.setLevel(self.level)

        self.initGUI()
        #self.initAudio()

    def initGUI(self):
        """ Inits the graphical components """

        #clear background
        self.screen.clear()
        self.screen.draw()

        #knob image
        img = pygame.image.load(self.path + 'knob.png')

        #plates
        self.plate = pygame.image.load(self.path + 'rust.png')

        self.knob = Knob(img)
        self.knob.set_plate(self.plate)
        #self.knob.set_shadow((-6,-4), 150, 25)
        knb_center = self.knob.get_rect().center
        self.knob = (self.knob, (self.center[0] - knb_center[0],
                                 self.center[1] - knb_center[1])
                     )  # also stores knob.rect at blit time

        self.center = self.screen.get_rect().center

        #"back"
        back_img = pygame.image.load(self.path + 'back.png')
        back_pos = (30, 30)
        #tuple width the image and it's position and a third element containting elements Rect.
        self.back = (back_img, (30, 30), self.screen.blit(back_img, back_pos))

        #arrow
        arrow_img = pygame.image.load(self.path + 'arrow.png')
        self.arrow = (arrow_img, (self.center[0] - arrow_img.get_width() / 2,
                                  104))

        #instructions, texts
        instrs = [
            'UP', 'DOWN', 'FINE UP', 'FINE DOWN', 'PRESS ENTER TO CONFIRM'
        ]
        font = pygame.font.Font(self.path + 'Actor-Regular.ttf', 10)

        #instructions, key images
        key_images = pygame.Surface(
            (184, 69), pygame.SRCALPHA, 32
        )  #collecting those images in a surface, for flexible positioning.
        key_images_cp = key_images.get_rect().center

        img = pygame.image.load(self.path + 'key.png')
        up = pygame.transform.rotozoom(img, 90, 1)
        key_images.blit(
            up, (key_images_cp[0] - up.get_size()[0] / 2, 0))  #up arrow
        key_images.blit(
            font.render(instrs[0], True, BLACK),
            (key_images_cp[0] - font.size(instrs[0])[0] / 2, 9))  #up text
        key_images.blit(
            font.render(instrs[3], True, BLACK),
            (0, key_images_cp[1] - font.size(instrs[3])[1] / 2))  #left text
        left = pygame.transform.rotozoom(img, 180, 1)
        key_images.blit(left, (font.size(instrs[3])[0] + 5, key_images_cp[1] -
                               left.get_size()[1] / 2))  #left arrow
        right = img
        key_images.blit(
            right, (key_images.get_width() - font.size(instrs[3])[0] - 5 -
                    right.get_size()[0], key_images_cp[1] -
                    right.get_size()[1] / 2))  #right arrow (reflects left)
        key_images.blit(font.render(instrs[2], True, BLACK),
                        (key_images.get_width() - font.size(instrs[3])[0] + 5 -
                         right.get_size()[0], key_images_cp[1] -
                         font.size(instrs[2])[1] / 2))  #right text
        key_images.blit(
            font.render(instrs[1], True, BLACK),
            (key_images_cp[0] - font.size(instrs[1])[0] / 2, 44))  #down text
        down = pygame.transform.rotozoom(img, 270, 1)
        key_images.blit(down, (key_images_cp[0] - down.get_size()[0] / 2,
                               69 - down.get_size()[1]))  #up arrow

        #public parent container for instructions
        self.instructions = pygame.Surface((self.screen.get_width(), 115),
                                           pygame.SRCALPHA, 32)
        self.instructions.blit(
            key_images,
            (self.instructions.get_rect().center[0] - key_images_cp[0], 0))
        self.instructions.blit(
            font.render(instrs[4], True, BLACK),
            (self.instructions.get_rect().center[0] -
             font.size(instrs[4])[0] / 2, key_images.get_height() + 20))

    def initAudio(self):
        """ Inits the two oscillators and their channels. """

        #guide tone
        self.guide_osc = Oscillator('sine', self.guide, BUFFER_SIZE)
        self.guide_ch = pygame.mixer.Channel(0)
        self.guide_ch.set_volume(0.9 / 2.0)

        #adjustable (the knob one), starts at same freq
        self.osc = Oscillator('sine', self.pitch, BUFFER_SIZE)
        self.osc_ch = pygame.mixer.Channel(1)
        self.osc_ch.set_volume(0.9 / 2.0)

    def setLevel(self, level):
        """ inits different levels """

        lowest_freq = 220  # low limit
        # for use in levels > 4
        rand_guide = self.stepToFreq(random.randint(0, 12),
                                     220)  # 220Hz < 440Hz in perfect notes.

        if level == 1:
            self.guide = 440
            self.steps = 0
            self.pitch = self.stepToFreq(1, self.guide)

        elif level == 2:
            self.guide = 440
            self.steps = 12
            self.pitch = self.stepToFreq(11, self.guide)

        elif level == 3:
            self.guide = 440
            self.steps = 7
            self.pitch = self.stepToFreq(6, self.guide)

        elif level == 4:
            self.guide = rand_guide
            self.steps = 5
            init_rand = random.randint(0, 11)
            self.pitch = self.stepToFreq(init_rand, self.guide)

        elif level == 5:
            self.guide = rand_guide
            self.steps = self.randExclude(self.prev_steps + [5], 0, 12)
            init_rand = random.randint(0, 11)
            self.pitch = self.stepToFreq(11, self.guide)

        elif level == 6:
            self.guide = rand_guide
            self.steps = self.randExclude(self.prev_steps + [6])
            init_rand = random.randint(0, 24)
            self.pitch = self.stepToFreq(11, self.guide)

        elif level >= 7:
            self.guide = rand_guide
            self.steps = random.randint(0, 24)  # whole range
            init_rand = random.randint(0, 24)
            self.pitch = self.stepToFreq(11, self.guide)

        else:
            return False

        self.prev_steps.append(
            self.steps)  #store, for unique intervals the first 6 levels

        # set min/max frequencies
        self.max_freq = self.guide * 4  # maximum frequency
        self.min_freq = self.guide - 20  # minimum frequency

        #set interval text
        self.setIntervalText()

    def setIntervalText(self):
        """ Text to display the wanted interval """
        font = pygame.font.Font(pygame.font.get_default_font(), 18)
        img = font.render(self.intervals.at(self.steps), True, BLACK)
        #interval surface gets made every time function is called, this is done during pauses in main loop. The inefficiency should not be a problem.
        self.interval = pygame.Surface(
            (self.screen.get_width(), font.get_height()), SRCALPHA, 32)
        self.interval.blit(img, (self.center[0] - img.get_width() / 2, 0))

    def draw(self):
        """ draw screen """

        self.back = (self.back[0], self.back[1],
                     self.screen.blit(self.back[0], self.back[1]))
        self.screen.blit(self.arrow[0], self.arrow[1])

        self.screen.blit(self.knob[0], self.knob[1])

        if not self.pause:
            self.screen.blit(self.interval, (0, 70))
            self.screen.blit(self.instructions, (0, 285))

        #practise mode?
        if self.practise is True:
            #display tuner
            goal = self.stepToFreq(self.steps, self.guide_osc.frequency())
            cents = self.hertzToCents(goal, self.pitch)
            self.tuner.update(cents)
            self.screen.blit(self.tuner,
                             (self.center[0] - self.tuner.center[0], 20))

        self.screen.draw()

    def updateChannels(self):
        """ update audio queues """
        if self.guide_ch.get_queue() == None:
            self.guide_ch.queue(self.guide_osc.samples())

        if self.osc_ch.get_queue() == None:
            self.osc_ch.queue(self.osc.samples())

    def set_practise(self, on=True):
        """ Turn practise mode on/off """
        self.practise = on
        self.tuner = Tuner(self.path)  #initiats at practise on, and stays.

    def message(self):
        """ Checks current frequency (at the adjustable oscillator)
			and sets a message to user
		"""
        font = pygame.font.Font(pygame.font.get_default_font(), 18)

        goal = self.stepToFreq(self.steps, self.guide_osc.frequency())
        cents = self.hertzToCents(goal, self.pitch)

        self.screen.clear()

        if cents < 0: off = 'flat'
        elif cents > 0: off = 'sharp'

        msg = ''

        #ok?
        if cents > -self.acceptable_off and cents < self.acceptable_off:
            self.level += 1
            self.setLevel(self.level)
            self.guide_osc.set_frequency(self.guide)

            msg = 'Well done! Just ' + str(round(cents,
                                                 1)) + ' cents ' + off + '.'
        else:
            msg = str(round(cents, 1)) + ' cents ' + off + '. Try again'

        if round(cents, 1) == 0:
            msg = 'Amazing! Right on the spot!'

        #display message
        img = font.render(msg.upper(), True, BLACK)
        self.screen.blit(img, (self.center[0] - img.get_width() / 2, 70))

        #instruction message
        cont = 'PRESS ANY KEY TO CONTINUE.'
        font = pygame.font.Font(self.path + 'Actor-Regular.ttf', 10)
        self.screen.blit(font.render(cont, True, BLACK),
                         (self.center[0] - font.size(cont)[0] / 2,
                          self.screen.get_height() - font.size(cont)[1] - 13))

        self.draw()

    def run(self):
        """ main game loop.
			Always starts from level 1, and reinits the oscillators/audio channels 
		"""

        if self.running:
            return False
        self.running = True
        degrees = 0
        self.setLevel(1)  # start from level 1 again
        self.initAudio()  # init audio here for fresh oscillators

        clock = pygame.time.Clock()

        while self.running:

            if not self.pause:
                #start with checking each channels audio queue
                self.updateChannels()
                self.screen.clear()

                mx, my = pygame.mouse.get_pos()
                keystate = pygame.key.get_pressed()

                #fast increase frequency
                if keystate[K_UP]:
                    if self.pitch < self.max_freq:
                        self.pitch += 1.6  #*= 1.01
                        #self.pitch *= 1.01
                        degrees += 1.3
                        self.knob[0].rotate(degrees)

                #fast decrease frequency
                elif keystate[K_DOWN]:
                    if self.pitch > self.min_freq:
                        self.pitch -= 1.6  #/= 1.01
                        #self.pitch /= 1.01
                        degrees -= 1.3
                        self.knob[0].rotate(degrees)

                #slow decrease frequency
                elif keystate[K_LEFT]:
                    if self.pitch > self.min_freq:
                        self.pitch -= 0.1
                        degrees -= 0.2
                        self.knob[0].rotate(degrees)

                #slow increase frequency
                elif keystate[K_RIGHT]:
                    if self.pitch < self.max_freq:
                        self.pitch += 0.1
                        degrees += 0.2
                        self.knob[0].rotate(degrees)

                self.osc.set_frequency(self.pitch)

            for e in pygame.event.get():
                if e.type == QUIT:
                    self.running = False

                elif e.type == MOUSEBUTTONDOWN:
                    #check back button
                    if self.back[2].collidepoint(e.pos):
                        self.running = False

                elif e.type == KEYUP:
                    #unpause
                    if self.pause:
                        self.pause = False
                        break
                    elif e.key == K_RETURN:
                        self.pause = True
                        self.message()

            if not self.pause:
                #redraw screen
                self.draw()
            clock.tick(60)

        self.running = False
        return True

    #helpers
    def hertzToCents(self, a, b):
        try:
            return 1200 * math.log((b / float(a)), 2)
        except Exception as e:
            print e
            return 0

    def posToDeg(self, pos):  #not used
        """ Returns a positions degree from windows center """
        degree = math.degrees(
            math.atan2(self.center[1] - pos[1], self.center[0] - pos[0])) + 180
        if degree == 360.0:
            degree = 0
        return round(degree)

    def randExclude(self, seq, low=0, high=24):
        """ returns a random integer

			seq: numbers to exclude (list)
			low: lowest int
			high: highest int
		"""
        rand = 0
        while rand in seq:
            rand = random.randint(low, high)
        return rand

    def stepToFreq(self, step, frequency=False):
        """ returns a frequncy scale or a new frequency

			step: number of keys
			frequency: from frequency
		"""
        if not frequency:
            return math.pow(2, step / 12.0)

        return frequency * math.pow(2, step / 12.0)

    def freqToNote(self, freq):  #not used
        """ Code for determining note name from frequency value.
			Code is written for equal temperament and A=440.
			Notes are displayed according to sharps. This can be overrided easily by changing the array definition below.

			Written by Firat Civaner (for mathlab)
			http://www.mathworks.com/matlabcentral/fileexchange/35330-frequency-to-note/content/freq2note.m


			return: A tuple with  a string with notename + octave and frequency offset in cents
		"""

        A4 = 440
        notenames = [
            'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B'
        ]

        centdif = round(1200 * math.log(freq / A4) / math.log(2))

        notedif = round(centdif / 100)
        if centdif % 100 > 50:
            notedif = notedif + 1

        error = centdif - notedif * 100
        notenumber = notedif + 9 + 12 * 4  #count of half tones starting from C0.

        octavenumber = round((notenumber) / 12)
        place = int(round(notenumber % 12 + 1))
        if place < 0 or place > len(notenames) - 1:
            print place
            return 'error'
        try:
            return (notenames[place] + str(octavenumber), error)
        except:
            return 'Error. Could not identify note'
Exemple #24
0
 def __init__(self):
     self.acc = PVector()
     self.vel = PVector(random(-1, 1), random(-1, 1))
     self.loc = PVector(random(width), random(height))
     self.mass = random(8, 16)
     self.osc = Oscillator(self.mass * 2)
Exemple #25
0
 def init(self):
     self.osc = Oscillator(freq=1)
     self.osc2 = Oscillator(freq=5, zero=True, phase=20)
     self.amplitude = 0
     self.add_parameter(name="amplitude", min=10, max=60)
Exemple #26
0
class OscbarApp:
    """ Oscbar object """
    def __init__(self):
        # config
        app_title = "Oscbar"
        interval = 2  # seconds per calibration step

        # initial oscillator settings
        self.wave_type = "sine_wave"
        self.amplitude = 0.5
        self.frequency = 440
        self.store_wave = None
        self.store_freq = None

        # object instances
        self.app = rumps.App(app_title, icon=APP_ICON)
        self.oct_timer = rumps.Timer(
            lambda sender, factor=2, max_freq=880, title='Octave Walk': self.
            advance_frequency(sender, factor, max_freq, title),
            interval)
        self.oct_thirds_timer = rumps.Timer(
            lambda sender, factor=(2**(1 / 3)), max_freq=880, title
            ='Octave Walk  â…“': self.advance_frequency(
                sender, factor, max_freq, title),
            interval)
        self.osc = Oscillator(self.wave_type, self.amplitude, self.frequency)

        # set up menu
        self.build_menu()
        self.osc_ready_menu()

    def build_menu(self):
        """ define menu, buttons, sliders """
        # menu items
        self.start_button = rumps.MenuItem(  # Start Osc
            title="Start Oscillator")
        self.stop_button = rumps.MenuItem(  # Stop Osc
            title="Stop Oscillator")
        self.amp_title = rumps.MenuItem(  # Volume title
            title=amp_title_format(self.amplitude),
            callback=None)
        self.amp_slider = rumps.SliderMenuItem(  # Volume slider
            value=self.amplitude,
            min_value=0.0,
            max_value=1.0,
            callback=self.adj_amp,
            dimensions=(200, 20))
        self.sine_wave_button = rumps.MenuItem(  # Sine Wave
            title="Sine Wave", callback=self.set_sine_wave)
        self.square_wave_button = rumps.MenuItem(  # Square Wave
            title="Square Wave", callback=self.set_square_wave)
        self.white_noise_button = rumps.MenuItem(  # White Noise
            title="White Noise", callback=self.set_white_noise)
        self.pink_noise_button = rumps.MenuItem(  # Pink Noise
            title="Pink Noise", callback=self.set_pink_noise)
        self.freq_title = rumps.MenuItem(  # Frequency: title
            title=freq_title_format(self.frequency),
            callback=None)
        self.freq_slider = rumps.SliderMenuItem(  # Frequency slider
            value=freq_to_slider(self.frequency),
            min_value=freq_to_slider(20),  # 20Hz - 20kHz
            max_value=freq_to_slider(20000),
            callback=self.adj_freq,
            dimensions=(200, 20))
        self.octave_button = rumps.MenuItem(  # Octave Walk
            title="Octave Walk",
            callback=lambda sender, timer=self.oct_timer: self.
            begin_octave_walk(sender, timer))
        self.octave_thirds_button = rumps.MenuItem(  # Octave Walk 1/3
            title="Octave Walk  â…“",
            callback=lambda sender, timer=self.oct_thirds_timer: self.
            begin_octave_walk(sender, timer))

        #populate menu
        self.app.menu = [
            self.start_button, self.stop_button, None, self.amp_title,
            self.amp_slider, None, self.sine_wave_button,
            self.square_wave_button, self.white_noise_button,
            self.pink_noise_button, None, self.freq_title, self.freq_slider,
            None, self.octave_button, self.octave_thirds_button, None
        ]

# ------------------------ Menu Bar App: Menu UI Methods -----------------------

    def remove_checkmark(self):
        """ clear wave type checkmarks from menu state """
        for item in self.app.menu:
            if hasattr(self.app.menu[item], 'state'):
                if self.app.menu[item].state == 1:
                    self.app.menu[item].state = 0

    def osc_ready_menu(self):
        """ menu while not playing osc """
        #self.app.title = "🎛"
        self.start_button.set_callback(self.start_osc)
        self.stop_button.set_callback(None)

        self.remove_checkmark()
        for item in self.app.menu:
            try:
                if self.osc.wave_type in self.app.menu[item].callback.__name__:
                    self.app.menu[item].state = 1
            except AttributeError:
                pass

    def osc_busy_menu(self):
        """ menu while playing osc """
        #self.app.title = "🔊"
        self.start_button.set_callback(None)
        self.stop_button.set_callback(self.stop_osc)

    def wave_change_menu(self, sender):
        """ menu change when selecting new wave type """
        self.remove_checkmark()
        sender.state = 1

# --------------------------- Menu Bar App: Callbacks --------------------------

    def start_osc(self, sender):
        """ Start Oscillator callback """
        self.osc_busy_menu()
        self.osc.play()

    def stop_osc(self, sender):
        """ Stop Oscillator callback """
        self.osc_ready_menu()
        self.osc.stop()

    def set_sine_wave(self, sender):
        """ Sine Wave callback """
        self.wave_change_menu(sender)
        self.osc.wave_type = 'sine_wave'

    def set_square_wave(self, sender):
        """ Square Wave callback """
        self.wave_change_menu(sender)
        self.osc.wave_type = 'square_wave'

    def set_white_noise(self, sender):
        """ White Noise callback """
        self.wave_change_menu(sender)
        self.osc.wave_type = 'white_noise'

    def set_pink_noise(self, sender):
        """ Pink Noise callback """
        self.wave_change_menu(sender)
        self.osc.wave_type = 'pink_noise'

    def prep_calibration(self, wave_type, frequency):
        """ retain oscillator settings during calibration """
        # stop osc if playing
        if not self.osc.stream is None:
            self.stop_osc(sender=None)
        # retain settings
        self.store_wave = self.osc.wave_type
        self.store_freq = self.osc.frequency
        # initial calibration settings
        self.osc.wave_type = wave_type
        self.osc.frequency = frequency

    def advance_frequency(self, sender, factor, max_freq, title):
        """
        Increase frequency by factor until max frequency is reached,
        then stop the timer
        """
        if self.osc.stream:
            self.stop_osc(sender=None)
        self.osc.frequency *= factor
        if self.osc.frequency > max_freq:
            self.oct_timer.stop()
            self.oct_thirds_timer.stop()
            # restore settings
            self.osc.wave_type = self.store_wave
            self.osc.frequency = self.store_freq
            self.osc_ready_menu()
        else:
            rumps.notification(title=title,
                               subtitle=None,
                               message=freq_title_format(self.osc.frequency),
                               sound=False,
                               icon=APP_ICON)

            self.osc.play()

    def begin_octave_walk(self, sender, timer):
        """
        Octave Walk callback
        Walk up by octave: A0 (27.5 Hz) - A6 (1760 Hz)
        """
        self.prep_calibration('sine_wave', 27.5)
        timer.start()

    def adj_freq(self, sender):
        """ Frequency slider callback """
        frequency = slider_to_freq(self.freq_slider.value)
        self.freq_title.title = freq_title_format(frequency)  # update title
        self.osc.frequency = frequency  # update oscillator
        print(
            f'SLIDER ===> {self.freq_slider.value}, FREQ ===> {self.osc.frequency}'
        )

    def adj_amp(self, sender):
        """ Amplitude slider callback """
        self.amp_title.title = amp_title_format(
            self.amp_slider.value)  # update title
        self.osc.amplitude = self.amp_slider.value  # update oscillator
        print(
            f'SLIDER ===> {self.amp_slider.value}, AMP ===> {self.osc.amplitude}'
        )

    def run(self):
        """ run it """
        self.app.run()
Exemple #27
0
import matplotlib.lines as mlines
import numpy as np
from matplotlib import animation
from matplotlib import pyplot as plt

from oscillator import Oscillator

fig = plt.figure()
ax = plt.axes(xlim=(0, 10), ylim=(-0.22, 0.22))

theta_line, = ax.plot([], [], lw=2, color="green")
theta_dash_line, = ax.plot([], [], lw=2, color="blue")

time_steps = 400
time_max = 10.0
osc = Oscillator()

x = np.linspace(0, time_max, time_steps + 1)
trajectory = osc.get_trajectory(time_max, time_steps)

y = [position for position, velocity in trajectory]
y_dash = [velocity for position, velocity in trajectory]


def init():
    theta_line.set_data([], [])
    plt.xlabel("Time", fontsize=13, family='monospace')
    plt.ylabel("Angular Displacement, Angular Velocity",
               fontsize=13,
               family='monospace')
    plt.title("Angular Displacement and Angular Velocity v/s Time",
Exemple #28
0
 def test_state_unchanged_after_zero_time(self):
     oscillator = Oscillator()
     self.assertListEqual(oscillator.state,
                          list(oscillator.get_trajectory(0, 1)[0]))