Gradually and with user feedback things improved: rb+ commands were added to give better control for playing music and triggering sfx, assets.txt was added so importing became less of a pain (you can now even feed it an mp3 and it'll convert to the format you need). In general, things improved - not perfect but still.
Then a second audio engine was added! People got sick of .mod files and wanted to stream some audio instead. The new audio engine by Zerosquare offers μLaw samples playback and while it does waste a lot of space, the results are quite impressive!
A major component of both sound engines is that they both handle joypad/rotary/etc input.
Add all this to the mix - confusion ensues!
So let's try to de-confuse things a little. First, a comparison between the two engines.
Can play .mod files: yes (4 channel ones)
Can play samples: yes, up to 4 raw PCM samples alongside with the .mod
Fine control of samples: yes - pitch and volume
Supports μLaw compressed samples: no
Supports mouse input: no (it probably can, never tested)
Can play .mod files: no
Can play samples: yes, up to 4 simultaneously
Fine control of samples: no - fire and forget affair
Supports μLaw compressed samples: yes
Supports mouse input: yes
Which one to choose? Well, that's up to you. Main difference is of course .mod files vs μLaw music playing. As for the rest... read on.
Selecting a sound engine in your project
This is quite easy to do. For legacy reasons the U235 engine is selected by default in every new project. In your project folder open rapapp.s and locate the following line:
player equ 1 ;0=Zerosquare's player, 1=U-235 playerAs instructed, replace the 1 with 0 if you want to use Zerosquare's engine.
In order to play a .mod file you first have to import it as an asset. Same goes for sound samples. Have a look at the assets.txt article for this.
Especially for samples, raptor (or U235) (or both IDK, LOL) require the use of sample banks. This is in essence a list where you have to define your samples. It is defined in file rapu235.s of your project. Typically an entry in that table looks like this:
sample0: dc.l explode_sam ; start of sample dc.l explode_sam_end ; end of sample dc.l 0 ; repeat offset dc.l 0 ; repeat length dc.w 0 ; <NULL> dc.b 0 ; fine tune s2_vol: dc.b 192 ; volume dc.l 8000 ; default play rateThe first two parameters are the sample's start and end addresses. These are automatically available for you from assets.txt. In this example if you import a sample and assign it the name explode_sam, rb+ will give you the addresses explode_sam and explode_sam_end for free. The next two parameters control sample looping: which sample from the start you would like looping to occur and how many samples it should be. NULL - well, just leave it to 0 . volume is a value from 0 to 255 and finally play rate is the replay frequency. This probably goes up to 32000 but I'm not sure really - just try it out if you're curious.
To play a module from rb+ it pretty straightforward. Just use MODPLAY(mod_address) and replace mod_address with the label you used to import the module in assets.txt. Stopping a module and restarting is a bit more tricky as the SE doesn't have a clear cut mechanism for it. This snippet of code might work but it's not fully tested on real hardware yet:
MODPLAY(0) SNDKILL(0) SNDKILL(1) SNDKILL(2) SNDKILL(3) VSYNC U235SE_modregdump=0 U235SE_modregdump=0 U235SE_modregdump=0 U235SE_modregdump=0 U235SE_modregdump=0 MODPLAY((int)strptr(Module2))To play a sound sample with the default values just use sndplay(voice,x) where voice is the channel you want to use (4 to 7, 0-3 are used for .mod playing) and x is the sample number from the start of the sample bank. If you want to play the sample at a different frequency you can use SNDPLAYFREQ(voice,x,y) which uses channel voice to play sample x at frequency y (Hz).
For more info on sample commands have a look at the list below (which is copied from rb_quickref.txt).
To handle the jagpads, first of all you have to set rotary_mode1 and rotary_mode2 to correspond to your controllers (1=rotary, -1=jagpad). For classic d-pad handling you first have to use getpad(x) where x=0,1 the joypad you wish to read (alternatively you can just read the variables U235SE_pad1 and U235SE_pad2 directly). These values contain the states for all buttons, so to detect just one button you need to mask out the rest. So something like
if x band (PAD_U) then 'checks for up if x band (PAD_U bor PAD_L) then 'checks for up+leftHave a look at the mask values below for the full set.
Here's the full command set for U235:
MODPLAY(mod_address) plays a .mod file at address "mod_address"
MODPLAY(0) stops .mod playing
GETPAD(x) returns values from either pad 1 or 2. (Can be replaced by reading U235SE_pad1 and U235SE_pad2 directly.)
SNDPLAYFREQ(voice,x,y) triggers sample x from module into channel "voice" at y frequency in Hz
MODVOL(x) sets mod music volume (x in range 0 - 63)
SNDVOL(x) sets global sfx volume (x in range 0 - 63)
SNDKILL(x) stops playing sample at channel number x
SNDVOLRESET(x) resets volume of current sample on channel x
SNDFREQRESET(x) resets frequency of current sample on channel x
SNDDELTA(x,y) set or adjust the volume on channel x to y (0 to 63)
SNDFREQ(x,y) sets frequency of channel x to y (0 to 65535)
rotary_mode1 +1 = rotary, - 1 = jagpad (Port 1) (.l)
rotary_mode2 +1 = rotary, - 1 = jagpad (Port 2) (.l)
turn_direction1 rotary value (bigger is faster) - +=left / 0=nothing / - =right (Port 1) (.l)
turn_direction2 rotary value (bigger is faster) - +=left / 0=nothing / - =right (Port 2) (.l)
rotary_interval1 trim value for rotary (Port 1) (.l)
rotary_interval2 trim value for rotary (Port 2) (.l)
spin_delta1 value to add to turn_direction per increment (Port 1) (.l)
spin_delta2 value to add to turn_direction per increment (Port 2) (.l)
Direction pad masks PAD_UP, PAD_U, PAD_DOWN, PAD_D, PAD_LEFT, PAD_L, PAD_RIGHT, PAD_R, PAD_HASH, PAD_9, PAD_6, PAD_3, PAD_PAUSE, PAD_A, PAD_OPTION, PAD_STAR, PAD_7, PAD_4, PAD_1, PAD_0, PAD_8, PAD_5, PAD_2, PAD_B, PAD_C.
Zerosquare's engine is much more simple in comparison, but is a bit less flexible.
You can play a sample in each of the 4 channels it has available using SNDZEROPLAY chan, start_address, len, frequency, params where chan=1 to 4, start_address and len can be obtained from assets.txt like above, frequency is an integer divisor to the main clock of 46168Hz and params sets the replay mode. The syntax is slightly different if playing a sample from RAM or ROM:
Example for playing samples from RAM (ABS):
SNDZEROPLAY(1, strptr(sample_start), (strptr(sample_end)-strptr(sample_start)+3) and 0xfffffffc, 46168/9233, Zero_Audio_8bit_muLaw|Zero_Audio_Looping)This will play a sample in channel 1 starting from sample_start, with length sample_end-sample_start rounded up to 4 bytes, with a channel divisor of 5 (i.e. 46168/9233) in order to play 9233Hz. The sample will be μLaw packed, so you need to import it as such. Finally we ask the engine to loop the sound forever.
Example for playing samples from ROM:
SNDZEROPLAY(1, (void *)sample_start, (sample_end-sample_start+3) and 0xfffffffc, 46168/9233, Zero_Audio_8bit_muLaw|Zero_Audio_Looping)This does exactly the same as above, only the sample is in ROM.
To silence a channel just play a zero sized sample (len=0).
Finally, to read inputs, first choose what inputs you need (d-pad, rotary, mouse) by calling the routines Input_SetNormalPadMode, Input_SetJoyPort1, Input_SetJoyPort2, Input_SetRotaryMode, Input_SetAtariMouseMode, Input_SetAmigaMouseMode. Then each time you need to read input just call ZEROPAD subroutine. Then variables zero_left_pad, zero_right_pad, zero_mousex_delta, zero_mousey_delta and zero_rotary_delta are filled accordgingly. Again you'll need to mask out the status for the buttons you don't need for pad, so something like
if zero_left_pad band Input_Pad_Star thenwill check left pad if the star button is pressed.
And here's the list of variables and functions exposed when you use the Zerosquare engine:
ZEROPAD() reads both pad ports and sends results back to variables zero_left_pad, zero_right_pad, zero_mousex_delta, zero_mousey_delta and zero_rotary_delta. By default the engine is configured to assume 2 joypads connected. This command needs to be used in capitals.
Input_SetNormalPadMode sets up the engine to read two pads (enabled by default). zero_left_pad and zero_right_pad can be read using these constants: Input_Pad_Pause, Input_Pad_A, Input_Pad_Up, Input_Pad_Down, Input_Pad_Left, Input_Pad_Right, Input_Pad_C1, Input_Pad_B, Input_Pad_Star, Input_Pad_7, Input_Pad_4, Input_Pad_1, Input_Pad_C2, Input_Pad_C, Input_Pad_0, Input_Pad_8, Input_Pad_5, Input_Pad_2, Input_Pad_C3, Input_Pad_Option, Input_Pad_Sharp, Input_Pad_9, Input_Pad_6, Input_Pad_3. example: "if zero_left_pad band Input_Pad_Star" will check left pad for star button press.
Input_SetJoyPort1 enables joypad port 1 to be used for rotary/mouse input. This doesn't enable rotary/mouse mode. zero_rotary_delta will give the number of rotary ticks since the last read command.
Input_SetJoyPort2 enables joypad port 2 to be used for rotary/mouse input. This doesn't enable rotary/mouse mode. zero_rotary_delta will give the number of rotary ticks since the last read command.
Input_SetRotaryMode enables rotary mode.
Input_SetAtariMouseMode enables Atari mouse mode. Input_Mouse_Left and Input_Mouse_Right are the masks to check for button presses zero_mousex_delta, zero_mousey_delta are the number of mouse ticks in x and y axis since the last read command.
Input_SetAmigaMouseMode enables Amiga mouse mode. Input_Mouse_Left and Input_Mouse_Right are the masks to check for button presses zero_mousex_delta, zero_mousey_delta are the number of mouse ticks in x and y axis since the last read command.
SNDZEROPLAY chan, start_address, len, frequency, params plays a sample starting from start_address with length len to channel chan with speed frequency and with flags params. *Channel* should be from 1 to 4. start_address should be aligned to 4 bytes. len should be a multiple of 4. frequency should be an integer that divides the base frequency of 46168Hz. So for example if it's set to 1, it'll play a sample at 46168Hz, a 2 will play a sample at 23084Hz etc. Available flags are: Zero_Audio_8bit_Signed (plays an 8-bit signed sample), Zero_Audio_8bit_Unsigned (plays an 8 - bit unsigned sample), Zero_Audio_8bit_muLaw (plays a 8 - bit compressed ?w sample) - Zero_Audio_Looping (enables sample loop). Example for playing samples from RAM (ABS): SNDZEROPLAY(1, strptr(sample_start), (strptr(sample_end)-strptr(sample_start)+3) and 0xfffffffc, 46168/9233, Zero_Audio_8bit_muLaw|Zero_Audio_Looping). Example for playing samples from ROM: SNDZEROPLAY(1, (void *)sample_start, (sample_end-sample_start+3) and 0xfffffffc, 46168/9233, Zero_Audio_8bit_muLaw|Zero_Audio_Looping)
Edited by ggn, Wed Mar 29, 2017 2:18 AM.