How do I translate SMB music data to a list of frequencies?

Discuss NSF files, FamiTracker, MML tools, or anything else related to NES music.

Moderator: Moderators

Post Reply
exactspace
Posts: 2
Joined: Thu Dec 30, 2021 1:47 pm

How do I translate SMB music data to a list of frequencies?

Post by exactspace »

I have a commented disassembly of SMB1. I see there's different music sequence data, as well as frequency and timing lookup tables. I'm not exactly sure how these work together, but I have a somewhat successful reproduction of the 1-UP sound by:

1. Taking that1-UP music data, converting it to a decimal array
2. Converting the frequency lookup table to a decimal array
3. Use each index value +1 of the 1-UP music to associate which index to use on the frequency lookup table
4. Playing back that value as a sine wave frequency * 16.

Note that I'm not using any timing data. It's not a concern for now, and once I figure out how to use the music and frequency table, I'm sure I'll figure out how the timing works. Other music does not quite work with the process I have above. First off, many of the indices that result from the music values to reference a freq table index are out of range.

Right now I'm just using the squarewave 2 portion of music. The comments say:
;MUSIC DATA
;square 2/triangle format
;d7 - length byte flag (0-note, 1-length)
;if d7 is set to 0 and d6-d0 is nonzero:
;d6-d0 - note offset in frequency look-up table (must be even)
;if d7 is set to 1:
;d6-d3 - unused
;d2-d0 - length offset in length look-up table
;value of $00 in square 2 data is used as null terminator, affects all sound channels
;value of $00 in triangle data causes routine to skip note
This is the ground music part one:

Code: Select all

GroundM_P1Data:
      .db $85, $2c, $22, $1c, $84, $26, $2a, $82, $28, $26, $04
      .db $87, $22, $34, $3a, $82, $40, $04, $36, $84, $3a, $34
      .db $82, $2c, $30, $85, $2a
Is "d7" always the first hex value in those horizontal lists? I've taken a look through, and I don't see much of a correspondence if it equals a 1 or 0.

Looking at the frequencies, I see now that maybe converting this into a linear array was the wrong approach?

Code: Select all

FreqRegLookupTbl:
      .db $00, $88, $00, $2f, $00, $00
      .db $02, $a6, $02, $80, $02, $5c, $02, $3a
      .db $02, $1a, $01, $df, $01, $c4, $01, $ab
      .db $01, $93, $01, $7c, $01, $67, $01, $53
      .db $01, $40, $01, $2e, $01, $1d, $01, $0d
      .db $00, $fe, $00, $ef, $00, $e2, $00, $d5
      .db $00, $c9, $00, $be, $00, $b3, $00, $a9
      .db $00, $a0, $00, $97, $00, $8e, $00, $86
      .db $00, $77, $00, $7e, $00, $71, $00, $54
      .db $00, $64, $00, $5f, $00, $59, $00, $50
      .db $00, $47, $00, $43, $00, $3b, $00, $35
      .db $00, $2a, $00, $23, $04, $75, $03, $57
      .db $02, $f9, $02, $cf, $01, $fc, $00, $6a
I've also heard that the derived notes has a connection with the processor's clock speed. So maybe there's something in the math there for that.

So in the end, how do I derive a linear sequence of frequencies to play for any given piece of music that uses that square 2 waveform?
Joe
Posts: 650
Joined: Mon Apr 01, 2013 11:17 pm

Re: How do I translate SMB music data to a list of frequencies?

Post by Joe »

exactspace wrote: Fri Dec 31, 2021 12:01 pmIs "d7" always the first hex value in those horizontal lists? I've taken a look through, and I don't see much of a correspondence if it equals a 1 or 0.
It's talking about bit 7, the most-significant or leftmost bit of the byte. You can see if it's a 1 or 0 by converting the value to binary. (You should see a pattern emerge pretty quickly: in values from $00 to $7F bit 7 is 0, and in values from $80 to $FF bit 7 is 1.)
exactspace wrote: Fri Dec 31, 2021 12:01 pmLooking at the frequencies, I see now that maybe converting this into a linear array was the wrong approach?
You've got the right idea, but each entry is actually two bytes and not one since it takes 11 bits to program the note frequency. So, for example, the note value $06 indicates the two bytes $02 $A6 in the table. Take those two bytes together as a single value, $02A6 (decimal 678), and then convert to a frequency.

1.789773 MHz / ( ( 678 + 1 ) * 16 ) = 164.74 Hz

This formula is mentioned in the wiki a few times, including on this page.
exactspace
Posts: 2
Joined: Thu Dec 30, 2021 1:47 pm

Re: How do I translate SMB music data to a list of frequencies?

Post by exactspace »

exactspace wrote: Fri Dec 31, 2021 12:01 pmLooking at the frequencies, I see now that maybe converting this into a linear array was the wrong approach?
You've got the right idea, but each entry is actually two bytes and not one since it takes 11 bits to program the note frequency. So, for example, the note value $06 indicates the two bytes $02 $A6 in the table. Take those two bytes together as a single value, $02A6 (decimal 678), and then convert to a frequency.

1.789773 MHz / ( ( 678 + 1 ) * 16 ) = 164.74 Hz

This formula is mentioned in the wiki a few times, including on this page.
Thank you so much! That is a ton of help. What I've noticed though, is the formula you have calculates to 0.00016474. So you are implying that with the MHz value should be 1789773.

e: I got it by the way. It's really cool to hear it playing back from the raw disassembly. It's like seeing The Moon using a telescope with your own eyes for the first time, or something.

The frequencies are a little off from real note values. (Also some of this is obviously not frequency data) I got this for the underground music:

Code: Select all

261.35703
522.71405
219.76584
438.66986
233.04337
466.08673
111860.81
261.35703
522.71405
219.76584
438.66986
233.04337
466.08673
111860.81
174.50984
348.47604
146.79897
293.59793
155.36224
310.7245
111860.81
174.50984
348.47604
146.79897
293.59793
155.36224
310.7245
111860.81
310.7245
293.59793
276.8832
261.35703
310.7245
293.59793
207.53398
195.90335
276.8832
261.35703
369.1776
348.47604
329.00238
466.08673
438.66986
414.29932
310.7245
246.93336
233.04337
219.76584
207.53398
111860.81
816.50226
video of it happening: https://www.youtube.com/watch?v=uFn9BDe_kZo
Last edited by exactspace on Mon Jan 03, 2022 2:49 pm, edited 4 times in total.
Post Reply