def startServer(rate=44100, jack=True, channels=2): global pyoserver if jack : audio= 'jack' else: audio = 'portaudio' if sys.platform == 'win32' : pyoserver = Server( sr=rate, nchnls=channels, duplex=0, ) else : pyoserver = Server( sr=rate, nchnls=channels, duplex=0, audio=audio, jackname="Slicer" ) if audio == 'jack': pyoserver.setJackAuto(False, False)## ERROR in laptop while autoconnecting pyoserver.boot() pyoserver.start()
def pink_noise_to_file(duration, filename, mono=True, sampletype=1): """ filename : file to generate duration : duration in seconds of the file to generate fs : fs of the file to generate sampletype : 16 bits int (default) 24 bits int 32 bits int 32 bits float 64 bits float U-Law encoded A-Law encoded mono : generates mono file if mono = True """ from pyo import Server, PinkNoise s = Server(duplex=0, audio="offline").boot() s.boot() name = filename s.recordOptions(dur=duration + 0.1, filename=filename, fileformat=0, sampletype=sampletype) a = PinkNoise(.1).out() s.start() s.shutdown() if mono == True: from transform_audio import wav_to_mono wav_to_mono(filename, filename)
def switchOn(sampleRate=44100): """Must explicitly switch on the microphone before use, can take several seconds. """ # imports from pyo, creates globals including pyoServer and pyoSamplingRate global haveMic haveMic = False t0 = time.time() try: global Server, Record, Input, Clean_objects, SfPlayer, serverCreated, serverBooted from pyo import Server, Record, Input, Clean_objects, SfPlayer, serverCreated, serverBooted global getVersion, pa_get_input_devices, pa_get_output_devices from pyo import getVersion, pa_get_input_devices, pa_get_output_devices haveMic = True except ImportError: msg = 'Microphone class not available, needs pyo; see http://code.google.com/p/pyo/' logging.error(msg) raise ImportError(msg) global pyoSamplingRate pyoSamplingRate = sampleRate global pyoServer if serverCreated(): pyoServer.setSamplingRate(sampleRate) pyoServer.boot() else: pyoServer = Server(sr=sampleRate, nchnls=2, duplex=1).boot() pyoServer.start() logging.exp('%s: switch on (%dhz) took %.3fs' % (__file__.strip('.py'), sampleRate, time.time() - t0))
def serverSetup(device, bufsize, api='portaudio', amp=1.0): _s = Server(sr=48000, nchnls=2, buffersize=bufsize, duplex=0, audio=api) _s.setOutputDevice(device) _s.setAmp(amp) _s.boot() _s.start() return _s
def startServer(rate=44100, jack=True, channels=2): global pyoserver if jack: audio = 'jack' else: audio = 'portaudio' if sys.platform == 'win32': pyoserver = Server( sr=rate, nchnls=channels, duplex=0, ) else: pyoserver = Server(sr=rate, nchnls=channels, duplex=0, audio=audio, jackname="Slicer") if audio == 'jack': pyoserver.setJackAuto( False, False) ## ERROR in laptop while autoconnecting pyoserver.boot() pyoserver.start()
def switchOn(sampleRate=48000, outputDevice=None, bufferSize=None): """You need to switch on the microphone before use, which can take several seconds. The only time you can specify the sample rate (in Hz) is during switchOn(). You can switchOff() and switchOn() with a different rate, and can `resample()` a given an `AudioCapture()` object (if one has been recorded). Considerations on the default sample rate 48kHz:: DVD or video = 48,000 CD-quality = 44,100 / 24 bit human hearing: ~15,000 (adult); children & young adult higher human speech: 100-8,000 (useful for telephone: 100-3,300) google speech API: 16,000 or 8,000 only Nyquist frequency: twice the highest rate, good to oversample a bit pyo's downsamp() function can reduce 48,000 to 16,000 in about 0.02s (uses integer steps sizes) So recording at 48kHz will generate high-quality archival data, and permit easy downsampling. outputDevice, bufferSize: set these parameters on the pyoServer before booting; None means use pyo's default values """ # imports from pyo, creates globals pyoServer t0 = core.getTime() try: global Server, Record, Input, Clean_objects, SfPlayer, serverCreated, serverBooted from pyo import Server, Record, Input, Clean_objects, SfPlayer, serverCreated, serverBooted global getVersion, pa_get_input_devices, pa_get_output_devices, downsamp, upsamp from pyo import getVersion, pa_get_input_devices, pa_get_output_devices, downsamp, upsamp global haveMic haveMic = True except ImportError: msg = 'Microphone class not available, needs pyo; see http://code.google.com/p/pyo/' logging.error(msg) raise ImportError(msg) global pyoServer if serverCreated(): pyoServer.setSamplingRate(sampleRate) else: pyoServer = Server(sr=sampleRate, nchnls=2, duplex=1) if outputDevice: pyoServer.setOutputDevice(outputDevice) if bufferSize: pyoServer.setBufferSize(bufferSize) pyoServer.boot() core.pyoServers.append(pyoServer) pyoServer.start() logging.exp('%s: switch on (%dhz) took %.3fs' % (__file__.strip('.py'), sampleRate, core.getTime() - t0))
import re import platform if platform.system() == 'Windows': import pyreadline else: import readline import string import sys import time from pyo import Server, Fader, Sine #s = Server(nchnls=1, audio='jack').boot() #s = Server(nchnls=2, audio='pulseaudio').boot() s = Server(nchnls=2).boot() s.start() class Lexer(object): tokens = [ 'NOTE', 'IS', 'OF', 'FLOAT', 'FRACTION', 'INTEGER', 'HERTZ', 'INTERVAL_NUMBER', 'INTERVAL_QUALITY', 'ABOVEBELOW', 'PLUSMINUS', 'COMMA_TYPE', 'COMMA', 'CENT', 'DROP', 'COMPARE', 'GENERATE', 'BASE', 'TRANSPOSE', 'UPDOWN', 'PLAY', 'TO', 'RPAREN', 'LPAREN', 'LOAD', 'SAVE', 'FILENAME', 'PRINT', 'ON', 'OFF', 'END_STMT' ] t_ignore = ' \t' t_NOTE = r'([A-G]b+|[A-G]\#*|[X-Z])' t_IS = r'\bis\b' t_OF = r'\bof\b'
players = [] 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
:Args: x : int New number of harmonics """ self._order = x self._tri_table.replace(self._create_list(x)) self.normalize() self.refreshView() @property def order(self): """int. Number of harmonics triangular waveform is made of.""" return self._order @order.setter def order(self, x): self.setOrder(x) # Run the script to test the TriTable object. if __name__ == "__main__": s = Server(duplex=0).boot() s.setAmp(0.05) s.start() t = TriTable(10, 8192) t.view() a = Osc(t, 500, mul=.3).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
def startPyo(): s = Server().boot() s.start() return s
def play(self, drum_kit, pattern, measure_length, syncope=False): """ This function plays the selected pattern with the selected drum machine Args: drum_kit (dict): created drum kit by the user pattern (dict): pattern or drum loop to play measure_length (int): relative length of th selected pattern syncope (bool): flag to select whether the pattern should be played syncopated or not """ sleep_time = (1 / (self.BPM / 60)) / 2 # Initialize server s = Server().boot() s.start() bar_counter = 0 measure_counter = 0 if not syncope: # Go over all the loops while measure_counter < self.loops: bar_counter += 1 # Go over all the measures if bar_counter > measure_length: bar_counter = 1 measure_counter += 1 players = [] for instrument, beats in pattern.items(): if bar_counter in beats: # Play in stereo! players.append( SfPlayer(drum_kit[instrument], speed=1, loop=False).out(chnl=[0])) players.append( SfPlayer(drum_kit[instrument], speed=1, loop=False).out(chnl=[1])) # Wait to reproduce the next note (computed with the BPM) sleep(sleep_time) else: # Syncope counter syncop_count = 2 while measure_counter < self.loops: bar_counter += 1 if bar_counter > measure_length: bar_counter = 1 measure_counter += 1 players = [] for instrument, beats in pattern.items(): if bar_counter in beats: players.append( SfPlayer(drum_kit[instrument], speed=1, loop=False).out(chnl=[0])) players.append( SfPlayer(drum_kit[instrument], speed=1, loop=False).out(chnl=[1])) # Syncopate notes by elongating by 2 half of the notes if syncop_count % 2 == 0: sleep(sleep_time * 2) else: sleep(sleep_time) syncop_count += 1
def setup_audio_server(): s = Server().boot() s.start() return s
class DspFileHandler(): def __init__(self, dspFile, svg=False, ir=False, af='', line=False, impLen=1, lenSec = 0.5, plotter=None): self.svg = svg self.dspFile = dspFile self.ir = ir self.af =af self.line=line self.lenSec = lenSec self.impLen = impLen self.sr = 44100. self.lenSamps = int(round(self.lenSec*self.sr)) self.audioInitialized = False self.irAvailable = False logging.debug(self.lenSamps) self.lastIR = np.zeros(self.lenSamps) self.lastSpec = None self.lastLine = None self.dspDir = os.path.dirname(os.path.abspath(dspFile)) self.baseName = os.path.basename(dspFile) self.projectName = self.baseName[:-4] self.outputPath= config.audioOutPath self.inputPath= config.audioInPath self.plotter = plotter logging.info('watching file: '+os.path.abspath(dspFile)) # self.initializeAudio() def initializeAudio(self): self.audioServer = Server(audio='jack') self.audioServer.boot() self.audioServer.start() self.reloadAudioFile() self.audioInitialized = True def reloadAudioFile(self): self.sfplayer = SfPlayer(self.outputPath, loop=False, mul=1).out() def compute(self): if not self.svg and not self.ir and not self.af and not self.line: logging.info('only compiling, no other action.') cmd = 'faust '+self.dspFile cmd = shlex.split(cmd) proc = subprocess.Popen( cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) resp = proc.communicate()[0] resp = resp.decode("utf-8") if 'ERROR' in resp: print(bcolors.FAIL+'>[ER]'+bcolors.ENDC+resp) elif 'WARNING' in resp: print(bcolors.WARNING+'>[WA]'+bcolors.ENDC+resp) else: print(resp) print(bcolors.OKGREEN+'>[OK]'+bcolors.ENDC) if self.svg: cmd = 'faust --svg '+self.dspFile cmd = shlex.split(cmd) proc = subprocess.Popen(cmd,stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) resp = proc.communicate()[0] resp = resp.decode("utf-8") if 'ERROR' in resp: print (bcolors.FAIL+'>[ER]'+bcolors.ENDC+resp) elif 'WARNING' in resp: print (bcolors.WARNING+'>[WA]'+bcolors.ENDC+resp) self.openSVG() else: print(resp) print (bcolors.OKGREEN+'>[OK]'+bcolors.ENDC) self.openSVG() if self.ir: returnCode = self.compile() if returnCode <2: self.getIR() self.plotSignalQt() if self.line: returnCode = self.compile() if returnCode <2: self.getLineResponse() self.plotSignalQt() if len(self.af)>0: returnCode = self.compile() if returnCode<2: self.inputPath = self.af self.sr, self.inputSignal = wavfile.read(self.af) self.processFile(self.af) self.plotSignalQt() return def compile(self): self.binaryPath = 'offlineProcessor' outfileCpp = 'offline.cpp' cmd = 'faust -a '+config.offlineCompArch+' -o '+outfileCpp+' '+self.dspFile cmd = shlex.split(cmd) proc = subprocess.Popen(cmd,stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) resp = proc.communicate()[0] resp = str(resp) cmd = 'g++ -lsndfile '+outfileCpp+' -o '+self.binaryPath cmd = shlex.split(cmd) proc = subprocess.Popen(cmd,stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) resp1 = proc.communicate()[0] if 'ERROR' in resp: print (bcolors.FAIL+'>[ER]'+bcolors.ENDC+resp) return 2 elif 'WARNING' in resp: print (bcolors.WARNING+'>[WA]'+bcolors.ENDC+resp) return 1 else: print (bcolors.OKGREEN+'>[OK]'+bcolors.ENDC) return 0 def openSVG(self): svgPath = os.path.join(self.dspDir,self.projectName+'-svg','process.svg') cmd = 'xdg-open '+svgPath cmd = shlex.split(cmd) proc = subprocess.Popen(cmd,stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) def getIR(self): impOffsetSamps = int(round(self.lenSamps*0.25)) impLength = self.impLen imp = np.zeros(self.lenSamps) imp[impOffsetSamps:impOffsetSamps+impLength] = 1 self.processArray(imp) return def getLineResponse(self): line = np.linspace(-1,1,self.sr) self.processArray(line) return def processFile(self, tempPath): cmd = os.path.join(self.dspDir,self.binaryPath)+' '+tempPath+' '+self.outputPath cmd = shlex.split(cmd) proc = subprocess.Popen(cmd,stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) resp = proc.communicate()[0] self.irAvailable = True if not self.audioInitialized: self.initializeAudio() self.play() return def processArray(self,anArray, sr=44100,inputPath='/tmp/offlineInput.wav'): assert type(anArray) ==np.ndarray self.inputSignal = anArray.astype(np.float32) wavfile.write(inputPath, sr, anArray) self.inputPath = inputPath cmd = os.path.join(self.dspDir,self.binaryPath)+' '+inputPath+' '+self.outputPath cmd = shlex.split(cmd) proc = subprocess.Popen(cmd,stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) resp = proc.communicate()[0] if not self.audioInitialized: self.initializeAudio() self.play() return def play(self): logging.debug('play function called') self.reloadAudioFile() # self.trig.play() def plotSignalQt(self): _, y = wavfile.read(self.outputPath) currentAndLast = np.array([self.lastIR,y]).T self.plotter.plot(currentAndLast) self.lastIR = y return def getSpec(self): x = self.inputSignal f, Pxx_den = sig.welch(x, self.sr, nperseg=1024)