Understanding a C64 program on the melody of a song as math equations

  • Thread starter tade
  • Start date
  • #1
tade
721
26
I came across this pretty impressive audio-visual demo called "A Mind is Born", as part of the challenge, it was done on a Commodore 64 and used just 256 bytes of memory to push the limits of the restrictions.
It utilizes procedural generation and I was reading this detailed write-up on it: https://www.linusakesson.net/scene/a-mind-is-born/index.php

And someone also made a piano version of the song where the notes are especially clear:

The thing which I'm interested in is how the program generates the notes of the melody. I'm interested in the math formulas by which the notes are created, actually moreso than in the coding and programming aspects.

And I'm quite the technical noob, so reading the write-up, I hardly understand what's going on. The last section of it is "Generating the melody". And what I'd like is to have assistance to understand the write-up and the program, to explain the code in terms of just math formulas, the math formulas on how the notes of the melody are generated. So hopefully my objective is simple enough for my lack of technical acumen lol
And so if you can assist with the BASIC many thanks 👍
 
Last edited:
Technology news on Phys.org
  • #2
The C64 had a sound chip. It wasn't done in software. You could shape the sound you wanted but the hardware handled the details of shaping the sound dynamically.





What you could do using BASIC to construct the sound you wanted:

 
  • Like
  • Informative
Likes hutchphd, DrClaude, Vanadium 50 and 2 others
  • #4
jedishrfu said:
The C64 had a sound chip. It wasn't done in software. You could shape the sound you wanted but the hardware handled the details of shaping the sound dynamically.





What you could do using BASIC to construct the sound you wanted:


oh i see, interesting, thanks for the resources

i was wondering how the author's (Linus Åkesson's) program procedurally generates the notes of the melody
 
  • #5
The program uses a Linear Feedback Shift Register (LFSR)
https://en.wikipedia.org/wiki/Linear-feedback_shift_register
This is a rather bad random number generator (for music this maybe good), that uses only a single byte for the seed, so it will repeat after at most 256 values.
The following python program reproduces the melody, starting with the last beat of measure 31.
Python:
seed = 65

notes = "_ecaBbCA"

for count in range (0,256):
    carry  = seed & 1
    seed = seed >> 1
    if carry:
        seed ^= 184
    print(notes[n], end = ' ')

The melody uses only 7 notes and a rest, according to the following table
Code:
freq   note    code
0       rest    0
16      A       7
18      B       4
19      C       6
24      e       1
32      a       3
36      b       5
38      c       2

The program only sets the high byte of the frequency register of the sound chip, and leaves the low byte at 0. These maybe the only notes that do not sound horrible.

The piano uses these notes, but the Commodore 64 will be tuned a bit higher, wich will depend on the clock frequency, wich depends on if you have a PAL or NTSC system.
 
  • Like
Likes tade and jedishrfu
  • #6
willem2 said:
The program uses a Linear Feedback Shift Register (LFSR)
https://en.wikipedia.org/wiki/Linear-feedback_shift_register
This is a rather bad random number generator (for music this maybe good), that uses only a single byte for the seed, so it will repeat after at most 256 values.
The following python program reproduces the melody, starting with the last beat of measure 31.
Python:
seed = 65

notes = "_ecaBbCA"

for count in range (0,256):
    carry  = seed & 1
    seed = seed >> 1
    if carry:
        seed ^= 184
    print(notes[n], end = ' ')

The melody uses only 7 notes and a rest, according to the following table
Code:
freq   note    code
0       rest    0
16      A       7
18      B       4
19      C       6
24      e       1
32      a       3
36      b       5
38      c       2

The program only sets the high byte of the frequency register of the sound chip, and leaves the low byte at 0. These maybe the only notes that do not sound horrible.

The piano uses these notes, but the Commodore 64 will be tuned a bit higher, wich will depend on the clock frequency, wich depends on if you have a PAL or NTSC system.
nice, great 👍

so for example, the speaker (of a C64) outputs note B at half the frequency of note C right? becoming like a physics question lol

and mathematically, what operation is first done to the initial seed value of 65? to express it in terms of just math equations
 
Last edited:
  • #7
tade said:
so for example, the speaker (of a C64) outputs note B at half the frequency of note C right? becoming like a physics question lol
No, the frequency values for A and B are 16*256 and 18 * 256, so the ratio between them is 9/8 = 1.125, the exact ration for a whole tone in just intonation. On an equal tempered piano that ratio would be 2^(2/12) = 1.1224... You probably can't hear the difference of 0.23% between those.
The e is 1.5 times the frequency of A, and a = 2x the frequency of A.

Code:
freq   note    code     ratio       equal tempered ratio
0       rest    0
16      A       7       1           1
18      B       4       1.125       1.1225
19      C       6       1.1875      1.1892
24      e       1       1.5         1.4983
32      a       3       2           2
36      b       5       2.25        2.2449
38      c       2       2.375       2.3784

The equal tempered frequency ratios will be used on a piano, and are also used in normal commodore 64 music programs, that use the full 16 bit frequency register of the SID chip. The maximum error here is with the b note, about 1% which still sounds Ok.
 
  • Like
Likes tade and jedishrfu
  • #8
willem2 said:
No, the frequency values for A and B are 16*256 and 18 * 256, so the ratio between them is 9/8 = 1.125, the exact ration for a whole tone in just intonation. On an equal tempered piano that ratio would be 2^(2/12) = 1.1224... You probably can't hear the difference of 0.23% between those.
The e is 1.5 times the frequency of A, and a = 2x the frequency of A.
oh yeah, sorry my bad, i made a mistake, i meant to ask if the speaker (of a C64) outputs note B at half the frequency of note b (becoming like a physics question lol) which i guess it does

and cool, you seem to be pretty knowledgeable on music too

and also i'd like to figure out the LFSR/python steps expressed in terms of just math equations, thanks :thumbup:
 
  • #10
  • #11
tade said:
oh i see, and sorry i meant the formulas for Åkesson's generation of his song's melody
There aren't any "formulas" involved: the word "formula" doesn't really have much use in computing (or science generally except for chemistry). The word you want here is algorithm.

In simple terms the program works out which note to play next by using the last digit of a (pseudo-)random number.

The algorithm (a crude linear feedback shift register) is explained in less simple terms above.
 
  • #12
pbuk said:
In simple terms the program works out which note to play next by using the last digit of a (pseudo-)random number.

The algorithm (a crude linear feedback shift register) is explained in less simple terms above.
so does it begin with the last digit of the seed, which i guess is 5

and then what's the next immediate mathematical operation which is performed on the number 5
 
  • #13
tade said:
so does it begin with the last digit of the seed, which i guess is 5
No, computers work in binary so it actually uses the last 3 binary digits (bits) of an 8-bit pseudo-random number.

This is not BASIC, it is 6502 assembler code (including an undocumented trick). This is not something you are going to fully understand until you are no longer
tade said:
quite the technical noob

@willem2's Python code is a bit easier to read but to understand what's going on you will need to learn about the logical operators AND, XOR (exclusive or) and bitwise shifts. Asking about "mathematical operations" is not going to help.
 
  • #15
The SID Chip was amazingly advanced and sophisticated for its time. With the addition of a memory expander, it was quite a formidable little device.

I arranged dozens of songs on it, including the entirety of Bach's Toccata and Fugue in D Minor, using up the entire 512K RAM expansion.
 
  • #16
Actually I've just noticed an error or two in @willem2's code so I have rewritten it below with more comments to help you work out what's going on.

Python:
# Print a binary value in a friendly way.
def byteToBinary(value):
    text = bin(value + 0x100)
    return text[3:7] + ' ' + text[7:11]

# Print some headings.
print(' current  index note')
print('--------- ----- ----')

# Set up the table of notes.
notes = '_ecaBbCA'

# Set the constants that determine the pseudo-random pattern.
# We are using these for bitwise operations so it makes most
# sense to show these in binary.
SEED =     0b01000001 # 0x41
CONSTANT = 0b10111000 # 0xb8

# Initialize the current value.
current = SEED

while True:
    # Test if the current value is odd.
    isOdd = current & 1

    # Shift the current value 1 bit to the right.
    current = current >> 1
 
    # If the value was odd...
    if (isOdd):
        # XOR with the constant.
        current = current ^ CONSTANT
 
    # Stop when the current value has looped round to the
    # seed to avoid an infinite loop.
    if current == SEED: break

    # Use the lowest 3 bits of the value to index the notes.
    index = current & 7

    print(byteToBinary(current), ' ', index, '   ', notes[index])
And the output:
Code:
 current  index note
--------- ----- ----
1001 1000   0     _
0100 1100   4     B
0010 0110   6     C
0001 0011   3     a
1011 0001   1     e
1110 0000   0     _
0111 0000   0     _
0011 1000   0     _
0001 1100   4     B
0000 1110   6     C
0000 0111   7     A
1011 1011   3     a
...
 
  • #17
pbuk said:
Actually I've just noticed an error or two in @willem2's code so I have rewritten it below with more comments to help you work out what's going on.

Python:
# Print a binary value in a friendly way.
def byteToBinary(value):
    text = bin(value + 0x100)
    return text[3:7] + ' ' + text[7:11]

# Print some headings.
print(' current  index note')
print('--------- ----- ----')

# Set up the table of notes.
notes = '_ecaBbCA'

# Set the constants that determine the pseudo-random pattern.
# We are using these for bitwise operations so it makes most
# sense to show these in binary.
SEED =     0b01000001 # 0x41
CONSTANT = 0b10111000 # 0xb8

# Initialize the current value.
current = SEED

while True:
    # Test if the current value is odd.
    isOdd = current & 1

    # Shift the current value 1 bit to the right.
    current = current >> 1
 
    # If the value was odd...
    if (isOdd):
        # XOR with the constant.
        current = current ^ CONSTANT
 
    # Stop when the current value has looped round to the
    # seed to avoid an infinite loop.
    if current == SEED: break

    # Use the lowest 3 bits of the value to index the notes.
    index = current & 7

    print(byteToBinary(current), ' ', index, '   ', notes[index])
And the output:
Code:
 current  index note
--------- ----- ----
1001 1000   0     _
0100 1100   4     B
0010 0110   6     C
0001 0011   3     a
1011 0001   1     e
1110 0000   0     _
0111 0000   0     _
0011 1000   0     _
0001 1100   4     B
0000 1110   6     C
0000 0111   7     A
1011 1011   3     a
...

oh i see, hmmm, my apologies, the output of your code seems like a different melody from what its supposed to be
 
  • #18
tade said:
oh i see, hmmm, my apologies, the output of your code seems like a different melody from what its supposed to be
No these are the correct notes, starting with the last beat of measure 32. On measures 17-32 the shift register is reset every beat of the kick drum, and the last beat of measure 32 is the last time this happens.
I've noticed the following looking at this shift register.
- A bit shift register like this only produces 1 random bit each time, yet 3 bits are used. if the first bit pattern is
xyz , the next one is ?xy and then you get ??x
One consequence is that each note has only 2 different notes that can follow it, and two different notes that can precede it. A rest 000 alwas has a rest 000 or an 'e' 001 preceding it, and a rest (000) or a B (100) following it, so the last note before a rest is always an 'e' and the last note after a rest is a "B"
 
  • #19
tade said:
oh i see, hmmm, my apologies, the output of your code seems like a different melody from what its supposed to be
hmm seems like i made an error somewhere and i'll have to take a closer look at it
 
  • #20
willem2 said:
No these are the correct notes, starting with the last beat of measure 32. On measures 17-32 the shift register is reset every beat of the kick drum, and the last beat of measure 32 is the last time this happens.
I've noticed the following looking at this shift register.
- A bit shift register like this only produces 1 random bit each time, yet 3 bits are used. if the first bit pattern is
xyz , the next one is ?xy and then you get ??x
One consequence is that each note has only 2 different notes that can follow it, and two different notes that can precede it. A rest 000 alwas has a rest 000 or an 'e' 001 preceding it, and a rest (000) or a B (100) following it, so the last note before a rest is always an 'e' and the last note after a rest is a "B"

oh i see, interesting

and this part is more of a music question, i've got the list of notes and i'm trying to match them with the piano version, cos i'm not sure if they do match



so 7 notes in an octave, and the song uses consecutive octaves
In "key1", a minus sign means that the note belongs to the lower octave, and a plus sign means the higher octave
In "key2", an equals sign means the lower octave, a minus sign the middle octave, and a plus sign the higher octave

Melody notes:
sr. note key1 key2
1    _    0    0
2    B    -3    =7
3    C    -4    -1
4    a    +2    -6
5    e    -6    -3
6    _    0    0
7    _    0    0
8    _    0    0
9    B    -3    =7
10    C    -4    -1
11    A    -2    =6
12    a    +2    -6
13    b    +3    -7
14    c    +4    +1
15    b    +3    -7
16    c    +4    +1
17    b    +3    -7
18    c    +4    +1
19    b    +3    -7
20    C    -4    -1
21    A    -2    =6
22    A    -2    =6
23    A    -2    =6
24    a    +2    -6
25    e    -6    -3
26    B    -3    =7
27    c    +4    +1
28    b    +3    -7
29    c    +4    +1
30    e    -6    -3
31    _    0    0
32    _    0    0
33    B    -3    =7
34    c    +4    +1
35    e    -6    -3
36    B    -3    =7
37    C    -4    -1
38    A    -2    =6
39    A    -2    =6
40    A    -2    =6
41    A    -2    =6
42    A    -2    =6
43    A    -2    =6
44    a    +2    -6
45    e    -6    -3
46    _    0    0
47    _    0    0
48    B    -3    =7
49    c    +4    +1
50    b    +3    -7
51    C    -4    -1
52    A    -2    =6
53    A    -2    =6
54    a    +2    -6
55    e    -6    -3
56    _    0    0
57    B    -3    =7
58    C    -4    -1
59    a    +2    -6
60    b    +3    -7
61    c    +4    +1
62    e    -6    -3
63    _    0    0
64    _    0    0
65    _    0    0
66    _    0    0
67    _    0    0
68    B    -3    =7
69    c    +4    +1
70    e    -6    -3
71    _    0    0
72    B    -3    =7
73    C    -4    -1
74    A    -2    =6
75    a    +2    -6
76    e    -6    -3
77    _    0    0
78    B    -3    =7
79    c    +4    +1
80    e    -6    -3
81    B    -3    =7
82    c    +4    +1
83    b    +3    -7
84    C    -4    -1
85    A    -2    =6
86    a    +2    -6
87    e    -6    -3
88    _    0    0
89    _    0    0
90    _    0    0
91    _    0    0
92    B    -3    =7
93    C    -4    -1
94    a    +2    -6
95    e    -6    -3
96    B    -3    =7
97    c    +4    +1
98    e    -6    -3
99    B    -3    =7
100    c    +4    +1
101    e    -6    -3
102    B    -3    =7
103    C    -4    -1
104    a    +2    -6
105    b    +3    -7
106    C    -4    -1
107    A    -2    =6
108    a    +2    -6
109    e    -6    -3
110    B    -3    =7
111    c    +4    +1
112    e    -6    -3
113    _    0    0
114    _    0    0
115    _    0    0
116    B    -3    =7
117    c    +4    +1
118    b    +3    -7
119    c    +4    +1
120    b    +3    -7
121    C    -4    -1
122    a    +2    -6
123    b    +3    -7
124    C    -4    -1
125    a    +2    -6
126    b    +3    -7
127    c    +4    +1
128    b    +3    -7
129    C    -4    -1
130    a    +2    -6
131    e    -6    -3
132    B    -3    =7
133    c    +4    +1
134    b    +3    -7
135    C    -4    -1
136    a    +2    -6
137    e    -6    -3
138    _    0    0
139    _    0    0
140    B    -3    =7
141    C    -4    -1
142    A    -2    =6
143    A    -2    =6
144    A    -2    =6
145    a    +2    -6
146    b    +3    -7
147    C    -4    -1
148    a    +2    -6
149    b    +3    -7
150    C    -4    -1
151    A    -2    =6
152    A    -2    =6
153    a    +2    -6
154    b    +3    -7
155    c    +4    +1
156    b    +3    -7
157    C    -4    -1
158    A    -2    =6
159    a    +2    -6
160    b    +3    -7
161    c    +4    +1
162    e    -6    -3
163    _    0    0
164    B    -3    =7
165    c    +4    +1
166    e    -6    -3
167    _    0    0
168    _    0    0
169    B    -3    =7
170    C    -4    -1
171    a    +2    -6
172    b    +3    -7
173    C    -4    -1
174    a    +2    -6
175    e    -6    -3
176    _    0    0
177    B    -3    =7
178    C    -4    -1
179    A    -2    =6
180    A    -2    =6
181    a    +2    -6
182    e    -6    -3
183    B    -3    =7
184    C    -4    -1
185    A    -2    =6
186    a    +2    -6
187    e    -6    -3
188    B    -3    =7
189    C    -4    -1
190    a    +2    -6
191    e    -6    -3
192    _    0    0
193    B    -3    =7
194    c    +4    +1
195    b    +3    -7
196    C    -4    -1
197    a    +2    -6
198    b    +3    -7
199    c    +4    +1
200    e    -6    -3
201    B    -3    =7
202    c    +4    +1
203    e    -6    -3
204    _    0    0
205    B    -3    =7
206    c    +4    +1
207    b    +3    -7
208    c    +4    +1
209    e    -6    -3
210    B    -3    =7
211    c    +4    +1
212    b    +3    -7
213    c    +4    +1
214    b    +3    -7
215    c    +4    +1
216    e    -6    -3
217    B    -3    =7
218    C    -4    -1
219    A    -2    =6
220    a    +2    -6
221    b    +3    -7
222    C    -4    -1
223    A    -2    =6
224    a    +2    -6
225    b    +3    -7
226    C    -4    -1
227    a    +2    -6
228    e    -6    -3
229    B    -3    =7
230    C    -4    -1
231    A    -2    =6
232    A    -2    =6
233    a    +2    -6
234    b    +3    -7
235    C    -4    -1
236    A    -2    =6
237    A    -2    =6
238    A    -2    =6
239    A    -2    =6
240    a    +2    -6
241    b    +3    -7
242    c    +4    +1
243    e    -6    -3
244    B    -3    =7
245    C    -4    -1
246    a    +2    -6
247    e    -6    -3
248    B    -3    =7
249    C    -4    -1
250    a    +2    -6
251    b    +3    -7
252    c    +4    +1
253    b    +3    -7
254    c    +4    +1
 
  • #21
willem2 said:
I've noticed the following looking at this shift register.
- A bit shift register like this only produces 1 random bit each time, yet 3 bits are used. if the first bit pattern is
xyz , the next one is ?xy and then you get ??x
One consequence is that each note has only 2 different notes that can follow it, and two different notes that can precede it.
Yes: for this application this is an advantage because it avoids dissonant intervals and provides a structure. If any note could follow any other it would sound terrible.

Music composed (or performed) like this is sometimes called aleatoric music.
 
  • #22
tade said:
hmm seems like i made an error somewhere and i'll have to take a closer look at it
@pbuk so i saw my mistake and fixed it, as in the note-list in post #20, though i'm still having difficulty matching the note-list to the correct melody
 
  • #23
tade said:
so 7 notes in an octave, and the song uses consecutive octaves
In "key1", a minus sign means that the note belongs to the lower octave, and a plus sign means the higher octave
In "key2", an equals sign means the lower octave, a minus sign the middle octave, and a plus sign the higher octave
I'm not sure what you mean by this, but the score in the YouTube video includes both the melody (on the upper stave) and what Linus refers to as the 'drone' on the lower (bass) stave. The drone is generated seperately as described in the article.

After being repeatedly restarted for 16 bars, sounding just the B and C, the melody proper 'kicks in' [Edit: 2.5] 3.5 beats into bar 32 (at about 38 seconds), at the second half of the [Edit: quaver] crotchet rest (each generated note or rest is a [Edit: semiquaver] quaver). Note that when you get to bar 49, the piano notes are doubled in octaves to imitate the effects used in the SID chip.
 
Last edited:
  • #24
pbuk said:
I'm not sure what you mean by this, but the score in the YouTube video includes both the melody (on the upper stave) and what Linus refers to as the 'drone' on the lower (bass) stave.
i'm referring to the note-list in #20. the seven notes used by the melody can be placed within two consecutive octaves (key1), or three consecutive ones too (key2)
and the numbers in the list refer to which note in an octave they are, if you number the notes in an octave from 1 to 7

pbuk said:
After being repeatedly restarted for 16 bars, sounding just the B and C, the melody proper 'kicks in' 2.5 beats into bar 32 (at about 38 seconds), at the second half of the quaver rest (each generated note or rest is a semiquaver).
in the piano video, the melody kicks in at about 0:39, and which number under the "sr." column does this point in time correspond to?
 
  • #25
tade said:
in the piano video, the melody kicks in at about 0:39, and which number under the "sr." column does this point in time correspond to?
The B on the fourth beat of bar 32 highlighted in the screengrab from the video below is the first (sounded) note of the melody, labelled 2 in your "sr." column.
1696509712010.png
 
  • #26
pbuk said:
The B on the fourth beat of bar 32 highlighted in the screengrab from the video below is the first (sounded) note of the melody, labelled 2 in your "sr." column.
View attachment 333069

thanks, and seems like there's something rather odd and interesting

go to https://virtualpiano.net , and under the "Sound" settings, turn off the sustain because it doesn't sound too good

and then make the piano auto-play the following string of keys:
dp uiy dfgfgfgfiy yydpugfgpugpuiyyyyyydpugfiyydpuidfgpugpuiydpugpugfiydpuidpugpugpuidfiydpugpugfgfidfidfgfidpugfidpuiyyydfidfiyydfgfiydfgpugpuidfidpuiyydpuiydpuidpugfidfgpugpugfgpugfgfgpuiydfiydfidpuiyydfiyyyydfgpuidpuidfgfg

i've managed to match and sort out the beginning of the song, but its getting quite difficult with the remainder

and its interesting that the beginning does match, and the rest of the string does sound very similar to the actual song

though i also notice quite a few repeated strings of y's which seem to be a quirk

and the string also seems to be missing out parts of the actual song
 
  • #27
tade said:
Good grief, is that site supposed to help anyone to learn anything about music? It seems utter nonsense to me.

tade said:
though i also notice quite a few repeated strings of y's
'y' on that site is D above middle C but there are no D's in the tune that is the subject of this thread.
 
  • #28
pbuk said:
Good grief, is that site supposed to help anyone to learn anything about music? It seems utter nonsense to me.
hmm seemed like a handy way to play some notes online

pbuk said:
'y' on that site is D above middle C but there are no D's in the tune that is the subject of this thread.
oh, i was thinking that the notes with the frequencies of 18, 19 and 24 are respectively each about 2, 3 and 7 semitones above the note with the frequency of 16

and if the note with the frequency of 16 is a D those increases in semitones would correspond with the notes of E, F and A
 
  • #29
tade said:
hmm seemed like a handy way to play some notes online
Lots of the write-up is nonsense and the key layout is crazy: if "i" is middle C then the logical key for C# (and the one that most other online pianos would use) is "9", not "I".

tade said:
if the note with the frequency of 16 is a D those increases in semitones would correspond with the notes of E, F and A
That is true but in the piano score the note with the "frequency" of 16 is scored as an A (however in the video of it playing on the C64 it sounds closer to Bb: the creator of the piano video presumably sharpened the piano pitch).

There is another complication: between bars 32 and 39 (shown as 64 and 78 in the piano score):
"The waveform is changed to $53, i.e. mixed waveform $51 with hard-sync. The hard-sync modifies the timbre of the sound, while also causing some notes to sound alike and other notes to disappear entirely, creating variety in the melody."​
Exactly what notes are heard during this passage therefore depends on the inner workings of the C64 SID (which is why the generated notes do not match what is being heard).
 
  • #30
pbuk said:
That is true but in the piano score the note with the "frequency" of 16 is scored as an A (however in the video of it playing on the C64 it sounds closer to Bb: the creator of the piano video presumably sharpened the piano pitch).
yeah i guess as long as we're aware of the relative semitone distances between the notes

pbuk said:
There is another complication: between bars 32 and 39 (shown as 64 and 78 in the piano score):
"The waveform is changed to $53, i.e. mixed waveform $51 with hard-sync. The hard-sync modifies the timbre of the sound, while also causing some notes to sound alike and other notes to disappear entirely, creating variety in the melody."​
Exactly what notes are heard during this passage therefore depends on the inner workings of the C64 SID (which is why the generated notes do not match what is being heard).
oh i see, that's interesting

though i'm already having trouble matching the melody in the beginning right after the "dp uiy dfgfgfgfiy" part
 
  • #31
tade said:
thanks, and seems like there's something rather odd and interesting

and its interesting that the beginning does match, and the rest of the string does sound very similar to the actual song
and if your code has an error, i was wondering if there might be an interesting mathematical property behind how it still sounds like a hashed version of the actual song

perhaps it might be related to this aspect
willem2 said:
One consequence is that each note has only 2 different notes that can follow it, and two different notes that can precede it.
 
  • #32
Of note to the perceived octave doubling : that would almost certainly be sawtooth + square (same frequency, phase). Not sure if it's an up or down saw that does it.

(And, I imagine writing the RNG routine inline saves a few bytes compared to an external call. This thread's out of my league, mostly)
 
Last edited:
  • #33
hmmm27 said:
Of note to the perceived octave doubling : that would almost certainly be sawtooth + square (same frequency, in sync). Not sure if it's an up or down saw that does it.

(And, I imagine writing the RNG routine inline saves a few bytes compared to an external call. This thread's out of my league, mostly)
oh interesting
i'm mainly interested in how to get the sequence of key presses on a piano or something like that lol
 

Similar threads

Back
Top