Computer Project 2024
Computer Project 2024
a) Introduction
1) b) Requirements 1
2) Modules Used 2
Screenshots
4) 14
a) Future
enhancements
5) b)Bibliography,webliogr 15
aphy
and group members
INTRODUCTION
This project introduces a digital audio
workstation application constructed using
Python and Pygame. By harnessing the
flexibility of Python and the multimedia
functionalities of Pygame, this application
offers a user-friendly interface for creating
and manipulating musical beats. This project
aims to demonstrate the potential of
programming in music production by
providing a platform that is both accessible
to beginners and capable of producing
sophisticated rhythmic patterns."
REQUIREMENTS
Software:
Python 3.7.32 bit
Pygame from pipinstaller
Tkinter
Hardware:
Windows 7/8/10
32/64 bit operating system
2GB RAM
MODULES USED
Pygame: It is a cross platform set of
Python modules designed for writing
video games. It includes computer
graphics and sound libraries designed to
be used with the Python standard
programming language
SOURCE CODE
import pygame
from pygame import mixer
import time
pygame.init()
WIDTH = 1400
HEIGHT = 800
black = (23,23,23)
white = (227,222,219)
gray = (128,128,128)
light_gray = (182,181,179)
dark_gray = (84,82,80)
green = (201,60,74)
gold = (212,175,55)
blue = (0, 255, 255)
screen = pygame.display.set_mode([WIDTH,HEIGHT])
pygame.display.set_caption("Beat Maker")
label_font = pygame.font.Font('HELN.TTF', 32)
medium_font = pygame.font.Font('HELN.TTF', 24)
def draw_grid(clicks, beat, actives, volume):
instrument_colors = [(201, 60, 74),
(240, 118, 70),
(242, 198, 101),
(18, 99, 119),
(31, 150, 153),
(156, 192, 185)]
left_box = pygame.draw.rect(screen , gray , [0, 0, 200, HEIGHT-
200], 5)
bottom_box = pygame.draw.rect(screen , gray , [0, HEIGHT-200,
WIDTH, 200], 5)
boxes = []
colors = [gray, white, gray]
for i in range(instruments):
pygame.draw.line(screen, gray, (0,(i*100)+100),(200,
(i*100)+100), 3)
for i in range(beats):
for j in range(instruments):
if clicks[j][i] == -1:
color = gray
else:
if actives[j] == 1:
color = instrument_colors[j]
else:
color = dark_gray
rect = pygame.draw.rect(screen, color, [i * ((WIDTH -
200)//beats) + 205 ,(j*100)+5, ((WIDTH-200) // beats)-10, ((HEIGHT-
200)//instruments -10)],0,3)
def draw_save_menu(beat_name,typing):
pygame.draw.rect(screen,black,[0,0,WIDTH,HEIGHT])
menu_text = label_font.render('Save Menu : Enter name for
current Beat',True,white)
saving_btn = pygame.draw.rect(screen,gray,[WIDTH//2 -
200,HEIGHT*0.75,400,100],0,5)
saving_txt = label_font.render('Save Beat',True,white)
screen.blit(saving_txt,(WIDTH//2-75,HEIGHT*0.75+30))
screen.blit(menu_text,(400,40))
exit_btn = pygame.draw.rect(screen,gray,[WIDTH-200, HEIGHT-
100, 180, 90],0,5)
exit_text = label_font.render('Close',True,white)
screen.blit(exit_text, (WIDTH-160,HEIGHT-70))
if typing:
pygame.draw.rect(screen,dark_gray,[400, 200, 600, 200],0,5)
entry_rect = pygame.draw.rect(screen,gray,
[400,200,600,200],5,5)
entry_txt = label_font.render(f'{beat_name}',True,white)
screen.blit(entry_txt,(430,250))
return exit_btn, saving_btn, entry_rect
def draw_load_menu(index):
global volume, notes, count
loaded_clicked = []
loaded_beats = 0
loaded_bpm = 0
loaded_count = 0
pygame.draw.rect(screen,black,[0,0,WIDTH,HEIGHT])
menu_text = label_font.render('Load Menu : Select Beat to
Load',True,white)
loading_btn = pygame.draw.rect(screen,gray,[WIDTH//2 -
200,HEIGHT*0.87,400,100],0,5)
loading_txt = label_font.render('Load Beat',True,white)
screen.blit(loading_txt,(WIDTH//2-75,HEIGHT*0.87+30))
delete_btn = pygame.draw.rect(screen,gray,[(WIDTH//2)-500,
HEIGHT * 0.87,200,100],0,5)
delete_txt = label_font.render("Delete Beat", True, white)
screen.blit(delete_txt,(WIDTH//2-485, HEIGHT * 0.87 + 30))
screen.blit(menu_text,(400,40))
exit_btn = pygame.draw.rect(screen,gray,[WIDTH-200, HEIGHT-
100, 180, 90],0,5)
exit_text = label_font.render('Close',True,white)
screen.blit(exit_text, (WIDTH-160,HEIGHT-70))
loaded_rectangle = pygame.draw.rect(screen,gray,[190, 90,
1000, 600],5,5)
saved_beats.sort(key=lambda x: int(x.split('count:')[1].strip()),
reverse=True)
if 0 <= index < len(saved_beats):
pygame.draw.rect(screen,light_gray,
[190,100+index*50,1000,50])
for beat in range(len(saved_beats)):
if beat < 10:
beat_clicked = []
row_text = medium_font.render(f'{beat + 1}', True, white)
screen.blit(row_text, (200, 100 + beat * 50))
name_index_start = saved_beats[beat].index('name:') + 6
name_index_end = saved_beats[beat].index(", beats: ")
count_index_start = saved_beats[beat].index('count:') + 7
name_text = medium_font.render(saved_beats[beat]
[name_index_start:name_index_end], True, white)
screen.blit(name_text, (240, 100 + beat * 50))
count_text = medium_font.render(f'Count:
{saved_beats[beat][count_index_start:]}', True, white) # Render
count
screen.blit(count_text, (700, 100 + beat * 50))
if 0 <= index < len(saved_beats) and beat == index:
beats_index_end = saved_beats[beat].index(', bpm:')
loaded_beats = int(saved_beats[beat][name_index_end +
8:beats_index_end])
bpm_index_end = saved_beats[beat].index(', selected:')
loaded_bpm_start = saved_beats[beat].index('bpm:') + 5
loaded_bpm_end = saved_beats[beat].index(',volume:')
loaded_bpm = int(saved_beats[beat]
[loaded_bpm_start:loaded_bpm_end].strip())
loaded_clicks_string = saved_beats[beat][bpm_index_end +
14: -3]
loaded_clicks_rows = list(loaded_clicks_string.split("], ["))
loaded_volume_start = saved_beats[beat].index('volume:') +
8
loaded_volume_end = saved_beats[beat].index(', selected')
+1
loaded_volume_string = saved_beats[beat]
[loaded_volume_start+1:loaded_volume_end-2]
loaded_volume = [int(vol) for vol in
loaded_volume_string.strip().strip('[]').split(", ")]
loaded_count_start = saved_beats[beat].index('count:') + 7
loaded_count = int(saved_beats[beat]
[loaded_count_start:].strip())
index = 100
fps = 60
timer = pygame.time.Clock()
beats = 8
instruments = 6
boxes = []
clicked = [[-1 for _ in range(beats)] for _ in range(instruments)]
active_list = [1 for _ in range(instruments)]
bpm = 240
playing = True
active_length = 0
active_beat = 0
beat_changed = True
save_menu = False
load_menu = False
saved_beats = []
file = open('saved_beats.txt','r')
for line in file:
saved_beats.append(line)
count = 0
# SOUNDS
hi_hat = mixer.Sound('sounds/hi hat.WAV')
snare = mixer.Sound('sounds/snare.WAV')
kick = mixer.Sound('sounds/kick.WAV')
crash = mixer.Sound('sounds/crash.wav')
clap = mixer.Sound('sounds/clap.wav')
def play_notes():
for i in range(len(clicked)):
if clicked[i][active_beat] == 1 and active_list[i] == 1:
# Set volume for each instrument
if i == 0:
hi_hat.set_volume(volume[i]/10)
hi_hat.play()
if i == 1:
snare.set_volume(volume[i]/10)
snare.play()
if i == 2:
kick.set_volume(volume[i]/10)
kick.play()
if i == 3:
crash.set_volume(volume[i]/10)
crash.play()
if i == 4:
clap.set_volume(volume[i]/10)
clap.play()
if i == 5:
sound_index = note_indices[active_beat] % len(notes)
sound = mixer.Sound(f"sounds/BASS
Notes/{notes[sound_index]}.wav")
sound.play()
sound.set_volume(volume[i]/10)
# GAME
run = True
while run:
timer.tick(fps)
screen.fill(black)
boxes = draw_grid(clicked, active_beat, active_list, volume)
# LOWER MENU
play_pause = pygame.draw.rect(screen, gray, [50, HEIGHT-
150,200,100],0,5)
play_text = label_font.render('Play/Pause',True,white)
screen.blit(play_text, (70, HEIGHT-130))
if playing:
play_text2 = medium_font.render('Playing', True, dark_gray)
else:
play_text2 = medium_font.render('Paused', True, dark_gray)
screen.blit(play_text2, (70, HEIGHT-90))
# BPM
bpm_rect = pygame.draw.rect(screen,gray,[300,HEIGHT-
150,200,100],5,5)
bpm_text = medium_font.render("Beats Per Min",True,white)
screen.blit(bpm_text,(318,HEIGHT-130))
bpm_text2 = label_font.render(f'{bpm}' , True, white)
screen.blit(bpm_text2,(370,HEIGHT-100))
bpm_add_rect = pygame.draw.rect(screen,gray,[510,HEIGHT-
150,48,48],0,5)
bpm_sub_rect = pygame.draw.rect(screen,gray,[510,HEIGHT-
100,48,48],0,5)
add_text = medium_font.render("+5",True,white)
sub_text = medium_font.render("-5",True,white)
screen.blit(add_text,(520,HEIGHT-140))
screen.blit(sub_text,(520,HEIGHT-90))
# BEATS
beats_rect = pygame.draw.rect(screen,gray,[600,HEIGHT-
150,200,100],5,5)
beats_text = medium_font.render("Beats In Loop",True,white)
screen.blit(beats_text,(618,HEIGHT-130))
beats_text2 = label_font.render(f'{beats}' , True, white)
screen.blit(beats_text2,(690,HEIGHT-100))
beats_add_rect = pygame.draw.rect(screen,gray,[810,HEIGHT-
150,48,48],0,5)
beats_sub_rect = pygame.draw.rect(screen,gray,[810,HEIGHT-
100,48,48],0,5)
beatsadd_text = medium_font.render("+1",True,white)
beatssub_text = medium_font.render("-1",True,white)
screen.blit(beatsadd_text,(820,HEIGHT-140))
screen.blit(beatssub_text,(820,HEIGHT-90))
# INSTRUMENTS
instrument_rects = []
for i in range(instruments):
rect = pygame.rect.Rect((0,i*100),(200,100))
instrument_rects.append(rect)
#VOLUME
volume_list = []
text_labels = ['Hi Hat', 'Snare', 'Kick', 'Crash', 'Clap', 'Tom',]
index2 = [0,1,2,3,4,5]
text_positions = [(30, i*100 + 30) for i in range(len(text_labels))]
for pos, num in zip(text_positions,index2 ):
# Draw volume button
volume_button_rect = pygame.Rect(150, pos[1], 40, 40)
pygame.draw.rect(screen, gray, volume_button_rect,0,5)
volume_list.append(volume_button_rect)
vol_text =
medium_font.render(f'{int(volume[num])}',True,white)
screen.blit(vol_text,(150, pos[1]+5))
# CLEAR BOARD
clear_button = pygame.draw.rect(screen,gray,[1150,HEIGHT-
150,200,100],0,5)
clear_text = label_font.render("RESET",True,white)
screen.blit(clear_text,(1190,HEIGHT-120))
if beat_changed:
play_notes()
beat_changed = False
elif beats_sub_rect.collidepoint(event.pos):
beats -= 1
for i in range(len(clicked)):
clicked[i].pop(-1)
if beats < len(note_indices):
note_indices = note_indices[:beats]
elif clear_button.collidepoint(event.pos):
clicked = [[-1 for _ in range(beats)] for _ in
range(instruments)]
note_indices = [0] * beats
elif save_button.collidepoint(event.pos):
save_menu = True
elif load_button.collidepoint(event.pos):
load_menu = True
loaded_info = saved_beats[index]
beats_index_start = loaded_info.index('beats:') + 7
beats_index_end = loaded_info.index(', bpm:')
beats =
int(loaded_info[beats_index_start:beats_index_end])
bpm_index_start = loaded_info.index('bpm:') + 5
bpm_index_end = loaded_info.index(',volume:')
bpm =
int(loaded_info[bpm_index_start:bpm_index_end])
volume_index_start = loaded_info.index('volume:') +
8
volume_index_end = loaded_info.index(', selected:')
volume_string =
loaded_info[volume_index_start:volume_index_end].strip().strip('[]')
volume = [int(vol) for vol in volume_string.split(',')]
clicked_index_start = loaded_info.index('selected:') +
11
clicked_index_end = loaded_info.index(',
bass_notes:')
clicked_string =
loaded_info[clicked_index_start:clicked_index_end].strip().strip('[]').s
plit('], [')
clicked = [[int(note) for note in row.split(', ')] for row
in clicked_string]
note_indices_index_start =
loaded_info.index('bass_notes:') + 12
note_indices_index_end = loaded_info.index(',
count:')
note_indices_string =
loaded_info[note_indices_index_start:note_indices_index_end].strip()
.strip('[]')
note_indices = [int(note) for note in
note_indices_string.split(', ')]
count_index_start = loaded_info.index('count:') + 7
count = int(loaded_info[count_index_start:])
index = 100
save_menu = False
load_menu = False
playing = True
typing = False
if playing:
if active_length < beat_length:
active_length += 1
else:
active_length = 0
if active_beat < beats - 1:
active_beat += 1
beat_changed = True
else:
active_beat = 0
beat_changed = True
pygame.display.flip()
pygame.quit(
SCREENSHOTS
FUTURE ENHANCEMENTS
To further develop this beat maker
application, incorporating additional
instruments, such as basslines and melodic
options, would significantly expand its
creative potential. Implementing a step
sequencer and melody editor could also
enhance users' ability to create complex and
original compositions. Moreover, features
like saving and loading projects, exporting
beats, and providing various project
templates would greatly improve user
experience and workflow.
BIBLIOGRAPHY:
Computer science with python: Textbook for
Class XII by Sumita Arora
WEBLIOGRAPHY:
https://www.geeksforgeeks.org/python-
gui-tkinter/
https://realpython.com/pygame-a-
primer/
https://www.activestate.com/blog/how-
to-use-pygame-for-game-development/
https://realpython.com/python-gui-
tkinter/
GROUP MEMBERS
Srikari Jois 12A
Rishikesh Srikrishnan 12B
Advaith Krishnan 12B