Skip navigation
Welcome, Guest! Please Login or Join

Loading...

Homebrew Nerdy Nights Sound: Part 1 make a music/sfx engine

Aug 20, 2009 at 9:08:49 AM
MetalSlime (0)
avatar
(Thomas Hjelm) < Crack Trooper >
Posts: 140 - Joined: 08/14/2008
Japan
Profile
The APU

Music and sound effects on the NES are generated by the APU (Audio Processing Unit), the sound chip inside the CPU.  The CPU "talks" to the APU through a series of I/O ports, much like it does with the PPU and joypads.

PPU: $2000-$2007
Joypads: $4016-$4017
APU: $4000-$4015, $4017

Channels

The APU has 5 channels: Square 1, Square 2, Triangle, Noise and DMC.  The first four play waves and are used in just about every game.  The DMC channel plays samples (pre-recorded sounds) and is used less often.

Square
The square channels produce square waveforms.  A square wave is named for its shape.  It looks like this:
 

As you can see the wave transitions instantaneously from its high point to its low point (where the lines are vertical).  This gives it a hollow sound like a woodwind or an electric guitar.

Triangle
The triangle channel produces triangle waveforms.  A triangle wave is also named for its shape.  It looks like this:
 

The sound of a triangle wave is smoother and less harsh than a square wave. On the NES, the triangle channel is often used for bass lines (in low octaves) or a flute (in high octaves).  It can also be used for drums.

Noise
The noise channel has a random generator, which makes the waves it produces sound like.. noise.  This channel is generally used for percussion and explosion sounds.

DMC
The DMC channel plays samples, which are pre-recorded sounds.  It is often used to play voice recordings ("Blades of Steel") and percussion samples.  Samples take up a lot of ROM space, so not many games make use of the DMC channel.


Enabling Channels

Before you can use the channels to produce sounds, you need to enable them.  Channels are toggled on and off via port $4015:

APUFLAGS ($4015)

76543210
   |||||
   ||||+- Square 1 (0: disable; 1: enable)
   |||+-- Square 2
   ||+--- Triangle
   |+---- Noise
   +----- DMC

Here are some code examples using $4015 to enable and disable channels:   
   
   lda #%00000001
   sta $4015 ;enable Square 1 channel, disable others
 
   lda #%00010110
   sta $4015 ;enable Square 2, Triangle and DMC channels.  Disable Square 1 and Noise.
 
   lda #$00
   sta $4015 ;disable all channels
 
   lda #$0F
   sta $4015 ;enable Square 1, Square 2, Triangle and Noise channels.  Disable DMC.
             ;this is the most common usage.
             
Try opening up some of your favorite games in FCEUXD SP and set a breakpoint on writes to $4015.  Take a look at what values are getting written there.  If you don't know how to do this, follow these steps:

1. Open FCEUXD SP
2. Load a ROM
3. Open up the Debugger by pressing F1 or going to Tools->Debugger
4. In the top right corner of the debugger, under "BreakPoints", click the "Add..." button
5. Type "4015" in the first box after "Address:"
6. Check the checkbox next to "Write"
7. Set "Memory" to "CPU Mem"
8. Leave "Condition" and "Name" blank and click "OK"

Now FCEUX will pause emulation and snap the debugger anytime your game makes a write (usually via STA) to $4015.  The debugger will tell you the contents of the registers at that moment, so you can check what value will be written to $4015.  Some games will write to $4015 every frame, and some only do so once at startup.  Try resetting the game if your debugger isn't snapping.

What values are being written to $4015?  Can you tell what channels your game is using?


Square 1 Channel

Let's make a beep.  This week we'll learn how to produce a sound on the Square 1 channel.  The Square channels are everybody's favorites because you can control the volume and tone and perform sweeps on them.  You can produce a lot of interesting effects using the Squares.

Square 1 is controlled via ports $4000-$4003.  The first port, $4000, controls the duty cycle (ie, tone) and volume for the channel.  It looks like this:

SQ1_ENV ($4000)

76543210
||||||||
||||++++- Volume
|||+----- Saw Envelope Disable (0: use internal counter for volume; 1: use Volume for volume)
||+------ Length Counter Disable (0: use Length Counter; 1: disable Length Counter)
++------- Duty Cycle

For our purposes, we will focus on Volume and Duty Cycle.  We will set Saw Envelope Disable and Length Counter Disable to 1 and then forget about them.  If we leave Saw Envelopes on, the volume of the channel will be controlled by an internal counter.  If we turn them off, WE have control of the volume.  If WE have control, we can code our own envelopes (much more versatile).  Same thing with the Length Counter.  If we disable it, we have more control over note lengths.  If that didn't make sense, don't worry.  It will become clearer later.  For now we're just going to disable and forget about them.

Volume controls the channel's volume.  It's 4 bits long so it can have a value from 0-F.  A volume of 0 silences the channel.  1 is very quiet and F is loud.

Duty Cycle controls the tone of the Square channel.  It's 2 bits long, so there are four possible values:

00 = a weak, grainy tone.  Think of the engine sounds in RC Pro-Am. (12.5% Duty)
01 = a solid mid-strength tone. (25% Duty)
10 = a strong, full tone, like a clarinet or a lead guitar (50% Duty)
11 = sounds a lot like 01 (25% Duty negated)

The best way to know the difference in sound is to listen yourself.  I recommend downloading FamiTracker and playing with the different Duty settings in the Instrument Editor.

For those interested, Duty Cycle actually refers to the percentage of time that the wave is in "up" position vs. "down" position.  Here are some pictures:

12.5%
25%

50%

25% negated


Don't sweat it if graphs and waves aren't your thing.  Use your ears instead.

Here's a code snippet that sets the Duty and Volume for the Square 1 channel:

    lda #%10111111; Duty 10 (50%), volume F (max!)
    sta $4000

$4001 controls sweeps for Square 1.  We'll skip them for now.

Setting the Note
$4002 and $4003 control the period of the wave, or in other words what note you hear (A, C#, G, etc).  Periods are 11-bits long.  $4002 holds the low 8-bits and $4003 holds the high 3-bits of the period.  We'll get into more detail in a future tutorial, but for now just know that changing the values written to these ports will change the note that is played.

SQ1_LO ($4002)

76543210
||||||||
++++++++- Low 8-bits of period

SQ1_HI ($4003)

76543210
||||||||
|||||+++- High 3-bits of period
+++++---- Length Counter

The Length Counter, if enabled, controls how long the note is played.  We disabled it up in the $4000 section, so we can forget about it for now.

Here is some code that will produce an eternal beep on the Square 1 channel:

    lda #%00000001
    sta $4015 ;enable square 1
 
    lda #%10111111 ;Duty 10, Volume F
    sta $4000
 
    lda #$C9    ;0C9 is a C# in NTSC mode
    sta $4002
    lda #$00
    sta $4003
    
Putting It All Together
Download and unzip the square1.zip sample files. All the code above is in the square1.asm file. Make sure square1.asm and square1.bat are all in the same folder as NESASM3, then double click square1.bat. That will run NESASM3 and should produce the square1.nes file. Run that NES file in FCEUXD SP to listen to your beep!  Edit square1.asm to change the Volume (0 to F), or to change the Duty Cycle for the square wave.  Try changing the period to produce different notes.

Next Week: Square 2 and Triangle.  Multiple beeps!

-------------------------
MetalSlime runs away

My nesdev blog: http://tummaigames.com/blog...


Edited: 09/01/2016 at 11:22 PM by NintendoAge Moderator

Aug 20, 2009 at 9:48:07 AM
Jero (1)
avatar
(Jeroen ) < El Ripper >
Posts: 1103 - Joined: 03/02/2008
Netherlands
Profile
Good idea! I'll read trough it later......looks promising. :-)

Aug 20, 2009 at 9:53:06 AM
AllYourBass (101)
avatar
(Pepe Silvia) < Bowser >
Posts: 5709 - Joined: 06/22/2009
Alberta
Profile
Awesome! Thanks for keeping Nerdy Nights going.

Aug 20, 2009 at 3:33:32 PM
udisi (88)
avatar
< King Solomon >
Posts: 3261 - Joined: 11/15/2006
United States
Profile
excellent, I will have to look at this tonight.

Aug 20, 2009 at 7:03:32 PM
MODERATOR
KHAN Games (88)
avatar
(Kevin Hanley) < Master Higgins >
Posts: 7509 - Joined: 06/21/2007
Florida
Profile

Aug 20, 2009 at 7:31:53 PM
Zzap (47)
avatar
(James ) < King Solomon >
Posts: 3298 - Joined: 05/01/2007
Australia
Profile
Looks great, you followed bunnys styling perfectly I think I'm going to learn a bit about some of the intricacies of the APU here too

-------------------------

Chunkout for iPhone, iPad and iTouch out now!
Chunkout Games: FaceBook | Web

Aug 22, 2009 at 9:48:17 PM
udisi (88)
avatar
< King Solomon >
Posts: 3261 - Joined: 11/15/2006
United States
Profile
well, this is pretty neat, played around a bit, and now the ball makes a little "blip" sound when it hits my paddles. Still don't know enough to get the exact sound I want, but I figured out how to go up and down in key, and how to make it a short blip instead of a steady tone.

Aug 23, 2009 at 11:55:37 PM
Vaevictus (0)

(Nathan Mahon) < Cherub >
Posts: 2 - Joined: 08/23/2009
United States
Profile
Took me a while to find this.  for NTSC roms, here's the period table.  You can convert pitches to codes with it.
http://www.freewebs.com/the_bott/...
So, to play an E, 3rd octave... you'd change that code from $0C9 to $152.
Specifically:
    lda #$C9    ;0C9 is a C# in NTSC mode
    sta $4002
    lda #$00
    sta $4003
To:
    lda #$52    ;152 is a E3 in NTSC mode
    sta $4002
    lda #$01
    sta $4003


I can't wait for the next section! 

-------------------------
 

Aug 24, 2009 at 12:01:15 AM
udisi (88)
avatar
< King Solomon >
Posts: 3261 - Joined: 11/15/2006
United States
Profile
excellent, I was trying to figure this out. trying to see why $00c9 was a c# I knew there was something to it, that chart is awesome.

Aug 24, 2009 at 12:49:39 AM
MetalSlime (0)
avatar
(Thomas Hjelm) < Crack Trooper >
Posts: 140 - Joined: 08/14/2008
Japan
Profile
That's the chart I use too. I'm saving the period charts for week 3. I didn't want to overwhelm anybody in the first lesson

-------------------------
MetalSlime runs away

My nesdev blog: http://tummaigames.com/blog...

Aug 24, 2009 at 6:11:04 PM
Vaevictus (0)

(Nathan Mahon) < Cherub >
Posts: 2 - Joined: 08/23/2009
United States
Profile
oops... didn't need to preempt, but some of us might be working a bit ahead  

-------------------------
 

Aug 27, 2009 at 1:46:13 AM
MetalSlime (0)
avatar
(Thomas Hjelm) < Crack Trooper >
Posts: 140 - Joined: 08/14/2008
Japan
Profile
no problem at all. Working ahead is encouraged

-------------------------
MetalSlime runs away

My nesdev blog: http://tummaigames.com/blog...

Jul 19, 2016 at 1:24:16 AM
Zutano (0)
avatar
(Oliver ) < Cherub >
Posts: 3 - Joined: 10/29/2015
Alabama
Profile
Sorry to dig up such an old thread. It looks like the example code links are broken for every APU tutorial. Does anyone have a mirror?

Jul 19, 2016 at 5:40:14 AM
user (5)

< El Ripper >
Posts: 1223 - Joined: 05/30/2014
Profile
Originally posted by: Zutano

Sorry to dig up such an old thread. It looks like the example code links are broken for every APU tutorial. Does anyone have a mirror?

Mog posted a new link a while ago, but I can't find it now.


Jul 19, 2016 at 10:55:18 AM
Mog (140)
avatar
(Mr Mog) < King Solomon >
Posts: 4530 - Joined: 05/02/2009
New York
Profile
Originally posted by: user

Originally posted by: Zutano

Sorry to dig up such an old thread. It looks like the example code links are broken for every APU tutorial. Does anyone have a mirror?

Mog posted a new link a while ago, but I can't find it now.
 


Here you go

Jul 20, 2016 at 10:25:44 AM
Zutano (0)
avatar
(Oliver ) < Cherub >
Posts: 3 - Joined: 10/29/2015
Alabama
Profile
Originally posted by: Mog
 
Originally posted by: user
 
Originally posted by: Zutano

Sorry to dig up such an old thread. It looks like the example code links are broken for every APU tutorial. Does anyone have a mirror?

Mog posted a new link a while ago, but I can't find it now.
 


Here you go

Thanks!
 

Oct 11, 2016 at 12:30:33 PM
Erdrick (0)
avatar
< Cherub >
Posts: 2 - Joined: 10/11/2016
Profile
I am looking for the mirror links for this tutorial's sample codes and I can't see it in your post. I would really appreciate help finding the links. Thank you.

Oct 11, 2016 at 6:33:36 PM
MODERATOR
KHAN Games (88)
avatar
(Kevin Hanley) < Master Higgins >
Posts: 7509 - Joined: 06/21/2007
Florida
Profile
Originally posted by: Erdrick

I am looking for the mirror links for this tutorial's sample codes and I can't see it in your post. I would really appreciate help finding the links. Thank you.

Did you look at the attached file two posts up?
 

Jan 13 at 5:45:01 PM
thejonwithnoh (0)
avatar
< Cherub >
Posts: 2 - Joined: 01/13/2017
Denmark
Profile
I'm also looking for the mirror links for this tutorial's sample code, and I've looked at the message from Mog that says "Here you go" indicating that the mirror is attached, and then Zutano saying "Thanks!" afterwards, but there doesn't seem to actually be any link or attachment for me to click?  Sorry if I'm missing something obvious.

Jan 13 at 6:31:27 PM
Mega Mario Man (39)
avatar
< Lolo Lord >
Posts: 1960 - Joined: 02/13/2014
United States
Profile
Originally posted by: thejonwithnoh

I'm also looking for the mirror links for this tutorial's sample code, and I've looked at the message from Mog that says "Here you go" indicating that the mirror is attached, and then Zutano saying "Thanks!" afterwards, but there doesn't seem to actually be any link or attachment for me to click?  Sorry if I'm missing something obvious.





It's attached to Mog's post at the very botton. It's not a link.

-------------------------
Current Project
Tailgate Party

My Homebrews - Orab Games - On Facebook
  
Happy Hour , Power Pad Demo


Edited: 01/13/2017 at 06:32 PM by Mega Mario Man

Jan 13 at 8:37:36 PM
thejonwithnoh (0)
avatar
< Cherub >
Posts: 2 - Joined: 01/13/2017
Denmark
Profile
Originally posted by: Mega Mario Man
 
Originally posted by: thejonwithnoh

I'm also looking for the mirror links for this tutorial's sample code, and I've looked at the message from Mog that says "Here you go" indicating that the mirror is attached, and then Zutano saying "Thanks!" afterwards, but there doesn't seem to actually be any link or attachment for me to click?  Sorry if I'm missing something obvious.



It's attached to Mog's post at the very botton. It's not a link.


Thank you so much!  When I was a guest looking at this forum, the link was not available, and then when I got an account, I must have not looked over it carefully again.  Knew it had to be something simple.

Jan 14 at 2:59:48 AM
user (5)

< El Ripper >
Posts: 1223 - Joined: 05/30/2014
Profile
Originally posted by: thejonwithnoh

Thank you so much! When I was a guest looking at this forum, the link was not available, and then when I got an account, I must have not looked over it carefully again. Knew it had to be something simple.



By the way, welcome to NA Brewery!  
Nice to see few more Europeans.