def create_chord_osc(clazz, **arguments): if is_audio and self.arp_filter_gui.input_mode.get().startswith("chords"): chord_keys = major_chord_keys(note, octave) if self.arp_filter_gui.input_mode.get() == "chords3": chord_keys = list(chord_keys)[:-1] a4freq = self.a4_choice.get() chord_freqs = [note_freq(n, o, a4freq) for n, o in chord_keys] self.statusbar["text"] = "major chord: "+" ".join(n for n, o in chord_keys) oscillators = [] arguments["amplitude"] /= len(chord_freqs) for f in chord_freqs: arguments["frequency"] = f oscillators.append(clazz(**arguments)) return MixingFilter(*oscillators) else: # no chord (or an LFO instead of audio output oscillator), return one osc for only the given frequency return clazz(**arguments)
def play_note(self, list_of_notes, released=False): # list of notes to play (length 1 = just one note, more elements = arpeggiator list) to_speaker = [self.oscillators[i] for i in self.to_speaker_lb.curselection()] if not to_speaker: self.statusbar["text"] = "No oscillators connected to speaker output!" return if released: for note, octave in list_of_notes: if (note, octave) in self.currently_playing: # stop the note sid = self.currently_playing[(note, octave)] self.output.stop_sample(sid) return first_note, first_octave = list_of_notes[0] first_freq = note_freq(first_note, first_octave, self.a4_choice.get()) for osc in self.oscillators: if osc.input_freq_keys.get(): osc.input_freq.set(first_freq*osc.input_freq_keys_ratio.get()) for osc in to_speaker: if osc.input_waveformtype.get() == "linear": self.statusbar["text"] = "cannot output linear osc to speakers" return else: osc.set_title_status("TO SPEAKER") oscs_to_play = [] for note, octave in list_of_notes: freq = note_freq(note, octave, self.a4_choice.get()) oscs = [self.create_osc(note, octave, freq * osc.input_freq_keys_ratio.get(), osc, self.oscillators, is_audio=True) for osc in to_speaker] mixed_osc = MixingFilter(*oscs) if len(oscs) > 1 else oscs[0] self.echos_ending_time = 0 if len(list_of_notes) <= 1: # you can't use filters and echo when using arpeggio for now mixed_osc = self.apply_filters(mixed_osc) current_echos_duration = getattr(mixed_osc, "echo_duration", 0) if current_echos_duration > 0: self.echos_ending_time = time.time() + current_echos_duration oscs_to_play.append(mixed_osc) if len(list_of_notes) > 1: rate = self.arp_filter_gui.input_rate.get() duration = rate * self.arp_filter_gui.input_ratio.get() / 100.0 self.statusbar["text"] = "playing ARP ({0}) from note {1} {2}".format(len(oscs_to_play), first_note, first_octave) for index, (note, octave) in enumerate(list_of_notes): sample = StreamingOscSample(oscs_to_play[index], self.synth.samplerate, duration) sid = self.output.play_sample(sample, delay=rate*index) self.currently_playing[(note, octave)] = sid self.arp_after_id = self.after(int(rate * len(list_of_notes) * 1000), lambda: self.play_note(list_of_notes)) # repeat arp! else: # normal, single note if self.rendering_choice.get() == "render": self.statusbar["text"] = "rendering note sample..." self.after_idle(lambda: self.render_and_play_note(mixed_osc)) else: self.statusbar["text"] = "playing note {0} {1}".format(first_note, first_octave) sample = StreamingOscSample(oscs_to_play[0], self.synth.samplerate) sid = self.output.play_sample(sample) self.currently_playing[(first_note, first_octave)] = sid def reset_osc_title_status(): for osc in to_speaker: osc.set_title_status("") self.after(1000, reset_osc_title_status)