#ifndef _ABI_H_1#define _ABI_H_23/**************************************************************************4* *5* Copyright (C) 1994, Silicon Graphics, Inc. *6* *7* These coded instructions, statements, and computer programs contain *8* unpublished proprietary information of Silicon Graphics, Inc., and *9* are protected by Federal copyright law. They may not be disclosed *10* to third parties or copied or duplicated in any form, in whole or *11* in part, without the prior written consent of Silicon Graphics, Inc. *12* *13**************************************************************************/1415/**************************************************************************16*17* $Revision: 1.32 $18* $Date: 1997/02/11 08:16:37 $19* $Source: /exdisk2/cvs/N64OS/Master/cvsmdev2/PR/include/abi.h,v $20*21**************************************************************************/2223/*24* Header file for the Audio Binary Interface.25* This is included in the Media Binary Interface file26* mbi.h.27*28* This file follows the framework used for graphics.29*30*/3132/* Audio commands: */33#define A_SPNOOP 034#define A_ADPCM 135#define A_CLEARBUFF 236#define A_RESAMPLE 537#define A_SETBUFF 838#define A_DMEMMOVE 1039#define A_LOADADPCM 1140#define A_MIXER 1241#define A_INTERLEAVE 1342#define A_SETLOOP 154344#ifndef VERSION_SH4546#define A_ENVMIXER 347#define A_LOADBUFF 448#define A_RESAMPLE 549#define A_SAVEBUFF 650#define A_SEGMENT 751#define A_SETVOL 952#define A_POLEF 145354#else5556#define A_ADDMIXER 457#define A_RESAMPLE_ZOH 658#define A_DMEMMOVE2 1659#define A_DOWNSAMPLE_HALF 1760#define A_ENVSETUP1 1861#define A_ENVMIXER 1962#define A_LOADBUFF 2063#define A_SAVEBUFF 2164#define A_ENVSETUP2 2265#define A_S8DEC 2366#define A_HILOGAIN 2467#define A_UNK_25 2568#define A_DUPLICATE 2669#define A_FILTER 277071#endif7273#define ACMD_SIZE 3274/*75* Audio flags76*/7778#define A_INIT 0x0179#define A_CONTINUE 0x0080#define A_LOOP 0x0281#define A_OUT 0x0282#define A_LEFT 0x0283#define A_RIGHT 0x0084#define A_VOL 0x0485#define A_RATE 0x0086#define A_AUX 0x0887#define A_NOAUX 0x0088#define A_MAIN 0x0089#define A_MIX 0x109091/*92* BEGIN C-specific section: (typedef's)93*/94#if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS)9596/*97* Data Structures.98*/99100typedef struct {101unsigned int cmd:8;102unsigned int flags:8;103unsigned int gain:16;104unsigned int addr;105} Aadpcm;106107typedef struct {108unsigned int cmd:8;109unsigned int flags:8;110unsigned int gain:16;111unsigned int addr;112} Apolef;113114typedef struct {115unsigned int cmd:8;116unsigned int flags:8;117unsigned int pad1:16;118unsigned int addr;119} Aenvelope;120121typedef struct {122unsigned int cmd:8;123unsigned int pad1:8;124unsigned int dmem:16;125unsigned int pad2:16;126unsigned int count:16;127} Aclearbuff;128129typedef struct {130unsigned int cmd:8;131unsigned int pad1:8;132unsigned int pad2:16;133unsigned int inL:16;134unsigned int inR:16;135} Ainterleave;136137typedef struct {138unsigned int cmd:8;139unsigned int pad1:24;140unsigned int addr;141} Aloadbuff;142143typedef struct {144unsigned int cmd:8;145unsigned int flags:8;146unsigned int pad1:16;147unsigned int addr;148} Aenvmixer;149150typedef struct {151unsigned int cmd:8;152unsigned int flags:8;153unsigned int gain:16;154unsigned int dmemi:16;155unsigned int dmemo:16;156} Amixer;157158typedef struct {159unsigned int cmd:8;160unsigned int flags:8;161unsigned int dmem2:16;162unsigned int addr;163} Apan;164165typedef struct {166unsigned int cmd:8;167unsigned int flags:8;168unsigned int pitch:16;169unsigned int addr;170} Aresample;171172typedef struct {173unsigned int cmd:8;174unsigned int flags:8;175unsigned int pad1:16;176unsigned int addr;177} Areverb;178179typedef struct {180unsigned int cmd:8;181unsigned int pad1:24;182unsigned int addr;183} Asavebuff;184185typedef struct {186unsigned int cmd:8;187unsigned int pad1:24;188unsigned int pad2:2;189unsigned int number:4;190unsigned int base:24;191} Asegment;192193typedef struct {194unsigned int cmd:8;195unsigned int flags:8;196unsigned int dmemin:16;197unsigned int dmemout:16;198unsigned int count:16;199} Asetbuff;200201typedef struct {202unsigned int cmd:8;203unsigned int flags:8;204unsigned int vol:16;205unsigned int voltgt:16;206unsigned int volrate:16;207} Asetvol;208209typedef struct {210unsigned int cmd:8;211unsigned int pad1:8;212unsigned int dmemin:16;213unsigned int dmemout:16;214unsigned int count:16;215} Admemmove;216217typedef struct {218unsigned int cmd:8;219unsigned int pad1:8;220unsigned int count:16;221unsigned int addr;222} Aloadadpcm;223224typedef struct {225unsigned int cmd:8;226unsigned int pad1:8;227unsigned int pad2:16;228unsigned int addr;229} Asetloop;230231/*232* Generic Acmd Packet233*/234235typedef struct {236uintptr_t w0;237uintptr_t w1;238} Awords;239240typedef union {241Awords words;242#if IS_BIG_ENDIAN && !IS_64_BIT243Aadpcm adpcm;244Apolef polef;245Aclearbuff clearbuff;246Aenvelope envelope;247Ainterleave interleave;248Aloadbuff loadbuff;249Aenvmixer envmixer;250Aresample resample;251Areverb reverb;252Asavebuff savebuff;253Asegment segment;254Asetbuff setbuff;255Asetvol setvol;256Admemmove dmemmove;257Aloadadpcm loadadpcm;258Amixer mixer;259Asetloop setloop;260#endif261long long int force_union_align; /* dummy, force alignment */262} Acmd;263264/*265* ADPCM State266*/267typedef short ADPCM_STATE[16];268269/*270* Pole filter state271*/272typedef short POLEF_STATE[4];273274/*275* Resampler state276*/277typedef short RESAMPLE_STATE[16];278279/*280* Resampler constants281*/282#define UNITY_PITCH 0x8000283#define MAX_RATIO 1.99996 /* within .03 cents of +1 octave */284285/*286* Enveloper/Mixer state287*/288typedef short ENVMIX_STATE[40];289290/*291* Macros to assemble the audio command list292*/293294/*295* Info about parameters:296*297* A "count" in the following macros is always measured in bytes.298*299* All volumes/gains are in Q1.15 signed fixed point numbers:300* 0x8000 is the minimum volume (-100%), negating the audio curve.301* 0x0000 is silent.302* 0x7fff is maximum volume (99.997%).303*304* All DRAM addresses refer to segmented addresses. A segment table shall305* first be set up by calling aSegment for each segment. When a DRAM306* address is later used as parameter, the 8 high bits will be an index307* to the segment table and the lower 24 bits are added to the base address308* stored in the segment table for this entry. The result is the physical address.309* With the newer rsp audio code, this segment table is not used. The address is310* used directly instead.311*312* Transfers to/from DRAM are executed using DMA and hence follow these restrictions:313* All DRAM addresses should be aligned by 8 bytes, or they will be314* rounded down to the nearest multiple of 8 bytes.315* All DRAM lengths should be aligned by 8 bytes, or they will be316* rounded up to the nearest multiple of 8 bytes.317*/318319/*320* Decompresses ADPCM data.321* Possible flags: A_INIT and A_LOOP.322*323* First set up internal data in DMEM:324* aLoadADPCM(cmd++, nEntries * 16, physicalAddressOfBook)325* aSetLoop(cmd++, physicalAddressOfLoopState) (if A_LOOP is set)326*327* Then before this command, call:328* aSetBuffer(cmd++, 0, in, out, count)329*330* Note: count will be rounded up to the nearest multiple of 32 bytes.331*332* ADPCM decompression works on a block of 16 (uncompressed) samples.333* The previous 2 samples and 9 bytes of input are decompressed to334* 16 new samples using the code book previously loaded.335*336* Before the algorithm starts, the previous 16 samples are loaded according to flag:337* A_INIT: all zeros338* A_LOOP: the address set by aSetLoop339* no flags: the DRAM address in the s parameter340* These 16 samples are immediately copied to the destination address.341*342* The result of "count" bytes will be written after these 16 initial samples.343* The last 16 samples written to the destination will also be written to344* the state address in DRAM.345*/346#define aADPCMdec(pkt, f, s) \347{ \348Acmd *_a = (Acmd *)pkt; \349\350_a->words.w0 = _SHIFTL(A_ADPCM, 24, 8) | _SHIFTL(f, 16, 8); \351_a->words.w1 = (uintptr_t)(s); \352}353354/*355* Not used in SM64.356*/357#define aPoleFilter(pkt, f, g, s) \358{ \359Acmd *_a = (Acmd *)pkt; \360\361_a->words.w0 = (_SHIFTL(A_POLEF, 24, 8) | _SHIFTL(f, 16, 8) | \362_SHIFTL(g, 0, 16)); \363_a->words.w1 = (uintptr_t)(s); \364}365366/*367* Clears DMEM data, where d is address and c is count, by writing zeros.368*369* Note: c is rounded up to the nearest multiple of 16 bytes.370*/371#define aClearBuffer(pkt, d, c) \372{ \373Acmd *_a = (Acmd *)pkt; \374\375_a->words.w0 = _SHIFTL(A_CLEARBUFF, 24, 8) | _SHIFTL(d, 0, 24); \376_a->words.w1 = (uintptr_t)(c); \377}378379/*380* Mixes an envelope with mono sound into 2 or 4 channels.381* Possible flags: A_INIT, A_AUX (indicates that 4 channels should be used).382*383* Before this command, call:384* aSetBuffer(cmd++, 0, inBuf, dryLeft, count)385* aSetBuffer(cmd++, A_AUX, dryRight, wetLeft, wetRight)386*387* The first time (A_INIT is set), volume also needs to be set:388* aSetVolume(cmd++, A_VOL | A_LEFT, initialVolumeLeft, 0, 0)389* aSetVolume(cmd++, A_VOL | A_RIGHT, initialVolumeRight, 0, 0)390* aSetVolume32(cmd++, A_RATE | A_LEFT, targetVolumeLeft, rampLeft)391* aSetVolume32(cmd++, A_RATE | A_RIGHT, targetVolumeRight, rampRight)392* aSetVolume(cmd++, A_AUX, dryVolume, 0, wetVolume)393*394* This command will now mix samples in inBuf into the destination buffers (dry and wet),395* but with the volume increased (or decreased) from initial volumes to target volumes,396* with the specified ramp rate. Once the target volume is reached, the volume stays397* at that level. Before the samples are finally mixed (added) into the destination398* buffers (dry and wet), the volume is changed according to dryVolume and wetVolume.399*400* Note: count will be rounded up to the nearest multiple of 16 bytes.401* Note: the wet channels are used for reverb.402*403*/404#define aEnvMixer(pkt, f, s) \405{ \406Acmd *_a = (Acmd *)pkt; \407\408_a->words.w0 = _SHIFTL(A_ENVMIXER, 24, 8) | _SHIFTL(f, 16, 8); \409_a->words.w1 = (uintptr_t)(s); \410}411412/*413* Interleaves two mono channels into stereo.414*415* First call:416* aSetBuffer(cmd++, 0, 0, output, count)417*418* The count refers to the size of each input. Hence 2 * count bytes will be written out.419* A left sample will be placed before the right sample.420*421* Note: count will be rounded up to the nearest multiple of 16 bytes.422*/423#define aInterleave(pkt, l, r) \424{ \425Acmd *_a = (Acmd *)pkt; \426\427_a->words.w0 = _SHIFTL(A_INTERLEAVE, 24, 8); \428_a->words.w1 = _SHIFTL(l, 16, 16) | _SHIFTL(r, 0, 16); \429}430431/*432* Loads a buffer from DRAM to DMEM.433*434* First call:435* aSetBuffer(cmd++, 0, in, 0, count)436*437* The in parameter to aSetBuffer is the destination in DMEM and the438* s parameter to this command is the source in DRAM.439*/440#define aLoadBuffer(pkt, s) \441{ \442Acmd *_a = (Acmd *)pkt; \443\444_a->words.w0 = _SHIFTL(A_LOADBUFF, 24, 8); \445_a->words.w1 = (uintptr_t)(s); \446}447448/*449* Mixes audio.450* Possible flags: no flags used, although parameter present.451*452* First call:453* aSetBuffer(cmd++, 0, 0, 0, count)454*455* Input and output addresses are taken from the i and o parameters.456* The volume with which the input is changed is taken from the g parameter.457* After the volume of the input samples have been changed, the result458* is added to the output.459*460* Note: count will be rounded up to the nearest multiple of 32 bytes.461*/462#define aMix(pkt, f, g, i, o) \463{ \464Acmd *_a = (Acmd *)pkt; \465\466_a->words.w0 = (_SHIFTL(A_MIXER, 24, 8) | _SHIFTL(f, 16, 8) | \467_SHIFTL(g, 0, 16)); \468_a->words.w1 = _SHIFTL(i,16, 16) | _SHIFTL(o, 0, 16); \469}470471// Not present in the audio microcode.472#define aPan(pkt, f, d, s) \473{ \474Acmd *_a = (Acmd *)pkt; \475\476_a->words.w0 = (_SHIFTL(A_PAN, 24, 8) | _SHIFTL(f, 16, 8) | \477_SHIFTL(d, 0, 16)); \478_a->words.w1 = (uintptr_t)(s); \479}480481/*482* Resamples audio.483* Possible flags: A_INIT, A_OUT? (not used in SM64).484*485* First call:486* aSetBuffer(cmd++, 0, in, out, count)487*488* This command resamples the audio using the given frequency ratio (pitch)489* using a filter that uses a window of 4 source samples. This can be used490* either for just resampling audio to be able to be played back at a different491* sample rate, or to change the pitch if the result is played back at492* the same sample rate as the input.493*494* The frequency ratio is given in UQ1.15 fixed point format.495* For no change in frequency, use pitch 0x8000.496* For 1 octave up or downsampling to (roughly) half number of samples, use pitch 0xffff.497* For 1 octave down or upsampling to double as many samples, use pitch 0x4000.498*499* Note: count represents the number of output sample bytes and is rounded up to500* the nearest multiple of 16 bytes.501*502* The state consists of the four following source samples when the algorithm stopped as503* well as a fractional position, and is initialized to all zeros if A_INIT is given.504* Otherwise it is loaded from DRAM at address s.505*506* The algorithm starts by writing the four source samples from the state (or zero)507* to just before the input address given. It then creates one output sample by examining508* the four next source samples and then moving the source position zero or more509* samples forward. The first output sample (when A_INIT is given) is always 0.510*511* When "count" bytes have been written, the following four source samples512* are written to the state in DRAM as well as a fractional position.513*/514#define aResample(pkt, f, p, s) \515{ \516Acmd *_a = (Acmd *)pkt; \517\518_a->words.w0 = (_SHIFTL(A_RESAMPLE, 24, 8) | _SHIFTL(f, 16, 8) |\519_SHIFTL(p, 0, 16)); \520_a->words.w1 = (uintptr_t)(s); \521}522523/*524* Stores a buffer in DMEM to DRAM.525*526* First call:527* aSetBuffer(cmd++, 0, 0, out, count)528*529* The out parameter to aSetBuffer is the source in DMEM and the530* s parameter to this command is the destination in DRAM.531*/532#define aSaveBuffer(pkt, s) \533{ \534Acmd *_a = (Acmd *)pkt; \535\536_a->words.w0 = _SHIFTL(A_SAVEBUFF, 24, 8); \537_a->words.w1 = (uintptr_t)(s); \538}539540/*541* Sets up an entry in the segment table.542*543* The s parameter is a segment index, 0 to 15.544* The b parameter is the base offset.545*/546#define aSegment(pkt, s, b) \547{ \548Acmd *_a = (Acmd *)pkt; \549\550_a->words.w0 = _SHIFTL(A_SEGMENT, 24, 8); \551_a->words.w1 = _SHIFTL(s, 24, 8) | _SHIFTL(b, 0, 24); \552}553554/*555* Sets internal DMEM buffer addresses used for later commands.556* See each command for how to use aSetBuffer.557*/558#define aSetBuffer(pkt, f, i, o, c) \559{ \560Acmd *_a = (Acmd *)pkt; \561\562_a->words.w0 = (_SHIFTL(A_SETBUFF, 24, 8) | _SHIFTL(f, 16, 8) | \563_SHIFTL(i, 0, 16)); \564_a->words.w1 = _SHIFTL(o, 16, 16) | _SHIFTL(c, 0, 16); \565}566567/*568* Sets internal volume parameters.569* See aEnvMixer for more info.570*/571#define aSetVolume(pkt, f, v, t, r) \572{ \573Acmd *_a = (Acmd *)pkt; \574\575_a->words.w0 = (_SHIFTL(A_SETVOL, 24, 8) | _SHIFTL(f, 16, 16) | \576_SHIFTL(v, 0, 16)); \577_a->words.w1 = _SHIFTL(t, 16, 16) | _SHIFTL(r, 0, 16); \578}579580/*581* Sets the address to ADPCM loop state.582*583* The a parameter is a DRAM address.584* See aADPCMdec for more info.585*/586#define aSetLoop(pkt, a) \587{ \588Acmd *_a = (Acmd *)pkt; \589_a->words.w0 = _SHIFTL(A_SETLOOP, 24, 8); \590_a->words.w1 = (uintptr_t)(a); \591}592593/*594* Copies memory in DMEM.595*596* Copies c bytes from address i to address o.597*598* Note: count is rounded up to the nearest multiple of 16 bytes.599*600* Note: This acts as memcpy where 16 bytes are moved at a time, therefore601* if input and output overlap, output address should be less than input address.602*/603#define aDMEMMove(pkt, i, o, c) \604{ \605Acmd *_a = (Acmd *)pkt; \606\607_a->words.w0 = _SHIFTL(A_DMEMMOVE, 24, 8) | _SHIFTL(i, 0, 24); \608_a->words.w1 = _SHIFTL(o, 16, 16) | _SHIFTL(c, 0, 16); \609}610611/*612* Loads ADPCM book from DRAM into DMEM.613*614* This command loads ADPCM table entries from DRAM to DMEM.615*616* The count parameter c should be a multiple of 16 bytes.617* The d parameter is a DRAM address.618*/619#define aLoadADPCM(pkt, c, d) \620{ \621Acmd *_a = (Acmd *)pkt; \622\623_a->words.w0 = _SHIFTL(A_LOADADPCM, 24, 8) | _SHIFTL(c, 0, 24); \624_a->words.w1 = (uintptr_t) (d); \625}626627// This is a version of aSetVolume which takes a single 32-bit parameter628// instead of two 16-bit ones. According to AziAudio, it is used to set629// ramping values when neither bit 4 nor bit 8 is set in the flags parameter.630// It does not appear in the official abi.h header.631/*632* Sets internal volume parameters.633* See aEnvMixer for more info.634*/635#define aSetVolume32(pkt, f, v, tr) \636{ \637Acmd *_a = (Acmd *)pkt; \638\639_a->words.w0 = (_SHIFTL(A_SETVOL, 24, 8) | _SHIFTL(f, 16, 16) | \640_SHIFTL(v, 0, 16)); \641_a->words.w1 = (uintptr_t)(tr); \642}643644#ifdef VERSION_SH645#undef aLoadBuffer646#undef aSaveBuffer647#undef aMix648#undef aEnvMixer649#undef aInterleave650651// New or modified operations in the new audio microcode below652653/**654* Decompresses S8 data.655* Possible flags: A_INIT and A_LOOP.656*657* First set up internal data in DMEM:658* aSetLoop(cmd++, physicalAddressOfLoopState) (if A_LOOP is set)659*660* Then before this command, call:661* aSetBuffer(cmd++, 0, in, out, count)662*663* Note: count will be rounded up to the nearest multiple of 32 bytes.664*665* S8 decompression works by expanding s8 bytes into s16 numbers,666* by performing a left shift of 8 steps.667*668* Before the algorithm starts, the previous 16 samples are loaded according to flag:669* A_INIT: all zeros670* A_LOOP: the address set by aSetLoop671* no flags: the DRAM address in the s parameter672* These 16 samples are immediately copied to the destination address.673*674* The result of "count" bytes will be written after these 16 initial samples.675* The last 16 samples written to the destination will also be written to676* the state address in DRAM.677*/678#define aS8Dec(pkt, f, s) \679{ \680Acmd *_a = (Acmd *)pkt; \681\682_a->words.w0 = _SHIFTL(A_S8DEC, 24, 8) | _SHIFTL(f, 16, 8); \683_a->words.w1 = (uintptr_t)(s); \684}685686/*687* Mix two tracks by simple clamped addition.688*689* s: DMEM source track 1690* d: DMEM source track 2 and destination691* c: number of bytes to write692*693* Note: count is first rounded down to the nearest multiple of 16 bytes694* and then rounded up to the nearest multiple of 64 bytes.695*/696#define aAddMixer(pkt, s, d, c) \697{ \698Acmd *_a = (Acmd *)pkt; \699\700_a->words.w0 = (_SHIFTL(A_ADDMIXER, 24, 8) | \701_SHIFTL((c) >> 4, 16, 8) | _SHIFTL(0x7fff, 0, 16)); \702_a->words.w1 = (_SHIFTL(s, 16, 16) | _SHIFTL(d, 0, 16)); \703}704705/*706* Loads a buffer from DRAM to DMEM.707*708* s: DRAM source709* d: DMEM destination710* c: number of bytes to copy (rounded down to 16 byte alignment)711*/712#define aLoadBuffer(pkt, s, d, c) \713{ \714Acmd *_a = (Acmd *)pkt; \715\716_a->words.w0 = _SHIFTL(A_LOADBUFF, 24, 8) | \717_SHIFTL((c) >> 4, 16, 8) | _SHIFTL(d, 0, 16); \718_a->words.w1 = (uintptr_t)(s); \719}720721/*722* Stores a buffer from DMEM to DRAM.723*724* s: DMEM source725* d: DRAM destination726* c: number of bytes to copy (rounded down to 16 byte alignment)727*/728#define aSaveBuffer(pkt, s, d, c) \729{ \730Acmd *_a = (Acmd *)pkt; \731\732_a->words.w0 = _SHIFTL(A_SAVEBUFF, 24, 8) | \733_SHIFTL((c) >> 4, 16, 8) | _SHIFTL(s, 0, 16); \734_a->words.w1 = (uintptr_t)(d); \735}736737/*738* Duplicates 128 bytes of data a number of times.739*740* 128 bytes are read from source DMEM address s.741* Then c identical copies of these bytes are written to DMEM address d.742*/743#define aDuplicate(pkt, s, d, c) \744{ \745Acmd *_a = (Acmd *)pkt; \746\747_a->words.w0 = (_SHIFTL(A_DUPLICATE, 24, 8) | \748_SHIFTL(c, 16, 8) | _SHIFTL(s, 0, 16)); \749_a->words.w1 = (_SHIFTL(d, 16, 16) | _SHIFTL(0x80, 0, 16)); \750}751752/*753* Copies memory in DMEM, second version.754*755* Copies t * c bytes from address i to address o.756*757* Note: count is first rounded up to the nearest multiple of 32 bytes,758* before the multiplication by t.759*760* Note: This acts as memcpy where 32 bytes are moved at a time, therefore761* if input and output overlap, output address should be less than input address.762*763* Not used in SM64.764*/765#define aDMEMMove2(pkt, t, i, o, c) \766{ \767Acmd *_a = (Acmd *)pkt; \768\769_a->words.w0 = _SHIFTL(A_DMEMMOVE2, 24, 8) | \770_SHIFTL(t, 16, 8) | _SHIFTL(i, 0, 16); \771_a->words.w1 = _SHIFTL(o, 16, 16) | _SHIFTL(c, 0, 16); \772}773774/*775* Fast resample.776*777* Before this command, call:778* aSetBuffer(cmd++, 0, in, out, count)779*780* This works like the other resample command but just takes the "nearest" sample,781* instead of a function of the four nearest samples.782*783* Initially the current position is calculated as (in << 16) + startFract.784* For every sample to create, the value is simply taken from the sample785* at address ((position >> 17) << 1). Then the current position is incremented786* by (pitch << 2).787*788* Note: count represents the number of output bytes to create, and is789* rounded up to the nearest multiple of 8 bytes.790*/791#define aResampleZoh(pkt, pitch, startFract) \792{ \793Acmd *_a = (Acmd *)pkt; \794\795_a->words.w0 = (_SHIFTL(A_RESAMPLE_ZOH, 24, 8) | \796_SHIFTL(pitch, 0, 16)); \797_a->words.w1 = _SHIFTL(startFract, 0, 16); \798}799800/*801* Fast downsampling by taking every other sample, discarding others.802*803* Note: nSamples refers to the number of output samples to create, and804* is first rounded up to the nearest multiple of 8.805*/806#define aDownsampleHalf(pkt, nSamples, i, o) \807{ \808Acmd *_a = (Acmd *)pkt; \809\810_a->words.w0 = (_SHIFTL(A_DOWNSAMPLE_HALF, 24, 8) | \811_SHIFTL(nSamples, 0, 16)); \812_a->words.w1 = _SHIFTL(i, 16, 16) | _SHIFTL(o, 0, 16); \813}814815/*816* Mixes audio.817*818* Input and output addresses are taken from the i and o parameters.819* The volume with which the input is changed is taken from the g parameter.820* After the volume of the input samples have been changed, the result821* is added to the output.822*823* Note: count is first rounded down to the nearest multiple of 16 bytes824* and then rounded up to the nearest multiple of 32 bytes.825*/826#define aMix(pkt, g, i, o, c) \827{ \828Acmd *_a = (Acmd *)pkt; \829\830_a->words.w0 = (_SHIFTL(A_MIXER, 24, 8) | \831_SHIFTL((c) >> 4, 16, 8) | _SHIFTL(g, 0, 16)); \832_a->words.w1 = _SHIFTL(i, 16, 16) | _SHIFTL(o, 0, 16); \833}834835/*836* See aEnvMixer for more info.837*/838#define aEnvSetup1(pkt, initialVolReverb, rampReverb, rampLeft, rampRight) \839{ \840Acmd *_a = (Acmd *)pkt; \841\842_a->words.w0 = (_SHIFTL(A_ENVSETUP1, 24, 8) | \843_SHIFTL(initialVolReverb, 16, 8) | \844_SHIFTL(rampReverb, 0, 16)); \845_a->words.w1 = _SHIFTL(rampLeft, 16, 16) | \846_SHIFTL(rampRight, 0, 16); \847}848849/*850* See aEnvMixer for more info.851*/852#define aEnvSetup2(pkt, initialVolLeft, initialVolRight) \853{ \854Acmd *_a = (Acmd *)pkt; \855\856_a->words.w0 = _SHIFTL(A_ENVSETUP2, 24, 8); \857_a->words.w1 = _SHIFTL(initialVolLeft, 16, 16) | \858_SHIFTL(initialVolRight, 0, 16); \859}860861/*862* Mixes an envelope with mono sound into 4 channels.863*864* To allow for many parameters, a sequence of aEnvSetup1, aEnvSetup2,865* aEnvMixer shall always be called.866*867* The function works in blocks of 8 samples.868* However, nSamples is rounded up to the nearest multiple of 16 samples.869*870* For each sample in a block:871* 1. sampleLeft = in * volLeft * (negLeft ? -1 : 1)872* 2. sampleRight = in * volRight * (negRight ? -1 : 1)873* 3. dryLeft += sampleLeft874* 4. dryRight += sampleRight875* 5. if swapReverb: swap sampleLeft and sampleRight876* 6. wetLeft += sampleLeft * volReverb877* 7. wetRight += sampleRight * volReverb878*879* After each block, all vol variables are added by their corresponding880* ramp value.881*882* Each volume variable is treated as a UQ0.16 number. Make sure883* the ramp additions don't overflow, or wrapping will occur.884* The initialVolReverb parameter is only 8 bits, but will be left885* shifted 8 bits by the rsp.886*/887#define aEnvMixer(pkt, inBuf, nSamples, swapReverb, negLeft, negRight, \888dryLeft, dryRight, wetLeft, wetRight) \889{ \890Acmd *_a = (Acmd *)pkt; \891\892_a->words.w0 = (_SHIFTL(A_ENVMIXER, 24, 8) | \893_SHIFTL((inBuf) >> 4, 16, 8) | \894_SHIFTL(nSamples, 8, 8)) | \895_SHIFTL(swapReverb, 2, 1) | _SHIFTL(negLeft, 1, 1) |\896_SHIFTL(negRight, 0, 1); \897_a->words.w1 = _SHIFTL((dryLeft) >> 4, 24, 8) | \898_SHIFTL((dryRight) >> 4, 16, 8) | \899_SHIFTL((wetLeft) >> 4, 8, 8) | \900_SHIFTL((wetRight) >> 4, 0, 8); \901}902903/*904* Interleaves two mono channels into stereo.905*906* The count refers to the size of each input. Hence 2 * count bytes907* will be written out.908*909* A left sample will be placed before the right sample.910* All addresses (output, left, right) are DMEM addresses.911*912* Note: count will be rounded up to the nearest multiple of 8 bytes.913* The previous version of this function rounded up to the nearest914* multiple of 16 bytes.915*/916#define aInterleave(pkt, o, l, r, c) \917{ \918Acmd *_a = (Acmd *)pkt; \919\920_a->words.w0 = _SHIFTL(A_INTERLEAVE, 24, 8) | \921_SHIFTL((c) >> 4, 16, 8) | _SHIFTL(o, 0, 16); \922_a->words.w1 = _SHIFTL(l, 16, 16) | _SHIFTL(r, 0, 16); \923}924925/*926* Linear filter function.927*928* Calculates out[i] = sum all elements in the vector in[i..i-7] * filter[0..7],929* where "*" represents dot multiplication. The input/output contains s16930* samples and filter contains Q1.15 signed fixed point numbers.931* Every result sample is rounded and clamped.932*933* First initiate by calling with the flag f set to 2, countOrBuf contains934* the length in bytes that shall be processed in the next call. The addr935* parameter shall contain the DRAM address to the filter table (16 bytes).936* The count will be rounded up to the nearest multiple of 16 bytes.937*938* The aFilter function shall then be called in direct succession, with flag939* set to either 0 or 1. The countOrBuf parameter shall contain the DMEM940* address for the input/output. The addr parameter shall contain the DRAM941* address for the state, containing the last previous 8 input samples.942* The state is always written to upon exit, but is only read at entry if943* the flag is 0 (otherwise all-zero samples are used instead).944*/945#define aFilter(pkt, f, countOrBuf, addr) \946{ \947Acmd *_a = (Acmd *)pkt; \948\949_a->words.w0 = _SHIFTL(A_FILTER, 24, 8) | _SHIFTL((f), 16, 8) | \950_SHIFTL((countOrBuf), 0, 16); \951_a->words.w1 = (uintptr_t)(addr); \952}953954/*955* Modifies the volume of samples using a simple UQ4.4 gain multiplier.956*957* Performs the following:958*959* 1. Count c is rounded up to 32 byte alignment960* 2. g is a u8 that contains a UQ4.4 number961* 3. Modify each sample s, so that s = clamp_s16(s * g >> 4)962*/963#define aHiLoGain(pkt, g, buflen, i) \964{ \965Acmd *_a = (Acmd *)pkt; \966\967_a->words.w0 = _SHIFTL(A_HILOGAIN, 24, 8) | \968_SHIFTL((g), 16, 8) | _SHIFTL((buflen), 0, 16); \969_a->words.w1 = _SHIFTL((i), 16, 16); \970}971972/*973* Performs the following:974*975* 1. Count c is rounded up to 64 byte alignment976* 2. f is added to i977* 3. i and o are from now treated as s16 pointers978* 4. 32 s16 samples are loaded from i to tbl979* 5. for (u32 idx = 0; idx * sizeof(s16) < c; idx++)980* o[idx] = clamp_s16((s32)o[idx] * (s32)tbl[idx % 32]);981*/982#define aUnknown25(pkt, f, c, o, i) \983{ \984Acmd *_a = (Acmd *)pkt; \985\986_a->words.w0 = (_SHIFTL(A_UNK_25, 24, 8) | \987_SHIFTL((f), 16, 8) | _SHIFTL((c), 0, 16)); \988_a->words.w1 = _SHIFTL((o), 16, 16) | _SHIFTL((i), 0, 16); \989}990991#endif992993#endif /* _LANGUAGE_C */994995#endif /* !_ABI_H_ */996997998