class ToneGenerator(QWidget): def __init__(self, parent=None): QWidget.__init__(self, parent) format = QAudioFormat() format.setChannelCount(AUDIO_CHANS) format.setSampleRate(SAMPLE_RATE) format.setSampleSize(SAMPLE_SIZE) format.setCodec("audio/pcm") format.setByteOrder(QAudioFormat.LittleEndian) format.setSampleType(QAudioFormat.SignedInt) self.output = QAudioOutput(format, self) output_buffer_size = \ int(2*SAMPLE_RATE \ *CTRL_INTERVAL/1000) self.output.setBufferSize(output_buffer_size) self.generator = Meep(format, self) self.generator.start() self.output.start(self.generator) # Create the port reader object self.midiListener = MidiPortReader() # Create a thread which will read it self.listenerThread = QThread() # Take the object and move it # to the new thread (it isn't running yet) self.midiListener.moveToThread(self.listenerThread) self.midiListener.newNoteFrequency.connect(self.generator.changeFreq) # Tell Qt the function to call # when it starts the thread self.listenerThread.started.connect(self.midiListener.listener) # Fingers in ears, eyes tight shut... self.listenerThread.start()
class ToneGenerator(QWidget): def __init__(self, parent=None): QWidget.__init__(self, parent) format = QAudioFormat() format.setChannelCount(AUDIO_CHANS) format.setSampleRate(SAMPLE_RATE) format.setSampleSize(SAMPLE_SIZE) format.setCodec("audio/pcm") format.setByteOrder(QAudioFormat.LittleEndian) format.setSampleType(QAudioFormat.SignedInt) self.output = QAudioOutput(format, self) output_buffer_size = \ int(2*SAMPLE_RATE \ *CTRL_INTERVAL/1000) self.output.setBufferSize(output_buffer_size) self.generator = Meep(format, self) self.generator.start() self.output.start(self.generator)
class MainWindow(QWidget): def __init__(self, parent=None): QWidget.__init__(self, parent) format = QAudioFormat() format.setChannelCount(AUDIO_CHANS) format.setSampleRate(SAMPLE_RATE) format.setSampleSize(SAMPLE_SIZE) format.setCodec("audio/pcm") format.setByteOrder(QAudioFormat.LittleEndian) format.setSampleType(QAudioFormat.SignedInt) self.output = QAudioOutput(format, self) output_buffer_size = \ int(2*CTRL_INTERVAL/1000) self.output.setBufferSize(output_buffer_size) self.generator = Generator(format, self) self.midiListener = MidiPortReader() self.listenerThread = QThread() self.midiListener.moveToThread(self.listenerThread) self.listenerThread.started.connect(self.midiListener.listener) self.midiListener.addVoice.connect(self.generator.addVoice) self.midiListener.removeVoice.connect(self.generator.removeVoice) self.createUI() self.pslider.valueChanged.connect(self.generator.changeP) self.fslider.valueChanged.connect(self.generator.qCalc) self.semiDown.clicked.connect(self.smDown) self.semiUp.clicked.connect(self.smUp) self.octaveDown.clicked.connect(self.ovDown) self.octaveUp.clicked.connect(self.ovUp) self.listenerThread.start() self.generator.start() self.output.start(self.generator) def createUI(self): label = QLabel() label.setText("Pulse ammount") self.pslider = QSlider(Qt.Horizontal) self.pslider.setMinimum(0) self.pslider.setMaximum(100) self.pslider.setValue(60) flabel = QLabel() flabel.setText("Q") self.fslider = QSlider(Qt.Horizontal) self.fslider.setMinimum(10) self.fslider.setMaximum(10000) self.fslider.setValue(1000) self.octaveUp = QPushButton("+12") self.octaveDown = QPushButton("-12") self.semiUp = QPushButton("+1") self.semiDown = QPushButton("-1") self.transLabel = QLabel(str(self.generator.transpose)) vl = QVBoxLayout(self) hl = QHBoxLayout() hl.addWidget(label) hl.addStretch(1) hl.addWidget(self.pslider) vl.addLayout(hl) fhl = QHBoxLayout() fhl.addWidget(flabel) fhl.addStretch(1) fhl.addWidget(self.fslider) vl.addLayout(fhl) bhl = QHBoxLayout() bhl.addWidget(self.octaveDown) bhl.addWidget(self.semiDown) bhl.addWidget(self.transLabel) bhl.addWidget(self.semiUp) bhl.addWidget(self.octaveUp) vl.addLayout(bhl) def transposeChange(self, amt): self.generator.transpose = self.generator.transpose + amt self.transLabel.setText(str(self.generator.transpose)) @pyqtSlot() def ovUp(self): self.transposeChange(12) @pyqtSlot() def ovDown(self): self.transposeChange(-12) @pyqtSlot() def smUp(self): self.transposeChange(1) @pyqtSlot() def smDown(self): self.transposeChange(-1)
class Window(QWidget): volSlide=pyqtSignal(int) def __init__(self,parent=None): #UI QWidget.__init__(self,parent) self.create_UI(parent) #audio formatting format=QAudioFormat() format.setChannelCount(AUDIO_CHANS) format.setSampleRate(SAMPLE_RATE) format.setSampleSize(SAMPLE_SIZE) format.setCodec("audio/pcm") format.setByteOrder( QAudioFormat.LittleEndian ) format.setSampleType( QAudioFormat.SignedInt ) self.output=QAudioOutput(format,self) output_buffer_size=\ int(2*SAMPLE_RATE \ *CTRL_INTERVAL/1000) self.output.setBufferSize( output_buffer_size ) self.generator=Generator(format,self) #THREADS self.midiListener=MidiPortReader() self.listenerThread=QThread() self.midiListener.moveToThread( self.listenerThread ) self.listenerThread.started.connect( self.midiListener.listener ) self.listenerThread.start() self.midiListener.noteOff.connect(self.generator.noteOff) self.midiListener.noteVelocity.connect(self.generator.noteVelocity) self.midiListener.noteOn.connect(self.generator.noteOn) self.volumeSlider.valueChanged.connect(self.generator.volSlide) self.qfacSlider.valueChanged.connect(self.generator.qFactor) self.generator.start() self.output.start(self.generator) def create_UI(self,parent): rockLabel=QLabel() rockLabel.setText("Let's ROCK!!!") volLabel=QLabel() volLabel.setText("Volume") self.volumeSlider=QSlider(Qt.Horizontal) self.volumeSlider.setMinimum(0) self.volumeSlider.setMaximum(100) qfacLabel=QLabel() qfacLabel.setText("Q-Factor") self.qfacSlider=QSlider(Qt.Horizontal) self.qfacSlider.setMinimum(0) self.qfacSlider.setMaximum(1000) self.qfacSlider.setValue(5000) self.quitButton=\ QPushButton(self.tr('&Quit')) self.volSlide.emit(7) self.lynch=QLabel() self.halfDown=QPushButton("+1") self.halfUp=QPushButton("-1") pixmap=QPixmap() pixmap.load('lynch2.jpeg') pixmap=pixmap.scaledToWidth(200) self.lynch.setPixmap(pixmap) vLayout=QVBoxLayout(self) h0Layout=QHBoxLayout() h0Layout.addWidget(rockLabel) h0Layout.addStretch(1) h0Layout.addWidget(self.lynch) vLayout.addLayout(h0Layout) hLayout=QHBoxLayout() hLayout.addWidget(volLabel) hLayout.addStretch(1) hLayout.addWidget(self.volumeSlider) vLayout.addLayout(hLayout) h2Layout=QHBoxLayout() h2Layout.addWidget(qfacLabel) h2Layout.addStretch(1) h2Layout.addWidget(self.qfacSlider) vLayout.addLayout(h2Layout) self.quitButton.clicked.connect( self.quitClicked ) @pyqtSlot() def quitClicked(self): self.close()
class ToneGenerator(QWidget): def __init__(self, parent=None): QWidget.__init__(self, parent) super().__init__(parent) # start new thread that constantly polls MIDI input self.create_MIDI() # create GUI (windows, slider, etc...) self.create_UI(parent) format = QAudioFormat() self.create_AUDIO(format) self.generator = Flute(format, self) self.generator.start() self.output.start(self.generator) def create_AUDIO(self, format): format.setChannelCount(AUDIO_CHANS) format.setSampleRate(SAMPLE_RATE) format.setSampleSize(SAMPLE_SIZE) format.setCodec("audio/pcm") format.setByteOrder( QAudioFormat.LittleEndian ) format.setSampleType( QAudioFormat.SignedInt ) self.output = QAudioOutput(format, self) output_buffer_size = \ int(2*SAMPLE_RATE \ *CTRL_INTERVAL/1000) self.output.setBufferSize( output_buffer_size ) def create_MIDI(self): # Create the port reader object self.midiListener = MidiPortReader() # Create a thread which will read it self.listenerThread = QThread() # Take the object and move it # to the new thread (it isn't running yet) self.midiListener.moveToThread(self.listenerThread) # Tell Qt the function to call # when it starts the thread self.listenerThread.started.connect(self.midiListener.listener) # connect pyqtSignals to slots in ToneGenerator self.midiListener.newNoteFrequency.connect(self.on_newNoteFrequency) self.midiListener.newNoteVelocity.connect(self.on_newNoteVelocity) self.midiListener.portClosed.connect(self.on_portClosed) # Fingers in ears, eyes tight shut... self.listenerThread.start() # Good grief, IT WORKS! def create_UI(self, parent): # Create a slider to fine tune freq and two buttons #self.octaveBox = QSlider(Qt.Horizontal) #self.octaveBox.setMinimum(-100) #self.octaveBox.setMaximum(100) self.octaveBox = QSpinBox() self.octaveBox.setRange(-5,5) self.octaveLabel = QLabel("Octave: ") self.quitButton = QPushButton(self.tr('&Quit')) # create dropdown menu so user can choose midi device in use (populate list from data from midi listener object) self.MIDIMenu = QComboBox() self.MIDIMenu.addItems(self.midiListener.getMIDIDevices()) # create ADSR sliders self.aSlider = QSlider(Qt.Vertical) self.aSlider.setMinimum(1) self.aSlider.setMaximum(50) self.aSlider.setSliderPosition(1) self.dSlider = QSlider(Qt.Vertical) self.dSlider.setMinimum(1) self.dSlider.setMaximum(50) self.dSlider.setSliderPosition(8) self.sSlider = QSlider(Qt.Vertical) self.sSlider.setMinimum(1) self.sSlider.setMaximum(100) self.sSlider.setSliderPosition(80) self.rSlider = QSlider(Qt.Vertical) self.rSlider.setMinimum(1) self.rSlider.setMaximum(100) self.rSlider.setSliderPosition(50) # No parent: we're going to add this # to vLayout. hLayout1 = QHBoxLayout() hLayout1.addWidget(self.octaveLabel) hLayout1.addWidget(self.octaveBox) hLayout2 = QHBoxLayout() hLayout2.addWidget(self.aSlider) hLayout2.addWidget(self.dSlider) hLayout2.addWidget(self.sSlider) hLayout2.addWidget(self.rSlider) hLayout3 = QHBoxLayout() hLayout3.addWidget(self.MIDIMenu) hLayout3.addWidget(self.quitButton) # parent = self: this is the # "top level" layout vLayout = QVBoxLayout(self) vLayout.addLayout(hLayout1) vLayout.addLayout(hLayout2) vLayout.addLayout(hLayout3) # connect qt object signals to slots self.quitButton.clicked.connect(self.quitClicked) self.octaveBox.valueChanged.connect(self.changeOctave) self.aSlider.valueChanged.connect(self.changeADSRParam) self.dSlider.valueChanged.connect(self.changeADSRParam) self.sSlider.valueChanged.connect(self.changeADSRParam) self.rSlider.valueChanged.connect(self.changeADSRParam) self.MIDIMenu.currentIndexChanged[str].connect(self.changeMIDIDevice) # this isn't a @pyqtSlot(), the text is passed directly to the function def changeMIDIDevice(self, dev): self.midiListener.setMIDIDevice(dev) @pyqtSlot() def quitClicked(self): self.close() @pyqtSlot() def changeOctave(self): #scale slider value to freq and pass to subclass to update filter self.generator.setOctave(self.octaveBox.value()) @pyqtSlot(float) def on_newNoteFrequency(self, freq): # change value of filter cutoff so it sounds like we're playing a different note self.generator.updateFilter(freq) @pyqtSlot(int) def on_newNoteVelocity(self, value): # note_off message doesn't work with shit USB keyboards, so we simulate a note_off message with the velocity if value != 0: self.generator.playNote() else: self.generator.stopNote() @pyqtSlot() def on_portClosed(self): # when port has closed, clear drop down menu and rescan for MIDI devices self.MIDIMenu.clear() self.MIDIMenu.addItems(self.midiListener.getMIDIDevices()) @pyqtSlot() def changeADSRParam(self): self.generator.updateADSR(self.aSlider.value()/10, self.dSlider.value()/10, self.sSlider.value()/100, self.rSlider.value()/10)
class ToneWindow(QWidget): """ Central Widget of the application. Defines the format of the audio channel and initializes the midi listener, generators and modifiers. The midi listener is operated on separate thread handled by a Qthread. The view components are initialized and put together in a general layout using the CreateUI method. """ def __init__(self, parent=None): print("Tone Widget inst") QWidget.__init__(self, parent) self.activeGen = ActiveGen(sampleRate=SAMPLE_RATE, samplePerRead=Meep.SAMPLES_PER_READ) self.createUI(self) # Meep playback format initialization format = QAudioFormat() format.setChannelCount(AUDIO_CHANS) format.setSampleRate(SAMPLE_RATE) format.setSampleSize(SAMPLE_SIZE) format.setCodec("audio/pcm") format.setByteOrder(QAudioFormat.LittleEndian) format.setSampleType(QAudioFormat.SignedInt) # check compatibility of format with device info = QAudioDeviceInfo(QAudioDeviceInfo.defaultOutputDevice()) if info.isFormatSupported(format) is False: print( "Raw audio format not supported by backend, cannot play audio." ) return None # Audio Output init self.output = QAudioOutput(format, self) output_buffer_size = \ int(2*SAMPLE_RATE \ *CTRL_INTERVAL/1000) self.output.setBufferSize(output_buffer_size) # initialize and start the audio playback self.generator = Meep(format, self.activeGen, self) self.generator.start() self.output.start(self.generator) # Create the port reader object self.midiListener = MidiPortReader() # Create a thread which will read it self.listenerThread = QThread() # move QObjet to a new thread self.midiListener.moveToThread(self.listenerThread) # Connect the signals to slot functions self.midiListener.newNoteFrequency.connect(self.activeGen.setFreq) self.midiListener.newNotePress.connect(self.activeGen.setNote) # Tell Qt the function to call # when it starts the thread self.listenerThread.started.connect(self.midiListener.listener) # start the thread self.listenerThread.start() def createUI(self, parent): """Receives a parent QWidget and produces the view in it""" print("Create UI") slidLayout = QHBoxLayout() vLayout = QVBoxLayout(self) vLayout.setSpacing(10) # initialize title label and UI constraints self.title = QLabel(self) self.title.setText("Tone Generator") self.title.setMargin(10) self.title.setFixedHeight(50) self.title.setFixedWidth(400) self.title.setAlignment(Qt.AlignCenter) # set title style self.title.setStyleSheet(""" font-family : "Lucida Console"; font-size: 20px; color : #F2F2F2; border: 2px solid green; border-radius: 4px; border-color: #082126; padding: 2px; background-color : #0E3740 ; """) # set background color self.setStyleSheet(" background-color : #082126 ; ") # initialize the view components filtSlider = sliders.FiltSlider(self.activeGen, parent).createUI(parent) adsrSlider = sliders.ADSRSlider(self.activeGen, parent).createUI(parent) masterSlider = sliders.MasterSlider(self.activeGen, parent).createUI(parent) genSlider = sliders.GenSlider(self.activeGen, parent).createUI(parent) # add the two sliders and ADSR layout in a horizontal layout slidLayout.addStretch(1) slidLayout.addWidget(filtSlider) slidLayout.addStretch(1) slidLayout.addWidget(adsrSlider, Qt.AlignHCenter) slidLayout.addStretch(1) slidLayout.addWidget(masterSlider) slidLayout.addStretch(1) # put all components in the vertical layout vLayout.addWidget(self.title) vLayout.setAlignment(self.title, Qt.AlignCenter) vLayout.addSpacing(20) vLayout.addLayout(slidLayout) vLayout.addSpacing(20) vLayout.addWidget(genSlider) vLayout.setAlignment(genSlider, Qt.AlignCenter)