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 sample_serializer(s: sample.Sample) -> Dict[str, Any]: return { "__class__": "synthplayer.sample.Sample", "samplerate": s.samplerate, "samplewidth": s.samplewidth, "duration": s.duration, "nchannels": s.nchannels, "name": s.name, "frames": s.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
def chunked_frame_data(self, chunksize: int, repeat: bool=False, stopcondition: Callable[[], bool]=lambda: False) -> Generator[memoryview, None, None]: assert not repeat sample_residue = Sample(nchannels=2) for n in range(0, 180): if stopcondition(): break freq = 0x8000 - n * 180 osc = FastTriangle(freq * _sidfreq, amplitude=0.8) filtered = EnvelopeFilter(osc, 0.002, 0.004, 0.0, 0.6, 0.02, stop_at_end=True) sample_residue = yield from self.render_samples(filtered, sample_residue, chunksize, return_residue=True) if len(sample_residue) > 0: yield sample_residue.view_frame_data()