def chunked_frame_data(self, chunksize: int, repeat: bool=False, stopcondition: Callable[[], bool]=lambda: False) -> Generator[memoryview, None, None]: notes = itertools.cycle(self.title_music) if repeat else iter(self.title_music) attack, decay, sustain, release = self.adsr_times num_frames = chunksize // synth_params.norm_samplewidth // synth_params.norm_nchannels sample_residue = Sample(None, nchannels=2) for v1, v2 in notes: if stopcondition(): break vf1 = self.music_freq_table[v1] vf2 = self.music_freq_table[v2] osc1 = FastTriangle(vf1 * _sidfreq, amplitude=0.5) osc2 = FastTriangle(vf2 * _sidfreq, amplitude=0.5) f1 = EnvelopeFilter(osc1, attack, decay, sustain, 1.0, release, stop_at_end=True) f2 = EnvelopeFilter(osc2, attack, decay, sustain, 1.0, release, stop_at_end=True) sample1 = Sample.from_oscillator(f1, 1, synth_params.norm_samplerate) # length is max. 1 second sample2 = Sample.from_oscillator(f2, 1, synth_params.norm_samplerate) # length is max. 1 second sample_residue.join(sample1.stereo_mix(sample2, "R")) while len(sample_residue) >= num_frames: # TODO optimize this a bit by not using Samples but instead by looping over a memoryview of the frames (just like the super class does) yield sample_residue.view_frame_data()[:chunksize] sample_residue = Sample.from_raw_frames(sample_residue.view_frame_data()[chunksize:], sample_residue.samplewidth, sample_residue.samplerate, sample_residue.nchannels) if len(sample_residue): yield sample_residue.view_frame_data()
def render_samples(self, osc: Oscillator, sample_residue: Sample, sample_chunksize: int, stopcondition: Callable[[], bool] = lambda: False, return_residue: bool = False) -> Generator[memoryview, None, Sample]: num_frames = sample_chunksize // synth_params.norm_samplewidth // synth_params.norm_nchannels blocks = osc.blocks() while not stopcondition(): try: block = next(blocks) except StopIteration: break sample = Sample.from_osc_block(block, osc.samplerate, 2 ** (8 * synth_params.norm_samplewidth - 1)).stereo() sample_residue.join(sample) while len(sample_residue) >= num_frames: yield sample_residue.view_frame_data()[:sample_chunksize] sample_residue = Sample.from_raw_frames(sample_residue.view_frame_data()[sample_chunksize:], sample_residue.samplewidth, sample_residue.samplerate, sample_residue.nchannels) if return_residue: return sample_residue yield sample_residue.view_frame_data() return sample_residue