audio-fm-mummer/audio_fm_mummer.py

984 lines
37 KiB
Python

#!/usr/bin/env python3
# Copyright (C) 2020 Harry Sentonbury
# GNU General Public License v3.0
import clip_dialog
import o_dialog
import preset_dialog
import numpy as np
import sounddevice as sd
import sys
import threading
import time
from PyQt5.Qt import Qt
from PyQt5.QtWidgets import (QMainWindow, QAction, qApp, QApplication, QFrame,
QListWidget, QLabel, QLineEdit, QPushButton,
QHBoxLayout, QWidget, QSlider, QVBoxLayout, QShortcut
)
from PyQt5.QtGui import QIcon, QKeySequence #, QPixmap
from PyQt5.QtCore import pyqtSlot
import thyaudio as ta
class SliderFrame(QFrame):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
def build(save=False):
"""Gets values and selections from gui then plays or saves"""
def tremelo(): # more of a tremelator!
trem_adder = 1.0 - trem_amount_value
if self.tremolo_sin[0] is True:
return np.sin(x * trem_speed) * trem_amount_value + trem_adder
else:
return np.cos(x * trem_speed) * trem_amount_value + trem_adder
def ramp_2_osc():
return ramp_2 * np.sin(fm * x)
def lfo_osc_wave(lfo_shape):
return lfo_shape() * np.sin(fm * x)
def ramp_3_fm2():
return ramp_3 * np.sin(fm2 * x)
def sine_wave(mod):
y = np.sin(x * freq + mod)
return y
def triangle(mod):
y = 2 / np.pi * np.arcsin(np.sin(freq * x + mod))
return y
def noise(ramp):
y = np.random.normal(0, 0.4, np.size(x))
y = np.clip(y, a_min=-1.0, a_max=1.0) * (ramp * 0.1)
return y
def lfo():
y = (np.sin(x * speed)) * lfo_amount
return y
def lfo_pluss():
y = np.sin(x * speed) * 2 + 1
y = np.clip(y, self.clippings[0], self.clippings[1]) * lfo_amount
return y
def lfo_fold():
y = np.sin(x * speed)
y = ta.ThyFoldinger(y, abs(self.foldings[0])).folding()
y = (ta.ThyFoldinger(y, abs(self.foldings[1]), positive=False).folding() + 1) * lfo_amount
#print(f"fold max: {np.max(y)} min: {np.min(y)}")
return y
def sweep():
return (1 - (np.abs(np.sin(x * speed)))) * lfo_amount
global waveform_stereo
freq = self.freq_slider.value() * 0.1
fm = self.fm1_slider.value() * 0.1
fm2 = self.fm2_slider.value() * 0.1
speed = self.lfo_slider.value() * 0.01
duration = self.duration_slider.value() / 10
lfo_amount = self.lfo_amp_slider.value() * 0.01
ramp_amount = self.ramp_slider.value() * 0.01
trem_speed = self.tremolo_slider.value() * 0.01
vol = self.volume_slider.value() * 0.01
trem_amount_value = self.trem_amp_slider.value() * 0.01
ramp3_divizor = self.fmt_slider.value() * 0.01
roller = self.delay_slider.value()
fade_size = 500 + int(duration * new_samplerate[0] *
self.fade_out_slider.value() * 0.01)
fade_in_size = 500 + int(duration * new_samplerate[0] *
self.fade_in_slider.value() * 0.01)
noise_shape = self.noise_slider.value() * 0.1
attenuation = 0.3
total_samples = int(duration * new_samplerate[0])
x = np.linspace(0, duration * 2 * np.pi, total_samples) # f(x)
ramp_3 = np.ones(len(x))
ramp_3_ramp = np.logspace(
1, 0, int(duration * new_samplerate[0] // ramp3_divizor))
ramp_0 = np.logspace(noise_shape, 1, total_samples, base=5)
ramp_1 = np.logspace(1, noise_shape, total_samples, base=5)
ramp_2 = np.logspace(0, 1, total_samples) * ramp_amount
ramp_3[: len(ramp_3_ramp)] = ramp_3_ramp
fade_ramp = np.linspace(1, 0, fade_size if fade_size < 120000 else 120000)
fade_in_ramp = np.linspace(0, 1, fade_in_size if fade_in_size < 120000 else 120000)
# wave selector
if self.choose_wave[0] is True:
if self.choose_fm2[0] is False:
if self.choose_lfo[0] == 0:
waveform = triangle(ramp_2_osc())
elif self.choose_lfo[0] == 1:
waveform = triangle(lfo_osc_wave(lfo))
elif self.choose_lfo[0] == 2:
waveform = triangle(lfo_osc_wave(lfo_pluss))
elif self.choose_lfo[0] == 3:
waveform = triangle(lfo_osc_wave(lfo_fold))
else:
waveform = triangle(lfo_osc_wave(sweep))
if self.choose_fm2[0] is True:
if self.choose_lfo[0] == 0:
waveform = 2 / np.pi * np.arcsin(np.sin(x * freq + ramp_2 * 2 / np.pi * np.arcsin(
np.sin(x * fm + ramp_3_fm2()))))
elif self.choose_lfo[0] == 1:
waveform = 2 / np.pi * np.arcsin(np.sin(x * freq + lfo() * 2 / np.pi * np.arcsin(
np.sin(x * fm + ramp_3_fm2())))) # bollox
elif self.choose_lfo[0] == 2:
waveform = 2 / np.pi * np.arcsin(np.sin(x * freq + lfo_pluss() * 2 / np.pi * np.arcsin(
np.sin(x * fm + ramp_3_fm2())))) # bollox
elif self.choose_lfo[0] == 3:
waveform = 2 / np.pi * np.arcsin(np.sin(x * freq + lfo_fold() * 2 / np.pi * np.arcsin(
np.sin(x * fm + ramp_3_fm2())))) # bollox
else:
waveform = 2 / np.pi * np.arcsin(np.sin(x * freq + sweep() * 2 / np.pi * np.arcsin(
np.sin(x * fm + ramp_3_fm2())))) # bollox
if self.choose_wave[0] is False:
if self.choose_fm2[0] is False:
if self.choose_lfo[0] == 0:
waveform = sine_wave(ramp_2_osc())
elif self.choose_lfo[0] == 1:
waveform = sine_wave(lfo_osc_wave(lfo))
elif self.choose_lfo[0] == 2:
waveform = sine_wave(lfo_osc_wave(lfo_pluss))
elif self.choose_lfo[0] == 3:
waveform = sine_wave(lfo_osc_wave(lfo_fold))
else:
waveform = sine_wave(lfo_osc_wave(sweep))
if self.choose_fm2[0] is True:
if self.choose_lfo[0] == 0:
waveform = np.sin(x * freq + ramp_2 * np.sin(
fm * x + ramp_3_fm2()))
elif self.choose_lfo[0] == 1:
waveform = np.sin(x * freq + lfo() * np.sin(
fm * x + ramp_3_fm2()))
elif self.choose_lfo[0] == 2:
waveform = np.sin(x * freq + lfo_pluss() * np.sin(
fm * x + ramp_3_fm2()))
elif self.choose_lfo[0] == 3:
waveform = np.sin(x * freq + lfo_fold() * np.sin(
fm * x + ramp_3_fm2()))
else:
waveform = np.sin(x * freq + sweep() * np.sin(
fm * x + ramp_3_fm2()))
if self.choose_noise[0] == 1:
waveform = waveform + noise(ramp_1)
if self.choose_noise[0] == 2:
waveform = waveform + noise(ramp_0)
if self.choose_noise[0] == 3:
waveform = waveform + noise((np.hanning(total_samples) * (15 + noise_shape)))
if self.choose_trem[0]:
waveform = waveform * tremelo()
if self.phlazing[0] is True:
waveform = ta.ThyPhlazer(waveform, new_samplerate[0], speed=self.phlaze_speed[0],
loops=self.phlaze_loops[0], depth=self.phlaze_depth[0]).phlaze()
if self.choose_fm2[0]:
waveform = (waveform / np.max(np.abs(waveform))) * attenuation * vol
else:
waveform = (waveform / np.max(np.abs(waveform))) * vol
waveform[:np.size(fade_in_ramp)] *= fade_in_ramp
waveform[- np.size(fade_ramp):] *= fade_ramp
if self.reverse_add[0] == 1:
waveform = np.concatenate((waveform, np.flip(waveform)))
if self.reverse_add[0] == 2:
waveform = np.flip(waveform)
# Split into stereo by delaying right speaker by roller variable amount.
waveform1 = np.roll(waveform, roller)
waveform1[:roller] = 0
waveform1[- 400:] *= np.linspace(1, 0, 400)
waveform_stereo = np.vstack((waveform, waveform1)).T
def stop():
global sound, sound_cache
sound = nothing
sound_cache = nothing
def apply_pressed():
global sound, waveform_stereo, sound_cache
sound = waveform_stereo
sound_cache = waveform_stereo
def add_pressed():
global waveform_stereo, sound_cache
sound_cache = waveform_stereo
def loop_pressed():
loop_flag[0] = not loop_flag[0]
if loop_flag[0] is True:
self.loop_button.setText("Looping")
else:
self.loop_button.setText("Loop")
def tremolo_pressed():
self.choose_trem[0] = next(tremolo_gen)
if self.choose_trem[0] == 1:
self.tremolo_sin[0] = True
self.trem_button.setText("Tremolo Sin")
elif self.choose_trem[0] == 0:
self.trem_button.setText("Tremolo Off")
else:
self.tremolo_sin[0] = False
self.trem_button.setText("Tremolo Cos")
def lfo_pressed():
self.choose_lfo[0] = next(lfo_gen)
if self.choose_lfo[0] == 0:
self.lfo_button.setText("Ramp")
elif self.choose_lfo[0] == 1:
self.lfo_button.setText("LFO")
elif self.choose_lfo[0] == 2:
self.lfo_button.setText("LFO Clip")
elif self.choose_lfo[0] == 3:
self.lfo_button.setText("LFO Fold")
else:
self.lfo_button.setText("Sweep")
def fm2_pressed():
self.choose_fm2[0] = not self.choose_fm2[0]
if self.choose_fm2[0] is True:
self.fm2_button.setText("FM2 On")
else:
self.fm2_button.setText("FM2 Off")
def noise_pressed():
self.choose_noise[0] = next(noise_gen)
if self.choose_noise[0] == 0:
self.noise_button.setText("Noise Off")
elif self.choose_noise[0] == 1:
self.noise_button.setText("Noise >")
elif self.choose_noise[0] == 2:
self.noise_button.setText("Noise <")
else:
self.noise_button.setText("Noise ^")
def wave_pressed():
self.choose_wave[0] = not self.choose_wave[0]
if self.choose_wave[0]:
self.wave_button.setText("Triangle")
else:
self.wave_button.setText("Sin")
def reverse_pressed():
self.reverse_add[0] = next(reverse_gen)
if self.reverse_add[0] == 1:
self.reverse_button.setText("And Reverse")
elif self.reverse_add[0] == 2:
self.reverse_button.setText("Reversed")
else:
self.reverse_button.setText("Not Reversed")
def changed_vol():
val = self.volume_slider.value() * 0.01
self.vol_val_label.setText(str("{:3.2f}".format(val)))
self.vol_val_label.adjustSize()
def changed_ramp():
val = self.ramp_slider.value() * 0.01
self.ramp_val_label.setText(str('{:3.2f}'.format(val)))
self.ramp_val_label.adjustSize()
def changed_duration():
val = self.duration_slider.value() * 0.1
self.duration_val_label.setText(str('{:2.1f}'.format(val)))
self.duration_val_label.adjustSize()
def changed_freq():
val = self.freq_slider.value() * 0.1
self.freq_val_label.setText(str('{:4.1f}'.format(val)))
self.freq_val_label.adjustSize()
def changed_fm1():
val = self.fm1_slider.value() * 0.1
self.fm1_val_label.setText(str('{:4.1f}'.format(val)))
self.fm1_val_label.adjustSize()
def changed_fm2():
val = self.fm2_slider.value() * 0.1
self.fm2_val_label.setText(str('{:4.1f}'.format(val)))
self.fm2_val_label.adjustSize()
def changed_lfo():
val = self.lfo_slider.value() * 0.01
self.lfo_val_label.setText(str('{:3.2f}'.format(val)))
self.lfo_val_label.adjustSize()
def changed_lfo_amp():
val = self.lfo_amp_slider.value() * 0.01
self.lfo_amp_val_label.setText(str('{:3.2f}'.format(val)))
self.lfo_amp_val_label.adjustSize()
def changed_fmt():
val = self.fmt_slider.value() * 0.01
self.fmt_val_label.setText(str('{:3.2f}'.format(val)))
self.fmt_val_label.adjustSize()
def changed_fade_in():
val = self.fade_in_slider.value() * 0.01
self.fade_in_val_label.setText(str('{:3.2f}'.format(val)))
self.fade_in_val_label.adjustSize()
def changed_tremolo():
val = self.tremolo_slider.value() * 0.01
self.tremolo_val_label.setText(str('{:4.2f}'.format(val)))
self.tremolo_val_label.adjustSize()
def changed_trem_amp():
val = self.trem_amp_slider.value() * 0.01
self.trem_amp_val_label.setText(str('{:4.2f}'.format(val)))
self.trem_amp_val_label.adjustSize()
def changed_noise():
val = self.noise_slider.value() * 0.1
self.noise_val_label.setText(str('{:3.1f}'.format(val)))
self.noise_val_label.adjustSize()
def changed_delay():
val = self.delay_slider.value()
self.delay_val_label.setText(str('{:4.3f}\nSeconds'.format(val / 48000)))
self.delay_val_label.adjustSize()
def changed_fade_out():
val = self.fade_out_slider.value() * 0.01
self.fade_out_val_label.setText(str('{:3.2f}'.format(val)))
self.fade_out_label.adjustSize()
def gen_3(start, max=3):
first_val = 0
n = start
while True:
yield n
n += 1
if n == max:
n = first_val
lfo_gen = gen_3(2, max=5)
noise_gen = gen_3(1, max=4)
tremolo_gen = gen_3(1, max=3)
reverse_gen = gen_3(1, max=3)
self.choose_lfo = [1]
self.choose_fm2 = [True]
self.choose_noise = [0]
self.choose_wave = [False]
self.choose_trem = [0]
self.clippings = [0.2, 1.0]
self.foldings = [0.0, 0.7]
self.reverse_add = [0]
self.phlazing = [False]
self.phlaze_speed = [0.1]
self.phlaze_loops = [2]
self.phlaze_depth = [100]
self.tremolo_sin = [True]
# play button
self.apply_button = QPushButton('Play', self)
self.apply_button.setStatusTip("Play built sound straight away")
self.apply_button.setGeometry(430, 10, 90, 70)
self.apply_button.setObjectName("blue_button")
self.apply_button.clicked.connect(apply_pressed)
self.shortcut_apply = QShortcut(QKeySequence('p'), self)
self.shortcut_apply.activated.connect(apply_pressed)
# build button
self.build_button = QPushButton("Build", self)
self.build_button.setStatusTip("Build sound ready to be played or added to loop")
self.build_button.setGeometry(430, 90, 90, 30)
self.build_button.clicked.connect(build)
self.shortcut_build = QShortcut(QKeySequence('b'), self)
self.shortcut_build.activated.connect(build)
# add button
self.add_button = QPushButton("Add", self)
self.add_button.setStatusTip("Add built sound to be played on next loop iteration")
self.add_button.setGeometry(525, 90, 40, 30)
self.add_button.clicked.connect(add_pressed)
self.shortcut_add = QShortcut(QKeySequence('a'), self)
self.shortcut_add.activated.connect(add_pressed)
# loop button
self.loop_button = QPushButton("Loop", self)
self.loop_button.setStatusTip("Repeats sound in a loop")
self.loop_button.setGeometry(430, 130, 90, 30)
self.loop_button.clicked.connect(loop_pressed)
self.shortcut_loop = QShortcut(QKeySequence('l'), self)
self.shortcut_loop.activated.connect(loop_pressed)
# stop button
self.stop_button = QPushButton("Stop", self)
self.stop_button.setGeometry(430, 170, 90, 30)
self.stop_button.clicked.connect(stop)
self.shortcut_stop = QShortcut(QKeySequence('s'), self)
self.shortcut_stop.activated.connect(stop)
# tremelo button
self.trem_button = QPushButton("Tremolo", self)
self.trem_button.setGeometry(430, 210, 90, 30)
self.trem_button.clicked.connect(tremolo_pressed)
self.shortcut_tremolo = QShortcut(QKeySequence('t'), self)
self.shortcut_tremolo.activated.connect(tremolo_pressed)
# FM2 button
self.fm2_button = QPushButton("FM2 On", self)
self.fm2_button.setStatusTip("Modulate the modulating frequency")
self.fm2_button.setGeometry(430, 250, 90, 30)
self.fm2_button.clicked.connect(fm2_pressed)
self.shortcut_fm2 = QShortcut(QKeySequence('f'), self)
self.shortcut_fm2.activated.connect(fm2_pressed)
# noise button
self.noise_button = QPushButton("Noise", self)
self.noise_button.setStatusTip("Noise fade out at start or fade in at the end")
self.noise_button.setGeometry(430, 290, 90, 30)
self.noise_button.clicked.connect(noise_pressed)
self.shortcut_noise = QShortcut(QKeySequence('n'), self)
self.shortcut_noise.activated.connect(noise_pressed)
# LFO button
self.lfo_button = QPushButton("LFO", self)
self.lfo_button.setStatusTip("Set LFO Clip Clipping values in dialogue from dropdown menu")
self.lfo_button.setGeometry(430, 330, 90, 30)
self.lfo_button.clicked.connect(lfo_pressed)
self.shortcut_lfo = QShortcut(QKeySequence('o'), self)
self.shortcut_lfo.activated.connect(lfo_pressed)
# wave button
self.wave_label = QLabel(self)
self.wave_label.setObjectName("wavetext")
self.wave_label.setText("Wave Shape")
self.wave_label.move(625, 38)
self.wave_button = QPushButton("Sin", self)
self.wave_button.setGeometry(730, 30, 110, 30)
self.wave_button.clicked.connect(wave_pressed)
self.shortcut_wave = QShortcut(QKeySequence('w'), self)
self.shortcut_wave.activated.connect(wave_pressed)
# volume
self.volume_label = QLabel(self)
self.volume_label.setText("Volume")
self.volume_label.move(20, 50)
set_vol = 70
self.volume_slider = QSlider(Qt.Horizontal, self)
self.volume_slider.setObjectName("fat_slider")
self.volume_slider.setMinimumWidth(250)
self.volume_slider.setMinimumHeight(20)
self.volume_slider.setMinimum(0)
self.volume_slider.setMaximum(100)
self.volume_slider.setSingleStep(1)
self.volume_slider.setValue(set_vol)
self.volume_slider.move(90, 50)
self.volume_slider.valueChanged.connect(changed_vol)
self.vol_val_label = QLabel(self)
self.vol_val_label.setText(str("{:3.2f}".format(set_vol * 0.01)))
self.vol_val_label.move(350, 50)
# freq
self.freq_label = QLabel(self)
self.freq_label.setText("Freq Hz")
self.freq_label.move(20, 110)
self.set_freq = 3600
self.freq_slider = QSlider(Qt.Horizontal, self)
self.freq_slider.setMinimumWidth(250)
self.freq_slider.setMinimum(100)
self.freq_slider.setMaximum(5100)
self.freq_slider.setSingleStep(1)
self.freq_slider.setValue(self.set_freq)
self.freq_slider.move(90, 110)
self.freq_slider.valueChanged.connect(changed_freq)
self.freq_val_label = QLabel(self)
self.freq_val_label.setText(str("{:4.1f}".format(self.set_freq * 0.1)))
self.freq_val_label.move(350, 110)
# fm1
self.fm1_label = QLabel(self)
self.fm1_label.setText("FM1 Hz")
self.fm1_label.move(20, 150)
self.set_fm1 = 600
self.fm1_slider = QSlider(Qt.Horizontal, self)
self.fm1_slider.setMinimumWidth(250)
self.fm1_slider.setMinimum(100)
self.fm1_slider.setMaximum(4000)
self.fm1_slider.setSingleStep(1)
self.fm1_slider.setValue(self.set_fm1)
self.fm1_slider.move(90, 150)
self.fm1_slider.valueChanged.connect(changed_fm1)
self.fm1_val_label = QLabel(self)
self.fm1_val_label.setText(str("{:4.1f}".format(self.set_fm1 * 0.1)))
self.fm1_val_label.move(350, 150)
# fm2
self.fm2_label = QLabel(self)
self.fm2_label.setText("FM2 Hz")
self.fm2_label.move(20, 190)
self.set_fm2 = 3023
self.fm2_slider = QSlider(Qt.Horizontal, self)
self.fm2_slider.setMinimumWidth(250)
self.fm2_slider.setMinimum(100)
self.fm2_slider.setMaximum(4000)
self.fm2_slider.setSingleStep(1)
self.fm2_slider.setValue(self.set_fm2)
self.fm2_slider.move(90, 190)
self.fm2_slider.valueChanged.connect(changed_fm2)
self.fm2_val_label = QLabel(self)
self.fm2_val_label.setText(str("{:4.1f}".format(self.set_fm2 * 0.1)))
self.fm2_val_label.move(350, 190)
# lfo speed
self.lfo_label = QLabel(self)
self.lfo_label.setText("LFO \nspeed")
self.lfo_label.move(20, 223)
self.set_lfo = 14
self.lfo_slider = QSlider(Qt.Horizontal, self)
self.lfo_slider.setMinimumWidth(250)
self.lfo_slider.setMinimum(5)
self.lfo_slider.setMaximum(500)
self.lfo_slider.setSingleStep(1)
self.lfo_slider.setValue(self.set_lfo)
self.lfo_slider.move(90, 230)
self.lfo_slider.valueChanged.connect(changed_lfo)
self.lfo_val_label = QLabel(self)
self.lfo_val_label.setText(str("{:3.2f}".format(self.set_lfo * 0.01)))
self.lfo_val_label.move(350, 230)
# lfo amp
self.lfo_amp_label = QLabel(self)
self.lfo_amp_label.setText("LFO Amp")
self.lfo_amp_label.move(20, 270)
self.set_lfo_amp = 180
self.lfo_amp_slider = QSlider(Qt.Horizontal, self)
self.lfo_amp_slider.setMinimumWidth(250)
self.lfo_amp_slider.setMinimum(10)
self.lfo_amp_slider.setMaximum(500)
self.lfo_amp_slider.setSingleStep(1)
self.lfo_amp_slider.setValue(self.set_lfo_amp)
self.lfo_amp_slider.move(90, 270)
self.lfo_amp_slider.valueChanged.connect(changed_lfo_amp)
self.lfo_amp_val_label = QLabel(self)
self.lfo_amp_val_label.setText(str("{:3.2f}".format(self.set_lfo_amp * 0.01)))
self.lfo_amp_val_label.move(350, 270)
# ramp_0
self.ramp_label = QLabel(self)
self.ramp_label.setText('Ramp')
self.ramp_label.move(20, 310)
self.set3 = 100
self.ramp_slider = QSlider(Qt.Horizontal, self)
self.ramp_slider.setMinimumWidth(250)
self.ramp_slider.setMinimum(10)
self.ramp_slider.setMaximum(800)
self.ramp_slider.setSingleStep(1)
self.ramp_slider.setValue(self.set3)
self.ramp_slider.move(90, 310)
self.ramp_slider.valueChanged.connect(changed_ramp)
self.ramp_val_label = QLabel(self)
self.ramp_val_label.setText(str('{:3.2f}'.format(self.set3 * 0.01)))
self.ramp_val_label.move(350, 310)
# fm2 time ratio
self.fmt_label = QLabel(self)
self.fmt_label.setText("FM2\nRamp Length")
self.fmt_label.move(20, 355)
self.set_fmt = 130
self.fmt_slider = QSlider(Qt.Horizontal, self)
self.fmt_slider.setMinimumWidth(250)
self.fmt_slider.setMinimum(130)
self.fmt_slider.setMaximum(1000)
self.fmt_slider.setSingleStep(1)
self.fmt_slider.setValue(self.set_fmt)
self.fmt_slider.move(90, 350)
self.fmt_slider.valueChanged.connect(changed_fmt)
self.fmt_val_label = QLabel(self)
self.fmt_val_label.setText(str("{:4.2f}".format(self.set_fmt * 0.01)))
self.fmt_val_label.move(350, 350)
# fade in
self.fade_in_label = QLabel(self)
self.fade_in_label.setText("Fade In")
self.fade_in_label.move(555, 166)
self.set_fade_in = 0
self.fade_in_slider = QSlider(Qt.Horizontal, self)
self.fade_in_slider.setMinimumWidth(200)
self.fade_in_slider.setMinimum(0)
self.fade_in_slider.setMaximum(50)
self.fade_in_slider.setSingleStep(1)
self.fade_in_slider.setValue(self.set_fade_in)
self.fade_in_slider.move(620, 170)
self.fade_in_slider.valueChanged.connect(changed_fade_in)
self.fade_in_val_label = QLabel(self)
self.fade_in_val_label.setText(str("{:3.2f}".format(self.set_fade_in * 0.01)))
self.fade_in_val_label.move(830, 170)
# tremelo speed
self.tremolo_label = QLabel(self)
self.tremolo_label.setText("Tremolo\nSpeed")
self.tremolo_label.move(555, 197)
self.set_tremolo = 600
self.tremolo_slider = QSlider(Qt.Horizontal, self)
self.tremolo_slider.setMinimumWidth(200)
self.tremolo_slider.setMinimum(50)
self.tremolo_slider.setMaximum(1500)
self.tremolo_slider.setSingleStep(1)
self.tremolo_slider.setValue(self.set_tremolo)
self.tremolo_slider.move(620, 210)
self.tremolo_slider.valueChanged.connect(changed_tremolo)
self.tremolo_val_label = QLabel(self)
self.tremolo_val_label.setText(str("{:4.2f}".format(self.set_tremolo * 0.01)))
self.tremolo_val_label.move(830, 210)
# tremolo amount
self.trem_amp_label = QLabel(self)
self.trem_amp_label.setText("Tremolo\n Amp")
self.trem_amp_label.move(555, 245)
self.set_trem_amp = 50
self.trem_amp_slider = QSlider(Qt.Horizontal, self)
self.trem_amp_slider.setMinimumWidth(200)
self.trem_amp_slider.setMinimum(0)
self.trem_amp_slider.setMaximum(100)
self.trem_amp_slider.setSingleStep(1)
self.trem_amp_slider.setValue(self.set_trem_amp)
self.trem_amp_slider.move(620, 250)
self.trem_amp_slider.valueChanged.connect(changed_trem_amp)
self.trem_amp_val_label = QLabel(self)
self.trem_amp_val_label.setText(str("{:4.2f}".format(self.set_trem_amp * 0.01)))
self.trem_amp_val_label.move(830, 250)
# noise shape
self.noise_label = QLabel(self)
self.noise_label.setText("Noise\nShape")
self.noise_label.move(555, 287)
self.set_noise = -20
self.noise_slider = QSlider(Qt.Horizontal, self)
self.noise_slider.setMinimumWidth(200)
self.noise_slider.setMinimum(-150)
self.noise_slider.setMaximum(0)
self.noise_slider.setSingleStep(1)
self.noise_slider.setValue(self.set_noise)
self.noise_slider.move(620, 290)
self.noise_slider.valueChanged.connect(changed_noise)
self.noise_val_label = QLabel(self)
self.noise_val_label.setText(str("{:3.1f}".format(self.set_noise * 0.1)))
self.noise_val_label.move(830, 290)
# delay
self.delay_label = QLabel(self)
self.delay_label.setText("Delay")
self.delay_label.move(555, 333)
self.set_delay = 4320
self.delay_slider = QSlider(Qt.Horizontal, self)
self.delay_slider.setMinimumWidth(200)
self.delay_slider.setMinimum(0)
self.delay_slider.setMaximum(6000)
self.delay_slider.setSingleStep(1)
self.delay_slider.setValue(self.set_delay)
self.delay_slider.move(620, 330)
self.delay_slider.valueChanged.connect(changed_delay)
self.delay_val_label = QLabel(self)
self.delay_val_label.setText(str("{:4.3f}\nSeconds".format(self.set_delay / 48000)))
self.delay_val_label.move(830, 323)
# fade out
self.fade_out_label = QLabel(self)
self.fade_out_label.setText("Fade\n Out")
self.fade_out_label.move(555, 365)
self.set_fade_out = 0
self.fade_out_slider = QSlider(Qt.Horizontal, self)
self.fade_out_slider.setMinimumWidth(200)
self.fade_out_slider.setMinimum(0)
self.fade_out_slider.setMaximum(50)
self.fade_out_slider.setSingleStep(1)
self.fade_out_slider.setValue(self.set_fade_out)
self.fade_out_slider.move(620, 370)
self.fade_out_slider.valueChanged.connect(changed_fade_out)
self.fade_out_val_label = QLabel(self)
self.fade_out_val_label.setText(str("{:3.2f}".format(self.set_fade_out * 0.01)))
self.fade_out_val_label.move(830, 370)
# duration
self.duration_label = QLabel(self)
self.duration_label.setText('Duration\nSeconds')
self.duration_label.move(20, 510)
self.set0 = 180
self.duration_slider = QSlider(Qt.Horizontal, self)
self.duration_slider.setObjectName("fat_slider")
self.duration_slider.setMinimumWidth(750)
self.duration_slider.setMinimumHeight(20)
self.duration_slider.setMinimum(1)
self.duration_slider.setMaximum(600)
self.duration_slider.setValue(self.set0)
self.duration_slider.setSingleStep(1)
self.duration_slider.move(90, 510)
self.duration_slider.valueChanged.connect(changed_duration)
self.duration_val_label = QLabel(self)
self.duration_val_label.setText(str(self.set0 * 0.1))
self.duration_val_label.move(860, 510)
self.reverse_button = QPushButton("Not Reversed", self)
self.reverse_button.setStatusTip(
"Add a fliped or reversed version of the sound to the end of each play or loop")
self.reverse_button.setGeometry(780, 550, 110, 30)
self.reverse_button.clicked.connect(reverse_pressed)
self.shortcut_apply = QShortcut(QKeySequence('r'), self)
self.shortcut_apply.activated.connect(reverse_pressed)
def open_output_dialog():
global output_dialog
if output_dialog is None or output_dialog.isVisible() is False:
output_dialog = o_dialog.OutputDialog(streaming, default_blocksize, new_blocksize,
output_device, stream_thread, stream_func, new_samplerate)
output_dialog.show()
else:
return
def open_clip_dialog():
global clipping_dialog
if clipping_dialog is None or clipping_dialog.isVisible() is False:
clipping_dialog = clip_dialog.ClipDialog(ex.widget.clippings, ex.widget.foldings,
ex.widget.phlazing, ex.widget.phlaze_speed,
ex.widget.phlaze_loops, ex.widget.phlaze_depth)
clipping_dialog.show()
else:
return
def open_save_presets():
global save_preset_window
if save_preset_window is None or save_preset_window.isVisible() is False:
settings_list = [
ex.widget.freq_slider.value(),
ex.widget.fm1_slider.value(),
ex.widget.fm2_slider.value(),
ex.widget.lfo_slider.value(),
ex.widget.duration_slider.value(),
ex.widget.lfo_amp_slider.value(),
ex.widget.ramp_slider.value(),
ex.widget.tremolo_slider.value(),
ex.widget.volume_slider.value(),
ex.widget.trem_amp_slider.value(),
ex.widget.fmt_slider.value(),
ex.widget.delay_slider.value(),
ex.widget.fade_out_slider.value(),
ex.widget.fade_in_slider.value(),
ex.widget.noise_slider.value(),
ex.widget.choose_lfo[0], # int
ex.widget.choose_fm2[0], # bool
ex.widget.choose_noise[0], # int
ex.widget.choose_wave[0], # bool
ex.widget.choose_trem[0], # bool
ex.widget.clippings[0],
ex.widget.clippings[1],
ex.widget.reverse_add[0],
ex.widget.foldings[0],
ex.widget.foldings[1],
ex.widget.phlazing[0],
ex.widget.phlaze_speed[0],
ex.widget.phlaze_loops[0], # int
ex.widget.phlaze_depth[0] # int
]
# print(f"settings_list {settings_list}")
save_preset_window = preset_dialog.PresetSaveDialog(settings_list)
save_preset_window.show()
else:
return
def open_recall_preset():
global recall_presets
if recall_presets is None or recall_presets.isVisible() is False:
recall_presets = preset_dialog.PresetRecallDialog(ex.widget)
recall_presets.show()
else:
return
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.exitAc = QAction(QIcon('exit.png'), '&Exit', self)
self.exitAc.setShortcut('Ctrl+Q')
self.exitAc.setStatusTip('Exit Application')
self.exitAc.triggered.connect(qApp.quit)
self.op_dialog_ac = QAction("Set Output Device, Blocksize and Samplerate", self)
self.op_dialog_ac.setShortcut('Ctrl+o')
self.op_dialog_ac.setStatusTip("Select output device and set a blocksize or select a new samplerate for output stream")
self.op_dialog_ac.triggered.connect(open_output_dialog)
self.clip_dialog_ac = QAction("Set LFO Clipping or Folding Values and Phlaze", self)
self.clip_dialog_ac.setShortcut('Ctrl+d')
self.clip_dialog_ac.setStatusTip("Set LFO sin wave clipping or Folding low and high values. activate Phlazing")
self.clip_dialog_ac.triggered.connect(open_clip_dialog)
self.save_preset_ac = QAction("Save As Presets", self)
self.save_preset_ac.setShortcut('Ctrl+s')
self.save_preset_ac.setStatusTip("Open dialogue to save settings as presets")
self.save_preset_ac.triggered.connect(open_save_presets)
self.recall_presets_ac = QAction("Recall Presets")
self.recall_presets_ac.setShortcut('Ctrl+r')
self.recall_presets_ac.setStatusTip("Open dialogue to recall setting presets from a file")
self.recall_presets_ac.triggered.connect(open_recall_preset)
self.status_bar = self.statusBar()
self.status_bar.setObjectName("status_bar_obj")
self.menubar = self.menuBar()
self.settingsMenu = self.menubar.addMenu('Settings, Exit')
self.settingsMenu.addAction(self.exitAc)
self.settingsMenu.addAction(self.op_dialog_ac)
self.settingsMenu.addAction(self.clip_dialog_ac)
self.settingsMenu.addAction(self.save_preset_ac)
self.settingsMenu.addAction(self.recall_presets_ac)
self.menubar.setObjectName("menubar_obj")
self.setWindowTitle("The Audio FM Mummer")
self.setWindowIcon(QIcon('images/scope-icon.jpg'))
self.setGeometry(20, 100, 930, 640)
self.widget = SliderFrame()
self.setCentralWidget(self.widget)
self.show()
def stream_func(device=-1, blocksize=256, rate=48000):
def callback(outdata, frames, time, status):
try:
data = next(sound_slice)
outdata[:, :] = data
except ValueError:
outdata[:, :] = np.zeros((blocksize, 2))
def gen():
global sound, sound_cache
sound = np.zeros((blocksize, 2))
while True:
slice = sound[:blocksize, :]
yield slice
sound = sound[blocksize:, :]
if loop_flag[0] is True and np.size(sound) < (1024):
sound = np.vstack((sound, sound_cache))
sound_slice = gen()
try:
device = device if device >= 0 else None
except TypeError:
device = None
print(f"Samplerate: {rate}")
stream = sd.OutputStream(device=device,
channels=2, callback=callback, blocksize=blocksize, samplerate=rate)
with stream:
# stopping stream, dont forget assign streaming bool add args to thread
while streaming[0] is True:
time.sleep(0.5)
else:
stream.__exit__()
#tremolo_sin = [True]
loop_flag = [False]
streaming = [True]
nothing = np.zeros((2048, 2))
sound_cache = np.zeros((2048, 2))
waveform_stereo = np.zeros((2048, 2))
output_device = [-1]
output_dialog = None
clipping_dialog = None
save_preset_window = None
recall_presets = None
sample_rate = 48000
new_samplerate = [48000]
blocksize = 256
default_blocksize = 256
new_blocksize = [default_blocksize]
stream_thread = threading.Thread(target=stream_func, args=[-1, default_blocksize], daemon=True)
stream_thread.start()
app = QApplication(sys.argv)
with open("styles.css", 'r') as f:
styles = f.read()
app.setStyleSheet(styles)
ex = MainWindow()
sys.exit(app.exec_())