コード例 #1
0
    def __init__(self, globalRoot, app):

        self.globalRoot = globalRoot
        self.audioInstance = Autoload().getInstanceAudio()
        self.app = app

        self.nbOfLoops = 2
        self.backtrack = None

        self.window = tk.Toplevel(self.globalRoot)
        self.window.config(cursor="none")
        self.window.attributes('-fullscreen', True)
        self.window.geometry("320x480")
        self.window["bg"] = "black"

        self.currentTrack = self.audioInstance.getCurrentTrack()
        trackName = self.currentTrack[0].split("/")[-1]
        trackLength = "{0:.2f}".format(self.currentTrack[1])

        self.window.lblStatic1 = MyLabel24(self.window, text="How many bars?")
        self.window.btnWithBacktrack = BtnBlack12(self.window, text="OK")
        self.window.btnWithBacktrack.config(command=self.nextWindow)
        self.window.nbOfLoops = MyLabel40(self.window, text=self.nbOfLoops)
        self.window.btnLess = BtnBlack12(self.window,
                                         text="<",
                                         command=self.lessLoops)
        self.window.btnMore = BtnBlack12(self.window,
                                         text=">",
                                         command=self.moreLoops)
        # self.window.lblBacktrack = MyLabel12(self.window, text="length one loop {} sec.".format(str(round(self.currentTrack[1],2))))
        self.window.lblBacktrack = MyLabel12(self.window, text="")
        self.window.btnWithoutBacktrack = BtnBlack12(self.window,
                                                     text="Cancel",
                                                     command=self.cancel)
        self.window.lblStatic2 = MyLabel12(
            self.window,
            wraplength=320,
            text="current backtrack:\n{}\n({} ms)".format(
                trackName, trackLength))

        # PLACEMENT
        yplacement = 40
        self.window.lblStatic1.place(x=0, y=yplacement, width=320, height=50)
        yplacement += 60
        self.window.btnLess.place(x=0, y=yplacement, width=80, height=60)
        self.window.nbOfLoops.place(x=40, y=yplacement, width=240, height=60)
        self.window.btnMore.place(x=240, y=yplacement, width=80, height=60)
        yplacement += 80
        self.window.lblStatic2.place(x=0, y=yplacement, width=320, height=80)
        yplacement += 100
        # self.window.lblBacktrack.place(x=20,y=yplacement, width=280, height=60)
        self.window.btnWithBacktrack.place(x=40,
                                           y=yplacement,
                                           width=240,
                                           height=60)
        yplacement += 80
        self.window.btnWithoutBacktrack.place(x=40,
                                              y=yplacement,
                                              width=240,
                                              height=60)
コード例 #2
0
    def __init__(self, parent, config):
        self.questionArray = []
        self.config = config
        self.delay = float(self.config["question_delay"]) / 100
        self.parent = parent
        self.isListening = False

        # variable for user score
        self.counter = 0
        self.score = 0
        self.globalIsListening = True

        debug = True
        self.stopGame = False
        self.waitingNotes = []

        self.midiIO = Autoload().getInstance()  # open connections and ports
        self.midiIO.setCallback(self.handleMIDIInput)

        # gamestate is used to know when the user is guessing
        self.gameState = "notStarted"

        # startGame
        self.startGame()
        self.startingNote = -1

        self.parent.btnSkip.configure(command=self.skip)

        self.melodies = Melody(self)
コード例 #3
0
    def __init__(self, bpm, backtrack, backtrackDuration, nbOfLoops, callback):
        self.sound = Autoload().getInstanceAudio()
        self.sound.loadTick()
        self.backtrack = backtrack
        self.backtrackDuration = backtrackDuration
        self.nbOfLoops = nbOfLoops
        # self.saved_volume = pygame.mixer.music.get_volume()
        # print(self.saved_volume)
        # pygame.mixer.music.set_volume(1)

        self.bpm = bpm
        self.count = 4
        self.delayBetweenBeats = 60 / float(self.bpm)
        print("delay between notes", self.delayBetweenBeats)
        self.callback = callback

        self.t1 = Timer(self.delayBetweenBeats, lambda: self.playFirstTick())
        self.t2 = Timer(2 * self.delayBetweenBeats, lambda: self.playTick())
        self.t3 = Timer(3 * self.delayBetweenBeats, lambda: self.playTick())
        self.t4 = Timer(4 * self.delayBetweenBeats,
                        lambda: self.playLastTick())

        self.t1.start()
        self.t2.start()
        self.t3.start()
        self.t4.start()
コード例 #4
0
    def __init__(self, parent, config):
        self.config = config
        self.parent = parent
        # print("config mode 0 ",config)
        self.delay = float(config["question_delay"]) / 100
        self.isListening = False

        # variable for user score
        self.counter = 0
        self.score = 0
        self.globalIsListening = True

        debug = True
        self.stopGame = False
        self.waitingNotes = []
        self.initMIDIArray(128)

        self.midiIO = Autoload().getInstance()
        self.midiIO.setCallback(self.handleMIDIInput)

        # gamestate is used to know when the user is guessing
        self.gameState = "notStarted"

        # startGame
        self.startGame()
        self.startingNote = -1

        self.changeAllBg("black")
        self.parent.btnSkip.configure(command=self.skip)

        self.maxInterval = 12
コード例 #5
0
    def __init__(self, globalRoot, root, config, app):
        # images
        self.playImage = ImageTk.PhotoImage(Image.open(env.PLAY_IMAGE))
        self.pauseImage = ImageTk.PhotoImage(Image.open(env.PAUSE_IMAGE))
        self.shuffleImage = ImageTk.PhotoImage(Image.open(env.SHUFFLE_IMAGE))

        self.midiIO = Autoload().getInstance()
        self.midiIO.setCallback(self.handleMIDIInput)

        self.isPlaying = False
        self.config = config
        self.globalRoot = globalRoot
        self.root = root
        self.app = app

        # Default path
        self.midiRepository = env.MIDI_FOLDER

        # Callbacks for buttons
        # self.root.btnRecord.config(command=self.showWithOrWithoutBacktrackWindow)
        self.root.btnPractiseLick.config(image=self.playImage, command=self.playOneLick)
        self.root.btnRandomLick.config(image=self.shuffleImage, command=self.pickRandomLick)
        self.root.btnDeleteSelected.config(command=self.deleteLick)
        self.root.btnPrev.config(command=self.previousLick)
        self.root.btnNext.config(command=self.nextLick)

        self.midiFiles = []
        self.reloadMidiFiles()
        self.fileIndex = 0
        self.recordNotes = None

        self.midiIO = Autoload().getInstance()
        self.audioInstance = Autoload().getInstanceAudio()
        # self.midiIO.setCallback(self.handleMIDIInput)

        self.bassNote = 0
        self.chordQuality = "-"
        self.transpose = 0
        self.activeCustomSignals = []
        self.lickRepetitionCounter = 1
        self.lickMaxRepetition = self.config["times_each_transpose"]
        self.playOnlyChord = False

        self.currentLickIndex = 0
        self.currentLick = None

        self.practiseAllLicks = False
        self.lastTranspose = 0
        self.futureTranspose = 0

        self.playBacktrackThread = None
        self.audioThread = None

        self.bass = None
        self.mType = None
        self.notes = None
        self.backtrackVolume = None

        self.loadASample(len(self.midiFiles) - 1)
コード例 #6
0
    def __init__(
        self, globalRoot, parent, config, app,
    ):
        self.currentTrack = None
        self.tracksWav = None

        # images
        self.playImage = ImageTk.PhotoImage(Image.open(env.PLAY_IMAGE))
        self.pauseImage = ImageTk.PhotoImage(Image.open(env.PAUSE_IMAGE))
        self.shuffleImage = ImageTk.PhotoImage(Image.open(env.SHUFFLE_IMAGE))
        self.page=0

        self.midiIO = Autoload().getInstance()
        self.midiIO.setCallback(self.handleMIDIInput)
        self.globalRoot = globalRoot
        self.app = app
        self.config = config
        metroBpmFile = open(env.CONFIG_METRO_BPM, 'r')
        self.metroBpm=int(metroBpmFile.read())
        self.isPlayingMetro=False

        self.parent = parent
        self.sound = Autoload().getInstanceAudio()

        # CLICK LISTENERS
        self.parent.btnPlay.config(command=self.toggleBacktrack)
        self.parent.btnMetro.config(command=self.playMetro)
        self.parent.btnBpmMinus.config(command=self.decreaseMetroTempo)
        self.parent.btnBpmPlus.config(command=self.increaseMetroTempo)
        self.parent.btnRandom.config(command=self.playRandom)
        self.parent.btnSwitchPage.config(command=self.switchPage)

        for i in range(0,len(self.parent.wav_buttons)):
            button=self.parent.wav_buttons[i]
            # we must extract the part with number of tracks to only keep the category
            button_text=button['text'].split('\n')[0]
            button.config(command=lambda button_text=button_text:self.pickRandomSampleInCategory(button_text))

        # this is a list which regroups all 4 folders (house , jazz ,latin, hiphop)
        self.tracksWav = self.sound.tracksWav

        self.parent.btnLick.config(
            command=self.showWithOrWithoutBacktrackWindow)
        self.parent.btnRandom.config(text="", image=self.shuffleImage)

        # recording variables

        self.recordingBassLick = False
        self.recordingNotes = False

        self.recordingCustomChords = False
        self.recordedNotes = []
        self.recordedCustomChords = []

        self.damper = []
        self.damperActive = False
コード例 #7
0
    def __init__(self, parent, config):
        # get audio instance to be sure the audio is loaded
        self.audio = Autoload().getInstanceAudio()
        self.midiIO = Autoload().getInstance()

        self.config = config
        self.parent = parent
        self.parent.btnConfig.config(command=self.openMidiPanel)

        self.loadInitialSettings()
        self.parent.btnSaveDefault.config(command=self.saveConfig)
コード例 #8
0
    def new_window(self, intMode):
        self.audioInstance = Autoload().getInstanceAudio()  # in order to create the first instance of audio file
        try:
            self.master.body.destroy()
            del self.app
        except:
            print("no window to destroy, recreation ...", intMode)
        print("Creating new window")
        # recreation of the body frame (middle frame)
        self.master.body = tk.Frame(self.master, bg="green")
        self.master.body.place(x=0, y=60, width=320, height=340)

        try:
            del self.app
            print("Should be empty  : ", self.app)
        except:
            pass

        if intMode == 0:
            self.app = Mode0(self.master.body, self.config)
            # specific to mode0 bc in order to skip all midi notes during another mode
            self.app.activateListening()
        elif intMode == 1:
            self.app = Mode1(self.master.body, self.config)
            self.app.activateListening()
        elif intMode == 2:
            self.app = Mode2(self.master, self.master.body, self.config, self)
        elif intMode == 3:
            self.app = Mode3(self.master, self.master.body, self.config, self)
        elif intMode == 4:
            self.app = ModeOptions(self.master.body, self.config,  self)
        else:
            return

        self.highLightActiveMode(intMode)
コード例 #9
0
    def handleMIDIInput(self, msg):
        # used for the midiListening button
        if Autoload().getInstance(
        ).isListening == False:  # check if user has midi  listen
            return
        if self.globalIsListening == False:
            return
        # Needed because we still receive signals even if the class is destroyed
        if self.isListening == False:
            print("[--] Ignoring queue message...", msg, self.isListening)
            return

        print("[-]receiving something", msg, self.isListening)
        if msg.type == "note_on" and msg.velocity > 10:
            # we test according to the gamestate

            if self.gameState == "waitingUserInput":
                self.changeGameState("listen")
                self.startingNote = msg.note
                # pick a random note
                questionNote = self.pickNewNote(self.startingNote)
                self.questionNote = QuestionNote(questionNote, self,
                                                 self.delay)
                # show the note on the ui
                self.lblUserShow = noteNameFull(self.startingNote) + "-> "
                self.parent.lblNote.config(text=self.lblUserShow)

            elif self.gameState == "waitingUserAnswer":
                if msg.note == self.startingNote:
                    # we want to ignore the starting note for the user.
                    return
                self.checkAnswer(msg.note)  # we check the answer
コード例 #10
0
    def handleMIDIInput(self, msg):
        if Autoload().getInstance().isListening == False:
            return
        if self.globalIsListening == False:
            return
        # Needed because we still receive signals even if the class is destroyed
        if self.isListening == False:
            print("[--] Ignoring queue message...", msg, self.isListening)
            return

        print("[-]receiving something", msg, self.isListening)
        if msg.type == "note_on" and msg.velocity > 10:
            # we test according to the gamestate

            if self.gameState == "waitingUserInput":
                self.isListening = False  # we will reactivate listening after all notes have been played
                self.startingNote = msg.note
                self.parent.lblNote["bg"] = "black"
                self.parent.lblNote.config(font=("Courier", 30, "bold"))
                self.parent.lblNote["text"] = noteNameFull(self.startingNote)
                # pick a random chord intervals
                self.question = self.pickNewChord(self.startingNote)
                self.questionArray = self.question[1]

                self.drawAndPlayAnswer()

                self.allIsCorrect = True  # var to know if we make a mistake in the answrs
                self.isFirstTry = True
                self.counter = self.counter + 1
                self.answerChord = []  # we initialize an answer chord
                self.answerBools = []
                # we initialize some vars and clear the canvas
                self.answerIndex = 0
                self.canvasCounter = 0

            elif self.gameState == "waitingUserAnswer":
                correctNote = self.questionArray[
                    self.answerIndex] + self.startingNote
                self.checkAnswer(msg.note, correctNote)
                self.answerIndex = self.answerIndex + 1
コード例 #11
0
 def test_getTracksWavIsAList(self):
     self.tracks = Autoload().getTracksWav()
     self.assertIsInstance(self.tracks, list)
コード例 #12
0
 def test_getActiveSampleIndexIsAnInt(self):
     self.activeSampleIndex = Autoload().getActiveSampleIndex()
     self.assertIsInstance(self.activeSampleIndex, int)
コード例 #13
0
 def test_getActiveSampleIsNotAnEmptyString(self):
     self.activeSample = Autoload().getActiveSample()
     self.assertIsInstance(self.activeSample, str)
     self.assertNotEqual(self.activeSample, "")
コード例 #14
0
 def test_getAudioInstanceReturnASound(self):
     self.instance = Autoload().getInstanceAudio()
     self.assertIsInstance(self.instance, Audio)
コード例 #15
0
 def test_creationOfAudioInstanceIsNotNote(self):
     self.assertIsNone(self.autoload)
     self.autoload = Autoload().getInstanceAudio()
     self.assertIsNotNone(self.autoload)
コード例 #16
0
 def changeVolume(self, offset ):
     actualVol = Audio.getVolume()
     if actualVol + offset <= 0.01:
         Autoload().getInstanceAudio().setVolume(0)
     else:
         Autoload().getInstanceAudio().setVolume(actualVol+offset)
コード例 #17
0
class RecordNotesGui:
    def __init__(self, globalRoot, choosenBpm, bassNote, chordQuality,
                 backtrack, backtrackDuration, nbOfLoops, chordNotes, app):
        # images
        self.recImage = ImageTk.PhotoImage(Image.open(env.RECORD_IMAGE))

        self.app = app
        self.globalRoot = globalRoot
        self.midiIO = Autoload().getInstance()
        self.midiIO.setCallback(self.handleMIDIInput)
        self.audioInstance = Autoload().getInstanceAudio()
        self.backtrack = backtrack
        self.backtrackDuration = backtrackDuration
        self.nbOfLoops = nbOfLoops
        self.choosenBpm = choosenBpm
        self.chordQuality = chordQuality
        self.bassNote = bassNote
        self.window = tk.Toplevel(self.globalRoot, cursor="none")
        self.window.attributes("-fullscreen", True)
        self.window.geometry("320x480")
        self.window["bg"] = "black"
        print("backtrack gui:", self.backtrack)
        self.chordNotes = chordNotes
        self.melodyNotes = []
        self.customSignals = []

        self.window.lbl1 = MyLabel12(self.window,
                                     text="Please record now...",
                                     wraplength=280)
        self.stringNotes = ""
        self.window.lbl2 = MyLabel40(self.window,
                                     text="{} {}".format(
                                         noteName(self.bassNote),
                                         self.chordQuality))
        self.window.lbl3 = MyLabel24(self.window,
                                     text="Notes : " + self.stringNotes,
                                     wraplength=280)
        self.window.lblRec = MyLabel18(self.window, text="")

        # Buttons
        self.window.btnCancel = BtnBlack12(self.window,
                                           text="Cancel",
                                           command=self.cancel)
        self.window.btnRetry = BtnBlack12(self.window,
                                          text="Retry",
                                          command=self.retry)
        self.window.btnSave = BtnBlack12(self.window,
                                         text="Save",
                                         command=lambda: self.saveMidi())
        # self.window.btnSave.config(state="disabled")

        self.window.canvas = tk.Canvas(self.window, bd=0, highlightthickness=0)

        self.window.lbl1.place(x=0, y=40, width=320, height=80)
        self.window.lbl2.place(x=0, y=120, width=320, height=60)
        self.window.lbl3.place(x=0, y=180, width=320, height=60)
        self.window.lblRec.place(x=20, y=250, width=280, height=40)
        self.window.btnCancel.place(x=20, y=310, width=100, height=130)
        self.window.btnRetry.place(x=120, y=310, width=80, height=130)
        self.window.btnSave.place(x=200, y=310, width=100, height=130)

        self.window.canvas.place(x=20, y=290, width=280, height=10)

        self.isRecording = False
        self.precountTimer = Bpm(self.choosenBpm, self.backtrack,
                                 self.backtrackDuration, self.nbOfLoops,
                                 lambda: self.activateRecording())
        self.startingTime = 0

        self.damper = []
        self.damperIsActive = False

    def cancel(self):
        self.window.destroy()
        self.thread.isAlive = False
        self.isRecording = False
        pygame.mixer.music.stop()
        self.app.new_window(2)
        del self

    def reset(self):
        self.cancelThreads()
        self.melodyNotes = []
        self.customSignals = []
        self.window.lbl1.config(text="Record Melody after the ticks")
        self.stringNotes = ""
        self.window.lblRec.config(image="")
        self.isRecording = False
        self.precountTimer = Bpm(self.choosenBpm, self.backtrack,
                                 self.backtrackDuration, self.nbOfLoops,
                                 lambda: self.activateRecording())
        self.startingTime = 0

    def retry(self):
        self.reset()
        self.window.canvas.delete("all")
        self.window.canvas.place_forget()
        self.window.canvas = tk.Canvas(self.window, bd=0, highlightthickness=0)
        self.window.canvas.place(x=20, y=290, width=280, height=10)

    def saveMidi(self):
        # self.parent.createJson(self.bassNote, self.chordQuality, self.backtrack, self.backtrackDuration,self.nbOfLoops)
        self.cancelThreads()
        self.saveLickAsJsonFile()
        # self.cancelRecorgindThreads()
        self.window.destroy()
        self.app.new_window(3)  # recreation of window 3
        self.isRecording = False
        self.cancelThreads()
        del self

    def cancelThreads(self):
        self.precountTimer.cancel()
        try:
            self.thread.isAlive = False
        except Exception as e:
            print(e)
        for signal in self.customSignals:
            signal.cancel()
        self.customSignals = []
        pygame.mixer.music.stop()
        # self.saveMidi()

    def saveLickAsJsonFile(self):
        volume = pygame.mixer.music.get_volume()
        obj = {
            "bass": self.bassNote,
            "type": self.chordQuality,
            "backtrack": self.backtrack,
            "backtrackDuration": self.backtrackDuration,
            "nbOfLoops": self.nbOfLoops,
            "chord_notes": self.chordNotes,
            "notes": self.melodyNotes,
            "volumeBacktrack": volume,
            "additional_latency": 0,  # Maybe it will be userful later
        }
        # creation d'un objet json
        json_object = json.dumps(obj, indent=4)
        # sauvegarde json dans un objet
        # TODO : Make try excerpt
        now_string = str(int(round(time.time()) * 1000))
        outfile = os.path.join(env.MIDI_FOLDER, now_string + ".json")
        # TODO : increase counter if file exists
        print("saving : ", outfile, "data :", json_object)
        with open(outfile, "w+") as outfile:
            outfile.write(json_object)
        # print("file saved") # TODO : maku user info for this
        self.recordedNotes = []
        self.startingTime = 0
        self.recordingNotes = False
        self.recordingBassLick = False
        # self.reloadMidiFiles()
        # self.currentLickIndex=len(self.midiFiles)-1
        # self.currentLick=self.midiFiles[self.currentLickIndex]
        # self.loadSelectedItem(self.currentLick)
        # self.recordNotes.destroy() # close windwo
        # self.currentLickIndex=len(self.midiFiles)-1
        # self.currentLick = self.midiFiles[self.currentLickIndex]
        # self.loadSelectedItem(self.currentLick)

    def activateRecording(self):
        # pass
        self.startingTime = int(round(time.time() * 1000))
        # self.playChord(self.bassNote, self.chordQuality) # in order to play the chord when the user recc
        for note in self.chordNotes:
            self.customSignals.append(
                CustomSignal(self, note["type"], note["note"],
                             note["velocity"], note["time"]))
        self.isRecording = True
        self.window.lblRec.config(image=self.recImage)
        self.thread = MyThread("thread-canvas", self.window.canvas,
                               self.audioInstance,
                               self.backtrackDuration * self.nbOfLoops, self)
        self.thread.start()
        # self.parent.recordingNotes = True

    def endRecording(self):
        # self.parent.recordingNotes=False
        self.window.lblRec.config(image="")
        self.window.lbl1.config(
            text="Click 'Save' to save the lick in the library.")
        self.window.canvas.delete("all")
        # self.window.btnSave.config(state="normal")
        self.window.canvas.place_forget()

    def destroy(self):
        self.window.destroy()

    def getTimeFromStart(self):
        return int(round(time.time() * 1000)) - self.startingTime

    def destroy(self):
        print("destroying last record windows")
        self.thread.isAlive = False
        for timer in self.customSignals:
            try:
                timer.cancel()
            except Exception as e:
                print(e)

        del self.thread

    def handleMIDIInput(self, msg):
        if self.isRecording == True:
            # if self.startingTime == 0: # it means it is the first played note
            # self.startingTime = int(round(time.time()*1000))
            if msg.type == "control_change":
                if msg.control == 64 and msg.value > 64:
                    self.damperIsActive = True
                if msg.control == 64 and msg.value <= 64:
                    self.damperIsActive = False
                    print("release damper", self.damper)
                    for damperedNote in self.damper:
                        mTime = self.getTimeFromStart()
                        dictionnary = {
                            "type": "note_off",
                            "note": damperedNote,
                            "velocity": 127,
                            "time": mTime
                        }
                    self.damper = []

            else:
                if self.damperIsActive == True and msg.type == "note_off":
                    self.damper.append(msg.note)
                    return
                else:
                    mTime = self.getTimeFromStart()
                    dictionnary = {
                        "type": msg.type,
                        "note": msg.note,
                        "velocity": msg.velocity,
                        "time": mTime
                    }
                    print("adding note ", dictionnary)
                    self.melodyNotes.append(dictionnary)
コード例 #18
0
class Game:
    def __init__(self, parent, config):
        self.config = config
        self.parent = parent
        # print("config mode 0 ",config)
        self.delay = float(config["question_delay"]) / 100
        self.isListening = False

        # variable for user score
        self.counter = 0
        self.score = 0
        self.globalIsListening = True

        debug = True
        self.stopGame = False
        self.waitingNotes = []
        self.initMIDIArray(128)

        self.midiIO = Autoload().getInstance()
        self.midiIO.setCallback(self.handleMIDIInput)

        # gamestate is used to know when the user is guessing
        self.gameState = "notStarted"

        # startGame
        self.startGame()
        self.startingNote = -1

        self.changeAllBg("black")
        self.parent.btnSkip.configure(command=self.skip)

        self.maxInterval = 12

    def toggleGlobalListen(self):
        if self.globalIsListening == True:
            self.globalIsListening = False
            self.parent.btnListen.configure(text="ListenOFF")
        else:
            self.globalIsListening = True
            self.parent.btnListen.configure(text="ListenON")

    def skip(self):
        try:
            self.parent.label2["text"] = "It was ;-)\n{}".format(
                formatOutputInterval(self.questionNote.note -
                                     self.startingNote))
            self.parent.label2["bg"] = "orange"
            # if we gave the good answer, we want a new note
            self.changeGameState("waitingUserInput")
        except:
            print("impossible to skip question")

    def startGame(self):
        self.changeGameState("waitingUserInput")
        self.melodies = Melody(self)

    def destroy(self):
        # print("destroying...")
        # self.isListening = False
        # self.midiIO.destroy() # delete everything in midiIO class
        self.midiIO.setCallback(None)

        # del self.waitingNotes # delete WantingNotes
        # del self

    def changeGameState(self, newstate):
        if newstate == "notStarted":
            pass
        elif newstate == "waitingUserInput":
            self.parent.label1["text"] = "Pick a starting Note"
            self.gameState = "waitingUserInput"
            percentage = int((self.score / self.counter) *
                             100) if (self.counter != 0) else 0
            self.parent.label3["text"] = "{}/{} ({}%)".format(
                self.score, self.counter, percentage)
        elif newstate == "listen":
            # self.parent["bg"] = "orange"
            # self.changeAllBg("orange")
            self.parent.label1["text"] = "Listen ..."
            self.parent.label2["text"] = ""
            self.parent.label2["bg"] = "black"
            self.parent.lblNoteUser["text"] = ""
            self.gameState = "listen"
            self.isListening = False
        elif newstate == "waitingUserAnswer":
            self.isListening = True
            # self.parent["bg"] = "blue"
            # self.changeAllBg("blue")
            self.parent.label1["text"] = "What is your answer ?"
            self.gameState = "waitingUserAnswer"

    # init a 128 array of WaitingNote in order to store all the timers

    def initMIDIArray(self, maxNote):
        for i in range(maxNote):
            self.waitingNotes.append(WaitingNote(i, self))

    # callback launched when the timer is at 0
    def noteOff(self, note):
        if self.isListening == False:
            return
        self.midiIO.sendOut("note_off", note)

    # prepare the future midi noteOff it is stored in waitingNotes list

    def prepareNoteOut(self, mNote, offset=0):
        if self.gameState == "waitingUserInput":
            self.changeGameState("listen")
        elif self.gameState == "listen":
            self.changeGameState("waitingUserAnswer")
        self.midiIO.sendOut("note_on", mNote)  # send note on
        currentNote = self.waitingNotes[mNote]
        currentNote.resetTimer(offset)

    def checkAnswer(self, answer):
        if answer == self.questionNote.note:
            self.parent.label2["text"] = "correct ;-)\n{}".format(
                formatOutputInterval(self.questionNote.note -
                                     self.startingNote))
            self.parent.label2["bg"] = "green"
            self.parent.lblNoteUser["text"] = noteNameFull(answer)
            self.parent.lblNoteUser["fg"] = "green"
            if self.questionNote.isFirstTry:
                self.score = self.score + 1

            # TODO : is it really the best way to do time.sleep here ?
            # if we gave the good answer, we want a new note
            self.changeGameState("waitingUserInput")
            time.sleep(0.4)
            self.melodies.playWinMelody()
            time.sleep(0.4)
        else:
            self.parent.label2["text"] = "incorrect\nA: {}".format(
                formatOutputInterval(answer - self.startingNote))
            self.questionNote.isFirstTry = False
            self.parent.label2["bg"] = "red"
            self.parent.lblNoteUser["text"] = noteNameFull(answer)
            self.parent.lblNoteUser["fg"] = "red"

            # time.sleep(1)
            # self.melodies.playLooseMelody()
            # time.sleep(1)
            # we replay the interval if the user didnt find the correct answer
            time.sleep(0.4)
            self.changeGameState("listen")
            # i want to replay both notes
            self.replayNote = QuestionNote(self.startingNote, self, 0)
            # i want to replay both notes
            self.replayNote = QuestionNote(self.questionNote.note, self,
                                           0 + self.delay)

        self.midiIO.panic()

    def pickNewNote(self, startingNote):
        self.counter = self.counter + 1
        # TODO : make the max interval customizable
        maxInterval = self.maxInterval
        offset = 0
        while offset == 0:  # we dont want the same note than the starting note
            offset = random.randint(-maxInterval, maxInterval)
        return startingNote + offset

    def handleQuestionNote(self, mNote):
        self.prepareNoteOut

    def changeAllBg(self, newColor):
        self.parent.label1["bg"] = newColor
        self.parent.label2["bg"] = newColor
        self.parent.label3["bg"] = newColor
        self.parent.lblNote["bg"] = newColor
        self.parent.lblNote["fg"] = "white"
        self.parent.label1["fg"] = "white"
        self.parent.label2["fg"] = "white"
        self.parent.label3["fg"] = "white"

    def handleMIDIInput(self, msg):
        # used for the midiListening button
        if Autoload().getInstance(
        ).isListening == False:  # check if user has midi  listen
            return
        if self.globalIsListening == False:
            return
        # Needed because we still receive signals even if the class is destroyed
        if self.isListening == False:
            print("[--] Ignoring queue message...", msg, self.isListening)
            return

        print("[-]receiving something", msg, self.isListening)
        if msg.type == "note_on" and msg.velocity > 10:
            # we test according to the gamestate

            if self.gameState == "waitingUserInput":
                self.changeGameState("listen")
                self.startingNote = msg.note
                # pick a random note
                questionNote = self.pickNewNote(self.startingNote)
                self.questionNote = QuestionNote(questionNote, self,
                                                 self.delay)
                # show the note on the ui
                self.lblUserShow = noteNameFull(self.startingNote) + "-> "
                self.parent.lblNote.config(text=self.lblUserShow)

            elif self.gameState == "waitingUserAnswer":
                if msg.note == self.startingNote:
                    # we want to ignore the starting note for the user.
                    return
                self.checkAnswer(msg.note)  # we check the answer
コード例 #19
0
    def __init__(self, globalRoot, bassNote, chordQuality, backtrack,
                 backtrackDuration, nbOfLoops, app):
        # images
        self.recImage = ImageTk.PhotoImage(Image.open(env.RECORD_IMAGE))

        self.app = app
        self.globalRoot = globalRoot
        self.midiIO = Autoload().getInstance()
        self.midiIO.setCallback(self.handleMIDIInput)
        self.audioInstance = Autoload().getInstanceAudio()
        self.backtrack = backtrack
        self.backtrackDuration = backtrackDuration
        self.nbOfLoops = nbOfLoops
        self.chordQuality = chordQuality
        self.bassNote = bassNote
        self.choosenBpm = 90

        self.sound = Autoload().getInstanceAudio()
        self.window = tk.Toplevel(self.globalRoot, cursor="none")
        self.window.attributes("-fullscreen", True)
        self.window.geometry("320x480")
        self.window["bg"] = "black"
        self.window.lblMessage = MyLabel12(
            self.window, text="Wait for the preparation of the backtrack")
        self.window.lblMessage.config(wraplength=280)
        self.window.lblBass = MyLabel40(self.window, text="Key")
        # self.window.btnRetry=BtnBlack12(self.window, text="Retry")
        self.window.btnCancel = BtnBlack12(self.window, text="Cancel")
        self.window.btnCancel.config(command=self.cancel)
        self.window.btnOK = BtnBlack12(self.window, text="OK")
        self.window.btnOK.config(command=self.nextWindow, state="disabled")

        self.window.lblRec = MyLabel18(self.window, text="")
        self.window.lblRec.config(background="black")

        self.window.canvas = tk.Canvas(self.window, bd=0, highlightthickness=0)

        # placement
        self.window.lblMessage.place(x=0, y=20, width=320, height=80)
        self.window.lblBass.place(x=0, y=120, width=320, height=50)
        self.window.lblRec.place(x=30, y=190, width=260, height=40)
        self.window.canvas.place(x=30, y=230, width=260, height=10)
        self.window.btnCancel.place(x=20, y=280, width=140, height=160)
        # self.window.btnRetry.place(x=120, y=360, width=80, height=80)
        self.window.btnOK.place(x=160, y=280, width=140, height=160)
        self.threads = []

        self.window.lblBass.config(
            text="{} {}".format(noteName(self.bassNote), self.chordQuality))
        # we want to launch a thread, it will activate recording after count-in
        # self.parent.precountTimer = Bpm(self.choosenBpm, self.backtrack, self.backtrackDuration, self.nbOfLoops,  lambda: self.activateRecordingChords())

        self.sound.prepareBacktrackForRecord(
            self.backtrack)  # load the backtrack file in pygame
        self.window.lblMessage.config(
            text="READY !\n Recording will start when you play a note...")
        self.chordNotes = []
        self.isRecording = True
        self.startingTime = 0

        self.damper = []
        self.damperIsActive = False
コード例 #20
0
class Game:
    def __init__(self, globalRoot, root, config, app):
        # images
        self.playImage = ImageTk.PhotoImage(Image.open(env.PLAY_IMAGE))
        self.pauseImage = ImageTk.PhotoImage(Image.open(env.PAUSE_IMAGE))
        self.shuffleImage = ImageTk.PhotoImage(Image.open(env.SHUFFLE_IMAGE))

        self.midiIO = Autoload().getInstance()
        self.midiIO.setCallback(self.handleMIDIInput)

        self.isPlaying = False
        self.config = config
        self.globalRoot = globalRoot
        self.root = root
        self.app = app

        # Default path
        self.midiRepository = env.MIDI_FOLDER

        # Callbacks for buttons
        # self.root.btnRecord.config(command=self.showWithOrWithoutBacktrackWindow)
        self.root.btnPractiseLick.config(image=self.playImage, command=self.playOneLick)
        self.root.btnRandomLick.config(image=self.shuffleImage, command=self.pickRandomLick)
        self.root.btnDeleteSelected.config(command=self.deleteLick)
        self.root.btnPrev.config(command=self.previousLick)
        self.root.btnNext.config(command=self.nextLick)

        self.midiFiles = []
        self.reloadMidiFiles()
        self.fileIndex = 0
        self.recordNotes = None

        self.midiIO = Autoload().getInstance()
        self.audioInstance = Autoload().getInstanceAudio()
        # self.midiIO.setCallback(self.handleMIDIInput)

        self.bassNote = 0
        self.chordQuality = "-"
        self.transpose = 0
        self.activeCustomSignals = []
        self.lickRepetitionCounter = 1
        self.lickMaxRepetition = self.config["times_each_transpose"]
        self.playOnlyChord = False

        self.currentLickIndex = 0
        self.currentLick = None

        self.practiseAllLicks = False
        self.lastTranspose = 0
        self.futureTranspose = 0

        self.playBacktrackThread = None
        self.audioThread = None

        self.bass = None
        self.mType = None
        self.notes = None
        self.backtrackVolume = None

        self.loadASample(len(self.midiFiles) - 1)

        # we need the number of licks in order to show the user

    def loadASample(self, index):
        nbOfSamples = len(self.midiFiles)
        if nbOfSamples == 0:
            self.root.lblNotes.config(text="No lick, record one first !")
        else:
            # we load last sample
            self.currentLickIndex = index
            self.loadSelectedItem(self.midiFiles[self.currentLickIndex])
            self.root.lblMessage.config(text="Lick {} / {} loaded.".format(index + 1, len(self.midiFiles)))
            self.showUserInfo(0)

    def reloadMidiFiles(self):
        counter = 0
        midiFiles = []
        for filename in os.listdir(self.midiRepository):
            # get only json files
            if os.path.splitext(filename)[1] == ".json":
                mFile = os.path.join(self.midiRepository, filename)
                midiFiles.append(mFile)
                counter += 1

        self.midiFiles = midiFiles
        self.midiFiles.sort()
        print("Reloading all MIDI files...", len(self.midiFiles))

    def loadSelectedItem(self, name):
        self.loadFile(os.path.join(self.midiRepository, name))

    def showUserInfo(self, transpose, counter=-1, nbBeforeTranspose=-1):
        self.userMessage = ""
        for note in self.notes:
            # print(note)
            if note["type"] == "note_on":
                if len(self.userMessage) > 30:
                    self.userMessage = self.userMessage[:28] + "..."
                else:
                    self.userMessage += noteName(note["note"] + transpose) + " "
        self.root.lblKey.config(foreground="white")
        self.root.lblKey.config(text="{} {}".format(noteName(self.bass + transpose), self.mType))
        self.root.lblNotes.config(foreground="white")
        self.root.lblNotes.config(text=self.userMessage)
        self.root.lblMessage.config(text="Lick {} / {} loaded.".format(self.currentLickIndex + 1, len(self.midiFiles)))
        if counter != -1:
            self.root.lblFollowing.config(
                text="{} / {} before transpose...".format(str(counter), str(nbBeforeTranspose)), foreground="white"
            )
        else:
            self.root.lblFollowing.config(text="")

    def showUserInfoNextTranspose(self, oldTranspose, newTranspose):
        beforeKey = noteName(self.bass + oldTranspose)
        afterKey = noteName(self.bass + newTranspose)
        self.root.lblKey.config(foreground="orange", text="{}=>{}".format(beforeKey, afterKey + self.mType))
        self.root.lblNotes.config(foreground="orange", text=formatOutputInterval(newTranspose - oldTranspose))
        self.root.lblFollowing.config(foreground="orange", text="Transpose next loop...")

    def loadFile(self, mFile):
        try:
            with open(mFile, "r") as f:
                datastore = json.load(f)
                self.currentLick = mFile
                self.bass = datastore["bass"]
                self.notes = datastore["notes"]
                self.mType = datastore["type"]
                self.backtrackVolume = datastore["volumeBacktrack"]
                self.showUserInfo(0)
        except Exception as e:
            print("problem loading file :", mFile, e)

    # def showWithOrWithoutBacktrackWindow(self):
    #     self.cancelThreads()
    #     try :
    #         del self.globalRoot.recordWindow
    #     except Exception as e:
    #         print(e)
    #     self.root.destroy()
    #     self.destroy()
    #     self.globalRoot.recordWindow= RecordWithBacktrack(self.globalRoot, self.app)

    def playChords(self, transpose):
        # notes_on_timing =[]
        # notes_on_notes=[]
        # notes_on_velocity=[]
        # notes_off_timing=[]
        # notes_off_notes=[]
        # for note in self.chord_notes:
        #     if note["type"] == "note_on":
        #         notes_on_timing.append(note["time"])
        #         notes_on_notes.append(note["note"]+transpose)
        #         notes_on_velocity.append(note["velocity"])
        #     elif note["type"]== "note_off":
        #         notes_off_timing.append(note["time"])
        #         notes_off_notes.append(note["note"]+transpose)
        # print(notes_on_timing)
        # print(notes_on_notes)

        # self.playingThread= TestThread(self,notes_on_timing, notes_on_notes, notes_on_velocity, notes_off_timing, notes_off_notes)
        self.playingThreadChord = TestThread(self, self.chord_notes, transpose)
        self.playingThreadChord.start()

        # for note in self.chord_notes:
        #     self.activeCustomSignals.append(CustomSignal(
        #         self,
        #         note["type"],
        #         note["note"] + transpose,
        #         note["velocity"],
        #         note["time"]
        #     ))

    def playMelody(self, transpose):
        # for note in self.melodyNotes:
        #     self.activeCustomSignals.append(CustomSignal(
        #         self,
        #         note["type"],
        #         note["note"] + transpose,
        #         note["velocity"],
        #         note["time"]
        #     ))
        self.playingThreadMelody = TestThread(self, self.melodyNotes, transpose)
        self.playingThreadMelody.start()

    def activateAudioThread(self, completeTraining):
        # self.cancelThreads()
        with open(self.currentLick, "r") as jsonfile:
            jsonLick = json.load(jsonfile)
        self.key = jsonLick["bass"]
        self.mType = jsonLick["type"]
        self.melodyNotes = jsonLick["notes"]
        self.chord_notes = jsonLick["chord_notes"]
        self.nbOfLoops = jsonLick["nbOfLoops"]
        self.backtrack = jsonLick["backtrack"]
        self.duration = jsonLick["backtrackDuration"] * self.nbOfLoops

        print("Current file has nb of notes :" + str(len(self.melodyNotes) + len(self.chord_notes)))

        self.audioThread = BackTrackThread(self, self.backtrack, self.nbOfLoops, completeTraining)
        self.audioThread.start()

    def previousLick(self):
        self.cancelThreads()
        pygame.mixer.music.stop()
        self.currentLickIndex += -1
        if self.currentLickIndex < 0:
            self.currentLickIndex = len(self.midiFiles) - 1
        self.loadFile(self.midiFiles[self.currentLickIndex])
        self.showUserInfo(0)

    def nextLick(self):
        self.cancelThreads()
        pygame.mixer.music.stop()
        self.currentLickIndex += 1
        if self.currentLickIndex >= len(self.midiFiles):
            self.currentLickIndex = 0
        self.loadFile(self.midiFiles[self.currentLickIndex])
        self.showUserInfo(0)

    def playOneLick(self, completeTraining=False):
        if self.isPlaying == False:
            self.root.btnPractiseLick.config(image=self.pauseImage)
            self.isPlaying = True
            self.activateAudioThread(completeTraining)
        else:
            self.root.btnPractiseLick.config(image=self.playImage)
            self.audioThread.isAlive = False
            # del self.audioThread
            self.isPlaying = False
            self.cancelThreads()
            return

    def pickRandomLick(self):
        # load a new random sample
        self.loadASample(random.randint(0, len(self.midiFiles) - 1))
        self.playOneLick(completeTraining=True)

    def deleteLick(self):
        self.cancelThreads()
        pygame.mixer.music.stop()
        if messagebox.askokcancel("delete ?", message="are you sure you want to delete the current Lick ?") == True:
            try:
                print("-->try to delete lick :", self.currentLick)
                os.remove(self.currentLick)
                self.reloadMidiFiles()
                self.currentLickIndex = 0
                if len(self.midiFiles) > 0:
                    self.currentLick = self.midiFiles[self.currentLickIndex]
                    self.loadSelectedItem(self.currentLick)
                else:
                    self.root.lblNotes.config(text="No lick, record one first !")
                    self.root.lblKey.config(text="")
                    self.root.lblFollowing.config(text="")
                    self.root.lblMessage.config(text="")
            except Exception as e:
                print("Error trying to delete lick", self.currentLick, e)
            self.reloadMidiFiles()

    def cancelThreads(self):
        try:
            self.root.btnPractiseLick.config(text="Practise Lick")
        except:
            print("can't update screen")
        self.isPlaying = False
        try:
            self.audioThread.isAlive = False
        except Exception as e:
            print("no threads to cancel", e)
        # we try to kill all notes no already played
        try:
            self.playingThreadChord.isAlive = False
        except Exception as e:
            print("no threads to cancel", e)
        try:
            self.playingThreadMelody.isAlive = False
        except Exception as e:
            print("no threads to cancel", e)
        for signal in self.activeCustomSignals:
            signal.timer.cancel()
        del self.activeCustomSignals
        self.activeCustomSignals = []
        self.midiIO.panic()

    def destroy(self):
        self.cancelThreads()
        pygame.mixer.music.stop()
        try:
            del self.activeCustomSignals
            del self.precountTimer
        except Exception as e:
            print("error in destroy :", e)
        del self

    def handleMIDIInput(self, msg):
        pass
コード例 #21
0
 def toggleMidiListen(self):
     instance = Autoload().getInstance()
     instance.panic()
     instance.toggleListening()
コード例 #22
0
class Game:
    def __init__(
        self, globalRoot, parent, config, app,
    ):
        self.currentTrack = None
        self.tracksWav = None

        # images
        self.playImage = ImageTk.PhotoImage(Image.open(env.PLAY_IMAGE))
        self.pauseImage = ImageTk.PhotoImage(Image.open(env.PAUSE_IMAGE))
        self.shuffleImage = ImageTk.PhotoImage(Image.open(env.SHUFFLE_IMAGE))
        self.page=0

        self.midiIO = Autoload().getInstance()
        self.midiIO.setCallback(self.handleMIDIInput)
        self.globalRoot = globalRoot
        self.app = app
        self.config = config
        metroBpmFile = open(env.CONFIG_METRO_BPM, 'r')
        self.metroBpm=int(metroBpmFile.read())
        self.isPlayingMetro=False

        self.parent = parent
        self.sound = Autoload().getInstanceAudio()

        # CLICK LISTENERS
        self.parent.btnPlay.config(command=self.toggleBacktrack)
        self.parent.btnMetro.config(command=self.playMetro)
        self.parent.btnBpmMinus.config(command=self.decreaseMetroTempo)
        self.parent.btnBpmPlus.config(command=self.increaseMetroTempo)
        self.parent.btnRandom.config(command=self.playRandom)
        self.parent.btnSwitchPage.config(command=self.switchPage)

        for i in range(0,len(self.parent.wav_buttons)):
            button=self.parent.wav_buttons[i]
            # we must extract the part with number of tracks to only keep the category
            button_text=button['text'].split('\n')[0]
            button.config(command=lambda button_text=button_text:self.pickRandomSampleInCategory(button_text))

        # this is a list which regroups all 4 folders (house , jazz ,latin, hiphop)
        self.tracksWav = self.sound.tracksWav

        self.parent.btnLick.config(
            command=self.showWithOrWithoutBacktrackWindow)
        self.parent.btnRandom.config(text="", image=self.shuffleImage)

        # recording variables

        self.recordingBassLick = False
        self.recordingNotes = False

        self.recordingCustomChords = False
        self.recordedNotes = []
        self.recordedCustomChords = []

        self.damper = []
        self.damperActive = False

    # def destroy(self):
    #     self.sound.unloadAudio()
    #     del self.sound
    #     del self

    def switchPage(self,):
        self.page += 1
        nb_pages_theorical = int((len(self.parent.wav_buttons) - 0.1) / 3)+1 # this is the theorical number of pages (3 elements by page)
        print('theorical pages : ', nb_pages_theorical)

        for button in self.parent.wav_buttons:
            button.place(x=-200, y=0)

        if self.page >= nb_pages_theorical:
            self.page=0
        
        if self.page ==0:
            self.parent.btnPlay.place(x=-200)
            self.parent.btnLick.place(x=-200)

            self.parent.btnMetro.place(x=10, y=20)
            self.parent.btnBpmMinus.place(x=130, y=20)
            self.parent.btnBpmPlus.place(x=220, y=20)

            counter= 0
            start_index=0
            for button in self.parent.wav_buttons:
                if (start_index + counter) < len(self.parent.wav_buttons):
                    if counter ==0 :
                        button.place(x=10, y=120)
                    elif counter == 1:
                        button.place(x=170, y=120)
                    elif counter==2:
                        button.place(x=10, y=220)
                    counter+=1

        
        elif self.page >=1:
            self.parent.btnMetro.place(x=-200)
            self.parent.btnBpmMinus.place(x=-200)
            self.parent.btnBpmPlus.place(x=-200)

            self.parent.btnPlay.place(x=10,y=20, width=140, height=80)
            self.parent.btnLick.place(x=170,y=20, width=140, height=80)

            counter= 0
            start_index=self.page*3
            for i in range(0,3):
                if (start_index + counter) < len(self.parent.wav_buttons):
                    if counter ==0 :
                        self.parent.wav_buttons[start_index+counter].place(x=10, y=120)
                    elif counter == 1:
                        self.parent.wav_buttons[start_index+counter].place(x=170, y=120)
                    elif counter==2:
                        self.parent.wav_buttons[start_index+counter].place(x=10, y=220)
                    counter+=1


    

    def playMetro(self,):
        if self.isPlayingMetro==True:
            self.sound.stopPlay()
            self.parent.btnMetro.config(text="Metro")
            self.isPlayingMetro =False
        else :
            self.sound.playRealMetro(self.metroBpm)
            self.parent.btnMetro.config(text="("+str(self.metroBpm)+")")
            self.isPlayingMetro=True

        # we would like to generate 2 bars of  audio file to certain bpm
    def decreaseMetroTempo(self,):
        minBpm=10
        self.metroBpm -= 10
        if self.metroBpm <=minBpm: # 10 is the minimum tempo
            self.metroBpm =minBpm
        self.saveMetroBpm(self.metroBpm)
        self.isPlayingMetro=False
        self.playMetro()

    def increaseMetroTempo(self,):
        maxBpm=190
        self.metroBpm +=10
        if self.metroBpm >= maxBpm: # max tempo
            self.metroBpm =maxBpm
        self.saveMetroBpm(self.metroBpm)
        self.isPlayingMetro=False
        self.playMetro()
    
    def saveMetroBpm(self,bpm):
        metroBpmFile = open(env.CONFIG_METRO_BPM, 'w')
        metroBpmFile.write(str(bpm))
        metroBpmFile.close()

    def showWithOrWithoutBacktrackWindow(self,):
        self.cancelThreads()
        try:
            del self.parent.recordWindow
        except Exception as e:
            print(e)
        self.parent.destroy()
        self.destroy()
        self.globalRoot.recordWindow = RecordWithBacktrack(
            self.globalRoot, self.app,)

    def showRandomTracks(self,):
        self.showCurrentPlayingInLabel()

    def showCurrentPlayingInLabel(self,):
        name = os.path.basename(self.currentTrack)
        # self.parent.labelCurrent.config(text="Currently Playing:\n"+ name + "\n" + str(self.sound.getCurrentTrack()[0]) +" sec")

    def changeTrack(self, index):
        try:
            self.stopBacktrack()
        except Exception:
            print("cant stop track during changeTrack.")
        self.currentTrack = self.activeSample[index]
        self.playBacktrack()
        self.showCurrentPlayingInLabel()
        self.sound.isPlaying = True

    def pickRandomSampleInCategory(self, category):
        print(category)
        self.sound.pickRandomSample(category)
        self.playBacktrack()

    def playRandom(self):
        self.sound.pickRandomSample()
        # TODO should display somewhere the number of files in the category and the index
        self.showRandomTracks()
        if self.sound.isPlaying == True:
            self.sound.stopPlay()

        self.currentTrack = self.sound.activeSample[0]
        self.showCurrentPlayingInLabel()
        self.sound.isPlaying = False
        self.playBacktrack()
        self.sound.isPlaying = True

    def toggleBacktrack(self):
        if pygame.mixer.music.get_busy() == True:
            self.stopBacktrack()
            self.sound.isPlaying = False
        else:
            self.playBacktrack()
            self.sound.isPlaying = True

    def stopBacktrack(self):
        self.sound.stopPlay()
        self.parent.btnPlay.config(image=self.playImage)

    def playBacktrack(self):
        self.sound.simplePlay()
        self.sound.isPlaying = True
        self.parent.btnPlay.config(image=self.pauseImage)
        trackInfo = self.sound.getCurrentTrack()
        trackName = trackInfo[0].split("/")[-1]
        trackLength = "{0:.2f}".format(trackInfo[1])
        # self.parent.labelCurrent.config(
        #     text="Currently Playing ({} / {}):\n{}\n({} sec length)".format(
        #         self.sound.activeSample[1], str(
        #             len(self.sound.tracksWav)), trackName, str(trackLength),
        #     )
        # )
        # thread for canvas
        self.parent.canvas.delete("all")
        try:
            self.thread.isAlive = False  # kill previous thread
        except Exception as e:
            print(e)
        self.thread = MyThreadForBacktrackScreen(
            "thread-canvas", self.parent.canvas, self.sound, self.sound.currentFileLength, self,)
        self.thread.start()

    def cancelThreads(self):
        try:
            self.thread.isAlive = False
        except Exception as e:
            print(e)
        try:
            del self.thread
        except Exception as e:
            print(e)
        pygame.mixer.music.stop()

    def destroy(self):
        print("trying cancel thread")
        self.cancelThreads()

    def handleMIDIInput(self, msg):
        print(msg)
        # if msg.type == "control_change":
        #     print("pedal ... : ", msg.control, msg.value)
        #     if msg.control == 64 and msg.value > 64:
        #         self.damperActive = True
        #     if msg.control == 64 and msg.value <= 64:
        #         self.damperActive = False
        #         print(self.damper)
        #         self.damper = []

        # if self.damperActive == True and msg.type == "note_off":
        #     self.damper.append(msg.note)

        # # No handle because we want to ignore the midi input messages
        pass
コード例 #23
0
class RecordChordsGui:
    def __init__(self, globalRoot, bassNote, chordQuality, backtrack,
                 backtrackDuration, nbOfLoops, app):
        # images
        self.recImage = ImageTk.PhotoImage(Image.open(env.RECORD_IMAGE))

        self.app = app
        self.globalRoot = globalRoot
        self.midiIO = Autoload().getInstance()
        self.midiIO.setCallback(self.handleMIDIInput)
        self.audioInstance = Autoload().getInstanceAudio()
        self.backtrack = backtrack
        self.backtrackDuration = backtrackDuration
        self.nbOfLoops = nbOfLoops
        self.chordQuality = chordQuality
        self.bassNote = bassNote
        self.choosenBpm = 90

        self.sound = Autoload().getInstanceAudio()
        self.window = tk.Toplevel(self.globalRoot, cursor="none")
        self.window.attributes("-fullscreen", True)
        self.window.geometry("320x480")
        self.window["bg"] = "black"
        self.window.lblMessage = MyLabel12(
            self.window, text="Wait for the preparation of the backtrack")
        self.window.lblMessage.config(wraplength=280)
        self.window.lblBass = MyLabel40(self.window, text="Key")
        # self.window.btnRetry=BtnBlack12(self.window, text="Retry")
        self.window.btnCancel = BtnBlack12(self.window, text="Cancel")
        self.window.btnCancel.config(command=self.cancel)
        self.window.btnOK = BtnBlack12(self.window, text="OK")
        self.window.btnOK.config(command=self.nextWindow, state="disabled")

        self.window.lblRec = MyLabel18(self.window, text="")
        self.window.lblRec.config(background="black")

        self.window.canvas = tk.Canvas(self.window, bd=0, highlightthickness=0)

        # placement
        self.window.lblMessage.place(x=0, y=20, width=320, height=80)
        self.window.lblBass.place(x=0, y=120, width=320, height=50)
        self.window.lblRec.place(x=30, y=190, width=260, height=40)
        self.window.canvas.place(x=30, y=230, width=260, height=10)
        self.window.btnCancel.place(x=20, y=280, width=140, height=160)
        # self.window.btnRetry.place(x=120, y=360, width=80, height=80)
        self.window.btnOK.place(x=160, y=280, width=140, height=160)
        self.threads = []

        self.window.lblBass.config(
            text="{} {}".format(noteName(self.bassNote), self.chordQuality))
        # we want to launch a thread, it will activate recording after count-in
        # self.parent.precountTimer = Bpm(self.choosenBpm, self.backtrack, self.backtrackDuration, self.nbOfLoops,  lambda: self.activateRecordingChords())

        self.sound.prepareBacktrackForRecord(
            self.backtrack)  # load the backtrack file in pygame
        self.window.lblMessage.config(
            text="READY !\n Recording will start when you play a note...")
        self.chordNotes = []
        self.isRecording = True
        self.startingTime = 0

        self.damper = []
        self.damperIsActive = False

    def nextWindow(self):
        self.window.destroy()
        self.globalRoot.recordWindow = RecordNotesGui(
            self.globalRoot,
            self.choosenBpm,
            self.bassNote,
            self.chordQuality,
            self.backtrack,
            self.backtrackDuration,
            self.nbOfLoops,
            self.chordNotes,
            self.app,
        )
        self.destroy()

    def customChordRetry(self):
        self.startingTime = 0
        self.recordedCustomChords = []

    def customChordCancel(self):
        self.recordingCustomChords = False
        self.window.destroy()

    def activateRecordingChords(self):
        # self.parent.startingTime=0 # in order to start at the first note
        # self.window.lblRec.config(text="REC.", background="red", foreground="white")
        self.window.lblRec.config(image=self.recImage)
        print("nbOfLoops :", self.nbOfLoops)
        pygame.mixer.music.stop()
        self.sound.playBacktrackForRecord(self.nbOfLoops)
        self.thread = MyThread("thread-canvas", self.window.canvas,
                               self.audioInstance,
                               self.backtrackDuration * self.nbOfLoops, self)
        self.thread.start()

    def endRecording(self):
        # self.parent.recordingCustomChords=False
        self.isRecording = False
        self.window.lblRec.config(image="",
                                  text="Finished!",
                                  background="black",
                                  foreground="white")
        self.window.lblMessage.config(text="Press 'OK' to proceed")
        self.window.btnOK.config(state="normal")
        self.window.canvas.delete("all")
        self.window.canvas.place_forget()

    def cancel(self):
        self.window.destroy()
        try:
            self.thread.isAlive = False
        except Exception as e:
            print(e)
        pygame.mixer.music.stop()
        self.app.new_window(2)
        del self
        # self.parent.cancelThreads()
        # self.parent.record

    def getTimeFromStart(self):
        return int(round(time.time() * 1000)) - self.startingTime

    def destroy(self):
        self.thread.isAlive = False
        del self.thread
        del self
        pass

    def handleMIDIInput(self, msg):
        if self.isRecording == True:

            if self.startingTime == 0:
                print("should start recording")
                self.activateRecordingChords()
                self.startingTime = int(round(time.time() * 1000))
                # print("first starting TIme trigger", self.startingTime)

            if msg.type == "control_change":
                if msg.control == 64 and msg.value > 64:
                    self.damperIsActive = True
                if msg.control == 64 and msg.value <= 64:
                    self.damperIsActive = False
                    print("release damper", self.damper)
                    for damperedNote in self.damper:
                        mTime = self.getTimeFromStart()
                        dictionnary = {
                            "type": "note_off",
                            "note": damperedNote,
                            "velocity": 127,
                            "time": mTime
                        }
                    self.damper = []
            else:
                if self.damperIsActive == True and msg.type == "note_off":
                    self.damper.append(msg.note)
                    return
                else:
                    mTime = self.getTimeFromStart()
                    dictionnary = {
                        "type": msg.type,
                        "note": msg.note,
                        "velocity": msg.velocity,
                        "time": mTime
                    }
                    self.chordNotes.append(dictionnary)
コード例 #24
0
class Game:
    def __init__(self, parent, config):
        self.questionArray = []
        self.config = config
        self.delay = float(self.config["question_delay"]) / 100
        self.parent = parent
        self.isListening = False

        # variable for user score
        self.counter = 0
        self.score = 0
        self.globalIsListening = True

        debug = True
        self.stopGame = False
        self.waitingNotes = []

        self.midiIO = Autoload().getInstance()  # open connections and ports
        self.midiIO.setCallback(self.handleMIDIInput)

        # gamestate is used to know when the user is guessing
        self.gameState = "notStarted"

        # startGame
        self.startGame()
        self.startingNote = -1

        self.parent.btnSkip.configure(command=self.skip)

        self.melodies = Melody(self)

    def toggleGlobalListen(self):
        if self.globalIsListening == True:
            self.globalIsListening = False
            self.parent.btnListen.configure(text="ListenOFF")
        else:
            self.globalIsListening = True
            self.parent.btnListen.configure(text="ListenON")

    def skip(self):
        try:
            notesAnswer = ""
            for note in self.questionArray:
                notesAnswer += noteName(note) + "-"
            self.parent.lblNote.config(font=("Courier", 18, "bold"))
            self.parent.lblNote["text"] = "It was\n{}".format(notesAnswer)
            # .format(formatOutputInterval(self.questionNote.note - self.startingNote))
            self.parent.lblNote["bg"] = "orange"
            self.changeGameState(
                "waitingUserInput"
            )  # if we gave the good answer, we want a new note
        except Exception as e:
            print("Impossible to skip question", e)

    def startGame(self):
        self.changeGameState("waitingUserInput")
        self.parent["bg"] = "black"
        self.changeAllBg("black")

    def destroy(self):
        self.isListening = False
        self.midiIO.destroy()  # delete everything in midiIO class
        del self.waitingNotes  # delete WantingNotes
        del self

    def changeGameState(self, newstate):
        if newstate == "notStarted":
            pass
        elif newstate == "waitingUserInput":
            self.parent.label1["text"] = "Pick a starting Note"
            self.gameState = "waitingUserInput"
            percentage = int((self.score / self.counter) *
                             100) if (self.counter != 0) else 0
            self.parent.label3["text"] = "{}/{} ({}%)".format(
                self.score, self.counter, percentage)
        elif newstate == "listen":
            self.parent.label2["bg"] = "black"
            self.parent.label1["text"] = "Listen ..."
            self.parent.label2["text"] = ""
            self.gameState = "listen"
            self.isListening = False
        elif newstate == "waitingUserAnswer":
            self.isListening = True
            self.parent.label1["text"] = "Your turn !"
            self.gameState = "waitingUserAnswer"
        else:
            print("ERROR : new state not defined", newstate)

    # callback launched when the timer is at 0
    def noteOff(self, note):
        if self.isListening == False:
            return
        self.midiIO.sendOut("note_off", note)

    # prepare the future midi noteOff it is stored in waitingNotes list
    def prepareNoteOut(self, mNote, offset=0):
        if self.gameState == "waitingUserInput":
            self.changeGameState("listen")
        elif self.gameState == "listen":
            if self.canvasCounter == len(self.questionChord) - 1:
                print("changing state...")
                self.changeGameState("waitingUserAnswer")

        self.midiIO.sendOut("note_on", mNote)  # send note on
        currentNote = self.waitingNotes[mNote]
        currentNote.resetTimer(offset)
        # draw on the canvas little rectangle to symbolyze the node
        rw = 2 * self.calcRectWidthOnCanvas()  # rw est 2 largeur de rectgangle
        self.parent.canvas.create_rectangle(rw + self.canvasCounter * rw,
                                            40,
                                            rw + self.canvasCounter * rw +
                                            rw / 2,
                                            80,
                                            fill="white")
        self.canvasCounter = self.canvasCounter + 1

    def drawAndPlayAnswer(self):
        self.parent.canvas.delete("all")
        self.timers = []
        counter = 0

        for note in self.questionArray:
            print(note + self.startingNote)
            # self.timers.append(Timer(1, lambda: self.midiIO.sendOut("note_on", self.startingNote+note, 100)))
            isLast = False
            if counter == len(self.questionArray) - 1:
                isLast = True
            # minimum delay ?
            self.timers.append(
                Timer(
                    1 + counter * self.delay,
                    self.sendOut,
                    ["note_on", self.startingNote + note, 100, isLast],
                ).start())
            self.timers.append(
                Timer(3 + counter * self.delay, self.sendOut,
                      ["note_off", self.startingNote + note, 100]).start())
            counter += 1

    def sendOut(self, mType, note, velocity, isLast=False):
        if mType == "note_on":
            self.midiIO.sendOut("note_on", note)
            rw = 2 * self.calcRectWidthOnCanvas(
            )  # rw est 2 largeur de rectgangle
            self.parent.canvas.create_rectangle(rw + self.canvasCounter * rw,
                                                40,
                                                rw + self.canvasCounter * rw +
                                                rw / 2,
                                                80,
                                                fill="white")
            self.canvasCounter = self.canvasCounter + 1
            if isLast == True:
                self.changeGameState("waitingUserAnswer")
        elif mType == "note_off":
            self.midiIO.sendOut("note_off", note)

    def resetQuestion(self):
        self.parent.canvas.delete("all")
        self.changeGameState("listen")
        self.parent.label2["text"] = "incorrect"
        self.parent.label2["bg"] = "red"
        self.drawAndPlayAnswer()
        self.answerBools = []
        self.allIsCorrect = True
        self.parent.canvas.delete("all")
        self.answerIndex = -1
        self.canvasCounter = 0
        self.isFirstTry = False
        self.midiIO.panic(
        )  # TODO : there is still a bug with first note ringing
        # affichage score
        self.parent.canvas.delete("all")

    def checkAnswer(self, userAnswer, correctAnswer):

        # print(answer, self.questionNote.note)
        rw = 2 * self.calcRectWidthOnCanvas()  # rw est 2 largeur de rectgangle
        if userAnswer == correctAnswer:

            # ok one answer is
            self.answerBools.append(True)
            self.parent.canvas.create_rectangle(rw + self.answerIndex * rw,
                                                0,
                                                rw + self.answerIndex * rw +
                                                rw / 2,
                                                40,
                                                fill="green")
        else:
            # we made a mistake on one note
            time.sleep(0.2)
            self.parent.label2["text"] = "incorrect"
            self.parent.label2["bg"] = "red"
            time.sleep(0.4)

            self.answerBools.append(False)
            self.allIsCorrect = False
            self.parent.canvas.create_rectangle(rw + self.answerIndex * rw,
                                                0,
                                                rw + self.answerIndex * rw +
                                                rw / 2,
                                                40,
                                                fill="red")
            self.resetQuestion()

        if self.answerIndex == len(self.questionArray) - 1:

            self.isListening = False
            if self.allIsCorrect == False:
                pass
            #                self.changeGameState( "listen")
            #
            #
            #                for note in self.questionChord:
            #                    print("resetting a timer")
            #                    note.resetTimer()
            #                self.answerBools = []
            #                self.allIsCorrect= True
            #                self.parent.canvas.delete("all")
            #                self.answerIndex=-1
            #                self.canvasCounter = 0
            #                self.isFirstTry= False
            #
            else:
                # We won
                self.parent.lblNote.config(font=("Courier", 18, "bold"))
                self.parent.lblNote["text"] = "correct ;-)\n{}".format(
                    self.chordName)
                self.parent.lblNote["bg"] = "green"
                if self.isFirstTry:
                    self.score = self.score + 1
                self.changeGameState("waitingUserInput")

                time.sleep(1)
                self.melodies.playWinMelody()
                time.sleep(1)
                self.isListening = True

            self.midiIO.panic(
            )  # TODO : there is still a bug with first note ringing
            self.parent
            self.parent.canvas.delete("all")

    def pickNewChord(self, startingNote):
        # TODO : pick random intervals
        chordsInit = MidiChords()
        chord = chordsInit.pickRandom()
        self.chordName = chord[0]
        self.chordNotes = chord[1]
        return chord

    def changeAllBg(self, newColor):
        self.parent.label1["bg"] = newColor
        self.parent.label2["bg"] = newColor
        self.parent.label3["bg"] = newColor
        self.parent.label1["fg"] = "white"
        self.parent.label2["fg"] = "white"
        self.parent.label3["fg"] = "white"

    def calcRectWidthOnCanvas(self):
        canvasW = 200
        nbRects = len(self.questionArray)
        # calcul savant !
        w = 2 * nbRects + 3
        return canvasW / w

    def handleMIDIInput(self, msg):
        if Autoload().getInstance().isListening == False:
            return
        if self.globalIsListening == False:
            return
        # Needed because we still receive signals even if the class is destroyed
        if self.isListening == False:
            print("[--] Ignoring queue message...", msg, self.isListening)
            return

        print("[-]receiving something", msg, self.isListening)
        if msg.type == "note_on" and msg.velocity > 10:
            # we test according to the gamestate

            if self.gameState == "waitingUserInput":
                self.isListening = False  # we will reactivate listening after all notes have been played
                self.startingNote = msg.note
                self.parent.lblNote["bg"] = "black"
                self.parent.lblNote.config(font=("Courier", 30, "bold"))
                self.parent.lblNote["text"] = noteNameFull(self.startingNote)
                # pick a random chord intervals
                self.question = self.pickNewChord(self.startingNote)
                self.questionArray = self.question[1]

                self.drawAndPlayAnswer()

                self.allIsCorrect = True  # var to know if we make a mistake in the answrs
                self.isFirstTry = True
                self.counter = self.counter + 1
                self.answerChord = []  # we initialize an answer chord
                self.answerBools = []
                # we initialize some vars and clear the canvas
                self.answerIndex = 0
                self.canvasCounter = 0

            elif self.gameState == "waitingUserAnswer":
                correctNote = self.questionArray[
                    self.answerIndex] + self.startingNote
                self.checkAnswer(msg.note, correctNote)
                self.answerIndex = self.answerIndex + 1
コード例 #25
0
 def test_creationOfMidiInstanceIsNotNone(self):
     self.assertIsNone(self.autoload)
     self.autoload = Autoload().getInstance()
     self.assertIsNotNone(self.autoload)
コード例 #26
0
class Bpm:
    def __init__(self, bpm, backtrack, backtrackDuration, nbOfLoops, callback):
        self.sound = Autoload().getInstanceAudio()
        self.sound.loadTick()
        self.backtrack = backtrack
        self.backtrackDuration = backtrackDuration
        self.nbOfLoops = nbOfLoops
        # self.saved_volume = pygame.mixer.music.get_volume()
        # print(self.saved_volume)
        # pygame.mixer.music.set_volume(1)

        self.bpm = bpm
        self.count = 4
        self.delayBetweenBeats = 60 / float(self.bpm)
        print("delay between notes", self.delayBetweenBeats)
        self.callback = callback

        self.t1 = Timer(self.delayBetweenBeats, lambda: self.playFirstTick())
        self.t2 = Timer(2 * self.delayBetweenBeats, lambda: self.playTick())
        self.t3 = Timer(3 * self.delayBetweenBeats, lambda: self.playTick())
        self.t4 = Timer(4 * self.delayBetweenBeats,
                        lambda: self.playLastTick())

        self.t1.start()
        self.t2.start()
        self.t3.start()
        self.t4.start()

    def playFirstTick(self):
        print("First TICK")
        self.sound.playTick()

    def playTick(self):
        print("TICK")
        self.sound.playTick()

    def playLastTick(self):
        print("TACK - recording...")
        # self.sound.playTick()
        self.sound.prepareBacktrackForRecord(self.backtrack)
        self.sound.playBacktrackForRecord(self.nbOfLoops)
        self.callback()
        # pygame.mixer.music.set_volume(self.saved_volume)

    def cancel(self):
        try:
            self.t4.cancel()
        except Exception as e:
            print(e)
        try:
            self.t3.cancel()
        except Exception as e:
            print(e)
        try:
            self.t2.cancel()
        except Exception as e:
            print(e)
        try:
            self.t1.cancel()
        except Exception as e:
            print(e)
コード例 #27
0
    def openMidiPanel(self):
        print("opening settings")
        self.window = tk.Toplevel(self.parent, cursor="none")
        self.window.attributes("-topmost", True)
        self.window.config(background="black")
        self.window.geometry("320x480")
        yplacement = 10
        label = LblSettings(self.window, text="click on your midi IN device:")
        label.place(x=0, y=yplacement, width=320, height=30)

        self.labelCurrentIn = LblSettings(self.window,
                                          text="actual In is : " +
                                          self.midiIO.inport.name)
        yplacement += 30
        self.labelCurrentIn.place(x=0, y=yplacement, width=320, height=30)

        # get all availables interface
        self.midiInstance = Autoload().getInstance()

        # midiInstance.showIOPorts() # just to shoe in the console
        midi_inputs = self.midiInstance.getAllMidiInputs()
        midi_outputs = self.midiInstance.getAllMidiOutputs()
        print(midi_inputs, midi_outputs)

        yplacement += 40

        for mInput in midi_inputs:
            if not "RtMidi" in mInput:
                btn = BtnBlack8(self.window, text=mInput)
                btn.config(command=lambda mInput=mInput: self.setIn(mInput),
                           wraplength=300)
                btn.place(x=10, y=yplacement, width=300, height=30)
                yplacement += 30

        yplacement += 15

        label2 = LblSettings(self.window,
                             text="click on your midi OUT device:")
        label2.place(x=0, y=yplacement, width=320, height=30)

        self.labelCurrentOut = LblSettings(self.window,
                                           text="actual out is : " +
                                           self.midiIO.outport.name)
        yplacement += 30
        self.labelCurrentOut.place(x=0, y=yplacement, width=320, height=30)

        yplacement += 10

        for mOutput in midi_outputs:
            if not "RtMidi" in mOutput:
                btn = BtnBlack8(self.window, text=mOutput)
                btn.config(
                    command=lambda mOutput=mOutput: self.setOut(mOutput),
                    wraplength=300)
                yplacement += 30
                btn.place(x=0, y=yplacement, width=320, height=30)

        yplacement += 15
        btnClose = BtnBlack20(self.window,
                              text="Close",
                              command=self.quitConfig)
        btnClose.place(x=80, y=380, width=160, height=80)
コード例 #28
0
class Game:
    def __init__(self, parent, config):
        # get audio instance to be sure the audio is loaded
        self.audio = Autoload().getInstanceAudio()
        self.midiIO = Autoload().getInstance()

        self.config = config
        self.parent = parent
        self.parent.btnConfig.config(command=self.openMidiPanel)

        self.loadInitialSettings()
        self.parent.btnSaveDefault.config(command=self.saveConfig)

    def saveConfig(self):
        # we must get all the parameters used in the app
        default_mode = 0  # for this time, default mode is hardcoded
        question_delay = self.parent.slider1_1.get()
        difficulty = self.parent.slider1_2.get()
        times_each_transpose = self.parent.slider2_1.get()
        nb_of_transpose_before_change = self.parent.slider2_2.get()
        midi_in = self.midiIO.inport.name
        midi_out = self.midiIO.outport.name

        print("settings: ", question_delay, difficulty, midi_in)
        obj = {
            "default_mode": default_mode,
            "question_delay": question_delay,
            "difficulty": difficulty,
            "times_each_transpose": times_each_transpose,
            "nb_of_transpose_before_change": nb_of_transpose_before_change,
            "MIDI_interface_in": midi_in,
            "MIDI_interface_out": midi_out,
            "midi_hotkey": 50,
        }
        json_object = json.dumps(obj, indent=4)
        print("trying to save...", json_object)
        outfile = env.CONFIG_FILE
        try:
            with open(outfile, "w+") as outfile:
                outfile.write(json_object)
            messagebox.showinfo(title="save as default",
                                message="Config saved successfully")
            print("Saved...")
        except Exception as e:
            messagebox.showerror(title="save as default",
                                 message="Failed at save config")
            print(e)

    def openMidiPanel(self):
        print("opening settings")
        self.window = tk.Toplevel(self.parent, cursor="none")
        self.window.attributes("-topmost", True)
        self.window.config(background="black")
        self.window.geometry("320x480")
        yplacement = 10
        label = LblSettings(self.window, text="click on your midi IN device:")
        label.place(x=0, y=yplacement, width=320, height=30)

        self.labelCurrentIn = LblSettings(self.window,
                                          text="actual In is : " +
                                          self.midiIO.inport.name)
        yplacement += 30
        self.labelCurrentIn.place(x=0, y=yplacement, width=320, height=30)

        # get all availables interface
        self.midiInstance = Autoload().getInstance()

        # midiInstance.showIOPorts() # just to shoe in the console
        midi_inputs = self.midiInstance.getAllMidiInputs()
        midi_outputs = self.midiInstance.getAllMidiOutputs()
        print(midi_inputs, midi_outputs)

        yplacement += 40

        for mInput in midi_inputs:
            if not "RtMidi" in mInput:
                btn = BtnBlack8(self.window, text=mInput)
                btn.config(command=lambda mInput=mInput: self.setIn(mInput),
                           wraplength=300)
                btn.place(x=10, y=yplacement, width=300, height=30)
                yplacement += 30

        yplacement += 15

        label2 = LblSettings(self.window,
                             text="click on your midi OUT device:")
        label2.place(x=0, y=yplacement, width=320, height=30)

        self.labelCurrentOut = LblSettings(self.window,
                                           text="actual out is : " +
                                           self.midiIO.outport.name)
        yplacement += 30
        self.labelCurrentOut.place(x=0, y=yplacement, width=320, height=30)

        yplacement += 10

        for mOutput in midi_outputs:
            if not "RtMidi" in mOutput:
                btn = BtnBlack8(self.window, text=mOutput)
                btn.config(
                    command=lambda mOutput=mOutput: self.setOut(mOutput),
                    wraplength=300)
                yplacement += 30
                btn.place(x=0, y=yplacement, width=320, height=30)

        yplacement += 15
        btnClose = BtnBlack20(self.window,
                              text="Close",
                              command=self.quitConfig)
        btnClose.place(x=80, y=380, width=160, height=80)

    def setIn(self, mInput):
        print("input selected: ", mInput)
        # TODO : check if it works
        self.midiInstance.setMidiInput(mInput)
        self.config["MIDI_interface_in"] = mInput
        self.labelCurrentIn.config(text="actual In is : " + mInput)

    def setOut(self, mOutput):
        # TODO : check if it works
        print("output selected:", mOutput)
        self.midiInstance.setMidiOutput(mOutput)
        self.config["MIDI_interface_out"] = mOutput
        self.labelCurrentOut.config(text="actual Out is : " + mOutput)

    def quitConfig(self):
        self.window.destroy()

    def destroy(self):
        print("trying destroy")
        del self

    def loadInitialSettings(self):
        value = int(self.config["question_delay"])
        print(value)
        self.parent.slider1_1.set(value)
コード例 #29
0
    def __init__(self, globalRoot, choosenBpm, bassNote, chordQuality,
                 backtrack, backtrackDuration, nbOfLoops, chordNotes, app):
        # images
        self.recImage = ImageTk.PhotoImage(Image.open(env.RECORD_IMAGE))

        self.app = app
        self.globalRoot = globalRoot
        self.midiIO = Autoload().getInstance()
        self.midiIO.setCallback(self.handleMIDIInput)
        self.audioInstance = Autoload().getInstanceAudio()
        self.backtrack = backtrack
        self.backtrackDuration = backtrackDuration
        self.nbOfLoops = nbOfLoops
        self.choosenBpm = choosenBpm
        self.chordQuality = chordQuality
        self.bassNote = bassNote
        self.window = tk.Toplevel(self.globalRoot, cursor="none")
        self.window.attributes("-fullscreen", True)
        self.window.geometry("320x480")
        self.window["bg"] = "black"
        print("backtrack gui:", self.backtrack)
        self.chordNotes = chordNotes
        self.melodyNotes = []
        self.customSignals = []

        self.window.lbl1 = MyLabel12(self.window,
                                     text="Please record now...",
                                     wraplength=280)
        self.stringNotes = ""
        self.window.lbl2 = MyLabel40(self.window,
                                     text="{} {}".format(
                                         noteName(self.bassNote),
                                         self.chordQuality))
        self.window.lbl3 = MyLabel24(self.window,
                                     text="Notes : " + self.stringNotes,
                                     wraplength=280)
        self.window.lblRec = MyLabel18(self.window, text="")

        # Buttons
        self.window.btnCancel = BtnBlack12(self.window,
                                           text="Cancel",
                                           command=self.cancel)
        self.window.btnRetry = BtnBlack12(self.window,
                                          text="Retry",
                                          command=self.retry)
        self.window.btnSave = BtnBlack12(self.window,
                                         text="Save",
                                         command=lambda: self.saveMidi())
        # self.window.btnSave.config(state="disabled")

        self.window.canvas = tk.Canvas(self.window, bd=0, highlightthickness=0)

        self.window.lbl1.place(x=0, y=40, width=320, height=80)
        self.window.lbl2.place(x=0, y=120, width=320, height=60)
        self.window.lbl3.place(x=0, y=180, width=320, height=60)
        self.window.lblRec.place(x=20, y=250, width=280, height=40)
        self.window.btnCancel.place(x=20, y=310, width=100, height=130)
        self.window.btnRetry.place(x=120, y=310, width=80, height=130)
        self.window.btnSave.place(x=200, y=310, width=100, height=130)

        self.window.canvas.place(x=20, y=290, width=280, height=10)

        self.isRecording = False
        self.precountTimer = Bpm(self.choosenBpm, self.backtrack,
                                 self.backtrackDuration, self.nbOfLoops,
                                 lambda: self.activateRecording())
        self.startingTime = 0

        self.damper = []
        self.damperIsActive = False
コード例 #30
0
    def __init__(self, globalRoot, backtrackFile, backtrackDuration, nbOfLoops,
                 app):
        self.app = app
        self.globalRoot = globalRoot
        self.midiIO = Autoload().getInstance()
        self.midiIO.setCallback(self.handleMIDIInput)
        self.backtrackFile = backtrackFile
        self.backtrackDuration = backtrackDuration
        self.nbOfLoops = nbOfLoops
        self.isRecording = False

        print("backtrack : ", backtrackFile, backtrackDuration, nbOfLoops)

        self.window = tk.Toplevel(self.globalRoot)
        self.window.config(cursor="none")
        self.window.geometry("320x480")
        self.window.attributes("-fullscreen", True)
        self.window["bg"] = "black"
        # creation of 2 labels and 2 buttons
        self.window.lbl1 = MyLabel12(
            self.window,
            text="Insert Bass reference note and click on chord type.",
            wraplength=280)

        # show window the detected bass
        self.window.lbl2 = MyLabel18(self.window, text="?")
        self.window.lbl2.config(foreground="red")
        # lable which show the bass entered by the user
        self.window.lblBass = MyLabel18(self.window, text="?")
        self.window.lblBass.config(foreground="red")
        # buttons minor and major
        self.window.btnMinor = BtnBlack12(self.window, text="Minor")
        self.window.btnMinor.config(
            command=lambda: self.setChordQuality("minor"))
        self.window.btnMajor = BtnBlack12(self.window, text="Major")
        self.window.btnMajor.config(
            command=lambda: self.setChordQuality("major"))
        self.window.btndom7 = BtnBlack12(self.window, text="Dom7")
        self.window.btndom7.config(
            command=lambda: self.setChordQuality("dom7"))
        # slider
        self.window.bpmScale = tk.Scale(self.window,
                                        from_=40,
                                        to=140,
                                        resolution=1,
                                        orient=tk.HORIZONTAL,
                                        showvalue=0)
        self.window.bpmScale.config(command=self.updateBpmValue)
        self.window.bpmScale.config(background="black",
                                    foreground="white",
                                    sliderlength=80,
                                    width=90,
                                    bd=0)
        self.window.bpmScale.set(60)  # default value for bpm record
        # custom progression
        self.window.btnCustom = BtnBlack12(self.window,
                                           text="OK",
                                           wraplength=130)
        self.window.btnCustom.config(command=self.validateBeforeShowingWindow)
        # Button cancel
        self.window.btnCancel = BtnBlack12(self.window, text="Cancel")
        self.window.btnCancel.config(command=self.cancel)

        # ----Placement------
        yplacement = 10
        self.window.lbl1.place(x=0, y=yplacement, width=320, height=60)
        yplacement += 70
        self.window.lblBass.place(x=80, y=yplacement, width=60, height=60)
        self.window.lbl2.place(x=150, y=yplacement, width=100, height=60)

        yplacement += 80
        self.window.btnMinor.place(x=25, y=yplacement, width=90, height=60)
        self.window.btnMajor.place(x=115, y=yplacement, width=90, height=60)
        self.window.btndom7.place(x=205, y=yplacement, width=90, height=60)
        # self.window.bpmScale.place(x=40, y=260, width=240, height=90)

        yplacement += 100
        self.window.btnCustom.place(x=25, y=yplacement, width=270, height=60)
        yplacement += 70
        self.window.btnCancel.place(x=25, y=yplacement, width=270, height=60)

        self.bassNote = 0  # reinitilisation of the bassnote
        self.chordQuality = "-"