NES chords and intervals
Moderator: Moderators
NES chords and intervals
I'm making my own game and I wanted some music. I found some sheet music for "Little Brown Jug". The music sounded pretty good. I wanted to make it sound better so I tried adding chords or intervals. I've been trying a combination of triangle and both square wave channels playing together in Perfect Fifth (seven semitones above root) intervals and major and minor chords. The Perfect Fifth interval sounds good but both chords sound sort of muddy and dissonant. Any ideas why? I thought chords would sound nice just as they do on my keyboard. Is it because of weird harmonics from square waves? Thanks for any help.
-
- Posts: 2158
- Joined: Sun Jun 05, 2005 2:04 pm
- Location: Minneapolis, Minnesota, United States
- Contact:
Are you coding your sound? well if you are, I have that problem too. There's something weird about balancing things out with 4002 and 4003. I have fixed values in 4003 like this:
music:
.db $90,$80,$70,$60,$50,$40,$30,$20,$30,$40,$50,$60,$70,$80,$90
I have that for a B flat scale that I have at the beggining of my basic minigame. This is what's going on in 4002:
musicc:
.db $BF,$B5,$A0,$90,$80,$7A,$6A,$60,$6A,$7A,$80,$90,$A0,$B5,$BF,$BF,$00
I could understand like musicc going down a value of $8 for like a halfstep, and $F for a wholestep, but I don't know why it did had to be set up like this. When I tried going down 8 for a halfstep and F for a wholestep, it got way screwed up, and there were all sorts of wrong notes, and it did not work at all. I have no idea why.
music:
.db $90,$80,$70,$60,$50,$40,$30,$20,$30,$40,$50,$60,$70,$80,$90
I have that for a B flat scale that I have at the beggining of my basic minigame. This is what's going on in 4002:
musicc:
.db $BF,$B5,$A0,$90,$80,$7A,$6A,$60,$6A,$7A,$80,$90,$A0,$B5,$BF,$BF,$00
I could understand like musicc going down a value of $8 for like a halfstep, and $F for a wholestep, but I don't know why it did had to be set up like this. When I tried going down 8 for a halfstep and F for a wholestep, it got way screwed up, and there were all sorts of wrong notes, and it did not work at all. I have no idea why.
Want to know the true formula behind note periods?
The 2A03 is clocked at M2 = 1789773 Hz (on NTSC), and if you write the 11-bit period p to the period register of a square wave channel, the square wave channels repeat once every 16*p CPU cycles, for a frequency of f = M2/(16*p). So if you want a given period p that will produce a given frequency f, it's p = M2/(16*f).
The frequency of the lowest valid note on the NES is 55 Hz, an A that's a bit more than 2 octaves below middle C. By the formula above, this is a period of 2034.
An octave is a 2:1 ratio (e.g. 2034 and 1017). A perfect fifth is a 3:2 ratio (e.g. 1017 and 678), and its complement is a perfect fourth, a 4:3 ratio (e.g. 1356 and 1017).
There are twelve semitones in an octave. To calculate their frequencies, you can use the rule of equal temperament. Given frequency f0 of the lowest valid note and an interval above it measuring n semitones, the frequency of this note is f = f0 * 2^(semitone number/12). Invert the formula for period: p = p0 / 2^(semitone number/12)
This post by 0xtob and my post a few column inches down should clarify things. Sample source code was posted here.
The 2A03 is clocked at M2 = 1789773 Hz (on NTSC), and if you write the 11-bit period p to the period register of a square wave channel, the square wave channels repeat once every 16*p CPU cycles, for a frequency of f = M2/(16*p). So if you want a given period p that will produce a given frequency f, it's p = M2/(16*f).
The frequency of the lowest valid note on the NES is 55 Hz, an A that's a bit more than 2 octaves below middle C. By the formula above, this is a period of 2034.
An octave is a 2:1 ratio (e.g. 2034 and 1017). A perfect fifth is a 3:2 ratio (e.g. 1017 and 678), and its complement is a perfect fourth, a 4:3 ratio (e.g. 1356 and 1017).
There are twelve semitones in an octave. To calculate their frequencies, you can use the rule of equal temperament. Given frequency f0 of the lowest valid note and an interval above it measuring n semitones, the frequency of this note is f = f0 * 2^(semitone number/12). Invert the formula for period: p = p0 / 2^(semitone number/12)
This post by 0xtob and my post a few column inches down should clarify things. Sample source code was posted here.
Thanks for the help. I used the same formulas to make a table of note frequencies and periods in the registers for both the square and triangle channels. I sort of understand the Wolf dissonance (not being any sort of musician). However the same chords played on my keyboard sound much better than on the NES (at least FCEUD emulation, I haven't put it into my devcart yet). I guess it could either be the emulation, the NES sound itself or the Wolf note or some combination. I suppose with a little bit of study I could alter the periods to avoid the Wolf problem. By the way, I made a table with 4 octaves (C2-B6) and the corresponding square and triangle periods if anybody wants it.
Lloyd Gordon
Lloyd Gordon
Not exactly.tepples wrote:An octave is a 2:1 ratio (e.g. 2034 and 1017). A perfect fifth is a 3:2 ratio (e.g. 1017 and 678), and its complement is a perfect fourth, a 4:3 ratio (e.g. 1356 and 1017).
Just try the formula :
2^(6/12)=1.49831 VS 3/2=1.50000
Pretty close, but NOT exactly the same value...
the same is valid about :
2^(5/12)=1.33484 VS 4/3=1.33333
very close but not the exact same. I've found a site explaining that in details and where there was sample tunes with both tuning method. And I founded the rational one pretty bad, while the logarithmic one sound better.
Useless, lumbering half-wits don't scare us.
That's because you're just used to the logarithmic one, with its wide-ass major 3rd and its narrow minor 3rd. Renaissance and Baroque music was written for just tuning or well temperament, not the modern equal temperament.Bregalad wrote:I've found a site explaining that in details and where there was sample tunes with both tuning method. And I founded the rational one pretty bad, while the logarithmic one sound better.
Interesting, heh. I just found the logarithmic one sounding better.tepples wrote: That's because you're just used to the logarithmic one, with its wide-ass major 3rd and its narrow minor 3rd. Renaissance and Baroque music was written for just tuning or well temperament, not the modern equal temperament.
Some people simply asked why there is 12 notes in an octave... and some answered it is because it's where both rational temperament and lograrithmic temperament were so close.
Anyway, the fact that there is 2 possible way of tuning should be mentionned.
Useless, lumbering half-wits don't scare us.
By the way, I made a programm to get the precise pitch on the NES, based from a note number (0-11), an octave number, and some different detune value to made pitch LFO, pitch bends and detunes. I foud fair to publish it there, because people is just talking about that :
This routine has 4 steps :
- Mix all different fine tunes (LFO, pitch bend and detune) together, to end up with a main detune value
- Add the corresponding main note to the fine detune value calculated before and make sure that the final value is in the correct octave range. If it's not, then modity the octave number to make it do.
- Add the table pointer to the tune pointer, and read data. Shift it right the number of octaves, if octave isn't minus.
- If octave is minus or if the period is above $800, just output with a pitch of $1 to make an inaudible sound, beacause the NES isn't able to produce very low frequenceys.
About the table, the values should be CPUSpeed/2^(n/384)*32.7*16, where n equals 0, then 1, then 2, up to 384 for each entry on the table.
If someone want to use it, I'll just post the some .dw line it does for NTSC, however, it's wrong in pal. (I used Excel to have those values fastly).
This routine has 4 steps :
- Mix all different fine tunes (LFO, pitch bend and detune) together, to end up with a main detune value
- Add the corresponding main note to the fine detune value calculated before and make sure that the final value is in the correct octave range. If it's not, then modity the octave number to make it do.
- Add the table pointer to the tune pointer, and read data. Shift it right the number of octaves, if octave isn't minus.
- If octave is minus or if the period is above $800, just output with a pitch of $1 to make an inaudible sound, beacause the NES isn't able to produce very low frequenceys.
Code: Select all
;Get a pitch (11 bit period)
;NoteOctave= Octave (0-8)
;PitchBend= Main pitch bend (-32768 - +32767)
;FineTune= Detune index (-128 - +127)
;VibFineTune = Vibrato detune index (-128 - +127)
;NotePitch = Main pitch (0-12)
;Output with PitchL, PitchH = walue to write in the period regs
GetPitch
lda #$00
sta PitchH
lda FineTune.w,X
clc
adc LFOFineTune.w,X ;Add LFO fine tune to main fine tune
sta PitchL ;Both are 8-bit signed
bpl +
bvs _fineTuneDone
dec PitchH ;If result is neg and if there is no overflow, the main thing is negative
bne _fineTuneDone
+ bvc _fineTuneDone
dec PitchH ;If result is positive and if there is overflow, the main thing is also negatinve
_fineTuneDone
lda PitchBendL.w,X
clc
adc PitchL
sta PitchL
lda PitchBendH.w,X
adc PitchH ;Add pitch bend (16 bit signed) to get a 16 bit signed result
asl PitchL
rol A
asl PitchL
rol A
asl PitchL
rol A ;Multiply the whole detune index by 8
;Add the note to the main pitch, then divide by 8
;This is the equivelent to multiply note by 32
clc
adc NotePitch
bmi _octaveAdjustNeg
_octaveAdjustPos
cmp #$0c
bcc _octaveAdjustDone
sec
sbc #$0c ;Add as many octaves than needed scince the detunes is higher than one octave
inc NoteOctave ;To avoid geting out of the pitch table because the detune would change the octave
jmp _octaveAdjustPos
_octaveAdjustNeg
clc
adc #$0c ;Same but remove octaves if the pitch goes one or more octave below
dec NoteOctave ;Note than PitchH is forcely positive from now
cmp #$0c
bcs _octaveAdjustNeg
_octaveAdjustDone
lsr A
ror PitchL
lsr A
ror PitchL
sta PitchH
lda PitchL
clc
adc #<PeriodTbl
sta PitchL
lda PitchH ;Load the pointer instead of pitch variables
adc #>PeriodTbl
sta PitchH
ldy #$00
lda [Pitch],Y
pha
iny
lda [Pitch],Y
sta PitchH
pla
ldy NoteOctave
bmi _PitchOutofRange
beq _octaveZero
cpy #$05
bcs _veryHighOctave
- lsr PitchH
ror A
dey
bne -
_octaveZero
sta PitchL
lda PitchH
cmp #$08 ;If the period is over 11 bits, the pitch is out of range
bcc +
_PitchOutofRange
lda #$01
sta PitchL ;Make an unaudible tone if pitch is out of range
lsr A
sta PitchH
+ rts
_veryHighOctave
- asl A
rol PitchH
iny
cpy #$08
bcc -
lda PitchH
sta PitchL
lda #$00
sta PitchH
rts
If someone want to use it, I'll just post the some .dw line it does for NTSC, however, it's wrong in pal. (I used Excel to have those values fastly).
Code: Select all
.dw 3420, 3414, 3408, 3402, 3396, 3390, 3383, 3377, 3371, 3365, 3359, 3353, 3347, 3341, 3335, 3329
.dw 3323, 3317, 3311, 3305, 3299, 3293, 3287, 3281, 3275, 3269, 3263, 3258, 3252, 3246, 3240, 3234
.dw 3228, 3223, 3217, 3211, 3205, 3199, 3194, 3188, 3182, 3176, 3171, 3165, 3159, 3153, 3148, 3142
.dw 3136, 3131, 3125, 3119, 3114, 3108, 3103, 3097, 3091, 3086, 3080, 3075, 3069, 3064, 3058, 3053
.dw 3048, 3042, 3037, 3031, 3026, 3020, 3015, 3009, 3004, 2998, 2993, 2988, 2982, 2977, 2972, 2966
.dw 2961, 2956, 2950, 2945, 2940, 2934, 2929, 2924, 2918, 2913, 2908, 2903, 2897, 2892, 2887, 2882
.dw 2877, 2871, 2866, 2861, 2856, 2851, 2846, 2840, 2835, 2830, 2825, 2820, 2815, 2810, 2805, 2800
.dw 2795, 2790, 2785, 2780, 2775, 2770, 2765, 2760, 2755, 2750, 2745, 2740, 2735, 2730, 2725, 2720
.dw 2715, 2710, 2705, 2700, 2696, 2691, 2686, 2681, 2676, 2671, 2667, 2662, 2657, 2652, 2647, 2643
.dw 2638, 2633, 2628, 2624, 2619, 2614, 2609, 2605, 2600, 2595, 2591, 2586, 2581, 2577, 2572, 2567
.dw 2563, 2558, 2553, 2549, 2544, 2540, 2535, 2531, 2526, 2521, 2517, 2512, 2508, 2503, 2499, 2494
.dw 2490, 2485, 2481, 2476, 2472, 2467, 2463, 2459, 2454, 2450, 2445, 2441, 2436, 2432, 2428, 2423
.dw 2419, 2415, 2410, 2406, 2401, 2397, 2393, 2389, 2384, 2380, 2376, 2371, 2367, 2363, 2359, 2354
.dw 2350, 2346, 2342, 2337, 2333, 2329, 2325, 2321, 2316, 2312, 2308, 2304, 2300, 2296, 2291, 2287
.dw 2283, 2279, 2275, 2271, 2267, 2263, 2259, 2254, 2250, 2246, 2242, 2238, 2234, 2230, 2226, 2222
.dw 2218, 2214, 2210, 2206, 2202, 2198, 2194, 2190, 2186, 2182, 2178, 2175, 2171, 2167, 2163, 2159
.dw 2155, 2151, 2147, 2143, 2139, 2136, 2132, 2128, 2124, 2120, 2116, 2113, 2109, 2105, 2101, 2097
.dw 2094, 2090, 2086, 2082, 2079, 2075, 2071, 2067, 2064, 2060, 2056, 2052, 2049, 2045, 2041, 2038
.dw 2034, 2030, 2027, 2023, 2019, 2016, 2012, 2008, 2005, 2001, 1998, 1994, 1990, 1987, 1983, 1980
.dw 1976, 1973, 1969, 1965, 1962, 1958, 1955, 1951, 1948, 1944, 1941, 1937, 1934, 1930, 1927, 1923
.dw 1920, 1916, 1913, 1910, 1906, 1903, 1899, 1896, 1892, 1889, 1886, 1882, 1879, 1875, 1872, 1869
.dw 1865, 1862, 1858, 1855, 1852, 1848, 1845, 1842, 1838, 1835, 1832, 1829, 1825, 1822, 1819, 1815
.dw 1812, 1809, 1806, 1802, 1799, 1796, 1793, 1789, 1786, 1783, 1780, 1776, 1773, 1770, 1767, 1764
.dw 1761, 1757, 1754, 1751, 1748, 1745, 1742, 1738, 1735, 1732, 1729, 1726, 1723, 1720, 1717, 1713
Useless, lumbering half-wits don't scare us.