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()
Exemple #5
0
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)