import numpy as np from matplotlib import pyplot as plt from scipy.fft import fft, ifft from IPython.display import Audio, display from scipy.io import wavfile from ipywidgets import widgets from functools import partial import pandas as pd from fractions import Fraction def create_signal(frequency, amplitude, delay, phase=0, sampling=44100, seconds=1.0): timesteps = np.linspace(0,seconds, int(seconds * sampling)) # return np.sum(amplitude * np.sin(frequency * 2*np.pi * (timesteps[:, np.newaxis]-delay)*(timesteps[:, np.newaxis]-delay > 0)), axis=1), timesteps return np.sum(amplitude * triangle(frequency, (timesteps[:, np.newaxis]-delay)*(timesteps[:, np.newaxis]-delay > 0)), axis=1), timesteps def create_waves(frequency, amplitude, phase=0, sampling=44100, seconds=1.0): timesteps = np.linspace(0,seconds, int(seconds * sampling)) # return amplitude * np.sin(frequency * 2*np.pi * timesteps[:, np.newaxis]), timesteps return amplitude * triangle(frequency, timesteps[:, np.newaxis]), timesteps def triangle(frequency, t): phase = (t * frequency + 0.25) % 1 - 0.25 return (phase <= 0.25) * phase + (phase > 0.25) * (0.5 - phase) def nonlinearity(x, param=1.0): # param for scaling of argument; higher values = more nonlinearity #return np.exp(x*param) return np.sign(x)*np.log(1+np.abs(x*param)) def myAudio(signal, rate=44100, autoplay=False, time_fade=0.2): length = signal.shape[0] print(length) fade = np.minimum(np.ones(length),np.arange(length)/(time_fade * rate)) return Audio(signal * fade * fade[::-1],rate=rate,autoplay=autoplay) #frequency = np.array([100., 200., 300, 400]) #frequency_edo12 = 220 * 2**(np.array([5,8,12,14])/12) #frequency_edo53 = 220 * 2**(np.array([22,36,53,62])/53) #frequency_edo53 = 220 * 2**(np.array([22,34,53,61])/53) #frequency_rein1 = 220 * 4/3 * np.array([1, 7/6, 9/6, 10/6]) #frequency_rein2 = 220 * 4/3 * np.array([1, 12/10, 15/10, 17/10]) dursept_edo12 = 220 * 2**(np.array([5,9,12,15])/12) # Durseptakkord in EDO12 dursept_edo53 = 220 * 2**(np.array([22,39,53,65])/53) # Dursept in EDO53 dursept_rein = 220 * 4/3 * np.array([1, 5/4, 6/4, 7/4]) # Dursept rein mollsept_edo12 = 220 * 2**(np.array([5,8,12,14])/12) # Mollseptakkord in EDO12 mollsept_edo53 = 220 * 2**(np.array([22,36,53,63])/53) # Mollseptakkord in EDO53 mollsept_rein = 220 * 4/3 * np.array([1, 12/10, 15/10, 17/10]) # Mollsept rein doppeltritone_rein = 220 * 4/3 * np.array([1, 12/10, 14/10, 17/10]) # doppeltritone rein doppeltritone_edo53 = 220 * 2**(np.array([22,36,48,63])/53) # doppeltritone in EDO53 amplitude = np.array([1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]) delay = np.array([0.0,0.2,0.4,0.6,0.8,1.0,1.2]) # list of chords to display. # chords = [dursept_edo12, dursept_edo53, dursept_rein, ] # chords = [mollsept_edo12, mollsept_edo53, mollsept_rein, ] chords = [doppeltritone_rein, doppeltritone_edo53, ] to_display = [] for chord in chords: notes = len(chord) signal, timesteps = create_signal(frequency=chord, amplitude=amplitude[:notes], delay=delay[:notes], phase=0, sampling=44100, seconds=5.0) to_display.append(signal) max_play_time = 2.0 for signal in to_display: display(myAudio(signal[timesteps < max_play_time],rate=44100, autoplay=False)) plot_time = 1.0 plt.figure(1, figsize=(20,6)) plt.xlabel("time [s]") for signal in to_display: plt.plot(timesteps[timesteps < plot_time], (1*signal[timesteps < plot_time])) plt.figure(2, figsize=(40,6)) plt.subplot(111, xscale='log', yscale='log') plt.xlabel("Frequenz [Hz]") plt.xlim(200,5000) plt.ylim(bottom=1e-1, top=1e4) for signal in to_display: plt.plot(np.abs(fft(nonlinearity(signal[timesteps > 1.0], 0.1))))