示例#1
0
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)
示例#2
0
def audio_server():
    # setup
    server = Server(sr=48000, buffersize=512, audio="manual").boot()

    yield server

    # teardown
    server.shutdown()
示例#3
0
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