Reply to topic  [ 1 post ] 
The programming language of samples declared as synth/hybrid 
Author Message
Administrator

Joined: 31. May 2005 05:23
Posts: 70
Location: Liège
Post The programming language of samples declared as synth/hybrid
Code:
The synth functions of TuComposer:
TuComposer's synth functions are designed to be as flexible as possible.
Each synth structure is assigned to a sample, also each synth structure
contains a list of waveforms, as well as synth programming lines. Samples
which have the synth structure but not a list of waveforms are called
Hybrids. This means that this is a normal sample which only uses the synth
programming language. I will describe now the synth programming language
in details. The programming language is splitted into lines. Each line
contains one instruction which does some action (like pitch sliding,
vibratos, arpeggios, panning slides, etc.). The programming language is
splitted into three parts:
1. Flow control/Variable accessing instructions
2. Arithmetic instructions
3. Sound instructions (which do the portamentoes, etc.)
4. Normal effect execution (any effect described some lines above)

The most flexible are the flow control/variable accessing instructions.
Each synth has 16 16-bit variables which can be accessed/changed freely
by the synth code. You can do calculations there. The synth code has 4
entry points: The volume, panning, slide and special entry points. That
means that you can treat a synth like a 4-processor system. Although they
all share the 16 variables, each has it's own condition variable, where
certain instructions (most arithmetic) store several states such as carry,
overflow, negative, zero. You can't access the condition variables directly,
because it's not required. The condition variables are compatible with the
MC680x0 CCR register (same bits allocated). That means that you must convert
the initial values according to the processor you're coding your player for.
All processors should support these flags. If not, you must write small
emulation code, but there shouldn't be any speed decreases to be noticed,
because that's so simple. The synth programming language supports up to 128
instructions (the negative instruction bytes are the normal commands).
The instruction format is as follows:
INST    vX+YYYY,vZ

Where X is the high nibble, Z the low nibble and YYYY the instruction data.
If YYYY is zero, it's omitted if Source parameter allowed. If X is zero,
the vX+ will not be displayed. The instructions are listed and described below
in detail (Parameters describe, which parameter bits the instruction takes:
None Source, Dest or Both). Note, Source means vX+YYYY, not vX only, except
for the instructions from NOT to SWAP. The negative instruction byte is
SETFXxx where xx is the inverted instruction byte, i.e. SETFX0E is F1. It
will execute the normal effects (in the example is Vibrato (0E)). Please
note that the vibrato/tremolo commands CAN'T BE INVOKED with this because
they need preparations and only work on host channels. Use the synth
VIBRATO/TREMOLO instead. This doesn't apply to track/global tremolo. But here
are the synth instructions:
Name    | Byte | Params | Description
STOP    |  00  | Source | Also named END. Stops synth execution here !
        |      |        | If source is non-zero it will set a external
        |      |        | influence forbid. If bit #15 is set, influences
        |      |        | will be permitted. The mask is defined as:
        |      |        | Mask | Meanings
        |      |        | 0001 | Forbid external JUMPVOL
        |      |        | 0002 | Forbid external JUMPPAN
        |      |        | 0004 | Forbid external JUMPSLD
        |      |        | 0008 | Forbid external JUMPSPC
KILL    |  01  | Source | Stops execution and frees current channel, normally
        |      |        | used in NNA/DNA trigger handling code. If source
        |      |        | is non-zero execution will continue until wait
        |      |        | counter is zero. To immediately stop, use a STOP
        |      |        | straight after KILL.
WAIT    |  02  | Source | Waits given amount in ticks before continue.
WAITVOL |  03  | Source | Waits until volume handling code has reached the
        |      |        | line you given in Source.
WAITPAN |  04  | Source | Waits until panning handling code has reached the
        |      |        | line you given in Source.
WAITSLD |  05  | Source | Waits until slide handling code has reached the line
        |      |        | you given in Source.
WAITSPC |  06  | Source | Waits until special handling code has reached the
        |      |        | line you given in Source.
JUMP    |  07  | Source | Jumps to the line you have given in Source.
JUMPEQ  |  08  | Source | Jumps, if zero flag is set, to the specified line,
        |      |        | else continues execution with the next line.
JUMPNE  |  09  | Source | Jumps, if zero flag is cleared, to the specified
        |      |        | else continues execution normally in the next line.
JUMPPL  |  0A  | Source | Jumps, if negative flag is cleared to the line,
        |      |        | you specified else continues normally.
JUMPMI  |  0B  | Source | Like JUMPPL but jumps if negative flag is set.
JUMPLT  |  0C  | Source | Jumps, if only one of negative and overflow flags
        |      |        | is set. If both are set or cleared nothing happens.
        |      |        | For easilier understanding: This jumps if the
        |      |        | destination is less than (signed) the source.
JUMPLE  |  0D  | Source | The same as JUMPLT but, in addition to the other
        |      |        | flags, the zero flag must be set to cause a jump.
        |      |        | This can be understand as less or equal than.
JUMPGT  |  0E  | Source | The exact opposition to JUMPLE. When JUMPLE jumps,
        |      |        | this won't jump, if JUMPLE doesn't jump, this does.
JUMPGE  |  0F  | Source | The exact opposition to JUMPLT.
JUMPVS  |  10  | Source | This jumps if a signed overflow is detected. V = 1
JUMPVC  |  11  | Source | This jumps if there's not a signed overflow. V = 0
JUMPCS  |  12  | Source | Also JUMPLO. Jumps if the carry flag is set.
JUMPCC  |  13  | Source | Also JUMPHS. Jumps if the carry flag is clear.
JUMPLS  |  14  | Source | This jumps if the carry and zero flags are set.
        |      |        | Also known as unsigned less or same.
JUMPHI  |  15  | Source | This jumps if the carry and zero flags are cleared.
        |      |        | Also known as unsigned higher than.
JUMPVOL |  16  | Source | Causes the volume handling code to jump to source.
JUMPPAN |  17  | Source | Causes the panning handling code to jump to source.
JUMPSLD |  18  | Source | Causes the slide handling code to jump to source.
JUMPSPC |  19  | Source | Causes the special handling code to jump to source.
CALL    |  1A  |  Both  | Pushes the next position to the destination
        |      |        | variable, then continues execution at the source.
RETURN  |  1B  |  Both  | Pops the line number from the source and continues
        |      |        | execution there. The old number will be stored in
        |      |          destination.
POSVAR  |  1C  | Source | Pushes the current line number into the source
        |      |        | variable and adds tcy_InstData to it afterwards.
LOAD    |  1D  |  Both  | Loads the destination with the source variable.
ADD     |  1E  |  Both  | Adds the source to the destination variable.
        |      |        | The condition variables are set accordingly.
ADDX    |  1F  |  Both  | Like ADD but adds also the extend flag. The Z
        |      |        | flag is only cleared if the result is non-zero.
        |      |        | It is UNCHANGED otherwise.
SUB     |  20  |  Both  | Like ADD but subtracts instead.
SUBX    |  21  |  Both  | Like ADDX but subtracts instead.
CMP     |  22  |  Both  | Like SUB but doesn't store the result in the
        |      |        | destination variable, i.e. it compares.
MULU    |  23  |  Both  | Does an unsigned multiply of the lower bytes
        |      |        | of the source and destinations. X is never
        |      |        | affected and C is always cleared. The other flags
        |      |        | are set accordingly to the result.
MULS    |  24  |  Both  | Same as MULU but uses signed arithmetic.
DMULU   |  25  |  Both  | Like MULU, but multiplies an 16-bit source with
        |      |        | and 16-bit destination and stores the upper word
        |      |        | in the destination variable and the lower word
        |      |        | in the destination variable + 1. If v15 is used,
        |      |        | the lower word will only be be stored.
DMULS   |  26  |  Both  | Like DMULU but uses signed arithmetic.
DIVU    |  27  |  Both  | Divides the destination with the source and places
        |      |        | the quotient in the destination. The flags are
        |      |        | affected the same way as the multiply instructions.
        |      |        | If a divide by zero occurs, the instruction is
        |      |        | ignored and all flags are set except X.
DIVS    |  28  |  Both  | Like DIVU but uses signed arithmetic instead.
MODU    |  29  |  Both  | Like DIVU but returns the remainder instead.
MODS    |  2A  |  Both  | Like DIVS but returns the remainder instead.
DDIVU   |  2B  |  Both  | Like DIVU, but divides a 32-bit destination (the
        |      |        | upper word is the destination variable, and the
        |      |        | lower word is the destination variable + 1) with
        |      |        | a 16-bit source. The quotient is placed in the
        |      |        | destination variable + 1 and the remainder is
        |      |        | placed in the destination variable). If the
        |      |        | destination variable is v15, the quotient will be
        |      |        | placed in destination variable. If an
        |      |        | overflow occurs the destination is not affected
        |      |        | and the negative flag is undefined.
DDIVS   |  2C  |  Both  | Like DDIVU but uses signed arithmetic instead.
ASHL    |  2D  |  Both  | Left shifts the destination by the amount of bits
        |      |        | given in the source. The flags are set as follows:
        |      |        | X - Set according to the last bit shifted out of
        |      |        |     the operand. Not affected when the shift count
        |      |        |     is zero.
        |      |        | Z - Set if the result is zero.
        |      |        | N - Set if the result is negative.
        |      |        | V - Set if the sign-bit is changed at any time
        |      |        |     during the operation.
        |      |        | C - Like X, but cleared when the shift count is 0.
ASHR    |  2E  |  Both  | Like ASHL but shifts right instead.
LSHL    |  2F  |  Both  | Like ASHL but the flags are set as follows:
        |      |        | X - Set according to the last bit shifted out.
        |      |        | Z - Set if the result is zero.
        |      |        | N - Set if the result is negative.
        |      |        | V - always cleared
        |      |        | C - like X
LSHR    |  30  |  Both  | Like LSHL but shifts right instead.
ROL     |  31  |  Both  | Like LSHL but rotates instead. That means the
        |      |        | bits shifted out of operand come in on the other
        |      |        | side. The flags set like in LSHL, except that X
        |      |        | is unaffected.
ROR     |  32  |  Both  | The same as ROL but rotates right instead.
ROLX    |  33  |  Both  | Like ROL but uses the extend flag, i.e. the extend
        |      |        | flag comes in on the other side. The flags are set
        |      |        | the same way as in ROL, except that X is set like
        |      |        | in the ASHL instruction.
RORX    |  34  |  Both  | The same as ROLX but rotates right instead.
OR      |  35  |  Both  | Performs a logical OR on the destination. The flags
        |      |        | are set normally except X, which is unaffected and
        |      |        | V and C, which are always cleared.
AND     |  36  |  Both  | Like OR but performs logical AND instead.
XOR     |  37  |  Both  | Like OR but performs logical eXclusive OR instead.
NOT     |  38  |  Both  | Inverts the destination. Flags are same as in OR.
        |      |        | After inversion, source is added to it.
NEG     |  39  |  Both  | The destination is negated. This is done by sub-
        |      |        | tracting it from zero. The flags are set like SUB.
        |      |        | After negating, source is added to it.
NEGX    |  3A  |  Both  | The destination is negated. This is done by sub-
        |      |        | tracting it + X flag from zero. The flags are set
        |      |        | the same way as in SUBX. After negating, source
        |      |        | is added to it.
EXTB    |  3B  |  Both  | Copies bit 7 to bit 8-15 in the destination and
        |      |        | adds the source to it afterwards. The flags are
        |      |        | set normally, except X is unaffected.
EXT     |  3C  |  Both  | Copies bit 15 of the destination variable + 1 to
        |      |        | bits 0 - 15 of destination variable and adds the
        |      |        | source to it afterwards. The flags are set while
        |      |        | treating the two variables like a 32-bit value.
        |      |        | If destination variable is 15, it will simply fill
        |      |        | out v15 with zeroes.
XCHG    |  3D  |  Both  | Exchanges the source variable with the destination
        |      |        | variable. After exchanging the instruction data is
        |      |        | added to the destination variable. The flags are
        |      |        | set like in EXT, threating the destination
        |      |        | variable as the upper 16 bits.
SWAP    |  3E  |  Both  | Swaps the upper byte with the lower byte of the
        |      |        | destination. Flags are set according to the result
        |      |        | of the swap without the source added to it, this
        |      |        | will be done after setting them.
GETWAVE |  3F  |  Both  | Stores the current sample waveform to the
        |      |        | destination. All flags are unaffected by this
        |      |        | instruction and the following ones.
GETWLEN |  40  |  Both  | Stores the current sample waveform's length to
                          the destination and adds source to it.
GETWPOS |  41  |  Both  | Stores the current sample waveform's position to
                          the destination and adds source to it.
GETCHAN |  42  |  Both  | Stores the current host channel + the source into
GETNOTE |  43  |  Both  | Stores the current note playing + the source into
        |      |        | the destination.
GETRANS |  44  |  Both  | Like GETNOTE but stores the current sample
        |      |        | transpose value.
GETPTCH |  45  |  Both  | Stores the current frequency in the destination
        |      |        | variable (upper word) and destination variable + 1
        |      |        | (lower word). If destination variable is v15,
        |      |        | only the lower word will be set.
GETPER  |  46  |  Both  | Like GETPTCH except that it stores the period.
GETFX   |  47  |  Both  | Stores the effect's value of the effect number in
                          the upper byte of source. This is the value passed
                          to the effect at last, e.g a upper byte value of 20
                          would return current volume. The result is directly
                          passable to SETFXxx...
GETARPW |  48  |  Both  | Stores the waveform number to the destinated and
        |      |        | adds source to it.
GETARPV |  49  |  Both  | Stores of waveform's value of the point specified
        |      |        | by the source to the destination.
GETARPL |  4A  |  Both  | Stores the waveform length + source into the
        |      |        | destination variable.
GETARPP |  4B  |  Both  | Like GETARPW but stores position of waveform.
GETVIBW |  4C  |  Both  | Like GETARPW but for the vibrato waveform instead.
GETVIBV |  4D  |  Both  | Like GETARPV but stores the current vibrato
        |      |        | waveform value instead.
GETVIBL |  4E  |  Both  | Like GETVIBW but stores waveform length.
GETVIBP |  4F  |  Both  | Like GETVIBW but stores position of waveform.
GETTRMW |  50  |  Both  | Like GETVIBW but for the tremolo waveform instead.
GETTRMV |  51  |  Both  | Like GETVIBV but stores the current tremolo
        |      |        | waveform value instead.
GETTRML |  52  |  Both  | Like GETTRMW but stores waveform length.
GETTRMP |  53  |  Both  | Like GETTRMW but stores position of waveform.
GETPANW |  54  |  Both  | Like GETTRMW but for the pannolo waveform instead.
GETPANV |  55  |  Both  | Like GETTRMV but stores the current pannolo
        |      |        | waveform value instead.
GETPANL |  56  |  Both  | Like GETPANW but stores waveform length.
GETPANP |  57  |  Both  | Like GETPANW but stores position of waveform.
GETRND  |  58  |  Both  | Stores a random value from 0 to source value to
        |      |        | the destination variable.
GETSINE |  59  |  Both  | Stores the sine of the source (degrees) to the
        |      |        | destination variable. The sine value ranges from
        |      |        | -$7FFF to $7FFF, so use DMULS and DDIVS to scale
        |      |        | to the required value.
PORTAUP |  5A  | Source | Slides the pitch up with the given amount. The
        |      |        | difference between this and the generic command is,
        |      |        | that the synth slides have their own memory.
PORTADN |  5B  | Source | Like PORTAUP but slides down instead.
VIBSPD  |  5C  | Source | Sets the vibrato speed to the given value.
VIBDPTH |  5D  | Source | Sets the vibrato depth to the given value.
VIBWAVE |  5E  | Source | Sets the vibrato waveform to the given value.
VIBWAVP |  5F  | Source | Sets the vibrato waveform's position to the given
                          value in the source.
VIBRATO |  60  | Source | Executes the vibrato. The upper byte contains the
        |      |        | speed or NULL to use the previous values. The lower
        |      |        | byte contains the depth or NULL for use the previous
        |      |        | values. Please note that the depth is signed.
VIBVAL  |  61  | Source | Vibrate with period given by source.
ARPSPD  |  62  | Source | Sets the speed of the arpeggio as given.
ARPWAVE |  63  | Source | Sets the arpeggio waveform to be used as given.
ARPWAVP |  64  | Source | Sets the arpeggio position as given.
ARPEGIO |  65  | Source | Executes the arpeggio. The upper byte contains the
        |      |        | speed or NULL for previous value and the low is a
        |      |        | finetune modifier (in most cases 0)
ARPVAL  |  66  | Source | Like ARPEGIO, except that it gets the transpose
        |      |        | from the source instead from the waveform. The
        |      |        | upper byte is the transpose value.
SETWAVE |  67  | Source | Sets the sample waveform to the given value.
        |      |        | The current waveform will finish playing.
ISETWAV |  68  | Source | Sets the sample waveform to the given value
        |      |        | immediately. The current waveform will be aborted.
SETWAVP |  69  | Source | Sets the sample waveform's position to the given
                          value.
SETRANS |  6A  | Source | Sets transpose number as given. The current
        |      |        | transpose will be overwritten.
SETNOTE |  6B  | Source | Sets the note but doesn't update the note field.
SETPTCH |  6C  |  Both  | Sets the current frequency taken from the
        |      |        | destination variable (upper word) and the
        |      |        | destination variable + 1 (lower word). The source
        |      |        | will then be added to the frequency.
SETPER  |  6D  |  Both  | Equals to SETPTCH except that it sets period.
RESET   |  6E  | Source | Resets vibrato/tremolo/pannolo counters. Source
        |      |        | is a mask which contains the following disables.
        |      |        | Mask | Meanings
        |      |        | 0001 | Disables arpeggio reset
        |      |        | 0002 | Disables vibrato reset
        |      |        | 0004 | Disables tremolo reset
        |      |        | 0008 | Disables pannolo reset
        |      |        | 0010 | Disables redo of portamento
        |      |        | 0020 | Disables portamento reset
VOLSLUP |  6F  | Source | Slides the volume up by the given amount.
VOLSLDN |  70  | Source | Slides the volume down by the given amount.
TRMSPD  |  71  | Source | Sets the tremolo speed to the given value.
TRMDPTH |  72  | Source | Sets the tremolo depth to the given value.
TRMWAVE |  73  | Source | Sets the tremolo waveform to the given value.
TRMWAVP |  74  | Source | Sets the tremolo waveform's position to given val.
TREMOLO |  75  | Source | Executes the tremolo. Look VIBRATO for more infos.
TRMVAL  |  76  | Source | Tremolo with given volume in source
PANLEFT |  77  | Source | Slides the panning left by the given amount.
PANRGHT |  78  | Source | Slides the panning right by the given amount.
PANSPD  |  79  | Source | Sets the pannolo speed to the given value.
PANDPTH |  7A  | Source | Sets the pannolo depth to the given value.
PANWAVE |  7B  | Source | Sets the pannolo waveform to the given value.
PANWAVP |  7C  | Source | Sets the pannolo waveform's position to the given
                          value specified by the source.
PANMOLO |  7D  | Source | Executes the pannolo. Look VIBRATO for more infos.
PANVAL  |  7E  | Source | Pannolo with given panning in source

A small example to help understanding all this better:
Line | Binary    | Instruction
0000 | 1D,01,1000 | LOAD    1000,v1
0001 | 1E,01,1000 | ADD     1000,v1
0002 | 2D,01,0001 | ASHL    0001,v1
0003 | 0B,00,0010 | JUMPMI  0010
0004 | 07,00,0002 | JUMP    0002
0005 | 1D,12,0080 | LOAD    v1+0080,v2
0006 | 23,02,0003 | MULU    0003,v2
0007 | 1D,04,000D | LOAD    000D,v4
0008 | 1D,25,0000 | LOAD    v2,v5
0009 | 1E,05,DEAD | ADD     DEAD,v5
000A | 13,40,0000 | JUMPCC  v4
000B | 6E,50,0080 | VOLSLDN v5+0080
000C | 07,40,0000 | JUMP    v4
000D | 21,55,0000 | SUBX    v5,v5
000E | 39,05,0000 | NEG     v5
000F | 1D,51,0000 | LOAD    v5,v1
0010 | 3E,01,0000 | SWAP    v1
0011 | 6D,10,0000 | VOLSLUP v1+0000
0012 | 02,00,0001 | WAIT    0001
0013 | 07,00,0000 | JUMP    0005
0014 | 00,00,0000 | STOP

This looks complex ? Well, let us step through it. Assume all variables are
0000 initially. Let us panning/slide/special handling code initially be
0014 and volume handling code be 0000. That means the other three will stop
immediately. The volume handling code will execute line 0000, which causes
register v1 to be loaded with v0+1000 (v0 isn't displayed, right?), because
v0 is 0000, v1 will be loaded with 1000. Then line 0001 will be executed
which causes to add v0+1000 to v1. v1 is 1000. 1000+1000 is 2000 and hence
2000 will be stored to v1. All flags will be cleared. Line 0003 causes
v1 to be arithmetic left shifted by v0+0001 which results in 4000. All
flags are still cleared. Now, in line 0004, the JUMPMI will not cause to
jump, because the negative flag is cleared (a JUMPPL would had jumped).
Line 0004 triggers a jump to v0+0002 and hence causes to restart at line
0002. Line 0002, you already know, shifts left one bit, which causes v1
to contain 8000. The N flag is set which causes the JUMPMI to jump in line
0003. Execution continues at line 0010. The SWAP instructions swaps the
low/high order bytes and causes v1 to be loaded with 0080+0000. Line 0011
triggers a volume slide up with speed in v1. v1 contains 0080, so the volume
will be slided up half a volume level. 0012 causes the code to wait v0+0001
ticks before going on. After the delay of 1 tick, the JUMP in line 0013
will cause a jump to line 0005. The LOAD instruction causes v2 to be loaded
with v1+0080, which gives 0100 because v1 is 0080. So v2 contains now 0100.
This next line (0006) causes a multiply of v2 with v0+0003 which results in
0300 in v2. Line 0007 is rather simple: It justs loads v4 with v0+000D. The
next line (0008) just loads v5 with the value of v2+0000, so v5 becomes 0300,
too. Adding DEAD+v0 (line 0009), results E1AD in v5. Carry and Extend are
cleared, which causes the JUMPCC (in line 000A) jumps to line v4+0000. v4
contains 000D (see line 0007), so the next instruction lies on line 000D.
The SUBX instruction subtracts v5 with v5+X+0000 which results in 0000,
because the extend flag is cleared. The zero flag is set. Line 000E causes
v5 to be negated and added 0000 afterwards. 0000 negated is 0000, so the
value keeps 0000. Line 000F justs loads v1 with v5+0000, which causes v1
to be cleared. Line 0010 swaps the two bytes. Because both are zero, the
result again is zero. Line 0011 does no volume slide (v1 is 0000). Line
11 causes one line to wait and line 0012 restarts the whole thing with
jumping to line 0005 again. I hope this helped you to understand this.

Please note, if the instruction byte is negative, it will be inverted, and
the resulting number will be a normal effect. That's the most important
to say. But one thing should not go unnoticed. The NNA trigger positions.
With synths you can fully control what should happen, when a NNA is
triggered. To have full control you should set NNA to continue and set
the NNA trigger positions to some useful synth programming code, i.e.
if a new note is played, the previous one will jump to this position. This
gives much enhanced control of what's to happen as when you use NNA off.
Give TuComposer's synth functions a try. It's really worth it! The same
applies to the DNA trigger positions: Note, if you use them, you should
position the NNA trigger positions to something that justs STOP. The DNA
(Duplicate Note Action) triggers do about the same. But applies to these
notes which are triggered by the DNA.


1. June 2005 12:17
Profile ICQ WWW
Display posts from previous:  Sort by  
Reply to topic   [ 1 post ] 

Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by STSoftware for PTF.