def _createTablesForSave(self): nbRecs = self._num_rec+1 self.dlg = wx.ProgressDialog("Saving...", "Creating files", maximum = nbRecs, parent=self._parent, style = wx.PD_APP_MODAL|wx.PD_ELAPSED_TIME) self.count = 0 #le timer garde la fenetre de progres a jour selon le compte timer = Metro(.75).play() trigfunc = TrigFunc(timer, self._updateProgress) if self._raw_data: for i in range(nbRecs): #creation de nouvelles tables avec la duree reelle des enreg. self._save_analyzed.append(NewTable(length=self._actual_rec_time[i], chnls=3)) self._save_raw.append(NewTable(length=self._actual_rec_time[i], chnls=3)) #population des nouvelles tables echantillon par echantillon for samp in range(self._save_analyzed[i].getSize(False)): self._save_analyzed[i][0].put(self.analyzed_list[i][0].get(samp), samp) self._save_analyzed[i][1].put(self.analyzed_list[i][1].get(samp), samp) self._save_analyzed[i][2].put(self.analyzed_list[i][2].get(samp), samp) self._save_raw[i][0].put(self.raw_list[i][0].get(samp), samp) self._save_raw[i][1].put(self.raw_list[i][1].get(samp), samp) self._save_raw[i][2].put(self.raw_list[i][2].get(samp), samp) self.count += 1 else: for i in range(nbRecs): self._save_analyzed.append(NewTable(length=self._actual_rec_time[i], chnls=3)) for samp in range(self._save_analyzed[i].getSize(False)): self._save_analyzed[i][0].put(self.analyzed_list[i][0].get(samp), samp) self._save_analyzed[i][1].put(self.analyzed_list[i][1].get(samp), samp) self._save_analyzed[i][2].put(self.analyzed_list[i][2].get(samp), samp) self.count += 1 timer.stop() trigfunc.stop() del timer del trigfunc del self.count
def __init__(self, notes=[], tempo=96): self.notes = [note.frequency for note in notes] self.times = [note.time(tempo) for note in notes] self.amps = [note.amp for note in notes] self.tempo = tempo self._metro = Metro() self.amp = Iter(self._metro, self.amps, init=self.amps[0]) self.time = Iter(self._metro, self.times, init=self.times[0]) self._metro.setTime(self.time) self.signal = Iter(self._metro, self.notes) #triggers are only sent when amp is >0 self.trigger = Ceil(self.amp * self._metro)
def __init__(self, notes=[], tempo=96): self.notes = [note.frequency for note in notes] self.times = [note.time(tempo) for note in notes] self.amps = [note.amp for note in notes] self.tempo = tempo self._metro = Metro() self.amp = Iter(self._metro, self.amps, init=self.amps[0]) self.time = Iter(self._metro, self.times, init=self.times[0]) self._metro.setTime(self.time) self.signal = Iter(self._metro, self.notes) #triggers are only sent when amp is >0 self.trigger = Ceil(self.amp*self._metro)
def __init__(self, port, address, smoothing=0): self.port = port self.address = address self.smoothing = smoothing self._buffer_size = 128 self._buffer_time = float(BUFFER_SIZE)/SAMP_RATE self._buffer_count = -1 self._buffer = NewTable(self._buffer_time, chnls=3) self._data = [] self._type = None self._createOSC(port, address) self._metro = Metro(self._buffer_time) self._table_rec = TrigTableRec([self._oscx,self._oscy,self._oscz], self._metro, self._buffer).stop() self._trig_dump = TrigFunc(self._table_rec['trig'], self._dump).stop()
def __init__(self, port, address, inmin=-1, inmax=1, smoothing=True): self.port = port self.address = address self._inmin = inmin self._inmax = inmax self._data = [] self._buffer = [] self._buffer_size = 64 self._buffer_count = -1 self._precision = float(BUFFER_SIZE)/SAMP_RATE self._trig_buffer = Trig().stop() self._type = None self._createOSC(port, address) self._metro = Metro(self._precision).play() if smoothing: self._trig_fill = TrigFunc(self._metro, self._fill_buffer_w_smooth) else: self._trig_fill = TrigFunc(self._metro, self._fill_buffer_wo_smooth)
def __init__(self): """Constructor for music_player""" """Make sure to call add_gui once initialized""" self.instruments = [] #instrument/track volume is here self.tempo = 120.0 #BPM (for now) self.global_volume = 0.75 #between 0 and 1 self.page_index = 0 #1st page self.play_all = False self.playhead_index = 0 self.beat_index = 0 self.server = Server(duplex=0) """Set proper output device for latency-free playback on Windows""" """Source: https://groups.google.com/d/msg/pyo-discuss/9fvFiGbch3c/tzJTfbpLUY8J""" if platform.system() == "Windows": out_devices = pa_get_output_devices() od_index = 0 for od in out_devices[0]: if "Primary Sound Driver" in od: pai = int(out_devices[1][od_index]) self.server.setOutputDevice(pai) break od_index += 1 self.server.boot() self.server.start() metronome_time = self.SECONDS_PER_MIN / self.tempo self.metronome = Metro(time=metronome_time) self.metronome_callback = TrigFunc(self.metronome, function=self.step) # Create instruments wavetable_a = WaveInstrument(self, WaveInstrument.BASS) wavetable_b = WaveInstrument(self, WaveInstrument.LEAD) drums = DrumInstrument(self) self.instruments.append(wavetable_a) self.instruments.append(wavetable_b) self.instruments.append(drums) self.mixer_setup()
class Sequence: """Sequence of midi notes and rythms using the least amount of pure python as possible """ def __init__(self, notes=[], tempo=96): self.notes = [note.frequency for note in notes] self.times = [note.time(tempo) for note in notes] self.amps = [note.amp for note in notes] self.tempo = tempo self._metro = Metro() self.amp = Iter(self._metro, self.amps, init=self.amps[0]) self.time = Iter(self._metro, self.times, init=self.times[0]) self._metro.setTime(self.time) self.signal = Iter(self._metro, self.notes) #triggers are only sent when amp is >0 self.trigger = Ceil(self.amp*self._metro) def append(self, note): self.notes.append(note.frequency) self.rythms.append(note.time(tempo)) self.amps.append(note.amp) self.amp.setChoice(self.amps) self.time.setChoice(self.times) self.signal.setChoice(self.notes) def set_notes(self, notes): self.notes = [note.frequency for note in notes] self.rythms = [note.time(self.tempo) for note in notes] self.amps = [note.amp for note in notes] self.amp.setChoice(self.amps) self.time.setChoice(self.times) self.signal.setChoice(self.notes) def play(self): self._metro.play() return self def stop(self): self._metro.stop()
class Sequence: """Sequence of midi notes and rythms using the least amount of pure python as possible """ def __init__(self, notes=[], tempo=96): self.notes = [note.frequency for note in notes] self.times = [note.time(tempo) for note in notes] self.amps = [note.amp for note in notes] self.tempo = tempo self._metro = Metro() self.amp = Iter(self._metro, self.amps, init=self.amps[0]) self.time = Iter(self._metro, self.times, init=self.times[0]) self._metro.setTime(self.time) self.signal = Iter(self._metro, self.notes) #triggers are only sent when amp is >0 self.trigger = Ceil(self.amp * self._metro) def append(self, note): self.notes.append(note.frequency) self.rythms.append(note.time(tempo)) self.amps.append(note.amp) self.amp.setChoice(self.amps) self.time.setChoice(self.times) self.signal.setChoice(self.notes) def set_notes(self, notes): self.notes = [note.frequency for note in notes] self.rythms = [note.time(self.tempo) for note in notes] self.amps = [note.amp for note in notes] self.amp.setChoice(self.amps) self.time.setChoice(self.times) self.signal.setChoice(self.notes) def play(self): self._metro.play() return self def stop(self): self._metro.stop()
self._reson1Env.play(dur, delay) self._reson2Env.play(dur, delay) self._amp1Env.play(dur, delay) self._amp2Env.play(dur, delay) return PyoObject.out(self, chnl, inc, dur, delay) # Run this script to test the Aqueous class. if __name__ == "__main__": from pyo import Delay, Metro, Server, Snap, TrigXnoiseMidi, WGVerb, Pattern s = Server(duplex=0).boot() s.setAmp(1.0) s.start() t = 3.776 metroAqueous = Metro(time=t * 2).play() noteAqeous = TrigXnoiseMidi(metroAqueous, dist=0, mrange=(42, 83)) snapAqueous = Snap(noteAqeous, choice=[0, 2, 4, 5, 7, 9, 11], scale=1) a = Aqueous(snapAqueous, dur=t * 0.75, mul=0.9) def noteOn(): a.play() playAqueous = Pattern(function=noteOn, time=t * 2).play() delay = Delay(a, delay=t * 0.75, feedback=0.6, maxdelay=t * 0.75, mul=0.445) wetdry = delay + a d = WGVerb(wetdry,
class AccDataAnalyser: def __init__(self, port, address, smoothing=0): self.port = port self.address = address self.smoothing = smoothing self._buffer_size = 128 self._buffer_time = float(BUFFER_SIZE)/SAMP_RATE self._buffer_count = -1 self._buffer = NewTable(self._buffer_time, chnls=3) self._data = [] self._type = None self._createOSC(port, address) self._metro = Metro(self._buffer_time) self._table_rec = TrigTableRec([self._oscx,self._oscy,self._oscz], self._metro, self._buffer).stop() self._trig_dump = TrigFunc(self._table_rec['trig'], self._dump).stop() def _createOSC(self, port, address): if isinstance(address, list) and len(address) == 3: self._type = "simple" self._osc = OscReceive(port=port, address=address) elif isinstance(address, str): self._type = "list" self._osc = OscListReceive(port=port, address=address, num=3) else: print ">>>class AccDataAnalyser :\n<Error type: 'address' attribute must contain either 1 or 3 addresses>" self._createScaleObjs() def _createScaleObjs(self): if self._type == "simple": self._oscx = Scale(self._osc[self.address[0]], inmin=-1, inmax=1, outmin=-90, outmax=90) self._oscy = Scale(self._osc[self.address[1]], inmin=-1, inmax=1, outmin=-90, outmax=90) self._oscz = Scale(self._osc[self.address[2]], inmin=-1, inmax=1, outmin=-90, outmax=90) elif self._type == "list": self._oscx = Scale(self._osc[self.address][0], inmin=-1, inmax=1, outmin=-90, outmax=90) self._oscy = Scale(self._osc[self.address][1], inmin=-1, inmax=1, outmin=-90, outmax=90) self._oscz = Scale(self._osc[self.address][2], inmin=-1, inmax=1, outmin=-90, outmax=90) def _convert_data(self, buffer): x_data = [] y_data = [] z_data = [] for i in range(self._buffer_size): x, y, z = buffer[0].get(i), buffer[1].get(i), buffer[2].get(i) degx = degrees(atan2(-y, -z) + pi); degy = degrees(atan2(-x, -z) + pi); degz = degrees(atan2(-y, -x) + pi); x_data.append(degx) y_data.append(degy) z_data.append(degz) return [x_data, y_data, z_data] def _dump(self): self._pending = self._buffer.copy() self._data.append(self._convert_data(self._pending)) self._buffer_count += 1 #Que fais-je maintenant de mes précieux échantillons? def _print_data(self): self.cpt += 1 if self.cpt <= self.num: print "Buffer %d :" % self._buffer_count print self._data[self._buffer_count] else: print "---------------------------------------------------------" self.trig_print.stop() del self.cpt del self.num del self.trig_print if hasattr(self, 'percent'): del self.percent ######################## ## Methodes publiques ## ######################## def play(self): self._metro.play() self._table_rec.play() self._trig_dump.play() return self def stop(self): self._metro.stop() self._table_rec.stop() self._trig_dump.stop() def print_data(self, num, step=1): self.cpt = 0 self.num = num print "\n>>>class AccDataAnalyser" if step > 1: print "[[X list], [Y list], [Z list]] Data for %d buffers in steps of %d." % (num, step) self.percent = Percent(self._table_rec['trig'], percent=100./step) self.trig_print = TrigFunc(self.percent, self._print_data) else: print "[[X list], [Y list], [Z list]] Data for %d buffer(s)." % num self.trig_print = TrigFunc(self._table_rec['trig'], self._print_data)
ESC = 27 PLUS = 43 MINUS = 45 notes1 = ['a', 'b', 'c'] notes2 = ['d', 'g', 'h'] notes3 = ['e', 'f', 'i', 'j'] screen = pygame.display.set_mode((800, 600)) run = True server = Server().boot() server.start() met = Metro(.125, 12).play() players.append(Player(met, notes1)) players.append(Player(met, notes2)) players.append(Player(met, notes3)) while run: for event in pygame.event.get(): if event.type == pygame.KEYUP: for player in players: player.note_off(chr(event.key)) if event.key == ESC: run = False break if event.key == PLUS:
# <http://code.google.com/p/pyo>. # Latest version always available at <http://gist.github.com/tildebyte>. # Copyright (C) 2014 Ben Alkov <*****@*****.**> # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version <http://www.gnu.org/licenses/>. from pyo import Delay, Snap, Metro, TrigXnoiseMidi, WGVerb from ground_state.pyo.instruments.whale import Whale from ground_state.pyo.utils.tempo import Tempo from ground_state.pyo.utils.dbToAmp import dbToAmp from ground_state.pyo.utils.serverSetup import serverSetup t = Tempo(63.5) # OSX s = serverSetup(2, 192, 'coreaudio') metro = Metro(time=t.whole * 4).play() note = TrigXnoiseMidi(metro, dist=0, mrange=(30, 41)) snap = Snap(note, choice=[0, 2, 4, 5, 7, 9, 11], scale=1) w = Whale(snap, metro, dur=t.whole, mul=0.9) delay = Delay(w, delay=t.whole, feedback=0.64, maxdelay=t.whole, mul=dbToAmp(-6)) wetdry = delay + w d = WGVerb(wetdry, feedback=[0.73, 0.76], cutoff=5000, bal=dbToAmp(-12.04), mul=dbToAmp(-10.5)).out() s.gui(locals())
class MusicPlayer: """Playback engine for sequencer samples and sounds""" NUM_PAGES = 8 NUM_ROWS = 8 NUM_COLS = 8 NUM_TRACKS = 3 NUM_BEATS = NUM_PAGES * NUM_COLS SECONDS_PER_MIN = 60.0 # Parameters for GUI to build sliders MIN_TEMPO = 40.0 MAX_TEMPO = 240.0 MIN_VOLUME = 0.0 MAX_VOLUME = 1.0 MIN_REVERB = 0.0 MAX_REVERB = 1.0 # Instrument descriptive constants WAVETABLE_A = 0 WAVETABLE_B = 1 DRUM_KIT = 2 def __init__(self): """Constructor for music_player""" """Make sure to call add_gui once initialized""" self.instruments = [] #instrument/track volume is here self.tempo = 120.0 #BPM (for now) self.global_volume = 0.75 #between 0 and 1 self.page_index = 0 #1st page self.play_all = False self.playhead_index = 0 self.beat_index = 0 self.server = Server(duplex=0) """Set proper output device for latency-free playback on Windows""" """Source: https://groups.google.com/d/msg/pyo-discuss/9fvFiGbch3c/tzJTfbpLUY8J""" if platform.system() == "Windows": out_devices = pa_get_output_devices() od_index = 0 for od in out_devices[0]: if "Primary Sound Driver" in od: pai = int(out_devices[1][od_index]) self.server.setOutputDevice(pai) break od_index += 1 self.server.boot() self.server.start() metronome_time = self.SECONDS_PER_MIN / self.tempo self.metronome = Metro(time=metronome_time) self.metronome_callback = TrigFunc(self.metronome, function=self.step) # Create instruments wavetable_a = WaveInstrument(self, WaveInstrument.BASS) wavetable_b = WaveInstrument(self, WaveInstrument.LEAD) drums = DrumInstrument(self) self.instruments.append(wavetable_a) self.instruments.append(wavetable_b) self.instruments.append(drums) self.mixer_setup() def mixer_setup(self): # Combine all tracks in mixer self.track_mixer = Mixer(outs=1) for inst_index in range(0, len(self.instruments)): instrument = self.instruments[inst_index] generator = instrument.get_generator() self.track_mixer.addInput(inst_index, generator) self.track_mixer.setAmp(inst_index, 0, instrument.get_volume()) # Prepare master output self.master_out = Mixer(outs=1, chnls=2) self.master_out.addInput(0, self.track_mixer[0]) self.master_out.setAmp(0, 0, self.global_volume) self.master_out.out() def add_gui(self, gui): """ Sets the GUI that this music player must instruct to update playhead. Must be called right after constructor before operation. Arguments: gui: GUI object monitoring this player """ self.gui = gui def terminate(self): """Terminate MusicPlayer server in preparation for shutdown""" self.server.stop() self.server.shutdown() def step(self): """ Step the music player through next beat """ # Set GUI to reflect current beat self.gui.update_playhead() # Play step for instruments for instrument in self.instruments: instrument.play_step() # For next iteration, increment playhead and beat indices self.playhead_index = (self.playhead_index + 1) % self.NUM_COLS if (self.play_all == True): self.beat_index = (self.beat_index + 1) % self.NUM_BEATS elif (self.play_all == False): self.beat_index = (self.page_index * self.NUM_COLS) +\ self.playhead_index def add_network_handler(self, network_handler): self.network_handler = network_handler """playback methods""" def play(self): self.metronome.play() def pause(self): for instrument in self.instruments: instrument.pause() self.metronome.stop() def set_session(self, session): """used to load a session into the music player""" # Reload pertinent MusicPlayer variables self.set_tempo(session.tempo) # Reconstruct each instrument from session data self.instruments = [] instrument_data = session.instrument_data for data in instrument_data: volume = data.volume reverb_mix = data.reverb_mix notes = data.notes if isinstance(data, WaveInstrumentData): wavetype = data.wavetype wave_instrument = WaveInstrument(self, wavetype, volume, reverb_mix, notes) self.instruments.append(wave_instrument) elif isinstance(data, DrumInstrumentData): drum_instrument = DrumInstrument(self, volume, reverb_mix, notes) self.instruments.append(drum_instrument) # Reload mixer to reflect new instruments self.mixer_setup() """ Modifiers """ def set_note(self, note): instrument = self.instruments[note.track_id] instrument.set_note(note) def set_global_volume(self, volume): self.global_volume = volume self.master_out.setAmp(0, 0, volume) def set_volume(self, track_id, volume): self.instruments[track_id].set_volume(volume) self.track_mixer.setAmp(track_id, 0, volume) def set_reverb(self, track_id, reverb): self.instruments[track_id].set_reverb(reverb) def set_tempo(self, new_tempo): new_time = self.SECONDS_PER_MIN / new_tempo self.metronome.setTime(new_time) self.tempo = new_tempo """getter methods""" def get_session(self): """Get descriptive MusicPlayer session to restore later""" session = Session(self, self.instruments) return session """getter methods for GUI""" def get_names(self, track_id): return self.instruments[track_id].get_names() def get_reverb(self, track_id): return self.instruments[track_id].get_reverb() def get_volume(self, track_id): return self.instruments[track_id].get_volume() def get_global_volume(self): return self.global_volume def get_tempo(self): return self.tempo def get_note(self, track_id, page_index, position, pitch): pass def get_current_page(self, track_id): instrument = self.instruments[track_id] notes = instrument.get_page(self.page_index) return notes
# (at your option) any later version <http://www.gnu.org/licenses/>. from pyo import Delay, Metro, Pattern, Snap, STRev, TrigXnoiseMidi # iPython: %cd \path\to\pyo\files from ground_state.pyo.instruments.aqueous import Aqueous from ground_state.pyo.instruments.whale import Whale from ground_state.pyo.utils.tempo import Tempo from ground_state.pyo.utils.dbToAmp import dbToAmp from ground_state.pyo.utils.serverSetup import serverSetup t = Tempo(63.5) # q=944ms, w=3.776s # Windows # server = serverSetup(10, 700) # OSX server = serverSetup(2, 192, 'coreaudio') metroWhale = Metro(time=t.whole * 4).play() metroAqueous = Metro(time=t.whole).play() noteWhale = TrigXnoiseMidi(metroWhale, dist=0, mrange=(30, 41)) noteAqeous = TrigXnoiseMidi(metroAqueous, dist=0, mrange=(42, 83)) snapWhale = Snap(noteWhale, choice=[0, 2, 4, 5, 7, 9, 11], scale=1) snapAqueous = Snap(noteAqeous, choice=[0, 2, 4, 5, 7, 9, 11], scale=1) whale = Whale(snapWhale, metroWhale, dur=t.whole, mul=dbToAmp(-9.0)) aqueous = Aqueous(snapAqueous, dur=t.whole * 2, mul=dbToAmp(-12.0)) def noteOn(): aqueous.play() playAqueous = Pattern(function=noteOn, time=t.whole * 2).play() delayWhale = Delay(whale,
""" Python code snippets vol 39: stevepython.wordpress.com 191-Generate melodies requirements: pip3 install pyo source: http://ajaxsoundstudio.com/software/pyo/ """ from pyo import CosTable, Metro, Osc, Server from pyo import SquareTable, TrigEnv, TrigXnoiseMidi s = Server().boot() s.start() wav = SquareTable() env = CosTable([(0, 0), (100, 1), (500, .3), (8191, 0)]) met = Metro(.125, 12).play() amp = TrigEnv(met, table=env, dur=1, mul=.1) pit = TrigXnoiseMidi(met, dist='loopseg', x1=20, scale=1, mrange=(48, 84)) out = Osc(table=wav, freq=pit, mul=amp).out()
class AccDataReceiver: """ >>>class AccDataReceiver Receives accelerometre data, converts it to degrees and smoothes it. Attr : port : Integer. Port to listen on. address : String. Address(es) that carries the data. smoothing : Boolean. Applies a gaussian smoother. Notes : - Give only one address if the stream is a list. If the data is coming on three different addresses, put them in a list as follows ["x_addr", "y_addr", "z_addr"]. - Attributes are available at initialization only. User can retreive original streams as follows : obj['coord'] where coord is x, y or z. User can also retreive a stream of triggers informing when a buffer has been filled the following way : obj['trig']. """ def __init__(self, port, address, inmin=-1, inmax=1, smoothing=True): self.port = port self.address = address self._inmin = inmin self._inmax = inmax self._data = [] self._buffer = [] self._buffer_size = 64 self._buffer_count = -1 self._precision = float(BUFFER_SIZE)/SAMP_RATE self._trig_buffer = Trig().stop() self._type = None self._createOSC(port, address) self._metro = Metro(self._precision).play() if smoothing: self._trig_fill = TrigFunc(self._metro, self._fill_buffer_w_smooth) else: self._trig_fill = TrigFunc(self._metro, self._fill_buffer_wo_smooth) def __getitem__(self, i): if i == 'trig': return self._trig_buffer if i == 'x': return self._oscx if i == 'y': return self._oscy if i == 'z': return self._oscz def _createOSC(self, port, address): if isinstance(address, list) and len(address) == 3: self._type = "simple" self._osc = OscReceive(port=port, address=address) elif isinstance(address, str): self._type = "list" self._osc = OscListReceive(port=port, address=address, num=3) else: print ">>>class AccDataAnalyser :\n<Error type: 'address' attribute must contain either 1 or 3 addresses>" self._createScaleObjs() def _createScaleObjs(self): if self._type == "simple": self._oscx = Scale(self._osc[self.address[0]], inmin=self._inmin, inmax=self._inmax, outmin=-90, outmax=90) self._oscy = Scale(self._osc[self.address[1]], inmin=self._inmin, inmax=self._inmax, outmin=-90, outmax=90) self._oscz = Scale(self._osc[self.address[2]], inmin=self._inmin, inmax=self._inmax, outmin=-90, outmax=90) elif self._type == "list": self._oscx = Scale(self._osc[self.address][0], inmin=self._inmin, inmax=self._inmax, outmin=-90, outmax=90) self._oscy = Scale(self._osc[self.address][1], inmin=self._inmin, inmax=self._inmax, outmin=-90, outmax=90) self._oscz = Scale(self._osc[self.address][2], inmin=self._inmin, inmax=self._inmax, outmin=-90, outmax=90) def _convert_data(self): x, y, z = self._oscx.get(), self._oscy.get(), self._oscz.get() degx = degrees(atan2(-y, -z) + pi) degy = degrees(atan2(-x, -z) + pi) degz = degrees(atan2(-y, -x) + pi) return [degx,degy,degz] ## Method when smoothing is on def _dump_w_smooth(self): self._pending = copy(self._buffer) del self._buffer[:] self._buffer_count += 1 self.call = CallAfter(self._smoother, .005) ## Method when smoothing is on def _fill_buffer_w_smooth(self): if len(self._buffer) < self._buffer_size: self._buffer.append(self._convert_data()) else: self._dump_w_smooth() self._buffer.append(self._convert_data()) ## Method when smoothing is off def _dump_wo_smooth(self): self._pending = copy(self._buffer) del self._buffer[:] self._buffer_count += 1 self.call = CallAfter(self._reorder, .005) ## Method when smoothing is off def _fill_buffer_wo_smooth(self): if len(self._buffer) < self._buffer_size: self._buffer.append(self._convert_data()) else: self._dump_wo_smooth() self._buffer.append(self._convert_data()) def _print_data(self): self.cpt += 1 if self.cpt <= self.num: self.temp_data.append(self._pending) self.temp_id.append(self._buffer_count) else: self.trig_print.stop() if self.print_mode == 0: print "\n>>>class AccDataAnalyser :" print "Data for %d buffer(s)." % self.num for i in range(self.num): print "\nBuffer %d" % self.temp_id[i] print "------------------------------------" for j in range(self._buffer_size): print "X: %.3f, Y: %.3f, Z: %.3f" % (self.temp_data[i][j][0], self.temp_data[i][j][1], self.temp_data[i][j][2]) print "------------------------------------" elif self.print_mode == 1: file = open(SAVE_PATH+"RAW_DATA_ACCELEROMETER.txt", "w") for i in range(self.num): file.write("Buffer %d\n" % self.temp_id[i]) for j in range(3): if j == 0: file.write("X : [") if j == 1: file.write("Y : [") if j == 2: file.write("Z : [") for k in range(self._buffer_size): file.write("%.3f" % self.temp_data[i][k][j]) if k < self._buffer_size-1: file.write(", ") file.write("]") file.write("\n") if i < self.num-1: file.write("\n") file.close() del self.trig_print del self.cpt del self.temp_data del self.temp_id del self.num del self.print_mode def _reorder(self): x = [self._pending[i][0] for i in range(self._buffer_size)] y = [self._pending[i][1] for i in range(self._buffer_size)] z = [self._pending[i][2] for i in range(self._buffer_size)] self._data.append([x, y, z]) self._trig_buffer.play() def _smoother(self, degree=5): x = [self._pending[i][0] for i in range(self._buffer_size)] y = [self._pending[i][1] for i in range(self._buffer_size)] z = [self._pending[i][2] for i in range(self._buffer_size)] smooth_x = self._gaussianListSmoother(x) smooth_y = self._gaussianListSmoother(y) smooth_z = self._gaussianListSmoother(z) self._data.append([smooth_x, smooth_y, smooth_z]) self._trig_buffer.play() def _gaussianListSmoother(self, buffer, degree=5): """ Smoothing algorithm from Scott W. Harden Source : http://www.swharden.com/blog/2008-11-17-linear-data-smoothing-in-python/ """ #Solution temporaire pour agrandir la liste de 9 elems #l'algorithme perd des donnees en cours de route #valide seulement pour un buffer de 64 et un degree de 5 list = [buffer[0]]*5 for i in range(len(buffer)):list.append(buffer[i]) for i in range(4):list.append(buffer[-1]) ######################################### window=degree*2-1 weight=numpy.array([1.0]*window) weightGauss=[] for i in range(window): i=i-degree+1 frac=i/float(window) gauss=1/(numpy.exp((4*(frac))**2)) weightGauss.append(gauss) weight=numpy.array(weightGauss)*weight smoothed=[0.0]*(len(list)-window) for i in range(len(smoothed)): smoothed[i]=sum(numpy.array(list[i:i+window])*weight)/sum(weight) return smoothed ######################## ## Methodes publiques ## ######################## def get(self): """ Returns last completed buffer after being smoothed. """ return self._data[self._buffer_count] def getData(self): """ Returns all data since the begining of the app. Data is smoothed and not raw. """ return self._data def getBufferSize(self): return self._buffer_size def play(self): """ Starts processing the accelerometer data. """ self._metro.play() self._trig_fill.play() self._osc.play() return self def stop(self): """ Stops processing the accelerometer data. """ self._metro.stop() self._trig_fill.stop() self._osc.stop() return self def print_data(self, num, mode=0): """ num : nunmber of buffers to print mode=0 : prints info on screen mode=1 : saves data to a .txt file where specified in the preferences """ self.cpt = 0 self.num = num self.temp_data = [] self.temp_id = [] self.print_mode = mode self.trig_print = TrigFunc(self._trig_buffer, self._print_data)