Ejemplo n.º 1
0
    def run(self, screen):
        screen_size = (1024,600)
        screen_color = (0, 0 ,0)
        
        #build frequency to note dictionary
        notes_dictionary = self.build_range()

        #sort the keys and turn into a numpy array for logical indexing
        frequencies = numpy.array(sorted(notes_dictionary.keys()))

        top_note = 24 #set it two octaves higher
        bottom_note = 0
        
        #other variables
        screen = pygame.display.set_mode(screen_size)
        screen.fill(screen_color)
        input_note = 1 #the y value on the plot
        old_position = (0,0) #the last position of note played
        show_notes = True #show the note
        signal_level = 0 #volume level
        trys = 1
        line = True
        sound_gate = 15 #zero is loudest possible input level
        target_note = 0 #closest note in the dictionary
        sound_recorder = SwhRecorder() #microphone
        
        while trys <> 0:
            trys += 1

            for n in range(0, screen_size[0], 40):
                sound_recorder.setup()
                raw_data_signal = sound_recorder.getAudio()
                signal_level = round(abs(self.loudness(raw_data_signal)),2) #find the volume level from raw data

                try: 
                    input_note = round(freq_from_autocorr(raw_data_signal,sound_recorder.RATE),2) #find the freq from the audio sample
                except:
                    input_note == 0
                sound_recorder.close()

                if input_note > frequencies[len(notes_dictionary)-1] or input_note < frequencies[0]: #if the frequency is too high, do nothing
                    continue
                if signal_level > sound_gate: #noise gate to prevent ambient noises
                    continue

                target_note = self.closest_value_index(frequencies, round(input_note, 2)) #find the closest note in the note dictionary
                position = ((n), (screen_size[1]-(int(screen_size[1]/(frequencies[top_note]-frequencies[bottom_note]) * (input_note - frequencies[bottom_note])))) ) 

                #user interface
                for event in pygame.event.get():
                    #quit program
                    if event.type ==  QUIT:
                        sound_recorder.close()
                        return
                    elif event.type == KEYDOWN:
                        #increase top_note range
                        if event.key == K_s:    
                            if top_note <= len(notes_dictionary)-7:
                                top_note += 6
                        #decrease top note range no lower than an octave higher than bottom note
                        if event.key == K_x:    
                            if top_note >= 6 and top_note >= bottom_note + 6:
                                top_note -= 6
                        #increase bottom note range no higher than an octave lower than top note
                        if event.key == K_a:    
                            if bottom_note < top_note:
                                bottom_note += 6
                        #decrease bottom note range
                        if event.key == K_z:    
                            if bottom_note >= 6:
                                bottom_note -= 6 

                        #quit program
                        if event.key == K_q:    
                            sound_recorder.close()
                            return

                if n == 0 or n == screen_size[0]:
                    old_position = position
                
                #draw info box on top
                meter = "###################################"
                info_font = pygame.font.Font(None, 18)
                top_info = info_font.render(
                   "Bottom : " + str(notes_dictionary[frequencies[bottom_note]]) + " :  dec(z), inc(a)     "
                   + "Top : " + str(notes_dictionary[frequencies[top_note]]) + " :  dec(x), inc(s)     "
                   #+ "         Show Notes(n):" + str(show_notes) + "         Lines(l):" + str(line)
                   + "         Loudness: " + meter[1:int(20-signal_level)]
                   , 1, (255,255,255))
                pygame.draw.rect(screen, (0,0,0), (0,0,screen_size[0],20))
                pygame.draw.line(screen, (200,200,200),(0,20),(1024,20), 1)
                screen.blit(top_info, (5,5))

                #draw lines
                if input_note < frequencies[len(notes_dictionary)-1]:
                    if old_position < position:
                        random_color = (randint(20,255),randint(20,255),randint(20,255))
                        pygame.draw.line(screen, random_color, old_position, position, 2)
                    old_position = position

                #draw notes name
                font = pygame.font.Font(None, 30)
                text = font.render(str(notes_dictionary[frequencies[target_note]]), 1, (0,255,0))
                screen.blit(text, (position))

                #update the display
                pygame.display.flip()
                pygame.display.update()

            #clear screen at the end of every loop run
            screen.blit(screen, (0, 0))
            screen.fill(screen_color)