How much CPU time a sound engine uses

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
How much CPU time a sound engine uses
by on (#71671)
Work on a NES sound engine raised my interest, how much CPU time sound engines from commercial games take. I got idea that I could measure it if I mod a NSF plugin, and tried it. I took Nosefart (was easy to compile, no other reasons) and added a cycle counter into it. I'm not sure it gives correct results, though, because some numbers are somewhat strange. I would understand if the numbers were too large (some non-sound code leaved in a NSF), but they are actually unbeliveable small.

For comparsion, numbers for my engine are <2000 cycles average, 3866 max (measured with VirtuaNES mod).

Some results for some games:

Batman, first stage - 1085, 3780
Battletoads, title song - 482, 1820
Battletoads and Double Dragons, title song - 726, 3344
Contra, first stage - 1090, 4554
Megaman, Cutman stage - 2311, 7639
Ferrari Grand Prix Challenge, title screen - 1583, 4317

Average here is per 1000 frames.

Would be interesting to compare this with results from VirtuaNES, through hacking. Experienced NSF ripper could do that rather easily.

If you want the modded plugin, it is here. It creates a text file after you stop song. When used with Winamp, seems you have to restart the Winamp to reset min/max (by some reason).

by on (#71676)
Results from the Megaman are confirmed by Gil, who tested it with the game and VirtuaNES (his results are 2075, 8252). jsr also confirms he getting similar numbers with his tests.

I can only wonder how Rare programmers managed to make so fast player in Battletoads then. And how Capcom programmers managed to make so slow player (at times) with rather simple sound.

by on (#71680)
I remember Bananmos had also looked into Megaman and said the sound engine was really inefficient.

It seems like the maximum would be the main thing to worry about. With Megaman, Cutman stage that comes out to over 67 NTSC scanlines. That's a lot of time.

by on (#71682)
My guess is that Megaman engine optimized by data size. Let's say, Contra has 8 songs by ~1 minute long, and three jingles, and it's NSF is 17K. Megaman 1 has about 10 songs with similar durations, and few jingles, and it is just 11K. Battletoads has about 20 songs, but it's NSF is 32K - probably optimized for speed.

by on (#71683)
Famitracker is ~1800 cycles on average, DragNSF v1 is ~1050 cycles on average.

by on (#71686)
I guess one way to reduce the worst-case time for a music engine is to process loading the next pattern in a separate frame on each channel. Do any music engines in commercial games do this?

by on (#71688)
Don't know about commercial games, but it was used in some players on home computers. Drawback of this method is limitation for max song speed/tempo, but you can have at least one additional frame, because speed 1 is surely not common.

by on (#75493)
I added NSF init/play timing to Nintendulator and got very similar results. Also worth noting is that Tim Follin tunes (Solstice, Silver Surfer, Tom & Jerry) are there in the same ballpark with Rare tunes with around 500-700 cycles avg. SMB3 also isn't too bad, only ~700 cycles on avg.

Darkwing Duck title tune uses 3,7k cycles on avg. :shock:

by on (#75538)
Dwedit wrote:
Famitracker is ~1800 cycles on average, DragNSF v1 is ~1050 cycles on average.


Playing around with this, it seems very dependent on the song.

Famitracker:

(FCM7) Dimension-Reversing Dualities: Min 1404 Max 7554 Average 2966
SundayAfternoonJam (No DPCM): Min 21 Max 6663 Average 1830
Greensleeves (No DPCM): Min 1196 Max 5604 Average 1870
(FCM7) Identity: Min 1050 Max 6824 Average 2840


PPMCK:

Fugue/Prelude in C minor: Min 425 Max 6790 Average 2376
Out There: Min 561 Max 5455 Average 1264
Secret of Mana/Grim Determination: Min 361 Max 5230 Average 1285

by on (#75541)
Quote:
It creates a text file after you stop song.

May I ask where ? Because I can't find any in Winamp nor in the NSF's folder.

by on (#75558)
In WinAmp (or other player you use) folder.

by on (#75563)
It may not have write rights to the application folder if it's not run as an administrator.

by on (#75567)
thefox wrote:
It may not have write rights to the application folder if it's not run as an administrator.

Then can you modify it to spit out the text file somewhere in the user's profile?

I really need to profile my own music engine sometime.

by on (#75568)
Found it !

I think my "simple" sound engine kicks all other's (including Battletoads') butt :wink: :
Min 136 Max 4076 Average 479

Then the semi-completed more complex sound engine I've done (with support of more effects such as vibratoes) has this :
Min 136 Max 7595 Average 3257


Which is MUCH less good. It wasn't finished or optimized anyway so that's why.

by on (#75570)
tepples, I can modify it if you have certain request - like 'put the file in .. dir' or 'display message box'. Also, I can't check if it works under non-administrator rights.

Bregalad, low average time is important thing, but peak time is also important, because usually it is few times greater than average, and it could introduce noticeable lag into the gameplay. Battletoads is 482 average vs 472 of your engine, but it has 1820 peak time, which is noticeably lower than 4076, so it has less chances to introduce the lag.

by on (#75571)
Shiru wrote:
tepples, I can modify it if you have certain request - like 'put the file in .. dir'

Common practice under Windows is for a program to create a folder within Application Data and drop stuff in there. The proper way to get the path to Application Data is through SHGetFolderPath. It'll look something like this:
Code:
char appData[MAX_PATH];

// SHGetFolderPath documented at
// http://msdn.microsoft.com/en-us/library/bb762181%28v=vs.85%29.aspx
// It fills appData with the path to the folder.
HRESULT err = SHGetFolderPath(NULL,
                              CSIDL_APPDATA|CSIDL_FLAG_CREATE,
                              NULL,
                              0,
                              appData);

// Then create a folder inside appData into which your app drops stuff.

Common practice under Linux is to create a folder inside the home directory whose name starts with a period and drop stuff in there.

The source code for Lockjaw demonstrates one way to do this.

by on (#75572)
http://thefox.aspekt.fi/nintendulator-nsf-timing.zip

Here's a special build of Nintendulator (mappers not included) in case anybody needs it. Open the debugger window to view the NSF init/play cycle counts. Note that the debugger window has to be open before the NSF starts for it to display the init cycles. This can be remedied by pressing RESET in the debugger. Also remember to press RESET always after changing songs (by pressing prev/next).

by on (#75573)
Shiru wrote:
Bregalad, low average time is important thing, but peak time is also important, because usually it is few times greater than average, and it could introduce noticeable lag into the gameplay. Battletoads is 482 average vs 472 of your engine, but it has 1820 peak time, which is noticeably lower than 4076, so it has less chances to introduce the lag.

This is true, but I'm pretty sure the max is at the begining when initializing all channels, it should take a lot of time to do that, and then the engine don't do that again until you start the next song. So if it would lag during gameplay it would lag one time which isn't all that bad.

Also I was kind of hironic but happy that the worst average of all of my songs were 10 cycles less than the best engine (which is completely negligible by the way). For smaller songs that didn't use all 4 channels, the average would be lower, the lowest I got was in the 350s.

by on (#75574)
"Initializing all channels" happens whenever the next pattern starts. "Starting the next song" happens during gameplay when the player enters a new area or certain events happen, such as time or oxygen running low or approaching the boss's room.

by on (#75576)
tepples, I know what the MSDN is, etc. Just tell me what exactly you need, not what common practices are. Alternatively, you can do the changes by yourself, the place is /src/machine/nsf.c, line 383.