For sound, the first thing I do is set a breakpoint on a write to one of the APU registers (usually $4000) and that will let me know which bank the sound engine is in.
The next thing I look for is the note table. On the NES, notes are 11-bit values that are written to the 3rd and 4th registers of each channel. ($4002/03 for Square 1, $4006/07 for Square 2, $400A/0B for Triangle).
Blargg's APU reference will help you to know what register does what. First I will try a hex search for common note values. (Look at
Celius's chart for reference). I'll search for the low A. Games generally store note values in two ways:
1) As pairs. ie, low A will be F107, Bb will be 8007, etc
2) Hi byte in one table, Low byte in another, in which case I'll search for something like "07 07 07 06 06" to see if I can spot the Hi byte table.
Not all games use Celius's values, so if F107 doesn't turn up for the low A, I'll try FF07, FE07, FD07, FC07, etc until I find it.
If I can't find the note table by hex searching, I will start the Trace Logger in FCEUXSP, and set a breakpoint for writes to these registers ($4002/03 for example) and then follow the bread-crumb trail backwards to see where they got the value.
After I get these two pieces of information, I'll try to find the song pointers, which has been described in the last couple of posts. Once I find the song pointers, I can look at the data. From here, I try to determine what bytes do what. Generally, there are four types of bytes:
1) note value (tells what note to play. A, B, C#, D, etc). These will usually jump out at you since they are the most frequent type
2) note length (tells whether you have a quarter note, 8th note, 16th note, etc)
3) opcodes (these bytes signal the sound engine to run subroutines that will do different things like set loops, alter the pitch, change song tempo, set the channel volume, etc. basically anything that 1) and 2) can't do).
4) operands for opcodes. After an opcode value, there will usually be one or more values that it takes as arguments/operands.
Each type will have a byte range. For the NES Final Fantasy 7 game for example, values of $00-3F are note lengths. $40-7F are notes and $C0-E5 are opcodes. You can usually guess the ranges just by looking at the data and listening to the song, but if that doesn't work, you can trace through the sound engine code and find them. There will usually be some branching code. For example, the final fantasy 7 code:
1) reads a byte from the song data
2) compares it to $40. If less than, jump to note length code
3) else compare to $C0. If less than, jump to note value code
4) else jump to opcode code.
Note values usually just index into the note table(s), and since I already know about the note table, I can quickly make a chart of what byte value equals what note.
Note lengths are fairly easy to figure out. Either they index into a note length table or they represent the note lengths themselves. (ie. 16th notes are half the value of 8th notes which are half the value of quarter notes, which are half the value of half notes, etc)
The opcodes take the most time to figure out and really require ASM knowledge. I usually have to trace through several frames of the sound engine one instruction at a time, taking notes along the way. You can try to speed up the process with ROM corruption though. Once you know which byte values are opcodes, you can alter the operands and listen for differences in the song. Changes in pitch or song speed can tip you off to whether the opcode alters the notes' pitch or the song tempo, for example.
Hope that helps! Good luck!
If anything I said wasn't clear, feel free to ask and I can try to explain it better.