summaryrefslogtreecommitdiff
path: root/content/projects/guitar-hero/index.md
blob: b364350d9bb90063dd1d04439d2f8d6e75a66c6f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
---
title: "Guitar Hero"
date: 2023-10-23T23:18:05-04:00
mermaid: true
draft: false
---

One of my University classes tasked me with creating a custom pcb remote as
well as a GUI software that interfaced with it. I decided to create a *Guitar
Hero* clone capable of reading files created for the similar project *Clone
Hero* using C++ and QT.

The goal of this class was to teach Computer Science students about GUI design
as well as teach electrical engineers about PCB design. Both type of students
would also get to learn about software and hardware integration. Each team
was composed of 6 people of both engineering discipline.

# Requirements

On the hardware side, the requirements were quite simple:

- The designed PCB needed to be less then or equal to 10x15cm
- A minimum of 5 switches were needed
- A joystick as well as an accelerometer had to get integrated
- We could choose wether to integrate a 5 segment or a bar graph display

After a little back and forth with our teachers, we came to an agreement that
we could configure some of our switches outside the pcb and mount them directly
to the guitar. This way, the pcb itself could be located at the base of a guitar
and host the strumming mechanism. We also convinced them it would be best for our
usecase to also mount the accelerometer on a guitar shaft and configure it as some
sort of trigger for a bonus streak.

On the software side of things, requirements were even simpler. All we
needed was to use the QT C++ library without any QML or QSS. It took very
little convincing to get my team on board with the *Guitar Hero* clone idea.

With those imposed constraints, we set ourselves a few targets of ourselves.

- Basic compatibility with songs create for [Clone Hero][1]
- Functional strumming mechanism
- Satisfying fret buttons
- Good input and visual latency

# PCB and Guitar Design

# File Parsing & Structure

*Clone Hero* is a popular game inspired by *Guitar Hero* where
players can download and play community developed songs. It uses
a games specific `.chart` file format to store data necessary
to play songs. Here is a small excerpt such a file:

```toml
[Song]
{
  Name = "Rock Is Too Heavy"
  Artist = "Owane"
  Charter = "GuitarZero132"
  Album = "Yeah Whatever"
  Year = ", 2018"
  Offset = 0
  Resolution = 192 # Only Mandatory
  Player2 = bass
  Difficulty = 6
  PreviewStart = 0
  PreviewEnd = 0
  Genre = "Jazz Fusion"
  MediaType = "cd"
  MusicStream = "song.ogg"
  GuitarStream = "drumbsdfklj.ogg"
}
[SyncTrack]
{
  0 = TS 4
  0 = B 161000
  1152 = B 162000
  1536 = B 160000
  21504 = TS 3
  22080 = TS 4
  ...
  69888 = TS 4
  71424 = TS 7 3
  72096 = TS 4
  73632 = TS 7 3
  74304 = TS 4
  75840 = TS 7 3
  76512 = TS 4
  84960 = TS 3
  85536 = TS 5
  86496 = TS 4
  89568 = TS 3
  90144 = TS 5
  91104 = TS 4
}
[ExpertSingle]
{
  1536 = N 2 0
  1536 = N 4 0
  1632 = N 2 256
  1632 = N 4 256
  1920 = N 2 0
  2016 = N 2 0
  2208 = N 0 0
  2304 = N 1 0
  2304 = N 5 0
  ...
  151008 = N 3 160
  151200 = N 2 0
  151296 = N 1 0
  151328 = N 0 128
  151488 = N 2 0
  151584 = N 0 0
  151680 = N 1 0
  151776 = N 3 256
  152064 = N 2 0
  152064 = N 5 0
  152112 = N 1 0
  152160 = N 0 0
  152352 = E soloend
}
```

Most of the `Song` section is fairly explanatory but the **Resolution** field
merits some explanation. In music, songs have a pulse measured in BPMs (beats
per minute). For extra precision for note timing, *Clone Hero* decided to split
each note into smaller units called ticks determined by the resolution. Using
easy numbers, if a 60 BPM song (1 beat lasts 1 second) had a resolution of
1000, each tick would have a duration of 1 millisecond.

Up to now, this concept seems elegant. But the format gets much uglier when you
take into account that many songs accelerate, slow down and/or have small non
musical intermissions. So how can ticks remain reliable if the tempo of a song
isn't always the same? The file spec requires a `[SyncTrack]` section


{{<mermaid>}}
classDiagram
  direction RL

  class Song {
    -title : string
    -artist : string
    -album : string
    -year : string
    -charter : string
    +easy : Chord[]
    +medium : Chord[]
    +hard : Chord[]
    +expert : Chord[]
  }

  class Chord {
    +notes : *notes[5]
    -duration : int
    -start : int
    -end : int
    -rushStart : int
    -dragStart : int
    -rushRelease : int
    -dragRelease : int
    -spawnTime : int
    -noteNB : int
  }

  class Note {
    -Fret : int
  }

  Note "1..5" o-- Chord
  Chord o-- Song
{{</mermaid>}}




# GUI Design

# Results

Here's a small playlist showcasing what we managed to achieve after a semesters
worth of work, both hardware and software wise:

{{< youtubepl PLGcbRdKslprBkKg2NyGtS4AGuB2Ng_22e >}}




<!-- Integration   https://youtu.be/FKOd6nEcEC8 -->
<!-- Song          https://youtu.be/G2GX4o7dhNY -->
<!-- Accelerometer https://youtu.be/xl-ZMSSMalw -->
<!-- Bar Graph     https://youtu.be/WZeAdRM9tGo -->
<!-- Strumming     https://youtu.be/TxubEPih7yw -->
<!-- Joystick      https://youtu.be/q-Qc5jLBBzU -->
<!-- Demo1         https://youtu.be/c_Gxq5UKYd4 -->
<!-- Demo2         https://youtu.be/69InfsTlqqA -->


[1]: https://clonehero.net/