def play(self, dur): times = sm.waves.tspan(dur) waves = [] for start, wdur, lf, hf, amp, amp_freq, amp_phase in zip( self.starts, self.durs, self.low_freqs, self.high_freqs, self.amps, self.amp_freqs, self.amp_phases ): ss = lr.time_to_samples(start, sm.sound.SAMPLE_RATE) es = lr.time_to_samples(start + wdur, sm.sound.SAMPLE_RATE) es = min(es, self.so.samples.size - 1) samps = self.so.samples[ss:es] if samps.size <= 0: continue if hf < lf: hf, lf = lf, hf if es - ss > 0.1 * sm.sound.SAMPLE_RATE: samps = sm.effects.band_pass(SoundObject(samps), lf, hf).samples peak = np.max(np.abs(samps)) if peak > 0.0: samps /= peak samp_dur = lr.samples_to_time(samps.size, sm.sound.SAMPLE_RATE) wave = np.interp( times, np.linspace(0, samp_dur, samps.size), samps, period=samp_dur ) * amp mod = sm.waves.sin(times, amp_freq, 1.0, amp_phase) wave *= mod waves.append(SoundObject(wave)) return sm.sound.join(waves)
def build_model(n, source: SoundObject): model = [] history = [] onsets = lr.onset.onset_detect(source.samples, sr=sm.sound.SAMPLE_RATE, backtrack=True, units="samples", wait=int(0.1 * sm.sound.SAMPLE_RATE / 512)) for o1, o2 in zip(onsets, onsets[1:]): if o2 - o1 < sm.sound.SAMPLE_RATE * 0.1: continue so = SoundObject(source.samples[o1:o2]) _, mtrack = so.track_pitch() pitch = max(so.get_f0(), 0) mag = max(np.mean(mtrack), 0) dur = max(so.duration, 0.15) note = Note(pitch, mag, dur) history.append(note) history = history[-n:] model.append(history) return model
def evolve(lso, n_generations, elitism, mut_prob, fitness_weights, fitness_params): npop = len(lso) population = [(so, fitness(so, fitness_weights, fitness_params)) for so in lso] for _ in range(n_generations): n_child = round(npop * (1 - elitism)) pot_parents = copy.deepcopy(population) childs = [] while len(childs) < n_child: if len(pot_parents) < 2: pot_parents = copy.deepcopy(population) parent0 = random.choices(pot_parents, weights=[ score for _, score in pot_parents ], k=1)[0] pot_parents.remove(parent0) parent1 = random.choices(pot_parents, weights=[ score for _, score in pot_parents ], k=1)[0] pot_parents.remove(parent1) child = crossover(parent0[0], parent1[0]) while random.uniform(0, 1) < mut_prob: mut = random.choice(mutations) print(f"Mutating: {mut.__name__}") new_child = mut(child) if not np.isnan(new_child.samples).any(): child = new_child else: print("Mutation Failed") try: child = SoundObject( lr.effects.trim(child.get_normalize_to(1.0))) except: continue fit = fitness(child, fitness_weights, fitness_params) if np.isnan(fit) or np.isinf(fit): continue childs.append((child, fit)) population = sorted(population, key=lambda ind: ind[1], reverse=True)[:int(elitism * npop)] + childs print(max([s for _, s in population])) out = [] for so, _ in population: ptrack, mtrack = so.track_pitch() pitch = lr.hz_to_midi(np.mean(ptrack)) velocity = np.clip(np.mean(mtrack) * 127, 0, 127) out.append((so, pitch, velocity)) return out
def band_pass(so: SoundObject, low, high, order=5): nyq = 0.5 * sm.sound.SAMPLE_RATE low = np.clip(low / nyq, 0.001, 0.999) high = np.clip(high / nyq, 0.001, 0.999) b, a = sp.signal.butter(order, [low, high], btype="band") out = sp.signal.lfilter(b, a, so.samples) return SoundObject(np.nan_to_num(out))
def crossover(so1: SoundObject, so2: SoundObject) -> SoundObject: so1 = copy.deepcopy(so1) so2 = copy.deepcopy(so2) env1 = sm.waves.sin(sm.waves.tspan(so1.duration), random.uniform(0.1, 4), 1.0, random.uniform(0, 2 * np.pi)) env2 = sm.waves.sin(sm.waves.tspan(so2.duration), random.uniform(0.1, 4), 1.0, random.uniform(0, 2 * np.pi)) so1.samples *= env1 so2.samples *= env2 so1.t = 0 so2.t = random.uniform(0, so1.duration) return sm.sound.join( [so1.get_normalize_to(0.5), so2.get_normalize_to(0.5)])
def fitness_target(so: SoundObject, target: SoundObject): nso = so.get_padded(target.duration) spect1 = lr.stft(nso) spect2 = lr.stft(target.samples) spect1 /= np.max(spect1) spect2 /= np.max(spect2) dif = np.abs(spect1 - spect2) return np.mean(dif)
def get_room(so: SoundObject, dur): dur_samps = lr.time_to_samples(dur, sm.sound.SAMPLE_RATE) room = np.zeros(dur_samps, dtype=so.samples.dtype) silences = lr.onset.onset_detect(so.samples, sm.sound.SAMPLE_RATE, wait=int(dur_samps / 512), units="samples") count = 0 for e,e2 in zip(silences, silences[1:]): ss = int(e + 0.01 * sm.sound.SAMPLE_RATE) es = int(min(ss + dur_samps, max(e2 - 0.01 * sm.sound.SAMPLE_RATE, 0))) if es < so.samples.size and es - ss > 0.1 * sm.sound.SAMPLE_RATE: response = so.samples[ss:es] room += SoundObject(response).get_padded(dur) count += 1 if count == 0: return None room /= count room *= np.linspace(1, 0.0, dur_samps) return SoundObject(room)
def mutate_chorus(so: SoundObject): samps = (Fx().chorus(random.uniform(0, 1), random.uniform(0, 1), [[ random.uniform(40, 60), random.uniform(0, 1), random.uniform(0.2, 0.3), random.uniform(1, 5), random.choice(["s", "t"]) ] for _ in range(random.randrange(1, 5))]))(so.samples) return SoundObject(samps)
def join_drones(drones, dur, amp): times = sm.waves.tspan(dur) waves = [] for drone in drones: so = drone.play(dur) mod_freq = random.uniform(1 / MAX_DRONE_DUR, 1 / MIN_DRONE_DUR) mod_phase = random.uniform(0, 2*np.pi) mod = sm.waves.sin(times, mod_freq, amp / 2, mod_phase) + (amp / 2) so = SoundObject(so.samples * mod) waves.append(so) return sm.sound.join(waves)
def play(self, dur): times = sm.waves.tspan(dur) waves = [] for freq, phase, amp, amp_freq, amp_phase in zip( self.freqs, self.phases, self.amps, self.amp_freqs, self.amp_phases ): wave = sm.waves.sin(times, freq, amp, phase) mod = sm.waves.sin(times, amp_freq, 1.0, amp_phase) wave *= mod waves.append(SoundObject(wave)) return sm.sound.join(waves)
def play(self, npitch, nmag, ndur): note = Note(npitch, nmag, ndur) if note.pitch <= 0: samps = np.zeros(int(note.dur * sm.sound.SAMPLE_RATE)) return SoundObject(samps) n_samples = int(note.dur * sm.sound.SAMPLE_RATE) factors = [] for so, pitch, mag, dur in self.sounds: p_dif = (note.pitch - pitch)**2 m_dif = (note.mag - mag)**2 d_dif = (note.dur - dur)**2 wei = 1 / np.sqrt(p_dif + m_dif + d_dif) samps = so.samples if samps.size > n_samples: samps = samps[:n_samples] elif samps.size < n_samples: samps = np.concatenate( [samps, np.zeros(n_samples - samps.size)]) factors.append([samps, wei]) total = sum([w for _, w in factors]) factors = sorted(factors, key=lambda fac: fac[1])[-MAX_SAMPLES:] out = np.zeros(n_samples) for samps, wei in factors: out += samps * wei / total pitch = SoundObject(out).get_f0() if pitch > 0: out = lr.effects.pitch_shift( out, sm.sound.SAMPLE_RATE, lr.hz_to_midi(note.pitch) - lr.hz_to_midi(pitch)) oso = sm.effects.band_pass(SoundObject(out), note.pitch, 20000) return oso
def side_chain(point_durs_int, so: SoundObject): times = sm.waves.tspan(so.duration) curve = np.ones_like(so.samples) for start, end, intens in point_durs_int: p = (start + end) / 2 w = end - start bump = sm.waves.bump(times, intens, p, w) curve -= bump curve = np.maximum(curve, 0.0) f = int(SWELL * so.duration * sm.sound.SAMPLE_RATE) l = curve.size curve = np.concatenate([ np.linspace(0, 1, f), np.ones(l - 2 * f), np.linspace(1, 0, f) ]) * curve return SoundObject(so.samples * curve)
def mutate_reverse(so: SoundObject): samps = np.flip(so.samples) return SoundObject(samps)
def reverberate(room: SoundObject, so: SoundObject): samps = np.convolve(so.samples, room.samples, mode='same') return SoundObject(samps)
def mutate_pitch(so: SoundObject): samps = lr.effects.pitch_shift(so.samples, sm.sound.SAMPLE_RATE, random.uniform(-12.0, 12.0)) return SoundObject(samps)
def mutate_compand(so: SoundObject): samps = (Fx().compand(random.uniform(0.1, 1.0), random.uniform(0.1, 1.0), random.uniform(0.5, 2.0), random.uniform(-20, -3), random.uniform(-20, -3), random.uniform(-20, -3)))(so.samples) return SoundObject(samps)
def mutate_tempo(so: SoundObject): samps = lr.effects.time_stretch(so.samples, random.uniform(0.5, 2.0)) return SoundObject(samps)
def mutate_bandreject(so: SoundObject): samps = (Fx().bandreject(random.uniform(20, 20e3), random.uniform(0.1, 2.0)))(so.samples) return SoundObject(samps)
def mutate_distortion(so: SoundObject): a = random.uniform(0, 1) samps = np.clip(so.samples, -a, a) return SoundObject(samps)
def mutate_reverb(so: SoundObject): samps = (Fx().reverb(random.uniform(0, 100), random.uniform(0, 100), random.uniform(0, 100), random.uniform(0, 100), random.uniform(0, 100)))(so.samples) return SoundObject(samps)
def mutate_fragment(so: SoundObject): fr = random.randrange(0, so.samples.size - 0.1 * sm.sound.SAMPLE_RATE) to = random.randrange(fr + 0.1 * sm.sound.SAMPLE_RATE, so.samples.size) samps = so.samples[fr:to] return SoundObject(samps)