Необходимо сделать режим записи, при котором в текстовом поле добавляются ноты по нажатию на кнопки синтезатора
нужна помощь! Необходимо сделать режим записи, при котором в текстовом поле добавляются ноты по нажатию на кнопки синтезатора. Заранее благодарю за помощь.
Файл main.py
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QFileDialog, QGridLayout
from PyQt5.QtCore import QUrl
from PyQt5 import QtMultimedia as M
from mainwindow import Ui_MainWindow
from synt import *
class MyWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self):
super(MyWindow, self).__init__()
self.setupUi(self)
self.url = None
self.player = M.QMediaPlayer()
self.player.setVolume(70)
synthesizer = Synthesizer()
self.window = MyWidget(synthesizer=synthesizer)
grid = QGridLayout(self.centralwidget)
grid.addWidget(self.pushButton_3, 0, 0)
grid.addWidget(self.pushButton, 0, 1)
grid.addWidget(self.pushButton_2, 0, 2)
grid.addWidget(self.pushButton_4, 0, 4)
grid.addWidget(self.pushButton_5, 0, 5)
grid.addWidget(self.label, 1, 0, 1, 3)
grid.setRowStretch(2, 2)
grid.addWidget(self.window, 5, 0, 1, 5)
grid.setRowStretch(5, 1)
def closeEvent(self, event):
reply = QMessageBox.question(self,
'Message',
"Are you sure to quit?",
QMessageBox.Yes, QMessageBox.No)
if reply == QMessageBox.Yes:
if self.window.synthesizer is not None:
self.window.synthesizer.terminate()
event.accept()
else:
event.ignore()
def play(self):
if self.url:
self.player.play()
def generate(self):
self.window.synthesizer.play(self.sound_edit.text())
def save(self):
options = QFileDialog.Options()
options |= QFileDialog.DontUseNativeDialog
fileName, _ = QFileDialog.getSaveFileName(self,"QFileDialog.getSaveFileName()","","All Files (*);;Wav Files (*.wav)", options=options)
if fileName:
self.window.synthesizer.save(fileName)
def pause(self):
if self.url:
self.player.pause()
def choose(self):
self.url, _ = QFileDialog.getOpenFileName(
None, 'OpenFile', './', 'Music (*.mp3 *.wav)'
)
if not self.url:
self.label.setText('')
return
self.url = QUrl.fromLocalFile(self.url)#QUrl(self.url)
self.content = M.QMediaContent(self.url)
self.player.setMedia(self.content)
self.label.setText(self.url.toString().split('/')[-1])
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
Файл mainwindow.py
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(90, 40, 75, 23))
self.pushButton.setObjectName("pushButton")
self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_2.setGeometry(QtCore.QRect(170, 40, 75, 23))
self.pushButton_2.setObjectName("pushButton_2")
self.pushButton_3 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_3.setGeometry(QtCore.QRect(10, 40, 75, 23))
self.pushButton_3.setObjectName("pushButton_3")
self.pushButton_4 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_4.setGeometry(QtCore.QRect(10, 40, 75, 23))
self.pushButton_4.setObjectName("pushButton_4")
self.pushButton_5 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_5.setGeometry(QtCore.QRect(10, 40, 75, 23))
self.pushButton_5.setObjectName("pushButton_5")
self.sound_edit = QtWidgets.QLineEdit(self.centralwidget)
self.sound_edit.setGeometry(QtCore.QRect(10, 90, 375, 23))
self.sound_edit.setObjectName("sound_edit")
self.sound_edit.setText('E4_5 G3_5 B5_5 A4_5 D#3_5 G4_5 B5_5 C5_5 D4_5')
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(20, 80, 221, 21))
self.label.setText("")
self.label.setObjectName("label")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 20))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton.setText(_translate("MainWindow", "play sound"))
self.pushButton_2.setText(_translate("MainWindow", "pause"))
self.pushButton_3.setText(_translate("MainWindow", "Open File"))
self.pushButton_4.setText(_translate("MainWindow", "Save File"))
self.pushButton_5.setText(_translate("MainWindow", "play melody"))
self.pushButton.clicked.connect(self.play)
self.pushButton_2.clicked.connect(self.pause)
self.pushButton_3.clicked.connect(self.choose)
self.pushButton_4.clicked.connect(self.save)
self.pushButton_5.clicked.connect(self.generate)
Файл synt.py
import sys
import pyaudio
import numpy as np
import threading
import wave
from PyQt5.QtCore import QEventLoop, QTimer
from scipy import signal
from PyQt5.QtWidgets import QApplication, QPushButton, QWidget, QHBoxLayout, \
QVBoxLayout, QGridLayout, QMessageBox
from PyQt5.QtGui import QKeySequence
from functools import partial
class Oscillator:
def __init__(self, rate, n_chunk, freq, otype, gain=0.1):
self.rate = rate
self.n_chunk = n_chunk
self.freq = freq
self.gain = gain
self.state = False
self.pi2_t0 = 2 * np.pi / (rate / freq)
self.offset = 0
self.period = n_chunk * rate
self.change_waveform(otype)
def out(self):
x = np.arange(self.offset, self.offset + self.n_chunk)
chunk = self.gain * self.generator(self.pi2_t0 * x)
self.offset += self.n_chunk
if self.offset == self.period:
self.offset = 0
return chunk
def is_run(self):
return self.state
def start(self):
self.state = True
def stop(self):
self.state = False
self.offset = 0
def change_waveform(self, type):
self.type = type
if self.type == "sin":
self.generator = np.sin
elif self.type == "saw":
self.generator = signal.sawtooth
class Synthesizer:
waveform = ["sin", "saw"]
def __init__(self, rate=44100, n_chunk=1024):
self.rate = rate
self.n_chunk = n_chunk
self.p = pyaudio.PyAudio()
self.stream = self.p.open(format=pyaudio.paFloat32, channels=1, rate=rate, output=1,
frames_per_buffer=n_chunk)
self.oscillators = []
self.frames = []
self.type = Synthesizer.waveform[0]
t = threading.Thread(target=self.render)
t.start()
def __seek_osc(self, freq):
osc = None
for o in self.oscillators:
if freq == o.freq:
osc = o
if osc is None:
osc = Oscillator(self.rate, self.n_chunk, freq, self.type)
self.oscillators.append(osc)
return osc
def render(self):
while self.stream.is_active():
chunk = np.zeros(self.n_chunk)
for osc in self.oscillators:
if osc.is_run():
chunk += osc.out()
self.frames.append(chunk.astype(np.float32).tostring())
self.stream.write(chunk.astype(np.float32).tostring())
def play(self, text: str):
for s in text.split(' '):
l = 5
ss = s.split('_')
if len(ss) > 1:
l = int(ss[1])
freq = MyWidget.pitch_freq_di[ss[0]]
self.request(freq)
loop = QEventLoop()
QTimer.singleShot(l*100, loop.quit)
loop.exec_()
self.request(freq)
def save(self, filename):
wf = wave.open(filename, 'wb')
wf.setnchannels(1)
wf.setsampwidth(self.p.get_sample_size(pyaudio.paFloat32))
wf.setframerate(self.rate)
wf.writeframes(b''.join(self.frames))
wf.close()
self.frames = []
def request(self, freq):
osc = self.__seek_osc(freq)
if not osc.is_run():
osc.start()
return True
else:
osc.stop()
return False
def terminate(self):
for osc in self.oscillators:
osc.stop()
self.stream.close()
self.p.terminate()
def change_waveform(self):
r = np.random.randint(len(Synthesizer.waveform))
self.type = Synthesizer.waveform[r]
for osc in self.oscillators:
osc.change_waveform(self.type)
return self.type
class MyWidget(QWidget):
pitch_class = ["A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#"]
pitch_freq_di = {pn + str(k): 440 * 2 ** (((12 * k + idx) - 48) / 12)
for idx, pn in enumerate(pitch_class) \
for k in range(0, 9)}
def __init__(self, synthesizer=None, keyset=(39, 52, 51, 64)):
super().__init__()
self.synthesizer = synthesizer
self.keyset = keyset
self.keymap = {
"Q": "C4", "2": "C#4", "W": "D4", "3": "D#4", "E": "E4",
"R": "F4", "5": "F#4", "T": "G4", "6": "G#4",
"Y": "A5", "7": "A#5", "U": "B5", "I": "C5",
"Z": "C3", "S": "C#3", "X": "D3", "D": "D#3", "C": "E3",
"V": "F3", "G": "F#3", "B": "G3", "H": "G#3",
"N": "A4", "J": "A#4", "M": "B4", ",": "C4",
}
self.params_list = []
print("# ================================")
print("# Initialize")
print("# ================================")
self.init_ui()
print("")
print("# ================================")
print("# <<Print key input>>")
print("# ================================")
self.show()
def __make_bt(self, id, name):
bt = QPushButton(name)
if "#" in name:
bt.key_off = lambda: bt.setStyleSheet("background-color: #999999")
bt.key_on = lambda: bt.setStyleSheet("background-color: #9999ff")
else:
bt.key_off = lambda: bt.setStyleSheet("background-color: #ffffff")
bt.key_on = lambda: bt.setStyleSheet("background-color: #9999ff")
bt.key_off()
bt.setContentsMargins(0, 0, 0, 0)
freq = MyWidget.pitch_freq_di[name]
params = {"freq": freq, "name": name, "id": id, "self_bt": bt}
bt.clicked.connect(partial(self.buttonClicked, params["freq"], [bt]))
bt.setMaximumWidth(40)
bt.setMaximumHeight(300)
print(f"{id}\t{name}\t{freq}")
self.params_list.append(params)
return bt
def init_ui(self):
self.setStyleSheet("background-color: #eeeeee")
self.setWindowTitle('Synthesizer')
keys = QGridLayout()
id = 0
for n in range(self.keyset[0], self.keyset[1]):
name = MyWidget.pitch_class[n % 12] + str(n // 12)
pos = n - self.keyset[0]
keys.addWidget(self.__make_bt(id, name), 1, pos)
id += 1
for n in range(self.keyset[2], self.keyset[3]):
name = MyWidget.pitch_class[n % 12] + str(n // 12)
pos = n - self.keyset[2]
keys.addWidget(self.__make_bt(id, name), 0, pos)
id += 1
self.setLayout(keys)
self.setGeometry(300, 300, 660, 160)
def buttonClicked(self, freq, bt_list):
sender = self.sender()
if self.synthesizer is not None:
state = self.synthesizer.request(freq)
if state:
for bt in bt_list:
bt.key_on()
else:
for bt in bt_list:
bt.key_off()
def closeEvent(self, event):
reply = QMessageBox.question(self,
'Message',
"Are you sure to quit?",
QMessageBox.Yes, QMessageBox.No)
if reply == QMessageBox.Yes:
if self.synthesizer is not None:
self.synthesizer.terminate()
event.accept()
else:
event.ignore()
def keyPressEvent(self, event):
key = QKeySequence(event.key()).toString()
bt_list = []
freq = 0.0
name = None
if key in self.keymap.keys():
v = self.keymap[key]
for p in self.params_list:
if p["name"] == v:
name = p["name"]
freq = p["freq"]
bt_list.append(p["self_bt"])
self.buttonClicked(freq, bt_list)
print(f"{key}: {name}")
elif key == "@":
type = self.synthesizer.change_waveform()
if __name__ == '__main__':
synthesizer = Synthesizer()
app = QApplication(sys.argv)
window = MyWidget(synthesizer=synthesizer)
sys.exit(app.exec_())
Ответы (1 шт):
Автор решения: S. Nick
→ Ссылка
Обратите внимание я заменил QLineEdit на QTextEdit, просто мне кажется, так будет лучше.
Я не проверял работу других методов не связанных с кнопками синтезатора.
Я поправил фокусировку, теперь вы можете не пользоваться мышкой, а стучать по кнопкам вашей клавиатуры.
main.py
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QFileDialog, QGridLayout
from PyQt5.QtCore import QUrl
from PyQt5 import QtMultimedia as M
from synt import *
#from mainwindow import Ui_MainWindow
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(90, 40, 75, 23))
self.pushButton.setObjectName("pushButton")
self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_2.setGeometry(QtCore.QRect(170, 40, 75, 23))
self.pushButton_2.setObjectName("pushButton_2")
self.pushButton_3 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_3.setGeometry(QtCore.QRect(10, 40, 75, 23))
self.pushButton_3.setObjectName("pushButton_3")
self.pushButton_4 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_4.setGeometry(QtCore.QRect(10, 40, 75, 23))
self.pushButton_4.setObjectName("pushButton_4")
self.pushButton_5 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_5.setGeometry(QtCore.QRect(10, 40, 75, 23))
self.pushButton_5.setObjectName("pushButton_5")
# self.sound_edit = QtWidgets.QLineEdit(self.centralwidget)
self.sound_edit = QtWidgets.QTextEdit(self.centralwidget) # QTextEdit
# self.sound_edit.setGeometry(QtCore.QRect(10, 90, 375, 23))
self.sound_edit.setGeometry(QtCore.QRect(10, 90, 375, 50))
self.sound_edit.setObjectName("sound_edit")
# self.sound_edit.setText('E4_5 G3_5 B5_5 A4_5 D#3_5 G4_5 B5_5 C5_5 D4_5') # -
self.sound_edit.setText('') # +
self.sound_edit.setReadOnly(True) # +
self.sound_edit.setStyleSheet("font-size: 15px;") # +
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(20, 80, 221, 21))
self.label.setText("")
self.label.setObjectName("label")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 20))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton.setText(_translate("MainWindow", "play sound"))
self.pushButton_2.setText(_translate("MainWindow", "pause"))
self.pushButton_3.setText(_translate("MainWindow", "Open File"))
self.pushButton_4.setText(_translate("MainWindow", "Save File"))
self.pushButton_5.setText(_translate("MainWindow", "play melody"))
self.pushButton.clicked.connect(self.play)
self.pushButton_2.clicked.connect(self.pause)
self.pushButton_3.clicked.connect(self.choose)
self.pushButton_4.clicked.connect(self.save)
self.pushButton_5.clicked.connect(self.generate)
class MyWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self):
super(MyWindow, self).__init__()
self.setupUi(self)
self.url = None
self.player = M.QMediaPlayer()
self.player.setVolume(70)
synthesizer = Synthesizer()
self.window = MyWidget(synthesizer=synthesizer, parent=self) # + , parent=self
grid = QGridLayout(self.centralwidget)
grid.addWidget(self.pushButton_3, 0, 0)
grid.addWidget(self.pushButton, 0, 1)
grid.addWidget(self.pushButton_2, 0, 2)
grid.addWidget(self.pushButton_4, 0, 4)
grid.addWidget(self.pushButton_5, 0, 5)
grid.addWidget(self.label, 1, 0, 1, 3)
grid.setRowStretch(2, 2)
grid.addWidget(self.window, 5, 0, 1, 5)
grid.setRowStretch(5, 1)
self.window.setFocus() # +++
def closeEvent(self, event):
reply = QMessageBox.question(self,
'Message',
"Are you sure to quit?",
QMessageBox.Yes, QMessageBox.No)
if reply == QMessageBox.Yes:
if self.window.synthesizer is not None:
self.window.synthesizer.terminate()
event.accept()
else:
event.ignore()
self.window.setFocus() #+++
def play(self):
if self.url:
self.player.play()
self.window.setFocus() #+++
def generate(self):
# self.window.synthesizer.play(self.sound_edit.text())
self.window.synthesizer.play(self.sound_edit.toPlainText()) # toPlainText()
self.window.setFocus() #+++
def save(self):
options = QFileDialog.Options()
options |= QFileDialog.DontUseNativeDialog
fileName, _ = QFileDialog.getSaveFileName(
self, "QFileDialog.getSaveFileName()", "",
"All Files (*);;Wav Files (*.wav)", options=options
)
if fileName:
self.window.synthesizer.save(fileName)
self.window.setFocus() #+++
def pause(self):
if self.url:
self.player.pause()
self.window.setFocus() #+++
def choose(self):
self.url, _ = QFileDialog.getOpenFileName(
None, 'OpenFile', './', 'Music (*.mp3 *.wav)'
)
self.window.setFocus() #+++
if not self.url:
self.label.setText('')
return
self.url = QUrl.fromLocalFile(self.url)#QUrl(self.url)
self.content = M.QMediaContent(self.url)
self.player.setMedia(self.content)
self.label.setText(self.url.toString().split('/')[-1])
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
synt.py
import sys
import pyaudio
import numpy as np
import threading
import wave
from PyQt5.QtCore import QEventLoop, QTimer
from scipy import signal
from PyQt5.QtWidgets import QApplication, QPushButton, QWidget, QHBoxLayout, \
QVBoxLayout, QGridLayout, QMessageBox
from PyQt5.QtGui import QKeySequence
from functools import partial
class Oscillator:
def __init__(self, rate, n_chunk, freq, otype, gain=0.1):
self.rate = rate
self.n_chunk = n_chunk
self.freq = freq
self.gain = gain
self.state = False
self.pi2_t0 = 2 * np.pi / (rate / freq)
self.offset = 0
self.period = n_chunk * rate
self.change_waveform(otype)
def out(self):
x = np.arange(self.offset, self.offset + self.n_chunk)
chunk = self.gain * self.generator(self.pi2_t0 * x)
self.offset += self.n_chunk
if self.offset == self.period:
self.offset = 0
return chunk
def is_run(self):
return self.state
def start(self):
self.state = True
def stop(self):
self.state = False
self.offset = 0
def change_waveform(self, type):
self.type = type
if self.type == "sin":
self.generator = np.sin
elif self.type == "saw":
self.generator = signal.sawtooth
class Synthesizer:
waveform = ["sin", "saw"]
def __init__(self, rate=44100, n_chunk=1024):
self.rate = rate
self.n_chunk = n_chunk
self.p = pyaudio.PyAudio()
self.stream = self.p.open(format=pyaudio.paFloat32, channels=1, rate=rate, output=1,
frames_per_buffer=n_chunk)
self.oscillators = []
self.frames = []
self.type = Synthesizer.waveform[0]
t = threading.Thread(target=self.render)
t.start()
def __seek_osc(self, freq):
osc = None
for o in self.oscillators:
if freq == o.freq:
osc = o
if osc is None:
osc = Oscillator(self.rate, self.n_chunk, freq, self.type)
self.oscillators.append(osc)
return osc
def render(self):
while self.stream.is_active():
chunk = np.zeros(self.n_chunk)
for osc in self.oscillators:
if osc.is_run():
chunk += osc.out()
self.frames.append(chunk.astype(np.float32).tostring())
self.stream.write(chunk.astype(np.float32).tostring())
def play(self, text: str):
for s in text.split(' '):
l = 5
ss = s.split('_')
if len(ss) > 1:
l = int(ss[1])
freq = MyWidget.pitch_freq_di[ss[0]]
self.request(freq)
loop = QEventLoop()
QTimer.singleShot(l*100, loop.quit)
loop.exec_()
self.request(freq)
def save(self, filename):
wf = wave.open(filename, 'wb')
wf.setnchannels(1)
wf.setsampwidth(self.p.get_sample_size(pyaudio.paFloat32))
wf.setframerate(self.rate)
wf.writeframes(b''.join(self.frames))
wf.close()
self.frames = []
def request(self, freq):
osc = self.__seek_osc(freq)
if not osc.is_run():
osc.start()
return True
else:
osc.stop()
return False
def terminate(self):
for osc in self.oscillators:
osc.stop()
self.stream.close()
self.p.terminate()
def change_waveform(self):
r = np.random.randint(len(Synthesizer.waveform))
self.type = Synthesizer.waveform[r]
for osc in self.oscillators:
osc.change_waveform(self.type)
return self.type
class MyWidget(QWidget):
pitch_class = ["A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#"]
pitch_freq_di = {pn + str(k): 440 * 2 ** (((12 * k + idx) - 48) / 12)
for idx, pn in enumerate(pitch_class) \
for k in range(0, 9)}
def __init__(self, synthesizer=None, keyset=(39, 52, 51, 64), parent=None): # + parent
super().__init__()
self.parent = parent # + parent
self.synthesizer = synthesizer
self.keyset = keyset
self.keymap = {
"Q": "C4", "2": "C#4", "W": "D4", "3": "D#4", "E": "E4",
"R": "F4", "5": "F#4", "T": "G4", "6": "G#4",
"Y": "A5", "7": "A#5", "U": "B5", "I": "C5",
"Z": "C3", "S": "C#3", "X": "D3", "D": "D#3", "C": "E3",
"V": "F3", "G": "F#3", "B": "G3", "H": "G#3",
"N": "A4", "J": "A#4", "M": "B4", ",": "C4",
}
self.params_list = []
print("# ================================")
print("# Initialize")
print("# ================================")
self.init_ui()
print("")
print("# ================================")
print("# <<Print key input>>")
print("# ================================")
self.show()
def __make_bt(self, id, name):
bt = QPushButton(name)
if "#" in name:
bt.key_off = lambda: bt.setStyleSheet("background-color: #999999")
bt.key_on = lambda: bt.setStyleSheet("background-color: #9999ff")
else:
bt.key_off = lambda: bt.setStyleSheet("background-color: #ffffff")
bt.key_on = lambda: bt.setStyleSheet("background-color: #9999ff")
bt.key_off()
bt.setContentsMargins(0, 0, 0, 0)
freq = MyWidget.pitch_freq_di[name]
params = {"freq": freq, "name": name, "id": id, "self_bt": bt}
bt.clicked.connect(partial(self.buttonClicked, params["freq"], [bt]))
bt.setMaximumWidth(40)
bt.setMaximumHeight(300)
print(f"{id}\t{name}\t{freq}")
self.params_list.append(params)
return bt
def init_ui(self):
self.setStyleSheet("background-color: #eeeeee")
self.setWindowTitle('Synthesizer')
keys = QGridLayout()
id = 0
for n in range(self.keyset[0], self.keyset[1]):
name = MyWidget.pitch_class[n % 12] + str(n // 12)
pos = n - self.keyset[0]
keys.addWidget(self.__make_bt(id, name), 1, pos)
id += 1
for n in range(self.keyset[2], self.keyset[3]):
name = MyWidget.pitch_class[n % 12] + str(n // 12)
pos = n - self.keyset[2]
keys.addWidget(self.__make_bt(id, name), 0, pos)
id += 1
self.setLayout(keys)
self.setGeometry(300, 300, 660, 160)
# !!!
def buttonClicked(self, freq, bt_list):
sender = self.sender()
if self.synthesizer is not None:
state = self.synthesizer.request(freq)
if state:
for bt in bt_list:
bt.key_on()
self.parent.sound_edit.setPlainText( # +++
self.parent.sound_edit.toPlainText() + f'{bt.text()}_5 ') # +++
else:
for bt in bt_list:
bt.key_off()
self.parent.sound_edit.setPlainText( # +++
self.parent.sound_edit.toPlainText().replace(f'{bt.text()}_5 ', '')) # +++
def closeEvent(self, event):
reply = QMessageBox.question(
self,
'Message',
"Are you sure to quit?",
QMessageBox.Yes, QMessageBox.No
)
if reply == QMessageBox.Yes:
if self.synthesizer is not None:
self.synthesizer.terminate()
event.accept()
else:
event.ignore()
def keyPressEvent(self, event):
key = QKeySequence(event.key()).toString()
bt_list = []
freq = 0.0
name = None
if key in self.keymap.keys():
v = self.keymap[key]
for p in self.params_list:
if p["name"] == v:
name = p["name"]
freq = p["freq"]
bt_list.append(p["self_bt"])
self.buttonClicked(freq, bt_list)
# print(f"{key}: {name}")
elif key == "@":
type = self.synthesizer.change_waveform()
if __name__ == '__main__':
synthesizer = Synthesizer()
app = QApplication(sys.argv)
window = MyWidget(synthesizer=synthesizer)
sys.exit(app.exec_())
