All sound options explained?

Ask anything your want about the 32X Mushroom programming.

Moderator: BigEvilCorporation

Post Reply
matthewnimmo
Very interested
Posts: 52
Joined: Thu Jan 07, 2021 8:04 pm

All sound options explained?

Post by matthewnimmo » Mon Jan 16, 2023 5:11 pm

Hello everyone! So, probably like many here or have been, i'm wanting to write my own game within the 32x. I will do this. This is not just a fling or a hobby that i'm going to abandon like a half-willed new years resolution. With that said I'm going to need a little help on the journey. Granted, I've already read quite a bit and sampled many demos until my eyes have bled lol. So with that said, I wanted to discuss all audio possibilities when developing for the 32x and i'm hoping others can help really flesh this out.

After looking for all things audio have stumbled across various methods from years of postings on this forum. with all of that information it can become very "noisy" no pun intended. I've heard of DMA, PCM, VGM, CD Audio, MOD and i'm sure i'm forgetting a few other acronyms and methods. In a recent plead of ignorance on the SGDK discord channel I had posted up a question to one of the 32x veterans (vic) who definitely knows his stuff. The question was around should i implement Chilly's XMPlayer into his Tilemap demo as I really liked the tilemap but was curious on how to evolve it further. he had responded that It maybe wiser to leverage VGM or CD Audio as XMPlayer takes up one of the 32x cpus. that response really lead to me writing up this posting as i realized I've got a lot to learn. What would be the idea method for music/sound effects when creating a game with the 32x? I'm guessing the answer is ... it depends and this is where i'd like to tease out all the variations as well as why.

1) What IS DMA, PCM, VGM, CD Audio, and MOD options I keep reading about? I'm assuming that these are not all separate options but part of options used. I guess I don't quiet understand these except with CD audio...i know what that is, but have no clue on how to best implement that within 32x game development.

2) I'm assuming that some 32x games would leverage sound from the Genesis while AI, input, gfx are handled by the 32x cpus? If that's the case what would that setup look like? Any examples out there?

3) In a setup where you would want the 32x to handle the sound? What would be the best option for that? Any examples?

4) Are there cases that a game would require both the Genesis and 32x to handle sound? If so, what does that situation look like? Any examples?

5) What's the best way of handling the audio assets? I believe I saw a few tools out there that allow developers to convert their mp3's or whatever raw music/sfx into their desired format.

6) Any drawings/architecture or mappings of how these methods are implemented for example. Let's say Method X is the gold standard something like below
SoundArchitectureExample.png
SoundArchitectureExample.png (9.19 KiB) Viewed 508 times
Lastly, I know some of the recent postings (in 2022 and now 2023) just point to D32xr and say "just look there...its done right" While that is probably very true. it still leaves newbies like myself a little lost on the "why" is it considered the gold standard.

Thanks everyone! I hope much smarter then me people are able to flesh this out...I could really use some help.

Chilly Willy
Very interested
Posts: 2963
Joined: Fri Aug 17, 2007 9:33 pm

Re: All sound options explained?

Post by Chilly Willy » Mon Jan 16, 2023 8:09 pm

matthewnimmo wrote:
Mon Jan 16, 2023 5:11 pm
1) What IS DMA, PCM, VGM, CD Audio, and MOD options I keep reading about? I'm assuming that these are not all separate options but part of options used. I guess I don't quiet understand these except with CD audio...i know what that is, but have no clue on how to best implement that within 32x game development.
DMA: The SH2 processors have two Direct Memory Access Controllers (each). These allow you to set a source from which to fetch data, a destination to store the data to, a count of how much data to transfer, and a control register to tell the channel things like whether or not to increment or decrement (or neither) the source and destination, how big the data units to be transferred are (byte/word/long/16 bytes), if the transfer is done, if there was an error, and to generate an interrupt when the transfer is done. Set the source to a buffer of samples, set the destination to the PWM registers, set the source to increment, set the destination to NOT increment, set the size to long (for stereo samples), and start the dma to play the buffer of samples. Rather simple and requires little overhead by the cpu to play.

PCM: I'm assuming this is referring to the PCM chip in the Sega CD. This chip has eight channels capable of playing a special 8-bit digital sample stream. You can set the pitch of the sample, the length, the start, and where it will loop when it reaches the end. I wrote a library for the SCD to help use the pcm chip, and made a mod player using the library for the SCD to show how you could play MOD music on the SCD.

VGM: This is a general purpose game music format that consists of a list of commands to store values to music chips, and to play samples. As regards the Genesis, a VGM will have commands to store data to the FM or PSG chips, wait commands, and (optionally) commands to play samples to the DAC inside the FM chip. It's a very simple format, but can be big for long music tracks as there's no facility for having repeated parts throughout the song - it plays from the start to the end, and then either loops or quits.

CDDA: You can command the CD in the Sega CD to play CD audio tracks. This gives you full 44.1kHz, 16-bit stereo music of the highest quality, but you're limited to no more than maybe 80 minutes of music due to limits in storage on a CD.

MOD: This is the old tracker format for music that arose in the 16-bit era, primarily on the Amiga, but then spreading to the PC and Atari ST. You can find specifications for MOD online, but it mainly allows 4 (or more optionally) tracks with commands like setting an instrument for the track, setting the note the instrument will play, setting things like the volume/treble/pitchbend/etc. It allows to loop pieces and branch around the score so that long songs can be stored in small MODs. Most of the space in a mod tends to be samples for instruments. I've written MOD players for the 32X and SCD. If you hunt around this forum, you'll find links to the code.

Doom 32X Resurrection also shows how to play VGM, CDDA, and keep a DMA PWM buffer playing on the 32X.
2) I'm assuming that some 32x games would leverage sound from the Genesis while AI, input, gfx are handled by the 32x cpus? If that's the case what would that setup look like? Any examples out there?
Look at D32XR.
3) In a setup where you would want the 32x to handle the sound? What would be the best option for that? Any examples?
Look at D32XR.
4) Are there cases that a game would require both the Genesis and 32x to handle sound? If so, what does that situation look like? Any examples?
Look at D32XR. :lol:
5) What's the best way of handling the audio assets? I believe I saw a few tools out there that allow developers to convert their mp3's or whatever raw music/sfx into their desired format.
Depends on the audio assets. If you have VGM files, maybe you store them compressed in rom and play them with the 68000... like D32XR. Maybe if you have sound samples, you play them with the 32X DMA, like D32XR. Maybe if you want to play CDDA tracks on the CD, you have the 68000 send commands to the CD... like D32XR. :wink:
6) Any drawings/architecture or mappings of how these methods are implemented for example. Let's say Method X is the gold standard something like below
SoundArchitectureExample.png
Not that I'm aware of. Sorry. It's all mainly "look at my code." We programmers tend to be long on code, and short on graphs. 8)
Lastly, I know some of the recent postings (in 2022 and now 2023) just point to D32xr and say "just look there...its done right" While that is probably very true. it still leaves newbies like myself a little lost on the "why" is it considered the gold standard.
D32XR has the latest updates to my 32X support code, both on the 32X side, and the Genesis side, with lots of bug fixes, and extra features. It works on every combination of MD/CD/32X that I'm aware of, as well as MiSTer. It also works on all 32X emulators (although older versions of Gens will have trouble with DMA PWM audio).

Anywho - look at my code. :mrgreen:
https://github.com/viciious/d32xr

matthewnimmo
Very interested
Posts: 52
Joined: Thu Jan 07, 2021 8:04 pm

Re: All sound options explained?

Post by matthewnimmo » Tue Jan 17, 2023 2:45 am

Chilly Willy wrote:
Mon Jan 16, 2023 8:09 pm

Lastly, I know some of the recent postings (in 2022 and now 2023) just point to D32xr and say "just look there...its done right" While that is probably very true. it still leaves newbies like myself a little lost on the "why" is it considered the gold standard.
D32XR has the latest updates to my 32X support code, both on the 32X side, and the Genesis side, with lots of bug fixes, and extra features. It works on every combination of MD/CD/32X that I'm aware of, as well as MiSTer. It also works on all 32X emulators (although older versions of Gens will have trouble with DMA PWM audio).

Anywho - look at my code. :mrgreen:
https://github.com/viciious/d32xr
All of these replies are EXCELLENT and was exactly what i was hoping for. Just some newbie acronym breakers for myself. Interesting enough, I started off my career as a developer (never at the lower levels of needing to write to buffers with C and asm ... i did setup framerelay between two different network switches using C with my undergrade...but that's the extent of C) mainly C#, Java. then turned architect where I stitch bunch of services/solutions together (so i like drawings haha). When i get my head around more of this, I'll create some drawings for the community to have and reference.

With that said, i quoted your last statement here to see if you can grant me a little bit more wisdom on the subject! I'm all in on studying D32xr, it's just it is unlike all the other examples that i've been able to study and ultimately make sense out of. For example, most of the projects/demos here have only one main.c and I know that this is where things pivot off of. I've also learned that the older examples using your toolkit have a separated sh2_crt0 library while the newer versions use the crt0 only. I've learned that assets that are brought into for compiling the rom such as images and audio have been brought in via some examples via .s files like image.s or file.s with assembly and referenced as "external" within the C code.

All of that to say, i've managed to follow the breadcrumbs and figure things out but the D32xr i'm a little more lost (its a full on game, so its quite understandable). with that said, all of this great foundation, bug fixes, etc....how can i distill down the D32xr solution into the core framework components that I can pull into a separate project and play with/understand and ultimately use as my foundation for my game? Perhaps the ask here, what would be the core files and their purposes? I don't necessarily need someone to pull them all out for me and put them in a nice package... i can do that. I just would like a list of "go and get these files matt and you should have a solid skeleton"

In Vic's tilemap example, I noticed he is using some of the doom files there...so i know there's some good foundation that i can pull out of it....he's just more skilled than i and knows what to pull and what to dismiss since he's just constructing a tilemapper.

Thanks again for all the help and deep insights!

Chilly Willy
Very interested
Posts: 2963
Joined: Fri Aug 17, 2007 9:33 pm

Re: All sound options explained?

Post by Chilly Willy » Tue Jan 17, 2023 11:08 pm

src-md folder
-----------------
Makefile - makes the 68000 code/data block used by the game. The binary block of data generate will be included into the 32X side at the proper place.

crt0.s - main start of the 68000 code. The 68000 jumps to _start after the 32X has been started. _start clears the ram, copies the data segment into ram, initializes the MD hardware, and then calls the 68000 _main entry. It contains all the assembly routines needed by the 68000 to handle communication between the 32X and SCD.

main.c - holds the main() entry point. It tries to initialize the CD, if present. It also tries to initialize the MegaSD cart (allows playing CDDA music like the CD) if present. then calls do_main, which is in crt0.s.

cd .s - the code loaded into the SCD program ram that controls the SCD. Currently just checks for an audio CD and waits for commands from the MD to play tracks.

everdrive.c - initializes the MED, if present. This sets a flag that tells the game we can use MED Pro resources for bank selection, save ram, etc.

font.s - the default ASCII font used by the MD side of things.

kos.s - the Kosinski decompression routine used to decompress the SCD BIOS when initializing the SCD.

megasd.c - initializes the MegaSD, if present. Also holds the routines to play CD tracks on the MegaSD instead of the SCD.

vgm.c - some VGM helpers routines. Initializes the lzss decompression used to decompress the compressed VGM files that D32XR uses. Also has a function to fetch the next buffer worth of decompressed VGM data.

vgm_player.s - my VGM player code. Was derived from the player code I wrote for the NeoMyth cart menu. It's aimed at playing v1.60+ VGM files (no individual PCM store commands, instead it uses the new stream commands).

xvprintf.c - a stripped down vprintf() function for faster debug string printing on the MD side.


Main folder
---------------
Makefile - the main makefile. It will make the 68000 block, then make the 32X code (which includes the 68000 block inside it), then concatenate the wad file, then pad the rom to the closest 512KB to keep the size nice and round.

32x.h - most of the 32X hardware includes for the IO and SH2.

crt0.s - this starts the rom. It starts with a standard Sega MD rom header, followed by a vector table for the 68000 that redirects the normal 68000 exceptions to the new location of the 68000 code in the 32X. That is followed by the standard 32X header that tells you things like where the data is at, where the primary and secondary sh2 start vectors are, and where the primary and secondary sh2 exception tables are. This is followed by the 68000 security block, which is merely code that initializes the 32X, then fall into the 68000 _start, which is where the 68000 block is included at. This is then followed by the primary and secondary exception tables. Then follows all the sh2 exception handling code, as well as the startup code. The primary startup code does some initialization, then jumps to main() on the 32X side of things. The secondary startup code does some initialization (less than the primary), and then jumps to secondary().

marshw.c - has much of the low-level 32X functions, like setting up the frame buffers, flipping the frame buffers, polling the mouse, the main 32X initialization routine, and lots of glue routines that interface between 32X C functions, and sending commands to the MD and receiving responses back.

marsnew.c - holds all the system specific functions Doom uses to interface with the specific system Doom is running on. Things like processing the controller input, getting the tick count, setting the palette, doing network functions, etc. This file also holds Mars_Secondary(), which is where the secondary sh2 runs. This initializes any secondary sh2 hardware like the DMA, then enters a loop to process commands sent by the primary sh2.

marsonly.c - this corresponds to jagonly.c - the main entry point of the Doom game. It has the 32X side main() function entry point. This does any system setup, reads the save ram, sets up the video, and calls D_DoomMain(), the start of Doom proper. This file also holds the secondary() function, which just calls Mars_Secondary().

marssave.c - holds the save/load functions used by Doom. Calls lower level load/save functions to do its work. Nothing really 32X specific here.

marssound.c - this holds the Doom sound effects and music function routines, converting them to 32X code to send commands to the MD/CD side to play music, and builds a list of channels for playing sound effects via the 32X PWM. This file has the DMA done interrupt handler function that drives the PWM sound double buffer. It also handles command interrupts sent by the 68000, which are used to send info about PCM streams to play from the VGM file. Those are mixed with the sound effects.

sh2_draw.s - the main hand-tuned assembly for drawing in Doom. This is important for people doing their own drawing as it shows how to place mov commands on the proper boundaries for better speed. Vic and I spent A LOT of time on these routines to wring out every last drop of blood this turnip can offer. :D

sh2_fixed.s - fixed point multiply and divide code. The divide uses the hardware divider in the sh2 rather than the normal divide program code the sh2 uses. Note that the Doom code doesn't call these very often as we made different inline code for doing these. In fact, the divide is normally broken into two pieces - starting the divide, and then a separate function to fetch the result so that you can do other things before fetching the result of the divide.

sh2_mixer.s - the main sound mixing code. It will mix normal 8-bit PCM samples, and 16-bit ADPCM samples, which are decompressed on the fly by the sh2 while mixing. We suggest not trying to mix more than 5 or 6 ADPCM samples at the same time as that can consume some cpu time, slowing the secondary sh2 elsewhere in the game.



And that's pretty much all the 32X specific files and what they handle. The rest is Doom code.

Chilly Willy
Very interested
Posts: 2963
Joined: Fri Aug 17, 2007 9:33 pm

Re: All sound options explained?

Post by Chilly Willy » Tue Jan 17, 2023 11:21 pm

A follow on post of some code from D32XR about some things you may want to do in your own code.

semaphores

Code: Select all

static char seg_lock = 0;

static void R_LockSeg(void)
{
    int res;
    do {
        __asm volatile (\
        "tas.b %1\n\t" \
            "movt %0\n\t" \
            : "=&r" (res) \
            : "m" (seg_lock) \
            );
    } while (res == 0);
}

static void R_UnlockSeg(void)
{
    seg_lock = 0;
}
inline fixed mul and normal integer div

Code: Select all

fixed_t	FixedMul (fixed_t a, fixed_t b);
fixed_t	FixedDiv (fixed_t a, fixed_t b);
#ifdef MARS
#define FixedMul2(c,a,b) do { \
        int32_t t; \
       __asm volatile ( \
            "dmuls.l %2, %3\n\t" \
            "sts mach, %1\n\t" \
            "sts macl, %0\n\t" \
            "xtrct %1, %0\n\t" \
            : "=r" (c), "=&r" (t) \
            : "r" (a), "r" (b) \
            : "mach", "macl"); \
        } while (0)

static inline fixed_t IDiv(fixed_t a, fixed_t b)
{
	fixed_t res;
	uintptr_t div;
	__asm volatile(
		"mov #-128, %1\n\t"
		"add %1,%1\n\t"
		"mov.l %3,@%1 /* set 32-bit divisor */\n\t"
		"mov.l %2,@(4,%1) /* set 32-bit dividend, start divide */\n\t"
		"/* note - overflow returns 0x7FFFFFFF or 0x80000000 after 6 cycles\n\t"
		"no overflow returns the quotient after 39 cycles */\n\t"
		"mov.l @(4,%1),%0 /* return 32-bit quotient */\n\t"
		: "=r" (res), "=&r"(div)
		: "r" (a), "r"(b)
	);
	return res;
}
#else
#define FixedMul2(c,a,b) ((c) = FixedMul(a,b))
#define IDiv(a,b) ((a) / (b))
#endif
starting an integer div

Code: Select all

#ifdef MARS
        volatile int32_t t;
        __asm volatile (
           "mov #-128, r0\n\t"
           "add r0, r0 /* r0 is now 0xFFFFFF00 */ \n\t"
           "mov #0, %0\n\t"
           "mov.l %0, @(16, r0) /* set high bits of the 64-bit dividend */ \n\t"
           "mov.l %1, @(0, r0) /* set 32-bit divisor */ \n\t"
           "mov #-1, %0\n\t"
           "mov.l %0, @(20, r0) /* set low  bits of the 64-bit dividend, start divide */\n\t"
           : "=&r" (t) : "r" (scalefrac) : "r0");
#else
        fixed_t scale = scalefrac;
#endif
ending the div and fetching the result

Code: Select all

#ifdef MARS
        __asm volatile (
            "mov #-128, r0\n\t"
            "add r0, r0 /* r0 is now 0xFFFFFF00 */ \n\t"
            "mov.l @(20, r0), %0 /* get 32-bit quotient */ \n\t"
            : "=r" (iscale) : : "r0");
#else
        iscale = 0xffffffffu / scale;
#endif

matthewnimmo
Very interested
Posts: 52
Joined: Thu Jan 07, 2021 8:04 pm

Re: All sound options explained?

Post by matthewnimmo » Tue Jan 17, 2023 11:50 pm

Chilly! This is absolute gold! Im going to take some time and chew through this. I may take these files and start up a new project and see if i can get something to simply compile

Im certain ill have a ton of questions

Chilly Willy
Very interested
Posts: 2963
Joined: Fri Aug 17, 2007 9:33 pm

Re: All sound options explained?

Post by Chilly Willy » Wed Jan 18, 2023 10:48 pm

I'll be here when you have questions. This is why I make all my code open source (when allowed by contract, of course) - maybe this will help people who don't want to reinvent the wheel... or maybe help someone build a better wheel. :D

matthewnimmo
Very interested
Posts: 52
Joined: Thu Jan 07, 2021 8:04 pm

Re: All sound options explained?

Post by matthewnimmo » Thu Jan 19, 2023 4:27 am

Chilly Willy wrote:
Wed Jan 18, 2023 10:48 pm
I'll be here when you have questions. This is why I make all my code open source (when allowed by contract, of course) - maybe this will help people who don't want to reinvent the wheel... or maybe help someone build a better wheel. :D
This is absolutely wonderful! I know that I can just "abandon ship" and use the SGDK to make a sega game...but ever since i got a 32x as a kid there was something about that system that I knew i wanted to make a game for. So, without your help and others that have pioneered how to tap into this old tech, i wouldn't have a chance.

With that said, I'm going to start a new thread about my journey build this game. It's going to happen, but it may take me a while to get it done. In that post I'll describe at a high level what the game is about and aspects of the game that I hope will make it interesting :) I'm not going to spoil anything in this reply, but probably tonight or tomorrow I'll have a new thread describing everything and that's the thread I'll be pleading a lot of ignorance on as i go through this journey lol.

Thanks again for everything.

EDIT: I went ahead and created that posting! http://gendev.spritesmind.net/forum/vie ... f=1&t=3348

Post Reply