This document describes macros and routines exposed by Mega PCM 2 you can use after installation. While this API is meant for M68K assembly projects, routines are also optimized for possible C/C++ integrations (only uses scratch registers and one argument at most).
The bare minimum you need is MegaPCM_LoadDriver and MegaPCM_LoadSampleTable routines for setup and MPCM_play macro for playback.
Here's a minimal Mega PCM 2 example which demonstrates most of API calls. MD Shell's Console.Sleep macro is used here to wait given number of frames during playback.
Main:
; Bootstrap code
jsr MegaPCM_LoadDriver
lea SampleTable, a0
jsr MegaPCM_LoadSampleTable
; Initiate playback
MPCM_setPan #$40 ; pan left
MCPM_setVol #8 ; 50% volume
MPCM_play #mybgm.id
; Playback control & effects
Console.Sleep #60 ; wait 1 second
MPCM_setPitch #mybgm.pitch/2 ; 50% playback speed
Console.Sleep #60 ; wait 1 second
MPCM_pause
Console.Sleep #30 ; wait 0.5 seconds
MPCM_unpause
Console.Sleep #300 ; wait 5 seconds
MPCM_stop
rts
SampleTable:
; type pointer Hz flags
mybgm: dcSample TYPE_DPCM, MyBGM, 16000, FLAGS_LOOP
dc.w -1 ; end marker
incdac MyBGM, "dac/mybgm.dpcmq"See examples/ directory for more usage examples.
This section documents macro commands exposed by Mega PCM 2 bundles since version 2.1. All these commands have routine equivalents, e.g.: MPCM_play is equivalent to jsr MegaPCM_PlaySample. Macros are usually faster and more convenient to use as they generate code in-place as opposed to calling routines and returning, but they result in slightly larger code.
For controlling playback, prefer macros over routines unless you really wish to save space.
(Added in Mega PCM 2.1)
Plays given sample by ID (>=$81). If currently playing sample has a higher priority, this command is ignored.
Note
Mega PCM accepts commands (play, pause, stop) once per frame, roughly a few scanlines after VBlank is over. If commands are sent more than once per frame, only the last stored command will be processed.
Syntax
MPCM_play sampleIdOpArguments
sampleIdOp- Sample ID operand (e.g. #$81, #mysample.id, d0)
Examples
MPCM_play #$81
MPCM_play #mysample.id ; when used with Named samples
MPCM_play d1 ; you should pass sample ID to d1Warning
Don't forget # before the argument, unless you pass a register or memory address! This macro accepts an operand, not a value! Think of MPCM_play X as move.b X, MegaPCM_CommandInput_Addr, so you need to pass e.g. #$81, not $81.
See also: A callable MegaPCM_PlaySample routine, which uses this macro under the hood.
(Added in Mega PCM 2.1)
Pauses playback completely until "unpause" command is sent or a new sample is requested.
Note
Mega PCM accepts commands (play, pause, stop) once per frame, roughly a few scanlines after VBlank is over. If commands are sent more than once per frame, only the last stored command will be processed.
Syntax
MPCM_pauseSee also: A callable MegaPCM_PausePlayback routine, which uses this macro under the hood.
(Added in Mega PCM 2.1)
Unpauses playback. If playback wasn't paused, it has no effect (rather than clearing the last sent command).
Note
Mega PCM accepts commands (play, pause, stop) once per frame, roughly a few scanlines after VBlank is over. If commands are sent more than once per frame, only the last stored command will be processed.
Syntax
MPCM_unpauseSee also: A callable MegaPCM_UnpausePlayback routine, which uses this macro under the hood.
(Added in Mega PCM 2.1)
Stops playback completely, regardless of currently playing sample's priority.
Note
Mega PCM accepts commands (play, pause, stop) once per frame, roughly a few scanlines after VBlank is over. If commands are sent more than once per frame, only the last stored command will be processed.
Syntax
MPCM_stopSee also: A callable MegaPCM_StopPlayback routine, which uses this macro under the hood.
(Added in Mega PCM 2.1)
Sets the default panning for normal (non-SFX) samples. SFX samples use a separate pan setting.
Note that Mega PCM 2 will update panning only when a new sample starts playing.
Syntax
MPCM_setPan panOpArguments
panOp- Panning operand (e.g.#$40,#$80,#$C0,d0etc)
Examples
MPCM_setPan #$40
MPCM_setPan d0 ; you should pass pan setting to d0See also: A callable MegaPCM_SetPan routine, which uses this macro under the hood.
(Added in Mega PCM 2.1)
Sets the default panning for SFX samples. Normal samples use a separate pan setting and are not affected by this.
Note that Mega PCM 2 will update panning only when a new sample starts playing.
Syntax
MPCM_setSfxPan panOpArguments
panOp- Panning operand (e.g.#$40,#$80,#$C0,d0etc)
Examples
MPCM_setSfxPan #$C0
MPCM_setSfxPan d6 ; you should pass pan setting to d6See also: A callable MegaPCM_SetSfxPan routine, which uses this macro under the hood.
(Added in Mega PCM 2.1)
Sets volume for normal (non-SFX) samples. SFX samples use a separate volume setting.
Mega PCM 2 updates volume once per frame. This setting is ignored in "turbo playback" mode.
Syntax
MPCM_setVol volumeOpArguments
volumeOp- Volume operand (e.g.#0(max),#$F(min),d0etc)
Examples
MPCM_setVol #$F
MPCM_setVol #0
MPCM_setVol d2 ; you should pass volume setting to d2See also: A callable MegaPCM_SetVolume routine, which uses this macro under the hood.
(Added in Mega PCM 2.1)
Sets volume for SFX samples. Normal samples use a separate volume setting and are not affected by this.
Mega PCM 2 updates volume once per frame. This setting is ignored in "turbo playback" mode.
Syntax
MPCM_setSfxVol volumeOpArguments
volumeOp- Volume operand (e.g.#0(max),#$F(min),d0etc)
Examples
MPCM_setSfxVol #0
MPCM_setSfxVol #$F
MPCM_setSfxVol d3 ; you should pass volume setting to d3See also: A callable MegaPCM_SetSfxVolume routine, which uses this macro under the hood.
(Added in Mega PCM 2.1)
Updates pitch of currently playing sample. Mega PCM pulls this setting once per frame. This is usually used for pitch effects (e.g. slowdown) and to pull it off properly, you should be aware of which sample is playing and its original (base) pitch value (see example below).
Warning
You cannot request to play a sample and immediately set its pitch! E.g. MPCM_play followed by MPCM_setPitch won't work. Because Mega PCM will only accept your sample by the end of VBlank and reset pitch after loading it. MPCM_setPitch is designed for gradually altering pitch over time for currently playing samples.
Syntax
MPCM_setPitch pitchOpArguments
pitchOp- Pitch operand (e.g.#mysample.pitch,#0= 0%,#$FF= 100% base rate)
Examples
MPCM_play #mysample.id
Console.Sleep #60 ; sleep for 60 frames
MPCM_setPitch #mysample.pitch/2 ; cut playback speed in half!See also: A callable MegaPCM_SetActiveSamplePitch routine, which uses this macro under the hood.
Loads Mega PCM driver into Z80 memory and waits for its initialization. You only need to call this function once during boot.
Note
Mega PCM 2 performs a few benchmarks during initialization to perfectly calibrate timings for both real hardware and inaccurate emulators alike. This process takes 3-4 frames and MegaPCM_LoadDriver will only return once calibration is complete.
Usage:
jsr MegaPCM_LoadDriver ; takes 3-4 frames to bootUses:
d0-d1,a0-a1
Loads a given sample table to Z80 memory. You must call this function after initialization to be able to play samples by IDs. Sample tables are defined using convenience macros provided by Mega PCM.
Note
You can use several sample tables and switch between them on the fly. However, uploading a large sample table may affect Mega PCM's performance and timings on that frame, so it's recommended to do so when Mega PCM is idling.
Note
If you have MD Debugger and Error handler installed, you can take advantage of detailed error reporting if something goes wrong, since Mega PCM 2 library comes bundled with MPCM_Debugger_LoadSampleTableException debugger.
Usage:
lea YourSampleTable, a0
jsr MegaPCM_LoadSampleTable
tst.w d0 ; has function returned error code?
beq.s SampleTable_ok ; if not, branch
; If you have MD Debugger v.2.5 or above:
RaiseError "MegaPCM_LoadSampleTable returned %<.b d0>", MPCM_Debugger_LoadSampleTableException
; Otherwise:
illegal
SampleTable_ok:
; <...>
; ---------------------------------------------------------------
SampleTable:
; type pointer Hz ; sample id
dcSample TYPE_DPCM, Kick, 8000 ; $81
dcSample TYPE_PCM, Snare, 24000 ; $82
dcSample TYPE_DPCM, Timpani, 7250 ; $83
dc.w -1 ; end marker
; ---------------------------------------------------------------
incdac Kick, "dac/kick.dpcm"
incdac Snare, "dac/snare.pcm"
incdac Timpani, "dac/timpani.dpcm"
evenInput:
a0- sample table pointer
Output:
d0- zero on success, non-zero error code on failurea0- pointer to a problematic sample in table (if applicable)
Uses:
d0-d1,a0-a1
Error codes:
Error codes are included in Mega PCM definitions:
MPCM_ST_TOO_MANY_SAMPLES: equ $01 ; Too many samples in table
MPCM_ST_UNKNOWN_SAMPLE_TYPE: equ $02 ; Unknown sample type or missing end marker. Please use one of: TYPE_PCM, TYPE_DPCM, TYPE_PCM_TURBO, TYPE_NONE
MPCM_ST_PITCH_NOT_SET: equ $10 ; Sample rate can't be auto-detected (only works for .WAV files). Please set it manually
MPCM_ST_WAVE_INVALID_HEADER: equ $20 ; WAVE error: Invalid WAVE header
MPCM_ST_WAVE_BAD_AUDIO_FORMAT: equ $21 ; WAVE error: Unsupported audio format. Only PCM is supported
MPCM_ST_WAVE_NOT_MONO: equ $22 ; WAVE error: Audio must be mono
MPCM_ST_WAVE_NOT_8BIT: equ $23 ; WAVE error: Audio must be 8-bit unsigned PCM
MPCM_ST_WAVE_BAD_SAMPLE_RATE: equ $24 ; WAVE error: Unsupported sample rate. Use <=25100 Hz for TYPE_PCM or 32000 Hz for TYPE_PCM_TURBO.
MPCM_ST_WAVE_MISSING_DATA_CHUNK: equ $25 ; WAVE error: Failed to locate 'data' chunk
MPCM_ST_DPCM_HQ_UNSUPPORTED_VERSION:equ $30 ; DPCM-HQ error: Unsupported version specified in header
MPCM_ST_DPCM_HQ_BAD_SAMPLE_RATE: equ $31 ; DPCM-HQ error: Unsupported sample rate. Use <=20600 Hz for TYPE_DPCM or 25800 Hz for TYPE_DPCM_TURBO.Plays given sample by ID (>=$81). If currently playing sample has a higher priority, this command is ignored.
Note
Mega PCM accepts commands (play, pause, stop) once per frame, roughly a few scanlines after VBlank is over. If commands are sent more than once per frame, only the last stored command will be processed.
Usage:
move.b #$81, d0 ; play the first sample in table
jsr MegaPCM_PlaySampleInput:
d0 .b- sample id to play (>=$81)
Pauses playback completely until MegaPCM_UnpausePlayback is called or a new sample is requested.
Note
Mega PCM accepts commands (play, pause, stop) once per frame, roughly a few scanlines after VBlank is over. If commands are sent more than once per frame, only the last stored command will be processed.
Usage:
jsr MegaPCM_PausePlaybackUnpauses playback. If playback wasn't paused, it has no effect (rather than clearing the last sent command).
Note
Mega PCM accepts commands (play, pause, stop) once per frame, roughly a few scanlines after VBlank is over. If commands are sent more than once per frame, only the last stored command will be processed.
Usage:
jsr MegaPCM_UnpausePlaybackStops playback completely, regardless of currently playing sample's priority.
Note
Mega PCM accepts commands (play, pause, stop) once per frame, roughly a few scanlines after VBlank is over. If commands are sent more than once per frame, only the last stored command will be processed.
Usage:
jsr MegaPCM_StopPlaybackSets the default panning for normal (non-SFX) samples. SFX samples use a separate pan setting.
Note that Mega PCM 2 will update panning only when a new sample starts playing.
Usage:
move.b #$40, d0
jsr MegaPCM_SetPanInput:
d0 .b- panning ($40,$80or$C0)
Sets the default panning for SFX samples. Normal samples use a separate pan setting.
Note that Mega PCM 2 will update panning only when a new sample starts playing.
Usage:
move.b #$40, d0
jsr MegaPCM_SetSFXPanInput:
d0 .b- panning ($40,$80or$C0)
Sets volume for normal (non-SFX) samples. SFX samples use a separate volume setting.
Mega PCM 2 updates volume once per frame. This setting is ignored in "turbo playback" mode.
Usage:
moveq #8, d0 ; 50% volume
jsr MegaPCM_SetVolumeInput:
d0 .b- volume level (0= max,$F= min)
Sets volume for SFX samples. Normal samples use a separate volume setting.
Mega PCM 2 updates volume once per frame. This setting is ignored in "turbo playback" mode.
Usage:
moveq #8, d0 ; 50% volume
jsr MegaPCM_SetSFXVolumeInput:
d0 .b- volume level (0= max,$F= min)
(Added in Mega PCM 2.1)
Updates pitch of currently playing sample. Mega PCM pulls this setting once per frame. This is usually used for pitch effects (e.g. slowdown) and to pull it off properly, you should be aware of which sample is playing and its original (base) pitch value (see example below).
Warning
You cannot request to play a sample and immediately set its pitch! E.g. jsr MegaPCM_PlaySample followed by jsr MegaPCM_SetActiveSamplePitch won't work. Because Mega PCM will only accept your sample by the end of VBlank and reset pitch after loading it. This command is designed for gradually altering pitch over time for currently playing samples.
Usage:
move.b #mysample.pitch/2, d0
jsr MegaPCM_SetActiveSamplePitch ; 50% playback speedInput:
d0 .b- pitch level (0= 0%,$FF= 100% base rate)