83 lines
3.6 KiB
Python
83 lines
3.6 KiB
Python
|
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))))
|