Copyright (c) Hyperion Entertainment and contributors.
Difference between revisions of "IFF FORM and Chunk Registry"
Steven Solie (talk | contribs) |
Steven Solie (talk | contribs) |
||
(56 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
== IFF FORM and Chunk Registry == |
== IFF FORM and Chunk Registry == |
||
+ | |||
+ | '''Last Updated: June 8, 2012''' |
||
This section contains the official list of registered FORM and Chunk names that are reserved and in use. This list is often referred to as the 3rd party registry since these are FORM and Chunk types created by application developers and not part of the original IFF specification. |
This section contains the official list of registered FORM and Chunk names that are reserved and in use. This list is often referred to as the 3rd party registry since these are FORM and Chunk types created by application developers and not part of the original IFF specification. |
||
Line 5: | Line 7: | ||
For all FORM and Chunk types that are public, the official specifications from the third party company are listed (in alphabetical order). At the end of this section are additional documents describing how the ILBM FORM type works on the Amiga. |
For all FORM and Chunk types that are public, the official specifications from the third party company are listed (in alphabetical order). At the end of this section are additional documents describing how the ILBM FORM type works on the Amiga. |
||
− | New chunks and FORMS should be registered with the AmigaOS development team. Please make all submissions via the [http://www.amigaos.net |
+ | New chunks and FORMS should be registered with the AmigaOS development team. Please make all submissions via the [http://www.amigaos.net AmigaOS web site] contact form. |
== Developing New IFF FORMs and Chunks == |
== Developing New IFF FORMs and Chunks == |
||
Line 66: | Line 68: | ||
| EA IFF 85 generic author chunk |
| EA IFF 85 generic author chunk |
||
|- |
|- |
||
− | | (any).CHRS |
+ | | [[FTXT_IFF_Formatted_Text#Data_Chunk_CHRS|(any).CHRS]] |
| [[IFF_Standard|IFF Standard]] |
| [[IFF_Standard|IFF Standard]] |
||
| EA IFF 85 generic character string chunk |
| EA IFF 85 generic character string chunk |
||
|- |
|- |
||
− | | [[ |
+ | | [[CSET_IFF_Text_Character_Set|(any).CSET]] |
| IFF_TP |
| IFF_TP |
||
| chunk for specifying character set |
| chunk for specifying character set |
||
Line 78: | Line 80: | ||
| Private ASDG global chunk |
| Private ASDG global chunk |
||
|- |
|- |
||
− | | [[ |
+ | | [[FVER_IFF_Version_String|(any).FVER]] |
| IFF_TP |
| IFF_TP |
||
| chunk for 2.0 VERSION string of an IFF file |
| chunk for 2.0 VERSION string of an IFF file |
||
|- |
|- |
||
− | | [[ |
+ | | [[HLID_IFF_Hotlink_Identification|(any).HLID]] |
| IFF_TP |
| IFF_TP |
||
| HotLink IDentification (Soft-Logik) |
| HotLink IDentification (Soft-Logik) |
||
|- |
|- |
||
− | | [[ |
+ | | [[INFO_IFF_Icon_Information|(any).INFO]] |
| propos |
| propos |
||
| This chunk contains data usually found in a file's .info file |
| This chunk contains data usually found in a file's .info file |
||
|- |
|- |
||
− | | [[ |
+ | | [[JUNK_IFF_Junk_Data|(any).JUNK]] |
| IFF_TP |
| IFF_TP |
||
| Always ignore this chunk |
| Always ignore this chunk |
||
+ | |- |
||
+ | | [[UTF8_IFF_UTF-8_Unicode_Text|(any).UTF8]] |
||
+ | | IFF_TP |
||
+ | | UTF-8 character text |
||
|- |
|- |
||
| (any).NAME |
| (any).NAME |
||
Line 118: | Line 124: | ||
| Looping chunks for 8SVX form |
| Looping chunks for 8SVX form |
||
|- |
|- |
||
− | | [[ |
+ | | [[ACBM_IFF_Amiga_Continuous_Bitmap|ACBM]] |
| IFF_TP |
| IFF_TP |
||
| Amiga Contiguous Bitmap form |
| Amiga Contiguous Bitmap form |
||
Line 146: | Line 152: | ||
| Audio 1-32 bit samples (Mac, Apple II, Synthia Pro) |
| Audio 1-32 bit samples (Mac, Apple II, Synthia Pro) |
||
|- |
|- |
||
+ | | [[AIFF_IFF_Audio_Samples#AIFF|AIFF.COMM]] |
||
− | | [[#ANBM|ANBM]] |
||
+ | | IFF_TP |
||
+ | | Describes fundamental parameters of the sampled sound |
||
+ | |- |
||
+ | | [[AIFF_IFF_Audio_Samples#AIFF|AIFF.SSND]] |
||
+ | | IFF_TP |
||
+ | | Contains the actual sample frames |
||
+ | |- |
||
+ | | [[ANBM_IFF_Animated_Bitmap|ANBM]] |
||
| IFF_TP |
| IFF_TP |
||
| Animated bitmap form (Framer, Deluxe Video) |
| Animated bitmap form (Framer, Deluxe Video) |
||
Line 162: | Line 176: | ||
| Stereo (3D) animations |
| Stereo (3D) animations |
||
|- |
|- |
||
− | | ANIM.op7 |
+ | | [[ANIM_IFF_CEL_Animations#ANIM.op7|ANIM.op7]] |
− | | |
+ | | IFF_TP |
+ | | Maximum playback speed and acceptable packing rates |
||
− | | unregistered (???) |
||
|- |
|- |
||
| [[ANIM_IFF_CEL_Animations#ANIM.op8|ANIM.op8]] |
| [[ANIM_IFF_CEL_Animations#ANIM.op8|ANIM.op8]] |
||
| IFF_TP |
| IFF_TP |
||
+ | | Maximum playback speed and acceptable packing rates. Easier to use than ANIM.op7 |
||
− | | - |
||
|- |
|- |
||
− | | ARC |
+ | | ARC |
| propos |
| propos |
||
| archive format proposal (old) |
| archive format proposal (old) |
||
Line 202: | Line 216: | ||
| EA IFF 85 group identifier |
| EA IFF 85 group identifier |
||
|- |
|- |
||
− | | CELP |
+ | | CELP |
| propos |
| propos |
||
| For storage of compressed ZyXEL voice data (reserved) |
| For storage of compressed ZyXEL voice data (reserved) |
||
Line 214: | Line 228: | ||
| CAT CLIP to hold various formats in clipboard |
| CAT CLIP to hold various formats in clipboard |
||
|- |
|- |
||
− | | [[#CMUS |
+ | | [[CMUS_IFF_Musical_Score#CMUS|CMUS]] |
| propos |
| propos |
||
| Common MUsical Score |
| Common MUsical Score |
||
Line 238: | Line 252: | ||
| private format for Inovatronics CanDo |
| private format for Inovatronics CanDo |
||
|- |
|- |
||
− | | [[#DEEP|DEEP]] |
+ | | [[DEEP_IFF_Chunky_Pixel_Image#DEEP|DEEP]] |
| IFF_TP |
| IFF_TP |
||
| Chunky pixel image files (used in TV Paint) |
| Chunky pixel image files (used in TV Paint) |
||
Line 258: | Line 272: | ||
| reserved by Jim Bayless, 12/90 |
| reserved by Jim Bayless, 12/90 |
||
|- |
|- |
||
− | | [[ |
+ | | [[DTYP_IFF_DataType_Identification|DTYP]] |
| IFF_TP |
| IFF_TP |
||
| DataTypes identification |
| DataTypes identification |
||
|- |
|- |
||
+ | | [[EXEC_IFF_Executable_Code|EXEC]] |
||
− | | <a href="http://amigan.1emu.net/reg/EXEC.txt">EXEC.proposal</a> |
||
| propos |
| propos |
||
| Proposed form for executable (loadseg-able) code |
| Proposed form for executable (loadseg-able) code |
||
Line 306: | Line 320: | ||
| EA IFF 85 formatted text form |
| EA IFF 85 formatted text form |
||
|- |
|- |
||
− | | GRYP |
+ | | GRYP |
| propos |
| propos |
||
| byteplane storage proposal (copyrighted) |
| byteplane storage proposal (copyrighted) |
||
Line 318: | Line 332: | ||
| Gesture and Motion Signal [http://acroe.imag.fr/gms/ GMS Web Site] |
| Gesture and Motion Signal [http://acroe.imag.fr/gms/ GMS Web Site] |
||
|- |
|- |
||
− | | GUI |
+ | | GUI |
| propos |
| propos |
||
| user interface storage proposal (private) |
| user interface storage proposal (private) |
||
|- |
|- |
||
− | | [[ |
+ | | [[HEAD_IFF_Flow_Idea_Processor_Format|HEAD]] |
| IFF_TP |
| IFF_TP |
||
| Flow - New Horizons Software |
| Flow - New Horizons Software |
||
Line 398: | Line 412: | ||
| Line by line palette control information (Sebastiano Vigna) |
| Line by line palette control information (Sebastiano Vigna) |
||
|- |
|- |
||
− | | [[ILBM_IFF_Interleaved_Bitmap#ILBM.PRVW |
+ | | [[ILBM_IFF_Interleaved_Bitmap#ILBM.PRVW|ILBM.PRVW]] |
| propos |
| propos |
||
| A mini duplicate ILBM used for preview (Gary Bonham) |
| A mini duplicate ILBM used for preview (Gary Bonham) |
||
Line 406: | Line 420: | ||
| Transparency map (temporarily reserved) |
| Transparency map (temporarily reserved) |
||
|- |
|- |
||
+ | | VTAG |
||
− | | <a href="http://amigan.1emu.net/reg/ILBM.VTAG.proposal.txt" "="">ILBM.VTAG.proposal</a> |
||
| propos |
| propos |
||
| Viewmode tags chunk suggestion |
| Viewmode tags chunk suggestion |
||
Line 458: | Line 472: | ||
| temporarily reserved |
| temporarily reserved |
||
|- |
|- |
||
+ | | [[MTRX_IFF_Matrix_Data_Storage#MTRX|MTRX]] |
||
− | | <a href="http://amigan.1emu.net/reg/MTRX.txt">MTRX</a> |
||
| IFF_TP |
| IFF_TP |
||
| Numerical data storage (MathVision - Seven Seas) |
| Numerical data storage (MathVision - Seven Seas) |
||
Line 466: | Line 480: | ||
| Numerical sequence (Stockhausen GmbH) |
| Numerical sequence (Stockhausen GmbH) |
||
|- |
|- |
||
+ | | [[OB3D_IFF_3-D_Object_Format|OB3D]] |
||
− | | <a href="http://amigan.1emu.net/reg/OB3D.proposal.txt">OB3D.proposal</a> |
||
| propos |
| propos |
||
| Proposal for a standard 3D object format |
| Proposal for a standard 3D object format |
||
Line 486: | Line 500: | ||
| EA IFF 85 reserved serial num. prop |
| EA IFF 85 reserved serial num. prop |
||
|- |
|- |
||
+ | | [[PGTB_IFF_Program_Traceback#PGTB|PGTB]] |
||
− | | <a href="http://amigan.1emu.net/reg/PGTB.txt">PGTB</a> |
||
| IFF_TP |
| IFF_TP |
||
| Program traceback (SAS Institute) |
| Program traceback (SAS Institute) |
||
Line 498: | Line 512: | ||
| EA IFF 85 reserved obsolete name |
| EA IFF 85 reserved obsolete name |
||
|- |
|- |
||
+ | | [[PMBC_IFF_High-color_Image_Format|PMBC]] |
||
− | | <a href="http://amigan.1emu.net/reg/PMBC.proposal.txt">PMBC.proposal</a> |
||
| propos |
| propos |
||
| reserved for Black Belt Systems 91.12.01 |
| reserved for Black Belt Systems 91.12.01 |
||
Line 504: | Line 518: | ||
| PREF |
| PREF |
||
| ---- |
| ---- |
||
− | | Reserved by |
+ | | Reserved by the AmigaOS Development Team for user preferences data, currently private |
|- |
|- |
||
| PREF.AHIG |
| PREF.AHIG |
||
Line 518: | Line 532: | ||
| EA IFF 85 group identifier |
| EA IFF 85 group identifier |
||
|- |
|- |
||
− | | [[ |
+ | | [[PRSP_IFF_Perspective_Move|PRSP]] |
| IFF_TP |
| IFF_TP |
||
| DPaint IV perspective move form (EA) |
| DPaint IV perspective move form (EA) |
||
Line 534: | Line 548: | ||
| 4-bit RGB (format not available) |
| 4-bit RGB (format not available) |
||
|- |
|- |
||
+ | | [[RGBN_and_RGB8_IFF_Image_Data|RGBN and RGB8]] |
||
− | | <a href="http://amigan.1emu.net/reg/RGBN-RGB8.txt">RGBN-RGB8</a> |
||
| IFF_TP |
| IFF_TP |
||
| RGB image forms, Turbo Silver (Impulse) |
| RGB image forms, Turbo Silver (Impulse) |
||
Line 546: | Line 560: | ||
| private animation form |
| private animation form |
||
|- |
|- |
||
+ | | [[SAMP_IFF_Sampled_Sound#SAMP|SAMP]] |
||
− | | <a href="http://amigan.1emu.net/reg/SAMP.txt">SAMP</a> |
||
| IFF_TP |
| IFF_TP |
||
| Sampled sound format |
| Sampled sound format |
||
Line 570: | Line 584: | ||
| EA IFF 85 simple music score form |
| EA IFF 85 simple music score form |
||
|- |
|- |
||
+ | | [[SPLT_IFF_File_Splitting#SPLT|SPLT]] |
||
− | | <a href="http://amigan.1emu.net/reg/SPLT.txt">SPLT</a> |
||
| IFF_TP |
| IFF_TP |
||
| ASDG's file SPLiTting system |
| ASDG's file SPLiTting system |
||
Line 590: | Line 604: | ||
| reserved by Merging Technologies |
| reserved by Merging Technologies |
||
|- |
|- |
||
+ | | [[TDDD_IFF_3-D_Rendering_Data#TDDD|TDDD]] |
||
− | | <a href="http://amigan.1emu.net/reg/TDDD.txt">TDDD</a> |
||
| IFF_TP |
| IFF_TP |
||
| 3D rendering data, Turbo Silver (Impulse) |
| 3D rendering data, Turbo Silver (Impulse) |
||
Line 598: | Line 612: | ||
| unregistered (???) |
| unregistered (???) |
||
|- |
|- |
||
+ | | [[TMUI_IFF_Project_File_Format#TMUI|TMUI]] |
||
− | | <a href="http://amigan.1emu.net/reg/TMUI.txt">TMUI</a> |
||
| IFF_TP |
| IFF_TP |
||
| Toolmaker IFF project file format (ToolMaker V1.19) |
| Toolmaker IFF project file format (ToolMaker V1.19) |
||
|- |
|- |
||
+ | | [[TREE_IFF_Tree_Data_Structure|TREE]] |
||
− | | <a href="http://amigan.1emu.net/reg/TREE.txt">TREE</a> |
||
| IFF_TP |
| IFF_TP |
||
| Storage of arbitrary data structures as trees (or nested lists) |
| Storage of arbitrary data structures as trees (or nested lists) |
||
|- |
|- |
||
+ | | [[TRKR_IFF_Tracker_Music_Module|TRKR]] |
||
− | | <a href="http://amigan.1emu.net/reg/TRKR.proposal.txt">TRKR.proposal</a> |
||
| propos |
| propos |
||
| TRacKeR style music module format proposal |
| TRacKeR style music module format proposal |
||
Line 626: | Line 640: | ||
| private Deluxe Video format |
| private Deluxe Video format |
||
|- |
|- |
||
+ | | [[WORD_IFF_Document_Storage#WORD|WORD]] |
||
− | | <a href="http://amigan.1emu.net/reg/WORD.txt">WORD</a> |
||
| IFF_TP |
| IFF_TP |
||
| ProWrite document format (New Horizons) |
| ProWrite document format (New Horizons) |
||
Line 638: | Line 652: | ||
| unregistered animation format (Wildfire) |
| unregistered animation format (Wildfire) |
||
|- |
|- |
||
+ | | [[YUVN_IFF_YUV_Image_Data#YUVN|YUVN]] |
||
− | | <a href="http://amigan.1emu.net/reg/YUVN.txt">YUVN</a> |
||
| IFF_TP |
| IFF_TP |
||
| For storage of Y:U:V image data (MacroSystems) |
| For storage of Y:U:V image data (MacroSystems) |
||
|} |
|} |
||
− | |||
− | === (any).CSET === |
||
− | |||
− | Chunk for specifying character set. |
||
− | |||
− | Registered by Martin Taillefer. |
||
− | |||
− | A chunk for use in any FORM, to specify character set used for text in FORM. |
||
− | |||
− | <syntaxhighlight> |
||
− | struct CSet { |
||
− | LONG CodeSet; /* 0=ECMA Latin 1 (std Amiga charset) */ |
||
− | /* AmigaOS development team will define additional values */ |
||
− | LONG Reserved[7]; |
||
− | } |
||
− | </syntaxhighlight> |
||
− | |||
− | === (any).FVER === |
||
− | |||
− | Chunk for 2.0 VERSION string of an IFF file. |
||
− | |||
− | Registered by Martin Taillefer. |
||
− | |||
− | A chunk for use in any FORM, to contain standard 2.0 version string. |
||
− | |||
− | $VER: name ver.rev |
||
− | |||
− | where "name" is the name or identifier of the file and ver.rev is a version/revision such as 53.1 |
||
− | |||
− | Example: |
||
− | |||
− | $VER: workbench.catalog 53.42 |
||
− | |||
− | |||
− | === (any).HLID === |
||
− | |||
− | HotLink IDentification (Soft-Logik) |
||
− | |||
− | HLID Generic chunk |
||
− | |||
− | Submitted by Dan Weiss, Deron Kazmaier, and Gary Knight (8/29/91) |
||
− | |||
− | Chunk ID: "HLID" (HotLink IDentification) |
||
− | |||
− | Description: This chunk is used by applications that store local copies of |
||
− | HotLink'ed files. When an application reads in a local copy and finds a HLID |
||
− | chunk, the application can check if any changes have been made to the file |
||
− | and get the new changes if any have been made. Also the application can set |
||
− | up a notification on the file, and treat it just like the application subscribed |
||
− | to the file. The format of the chunk is 3 long words. The first two hold the |
||
− | publication ID and the last one holds the publication version number. These |
||
− | are all the entries needed to load a hotlink'ed file from HotLinks. |
||
− | |||
− | Example: |
||
− | HLID ;chunk ID |
||
− | 0000000C ;chunk length (12 bytes) |
||
− | 00000001 ;publication ID (part 1) |
||
− | 00000005 ;publication ID (part 2) |
||
− | 00000002 ;publication version number |
||
− | |||
− | === (any).INFO.proposal === |
||
− | |||
− | This chunk contains data usually found in a file's .info file. |
||
− | |||
− | Proposed by Chris Ludwig 91.12.19. |
||
− | |||
− | === (any).JUNK === |
||
− | |||
− | Always ignore this chunk. |
||
− | |||
− | This chunk was designed to let garbage data in an IFF file be quickly marked |
||
− | as such. Instead of actually having to remove the garbage chunk, just rename |
||
− | it "JUNK". All IFF readers should ignore "JUNK" chunks. Thanks to David |
||
− | Ellis for this idea. Registered 91.11. |
||
− | |||
− | === ACBM === |
||
− | |||
− | <pre> |
||
− | Amiga Contiguous Bitmap form |
||
− | |||
− | IFF FORM / CHUNK DESCRIPTION |
||
− | ============================ |
||
− | |||
− | Form/Chunk ID: FORM ACBM (Amiga Contiguous BitMap) |
||
− | Chunk ABIT (Amiga BITplanes) |
||
− | |||
− | Date Submitted: 05/29/86 |
||
− | Submitted by: Carolyn Scheppner CBM |
||
− | |||
− | |||
− | FORM |
||
− | ==== |
||
− | |||
− | FORM ID: ACBM (Amiga Contiguous BitMap) |
||
− | |||
− | FORM Description: |
||
− | |||
− | FORM ACBM has the same format as FORM ILBM except the normal BODY |
||
− | chunk (InterLeaved BitMap) is replaced by an ABIT chunk (Amiga BITplanes). |
||
− | |||
− | FORM Purpose: |
||
− | |||
− | To enable faster loading/saving of screens, especially from Basic, |
||
− | while retaining the flexibility and portability of IFF format files. |
||
− | |||
− | |||
− | CHUNKS |
||
− | ====== |
||
− | |||
− | Chunk ID: ABIT (Amiga BITplanes) |
||
− | |||
− | Chunk Description: |
||
− | |||
− | The ABIT chunk contains contiguous bitplane data. The chunk contains |
||
− | sequential data for bitplane 0 through bitplane n. |
||
− | |||
− | Chunk Purpose: |
||
− | |||
− | To enable loading/storing of bitmaps with one DOS Read/Write per |
||
− | bitplane. Significant speed increases are realized when loading/saving |
||
− | screens from Basic. |
||
− | |||
− | |||
− | SUPPORTING SOFTWARE |
||
− | =================== |
||
− | |||
− | (Public Domain, available soon via Fish PD disk, various networks) |
||
− | |||
− | LoadILBM-SaveACBM (AmigaBasic) |
||
− | Loads and displays an IFF ILBM pic file (Graphicraft, DPaint, Images). |
||
− | Optionally saves the screen in ACBM format. |
||
− | |||
− | LoadACBM (AmigaBasic) |
||
− | Loads and display an ACBM format pic file. |
||
− | |||
− | SaveILBM (AmigaBasic) |
||
− | Saves a demo screen as an ILBM pic file which can be loaded into |
||
− | Graphicraft, DPaint, Images.</pre> |
||
− | |||
− | === ANBM === |
||
− | |||
− | <pre> |
||
− | Animated bitmap form (Framer, Deluxe Video) |
||
− | |||
− | TITLE: Form ANBM (animated bitmap form used by Framer, Deluxe Video) |
||
− | |||
− | (note from the author) |
||
− | |||
− | The format was designed for simplicity at a time when the IFF |
||
− | standard was very new and strange to us all. It was not designed |
||
− | to be a general purpose animation format. It was intended to be |
||
− | a private format for use by DVideo, with the hope that a more |
||
− | powerful format would emerge as the Amiga became more popular. |
||
− | |||
− | I hope you will publish this format so that other formats will |
||
− | not inadvertantly conflict with it. |
||
− | |||
− | PURPOSE: To define simple animated bitmaps for use in DeluxeVideo. |
||
− | |||
− | In Deluxe Video objects appear and move in the foreground |
||
− | with a picture in the background. Objects are "small" bitmaps |
||
− | usually saved as brushes from DeluxePaint and pictures are large |
||
− | full screen bitmaps saved as files from DeluxePaint. |
||
− | |||
− | Two new chunk headers are defined: ANBM and FSQN. |
||
− | |||
− | An animated bitmap (ANBM) is a series of bitmaps of the same |
||
− | size and depth. Each bitmap in the series is called a frame and |
||
− | is labeled by a character, 'a b c ...' in the order they |
||
− | appear in the file. |
||
− | |||
− | The frame sequence chunk (FSQN) specifies the playback |
||
− | sequence of the individual bitmaps to achieve animation. |
||
− | FSQN_CYCLE and FSQN_TOFRO specify two algorithmic sequences. If |
||
− | neither of these bits is set, an arbitrary sequence can be used |
||
− | instead. |
||
− | |||
− | |||
− | ANBM - identifies this file as an animated bitmap |
||
− | .FSQN - playback sequence information |
||
− | .LIST ILBM - LIST allows following ILBMs to share properties |
||
− | ..PROP ILBM - properties follow |
||
− | ...BMHD - bitmap header defines common size and depth |
||
− | ...CMAP - colormap defines common colors |
||
− | ..FORM ILBM - first frame follows |
||
− | ..BODY - the first frame |
||
− | . - FORM ILBM and BODY for each remaining frame |
||
− | . |
||
− | . |
||
− | |||
− | Chunk Description: |
||
− | |||
− | The ANBM chunk identifes this file as an animated bitmap |
||
− | |||
− | Chunk Spec: |
||
− | |||
− | #define ANBM MakeID('A','N','B','M') |
||
− | |||
− | Disk record: |
||
− | |||
− | none |
||
− | |||
− | Chunk Description: |
||
− | |||
− | The FSQN chunk specifies the frame playback sequence |
||
− | |||
− | Chunk Spec: |
||
− | |||
− | #define FSQN MakeID('F','S','Q','N') |
||
− | |||
− | /* Flags */ |
||
− | #define FSQN_CYCLE 0x0001 /* Ignore sequence, cycle a,b,..y,z,a,b,.. */ |
||
− | #define FSQN_TOFRO 0x0002 /* Ignore sequence, cycle a,b,..y,z,y,..a,b, */ |
||
− | /* Disk record */ |
||
− | typedef struct { |
||
− | WORD numframes; /* Number of frames in the sequence */ |
||
− | LONG dt; /* Nominal time between frames in jiffies */ |
||
− | WORDBITS flags; /* Bits modify behavior of the animation */ |
||
− | UBYTE sequence[80]; /* string of 'a'..'z' specifying sequence */ |
||
− | } FrameSeqn; |
||
− | |||
− | |||
− | Supporting Software: |
||
− | |||
− | DeluxeVideo by Mike Posehn and Tom Case for Electronic Arts |
||
− | |||
− | |||
− | Thanks, |
||
− | Mike Posehn |
||
− | </pre> |
||
− | |||
− | |||
− | === CMUS.proposal === |
||
− | |||
− | Common MUsical Score |
||
− | |||
− | <pre> |
||
− | /* ========================================================================= * |
||
− | CMUS - Common Musical Score |
||
− | |||
− | An IFF File format for interchanging |
||
− | musical data using Common Music Notation |
||
− | |||
− | by Talin (David Joiner) |
||
− | |||
− | Verion 0.4 |
||
− | * ========================================================================= */ |
||
− | |||
− | #ifndef CMUS_H |
||
− | #define CMUS_H |
||
− | |||
− | /* ========================================================================= * |
||
− | Note to Non-Amiga users of this document |
||
− | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||
− | CMUS is an IFF (Interchange File Format) file. IFF is a "Meta-standard" |
||
− | for making extensible, self-identifying file formats, and was developed |
||
− | by Commodore and Electronic Arts. In order to understand CMUS you will |
||
− | need to get the IFF Documentation. The quickest way to do this is to |
||
− | get the "Amiga ROM Kernal Manual: Devices" volume and look in the Appendix. |
||
− | * ========================================================================= * |
||
− | Note on Timing: |
||
− | ~~~~~~~~~~~~~~~ |
||
− | Common Music Notation is a symbolic, rather than a literal |
||
− | representation. It is supposed to be interpreted by the player. A note |
||
− | which is listed as "A quarter note", will seldom be played at the exact |
||
− | time or duration as written. These deviations from mathematically perfect |
||
− | time are important; they are part of what musicians call "feel" or |
||
− | "liveliness". |
||
− | Accordingly, FORM CMUS has two different kinds of timing information. |
||
− | _Formal Time_ is represented in symbolic form: Each symbol has a field |
||
− | which indicates it's duration (dotted quarter-note, etc) in symbolic units. |
||
− | The formal start time of an event can be obtained by summing the durations |
||
− | of all the previous times in the measure. |
||
− | In addition, there is also _Casual Time_. Each event has a "start time" |
||
− | which is the number of basic clock units from the start of the measure to |
||
− | the start of that event. Some event types also have "duration" fields of |
||
− | a similar nature. |
||
− | In general, although there will probably be a strong correlation |
||
− | between formal time and casual time, there is no guarantee of this. |
||
− | Certainly this FORM does not enforce any relationship between the two. |
||
− | This means that you cannot, in general, derive one from the other. You can |
||
− | at most make an educated guess, and even that is a non-trivial problem |
||
− | from an algorithmic point of view. |
||
− | |||
− | * ========================================================================= * |
||
− | Note on Layout Measurements: |
||
− | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||
− | In general, I have tried to make all measurements as "device- |
||
− | independent" as possible. |
||
− | |||
− | Measurements of page dimensions and other page-related information |
||
− | such as margins and indentations are represented in micrometers. |
||
− | Converting from micrometers to inches and "big points" (the definition |
||
− | of points used by Adobe and Apple) can be done with the following |
||
− | formulas: |
||
− | |||
− | inches = micrometers / 25400; |
||
− | |||
− | points = micrometers * 72 / 25400; |
||
− | |||
− | Vertical distances of musical items are all measured in "Levels". |
||
− | A level is one half the distance between the lines of a staff. A note on |
||
− | the centerline of the staff is at level zero. Placing the note just above |
||
− | that line (between the 2nd and 3rd staff line) makes it level 1, while |
||
− | placing it below the centerline makes it level -1. Note that up is positive |
||
− | in this coordinate system. |
||
− | Note positions are recorded as a fraction of the measure width. |
||
− | |||
− | * ========================================================================= * |
||
− | Rules for clipboard use: |
||
− | ~~~~~~~~~~~~~~~~~~~~~~~~ |
||
− | A CMUS chunk may be copied to the clipboard. In such cases, it is |
||
− | possible that only a subset of the data might be written. Specifically, |
||
− | measures and signatures which occur before the first selection point, |
||
− | or after the last selection point should not be included. Note that |
||
− | the measure containing the first selection point should be written, |
||
− | however, even if it is not in the selection range itself. (As to whether |
||
− | measure-lines are selectable is up to the application). In addition, |
||
− | an initial time signature item for that measure should be written as |
||
− | well; key signature and clef items are optional in this case. The |
||
− | application receiving the clip has the option of whether to use the |
||
− | signature items in the clip, or to ignore them and use the existing |
||
− | signatures in the score. The application can also decide to "insert" |
||
− | the clip into the score (causing existing other events to be shifted |
||
− | later in time), or "merging" the events with the existing items. |
||
− | The application can also choose to respect measure lines in the clip |
||
− | (each new measure line causes the notes to be pasted into the next |
||
− | measure) or to "flow" the notes across measure boundaries. |
||
− | Note that the notes in a clip may be non-contiguous. For example, |
||
− | If the user were to select every second note and copy those to the |
||
− | clipboard, there would be "gaps" in the clipped track. Unfortunately, |
||
− | a reader program would not be able to detect those gaps (since formal |
||
− | time does not have an explicit start time) and thus the formal time |
||
− | and the casual time would get out of sync. To avoid this problem, |
||
− | "filler" events can be inserted into the score to fill up the empty space. |
||
− | Note that the duration of a filler event is formal, unlike all the |
||
− | other events. |
||
− | Notation programs which only support contiguous selection (i.e. |
||
− | can't have a deselected note between two selected notes) can ignore |
||
− | filler items. |
||
− | A filler event at the end of the measure is not neccessary. |
||
− | In fact, there is no requirement in CMUS that a measure be "filled". |
||
− | In addition, certain music programs allow more notes in a measure than |
||
− | would legally fit (only while editing, the extra notes are never played). |
||
− | CMUS readers should handle this case robustly. |
||
− | |||
− | This allows a reader to make intelligent use of the clip. The clip |
||
− | can be pasted relative to an insertion point, and the relationship of |
||
− | notes to measures can be (optionally) preserved, even if the selection |
||
− | was non-contiguous. |
||
− | * ========================================================================= * |
||
− | Future Directions |
||
− | ~~~~~~~~~~~~~~~~~ |
||
− | A number of musical features are currently mising from the CMUS spec, |
||
− | such as the ability for a track to jump from one staff to another. In |
||
− | addition, there are a number of features which would be desirable on the |
||
− | "page" level, such as seperate margins for each page (currently, there is |
||
− | no representation of individual pages in the spec). |
||
− | All of these things can easily be added by defining new IFF chunks |
||
− | or new event types. I have not done this because I feel that these |
||
− | additional features would best be designed by the person who needs them, |
||
− | in other words someone designing a music product that requires such |
||
− | features and is familiar with the issues inolved. Otherwise, the format |
||
− | might be defined wrongly, missing subtle advantages which |
||
− | */ |
||
− | |||
− | /* ========================================================================= * |
||
− | General Definitions |
||
− | * ========================================================================= */ |
||
− | |||
− | typedef long Micrometers; |
||
− | |||
− | #if CM_MICRO_CONVERSION |
||
− | |||
− | /* (optional) conversion to / from inches */ |
||
− | |||
− | #define InchesToMicros(inches) ((inches) * 25400) |
||
− | #define MicrosToInches(micros) (((micros) + 12700) / 25400) |
||
− | |||
− | #define HundredthsToMicros(inches) ((inches) * 254) |
||
− | #define MicrosToHundredths(micros) (((micros) + 127) / 254) |
||
− | |||
− | #define PointsToMicros(points) (((points) * 25400 + 36) / 72) |
||
− | #define MicrosToPoints(micros) (((micros) * 72 + 12700) / 25400) |
||
− | |||
− | #endif |
||
− | |||
− | /* ========================================================================= * |
||
− | Score Header Chunk (SCHD) |
||
− | * ========================================================================= */ |
||
− | |||
− | typedef struct { |
||
− | WORD scBarsPerLine; /* preferred bars per line */ |
||
− | WORD scOverallVolume; /* overall volume of score */ |
||
− | |||
− | Micrometers scPageWidth, /* width of page */ |
||
− | scPageHeight, /* height of page */ |
||
− | scTopMargin, /* top margin of score on page 1*/ |
||
− | scFirstLineIndent, /* left margin indent on line 1 */ |
||
− | scLineIndent; /* left indent on other lines */ |
||
− | } CM_ScoreHeader; |
||
− | |||
− | /* ========================================================================= * |
||
− | Staff Table Chunk (STAF) |
||
− | |||
− | This section describes the data structures which are used in the CMUS 'STAF' |
||
− | Chunk. There is one STFF chunk per score, which contains an array of |
||
− | StaffEntry structres (1 per staff in the document). |
||
− | |||
− | * ========================================================================= */ |
||
− | |||
− | typedef struct { |
||
− | WORD staffFlags; /* various flags */ |
||
− | |||
− | /* This defines the vertical size of a measure. Both of the distances |
||
− | are measured from the center line of the staff (in fact all staff- |
||
− | relative distances are represented this way). |
||
− | */ |
||
− | |||
− | Micrometers staffSpaceAbove, /* space above staff */ |
||
− | staffSpaceBelow; /* space below staff */ |
||
− | |||
− | Micrometers staffLevelSize; /* distance between staff lines */ |
||
− | |||
− | } CM_StaffEntry; |
||
− | |||
− | /* This flag indicates that a formfeed should be done before printing |
||
− | this staff (used when a score has more staffs than will fit on a page. |
||
− | */ |
||
− | |||
− | #define STAFF_PAGEBREAK (1<<0) |
||
− | |||
− | /* This indicates that the measure lines for this staff should not be |
||
− | connected to the measure lines for the staff below |
||
− | */ |
||
− | |||
− | #define STAFF_BAR_BROKEN (1<<1) |
||
− | |||
− | /* This flag indicates that a set of "curly braces" should connect this |
||
− | staff with the staff below. |
||
− | */ |
||
− | |||
− | #define STAFF_BRACED (1<<2) /* Staff is "braced" with next */ |
||
− | |||
− | /* These flags indicate the start and end of a square bracket which can |
||
− | span over several staffs. The brace should start at the staff |
||
− | marked with the "START" bit and continue until a staff with the |
||
− | "END" bit is encountered. |
||
− | */ |
||
− | |||
− | #define STAFF_BRACKET_START (1<<3) |
||
− | #define STAFF_BRACKET_END (1<<4) |
||
− | |||
− | /* ========================================================================= * |
||
− | Track Chunk (TRCK) |
||
− | |||
− | This section describes the data structures which are used in the CMUS 'TRCK' |
||
− | Chunk. |
||
− | |||
− | A track is a sequence of notes which reside on a staff. In the simplest |
||
− | case, there is one TRCK chunk per melody line in the score. However, a |
||
− | track can contain chords, rests, etc, as well. |
||
− | |||
− | A more precise definition of a track is that a track is a sequence of |
||
− | chords, where all the notes within each chord have the same start time |
||
− | and the same duration (in formal time of course; in casual time anything |
||
− | is possible). Note that ties can be used to create the illusion of |
||
− | having broken this rule. |
||
− | |||
− | * ========================================================================= */ |
||
− | |||
− | /* Track Header structure: |
||
− | |||
− | Each track begins with a track header structure, followed by any number |
||
− | of score items. (Use the chunk length to determine when to stop reading |
||
− | score items). |
||
− | */ |
||
− | |||
− | typedef struct { |
||
− | UWORD trkStaff, /* staff number to place this on*/ |
||
− | trkTrack, /* track number within staff */ |
||
− | trkFlags; /* flags for staff header */ |
||
− | |||
− | /* Sometimes notes on the staff are written transposed from how they |
||
− | should actually be played. This is the number that should be added |
||
− | to the pitch before it is actually played back. |
||
− | */ |
||
− | |||
− | WORD trkTransposition; /* playback transposition */ |
||
− | |||
− | } CM_TrackHeader; |
||
− | |||
− | /* ========================================================================= * |
||
− | Track Item |
||
− | * ========================================================================= */ |
||
− | |||
− | /* Item Header: |
||
− | |||
− | Score items are variable in length. The first byte of the item is the |
||
− | length of the item in WORDS. This will allow new item types to be added |
||
− | in the future. All score items are an integer number of WORDS long. |
||
− | |||
− | Each score item has a standard header structure, followed by a variable |
||
− | amount of item-specific data. The 'itemType' field is used to determine what |
||
− | that data is. |
||
− | |||
− | 'itemLength' is the length of the item in WORDS. This allows items to be |
||
− | from 2 to 512 bytes long. (The value '0' is reserved as a special case). |
||
− | |||
− | 'itemXPos' contains the X position of the item in fractions of the measure's |
||
− | width. Note that the area containing the signatures, and the area just |
||
− | before the ending measure line are not considered part of this range. |
||
− | Think of it this way: The value 0 is the first possible note position. |
||
− | The value 0x7fff if the last possible note position. Items placed at |
||
− | these positions should not run into the graphics at either the beginning |
||
− | or the end of the measure. In addition, negative numbers are also |
||
− | allows, which is used for symbols which penetrate into the "signature" |
||
− | area. In this case, 0 represents the first possible note position, and |
||
− | -0x8000 represents the actual barline. This convention is normally only |
||
− | used for lyrics, which can intrude into the signature area. |
||
− | |||
− | 'itemStart' is used to represent the real starting time of each event. |
||
− | This is recorded as a delta-time, in other words itemStart contains |
||
− | how many clock ticks have elapsed between the current item and the item |
||
− | before it. Note that because of the fact that events can sometimes occur |
||
− | out of order (for example, notes in a chord can be ordered by pitch rather |
||
− | than by time, and they might not all start at exactly the same clock), |
||
− | this value can be negative. |
||
− | In addition, the clock is reset at each measure boundary. In other |
||
− | words, the length of a measure is determined only by it's time signature, |
||
− | and not by the delta between the last note and the next measure line. |
||
− | In fact, the itemStart field for measure line items is ignored and should |
||
− | always be set to zero. |
||
− | An item's start time does NOT have to exactly match the event's |
||
− | "formal" time. For example, an event at the beginning of a measure does |
||
− | not have to start at exactly time zero, but can be offset somewhat. |
||
− | This allows the subtle nuances of a live performance to be preserved, if |
||
− | the notation software allows for that capability. |
||
− | |||
− | The 'itemStart' field (and the noteDuration field defined later) use a |
||
− | clock standard of 960 clock ticks per whole note. Thus, a quarter note |
||
− | is one/quarter that, or 240. This number is divisible by 3, 5, and several |
||
− | powers of two, making it convenient for representing triplets and |
||
− | quintuplets as well as small note values. |
||
− | */ |
||
− | |||
− | typedef struct { |
||
− | UBYTE itemLength, /* length of item in WORDS */ |
||
− | itemType; /* type of item */ |
||
− | WORD itemXPos; /* horizontal position of item */ |
||
− | WORD itemStart; /* start time, in ticks */ |
||
− | } CM_ItemHeader; |
||
− | |||
− | #define WHOLE_NOTE_DURATION 960 /* duration of a whole note */ |
||
− | |||
− | #define MAX_ITEM_XPOS 0x7fff |
||
− | #define MMIN_ITEM_XPOS -0x8000 |
||
− | |||
− | /* type codes for chunk item types */ |
||
− | |||
− | enum notation_item_types { |
||
− | MEASURE_ITEM = 0, /* measure line */ |
||
− | SIGNATURE_ITEM, /* time sig., key sig., or clef */ |
||
− | NOTE_ITEM, /* first note in a chord */ |
||
− | CHORD_ITEM, /* additional notes in a chord */ |
||
− | FILLER_ITEM, /* fills up empty gaps */ |
||
− | DYNAMIC_ITEM, /* dynamic volume item (fff) */ |
||
− | INSTRUMENT_ITEM, /* instrument change item */ |
||
− | TEMPO_ITEM, /* tempo change item */ |
||
− | REPEAT_ITEM, /* for jumping around in score */ |
||
− | BEGIN_GROUP_ITEM, /* begin slur, crescendo, etc. */ |
||
− | END_GROUP_ITEM, /* end slur, crecendo, etc. */ |
||
− | TABLATURE_ITEM, /* guitar or other tablature */ |
||
− | }; |
||
− | |||
− | /* ========================================================================= * |
||
− | Measure Line Item |
||
− | * ========================================================================= */ |
||
− | |||
− | /* This item represents the beginning of a new measure. As such, there should |
||
− | be one of these at the beginning of the track, but not at the end. |
||
− | */ |
||
− | |||
− | typedef struct { |
||
− | CM_ItemHeader measureItem; /* item header */ |
||
− | Micrometers measureWidth; /* width of measure */ |
||
− | UBYTE measureFlags; /* various flags, see below */ |
||
− | |||
− | /* measureEnding: If non-zero, it means that this measure is part |
||
− | of an ending block. The value indicates which ending this measure |
||
− | is part of. For example, if the value = 1, then this measure |
||
− | is only played the first time through, if the value = 2 then |
||
− | it is only played the second time through. |
||
− | |||
− | Each "repeat" section in the score can have it's own set of |
||
− | endings. |
||
− | |||
− | "Endings" can be longer than one measure. Each measure that |
||
− | is encountered that has the same value of measureEnding as the |
||
− | previous measure is considered part of the same ending. |
||
− | */ |
||
− | |||
− | UBYTE measureEnding; /* "ending" this measure is in */ |
||
− | } CM_Measure; |
||
− | |||
− | #define MEASURE_FULL_WIDTH 0x7fff /* full width of score */ |
||
− | |||
− | enum measureFlags { |
||
− | |||
− | /* Draw a double bar at the end of this measure. The reason for |
||
− | associating the double-bar flag with the next measure line is |
||
− | because double bar can occur at the end of the score but not |
||
− | at the beginning. |
||
− | */ |
||
− | MEASUREF_DOUBLE_BAR = (1<<0), |
||
− | |||
− | /* This is a "line break", in other words it indicates that this |
||
− | measure should start a new line. |
||
− | */ |
||
− | |||
− | MEASUREF_NEW_LINE = (1<<1), |
||
− | |||
− | /* If set, this flags means that the measure width was set by the |
||
− | user. It not set, it means that measure width was calculated on |
||
− | the fly, and can be re-adjusted feely if needed to line things |
||
− | up. Note that this width includes signatures, but does not include |
||
− | any indentation from the left margin of the document. |
||
− | */ |
||
− | |||
− | MEASUREF_FIXED = (1<<2), |
||
− | |||
− | }; |
||
− | |||
− | /* ========================================================================= * |
||
− | Signature Items |
||
− | * ========================================================================= */ |
||
− | |||
− | /* Signature items are usually placed just after the measure line. |
||
− | |||
− | Some notators have the ability to change clef in the middle of a |
||
− | measure, but not all notators need support this. If it is not |
||
− | supported, and a clef is encountered in the middle of a measure, it |
||
− | is assumed to apply to the entire measure and therefore is associated |
||
− | with the previous measure line. |
||
− | */ |
||
− | |||
− | /* Signature types: Each signature has a "sigSubType" field which |
||
− | indicates the type of signature. In addition, the high bit of the |
||
− | signature type field indicates that the signature should not be |
||
− | shown visibly. |
||
− | */ |
||
− | |||
− | enum SignatureTypes { |
||
− | SIGTYPE_TIMESIG=1, |
||
− | SIGTYPE_CLEF, |
||
− | SIGTYPE_MAJORKEY, |
||
− | SIGTYPE_MINORKEY, |
||
− | |||
− | SIGTYPE_HIDDEN=(1<<7) |
||
− | }; |
||
− | |||
− | /* Stores a time signature. 'Beats' is the number above the line, and |
||
− | 'Notes' is the number below the line. For example, '3/4' time is |
||
− | stored as beats = 3, notes = 4. |
||
− | |||
− | "Common Time" (The "C" symbol) which is equivalent to 4/4 is stored |
||
− | as 4/0 (beats = 4, notes = 0). |
||
− | |||
− | "Cut Time" ("C" with a slash through it) which is equivalent to |
||
− | 2/4 is stored as 2/0 (beats = 2, notes = 0). |
||
− | |||
− | In other words, the value "0" in "sigNotes" should always be treated |
||
− | as the value "4" when calculating measure lengths. See the |
||
− | MEASURE_LENGTH macro for an example of this. |
||
− | */ |
||
− | |||
− | typedef struct { |
||
− | CM_ItemHeader sigItem; /* item header */ |
||
− | UBYTE sigSubType, /* (= SIGTYPE_TIMESIG) */ |
||
− | sigBeats, /* beats per bar */ |
||
− | sigNotes, /* size of each beat */ |
||
− | sigPad; |
||
− | } CM_TimeSignature; |
||
− | |||
− | /* compute the measure length in clock ticks */ |
||
− | |||
− | #define MEASURE_LENGTH(beats, notes) \ |
||
− | (WHOLE_NOTE_DURATION * beats / (notes ? notes : 4)) |
||
− | |||
− | /* stores a Clef */ |
||
− | |||
− | typedef struct { |
||
− | CM_ItemHeader sigItem; /* item header */ |
||
− | UBYTE sigSubType; /* (= SIGTYPE_CLEF) */ |
||
− | UBYTE sigClef; /* new clef */ |
||
− | } CM_Clef; |
||
− | |||
− | /* Definitions of clef types. Note clef modifier bits which are used as |
||
− | part of this field as well. |
||
− | */ |
||
− | |||
− | enum ClefTypes { |
||
− | TREBLE_CLEF = 0, /* G clef in normal position */ |
||
− | BASS_CLEF, /* F clef in normal position */ |
||
− | ALTO_CLEF, /* C clef centered on line 3 */ |
||
− | TENOR_CLEF, /* C clef centered on line 2 */ |
||
− | |||
− | /* optional clefs, some of which are obselete (in the U.S.) */ |
||
− | |||
− | SOPRANO_CLEF, /* C clef centered on line 5 */ |
||
− | MEZZO_SOPRANO_CLEF, /* C clef centered on line 4 */ |
||
− | BARITONE_CLEF, /* F clef one line lower */ |
||
− | FRENCH_VIOLIN_CLEF, /* G clef one line lower */ |
||
− | |||
− | /* For drum scores. One of the things implied by a drum clef is that |
||
− | there might not be a relationship between a note's vertical |
||
− | position and it's MIDI note number, unlike other clef types. |
||
− | (This could be especially handy for work with MIDI drum machines). |
||
− | */ |
||
− | |||
− | DRUM_CLEF, /* vertical lines or box */ |
||
− | |||
− | /* clef modifier bits: A clef can be raised or lowered by one or two |
||
− | octaves. This is notated by placing a small "8" or "15" above or |
||
− | below the clef. |
||
− | */ |
||
− | |||
− | CLEF_DOWN_1_OCTAVE=(1<<4), /* clef 1 oct lower (8 below) */ |
||
− | CLEF_DOWN_2_OCTAVES=(1<<5), /* clef 2 oct lower (15 below) */ |
||
− | CLEF_UP_1_OCTAVE=(1<<6), /* clef 1 oct higher (8 above) */ |
||
− | CLEF_UP_2_OCTAVE=(1<<7), /* clef 2 oct higher (15 above) */ |
||
− | }; |
||
− | |||
− | /* stores a Key Signature. (used for both major and minor) |
||
− | |||
− | 'sigKeySig' is a signed BYTE, where '0' is the key of C. Positive |
||
− | numbers represent the number of sharps, so 1=G, 2=D, etc, around the |
||
− | circle of fifths. Negative numbers represent the number of flats, |
||
− | F=-1, B-Flat = -2, etc. |
||
− | |||
− | For minor keys, 0 is the key of A-minor, which like C has no sharps |
||
− | or flats. |
||
− | |||
− | Other types of key signatures may be supported in the future, but |
||
− | will probably be done as a different type of signature item. |
||
− | */ |
||
− | |||
− | typedef struct { |
||
− | CM_ItemHeader sigItem; /* item header */ |
||
− | UBYTE sigSubType; /* (== SIGTYPE_KEYSIG) */ |
||
− | BYTE sigKeySig; /* new key signature */ |
||
− | } CM_KeySignature; |
||
− | |||
− | /* major key definitions */ |
||
− | |||
− | #define KEY_OF_C_MAJOR 0 |
||
− | #define KEY_OF_G_MAJOR 1 |
||
− | #define KEY_OF_D_MAJOR 2 |
||
− | #define KEY_OF_A_MAJOR 3 |
||
− | #define KEY_OF_E_MAJOR 4 |
||
− | #define KEY_OF_B_MAJOR 5 |
||
− | #define KEY_OF_F_SHARP_MAJOR 6 |
||
− | #define KEY_OF_C_SHARP_MAJOR 7 |
||
− | #define KEY_OF_F_MAJOR -1 |
||
− | #define KEY_OF_B_FLAT_MAJOR -2 |
||
− | #define KEY_OF_E_FLAT_MAJOR -3 |
||
− | #define KEY_OF_A_FLAT_MAJOR -4 |
||
− | #define KEY_OF_D_FLAT_MAJOR -5 |
||
− | #define KEY_OF_G_FLAT_MAJOR -6 |
||
− | #define KEY_OF_C_FLAT_MAJOR -7 |
||
− | |||
− | /* minor key definitions */ |
||
− | |||
− | #define KEY_OF_A_MINOR 0 |
||
− | #define KEY_OF_E_MINOR 1 |
||
− | #define KEY_OF_B_MINOR 2 |
||
− | #define KEY_OF_F_SHARP_MINOR 3 |
||
− | #define KEY_OF_C_SHARP_MINOR 4 |
||
− | #define KEY_OF_G_SHARP_MINOR 5 |
||
− | #define KEY_OF_D_SHARP_MINOR 6 |
||
− | #define KEY_OF_A_SHARP_MINOR 7 |
||
− | #define KEY_OF_D_MINOR -1 |
||
− | #define KEY_OF_G_MINOR -2 |
||
− | #define KEY_OF_C_MINOR -3 |
||
− | #define KEY_OF_F_MINOR -4 |
||
− | #define KEY_OF_B_FLAT_MINOR -5 |
||
− | #define KEY_OF_E_FLAT_MINOR -6 |
||
− | #define KEY_OF_A_FLAT_MINOR -7 |
||
− | |||
− | /* ========================================================================= * |
||
− | Note or Chord item |
||
− | * ========================================================================= */ |
||
− | |||
− | /* Note Items. |
||
− | |||
− | CHORDS: The first note of a chord is always of type "note". |
||
− | Additional notes, or "intervals" are stored using the "chord" |
||
− | type. The itemXPos, noteTuple, noteDots, noteDivision, noteStyle, |
||
− | noteArpeggio, noteTrill and and noteBeamHeight fields are ignored |
||
− | for chord items and are derived from the base note, however score |
||
− | writers should set them to the same as the base note for consistency. |
||
− | |||
− | RESTS: A rest is a note item with a notePitch of 255. Rests may not |
||
− | be chorded. |
||
− | |||
− | DRUM HEADS: If the NOTEF_DRUM flag is set, indicating that the |
||
− | note has a "drum head" rather than an ordinary note head, then |
||
− | all of the pitch-modifier fields should be ignored. |
||
− | |||
− | OPTIONAL FIELDS: For less sophisticated programs, many of the fields |
||
− | in the note structure can be ignored. |
||
− | At a minimum, notation programs should look at noteLevel, |
||
− | noteAccidental, noteDivision and noteDots. When writing, all other |
||
− | fields can be set to zero, with the exception of noteDuration |
||
− | which should be set to the formal duration of the note in clock |
||
− | ticks. |
||
− | Sequencer programs should look at notePitch and noteDuration |
||
− | when loading CMUS scores. Writing is more difficult. It is suggested |
||
− | that unless the program is very sophisticated, that a different |
||
− | FORM, or perhaps a Standard MIDI File, be used for writing out |
||
− | sequencer data, as most of the fields in CMUS have meaning only to |
||
− | a notator-type program. |
||
− | |||
− | Explanation of Fields: |
||
− | ~~~~~~~~~~~~~~~~~~~~~~ |
||
− | |||
− | noteDuration -- The casual duration of the note. |
||
− | |||
− | noteFlags -- various flags which affect either this note. Note that |
||
− | the NOTEF_TIED and NOTEF_TIEDOWN can be different for each |
||
− | note in a chord. |
||
− | |||
− | noteDots: 0, 1 or 2 depending on the number of "dots" this note |
||
− | has. A dotted note is 50% longer. A double-dotted note is |
||
− | 75% longer. |
||
− | |||
− | noteDivision: Indicates the base duration of the note: whole note, |
||
− | half note, quarter note, etc. |
||
− | |||
− | notePitch: The MIDI pitch number for this note. |
||
− | |||
− | noteArpeggio: Indicates an arpeggiated chord, one where the individual |
||
− | notes are played sequentially (like a harp). |
||
− | |||
− | noteTrill: Trills are a rapid alternation between two notes. There |
||
− | are vaious kinds, see below. |
||
− | |||
− | noteAccidental: This includes things like sharps and flats. |
||
− | |||
− | noteLevel: This is the distance, in levels, from the center line of |
||
− | the staff. |
||
− | |||
− | noteBeamHeight: The height of a beamed group of notes isn't always |
||
− | related to the height that the stem would be if the note were not |
||
− | beamed. This field is the distance, in levels, from the center |
||
− | line of the staff to the beam's position. This field is only |
||
− | meaningful for the first and last note of a beam. |
||
− | |||
− | noteStyle: This is a field of flags which indicate things like |
||
− | Staccato, Legato, and other "performance style" modifiers. |
||
− | */ |
||
− | |||
− | /* What the note structure looks like with bitfields: |
||
− | |||
− | CM_ItemHeader noteItem; -- item header |
||
− | |||
− | UWORD noteDuration; -- real duration, in ticks |
||
− | UWORD noteFlags; |
||
− | |||
− | unsigned int Pad1 : 2 |
||
− | noteDots : 2, -- dotted, double-dotted |
||
− | noteDivision : 4, -- quarter note, etc. |
||
− | |||
− | UBYTE notePitch; -- MIDI note number |
||
− | unsigned int noteArpeggio : 2, -- arpeggiation |
||
− | noteTrill : 3, -- various trill types |
||
− | noteAccidental : 3; -- sharp, flat, etc. |
||
− | |||
− | BYTE noteLevel; -- dist from staff centerline |
||
− | BYTE noteBeamHeight; -- Y position of beam |
||
− | UBYTE noteStyle; -- Note Style type |
||
− | */ |
||
− | |||
− | typedef struct { |
||
− | CM_ItemHeader noteItem; /* item header */ |
||
− | |||
− | UWORD noteDuration; /* real duration, in ticks */ |
||
− | UWORD noteFlags; /* various note flags */ |
||
− | |||
− | UBYTE noteDivision; /* formal note length */ |
||
− | |||
− | UBYTE notePitch; /* MIDI note number */ |
||
− | UBYTE notePitchMods; /* modifications to pitch */ |
||
− | BYTE noteLevel; /* vertical position */ |
||
− | |||
− | BYTE noteBeamHeight; /* y position of beam */ |
||
− | UBYTE noteStyle; /* Note Style type */ |
||
− | } CM_Note; |
||
− | |||
− | /* macros to access the various bitfields */ |
||
− | |||
− | #define CM_NoteDots(f) (((f).noteDivision >> 4) & 0x03) |
||
− | #define CM_NoteDivision(f) ((f).noteDivision & 0x0f) |
||
− | |||
− | #define CM_NoteAccidental(f) ((f).notePitchMods & 7) |
||
− | #define CM_NoteTrill(f) (((f).notePitchMods >> 3) & 7) |
||
− | #define CM_NoteArpeggiation(f) (((f).notePitchMods >> 6) & 3) |
||
− | |||
− | #define CM_SetNoteDivision(note, division, dots) \ |
||
− | ((note).noteDivision = (dots << 4) | division) |
||
− | |||
− | #define CM_SetNotePitchMods(note, arp, trill, accidental) \ |
||
− | ((note).notePitchMods = (arp << 6) | ((trill << 3) & 7) | (accidental & 7)) |
||
− | |||
− | #define CM_RestPitch 255 |
||
− | |||
− | enum note_dots { |
||
− | NO_DOT = 0, /* Note is normal duration */ |
||
− | DOTTED_NOTE = 1, /* Note is 50% longer */ |
||
− | DOUBLE_DOTTED = 2 /* note is 75% longer */ |
||
− | }; |
||
− | |||
− | enum note_divisions { |
||
− | DOUBLE_WHOLE_NOTE = 0, |
||
− | WHOLE_NOTE, |
||
− | HALF_NOTE, |
||
− | QUARTER_NOTE, |
||
− | EIGHTH_NOTE, |
||
− | SIXTEENTH_NOTE, |
||
− | NOTE_32, |
||
− | NOTE_64, |
||
− | NOTE_128, |
||
− | NOTE_256 |
||
− | }; |
||
− | |||
− | enum note_accidentals { |
||
− | NOTE_ACC_NONE=0, |
||
− | NOTE_ACC_DOUBLE_FLAT, |
||
− | NOTE_ACC_FLAT, |
||
− | NOTE_ACC_HALF_FLAT, |
||
− | NOTE_ACC_NATURAL, |
||
− | NOTE_ACC_HALF_SHARP, |
||
− | NOTE_ACC_SHARP, |
||
− | NOTE_ACC_DOUBLE_SHARP, |
||
− | |||
− | /* drum styles: used in place of accidental when NOTEF_DRUM is set. |
||
− | Hollow symbols are used in place of "hollow" note heads, such |
||
− | as half notes. |
||
− | |||
− | Note that the assignment of drum parts to symbols is arbtrary, |
||
− | however the X symbol in jazz notation means "brush", and the |
||
− | triangle symbol is often assigned to the triangle instrument. |
||
− | Note also that normal note heads are often used for many |
||
− | drum instruments. |
||
− | */ |
||
− | |||
− | NOTE_DRUM_X=0, /* An "x" instead of note head */ |
||
− | NOTE_DRUM_DIAMOND, /* diamond shape */ |
||
− | NOTE_DRUM_SQUARE, /* square box */ |
||
− | NOTE_DRUM_TRIANGLE, /* triangle */ |
||
− | |||
− | }; |
||
− | |||
− | /* trills and tremolos and other pitch modulations which can be attached |
||
− | to a note. Note that these apply to the entire chord. |
||
− | */ |
||
− | |||
− | enum note_trills { |
||
− | NOTE_PMOD_NONE=0, |
||
− | NOTE_PMOD_TRILL, |
||
− | NOTE_PMOD_MORDENT, |
||
− | NOTE_PMOD_INV_MORDENT, |
||
− | NOTE_PMOD_TURN, |
||
− | }; |
||
− | |||
− | /* Arpeggiation, indicated as a vertical sqiggly line before the chord */ |
||
− | |||
− | enum note_arp_mods { |
||
− | NOTE_ARPEGGIO = 1, |
||
− | NOTE_REV_ARPEGGIO = 2, |
||
− | }; |
||
− | |||
− | /* note style flags */ |
||
− | |||
− | #define NSTYLEF_STACCATO (1<<0) /* Staccatto mark ('.') */ |
||
− | #define NSTYLEF_STACCATISSIMO (1<<1) /* Staccattissimo mark (wedge) */ |
||
− | #define NSTYLEF_LEGATO (1<<2) /* Legato ('-') */ |
||
− | #define NSTYLEF_SFORZANDO (1<<3) /* Szorzando ('^') */ |
||
− | #define NSTYLEF_ACCENT (1<<4) /* Accent ('>') */ |
||
− | #define NSTYLEF_TENUTO (1<<5) /* Tenuto (short '-') */ |
||
− | |||
− | /* general note flags */ |
||
− | |||
− | enum noteFlags { |
||
− | NOTEF_STEMDOWN = (1<<0), /* Note's stem is down */ |
||
− | NOTEF_BEAMED = (1<<1), /* Note is beamed with next note*/ |
||
− | NOTEF_TIED = (1<<2), /* Note is tied with next note */ |
||
− | NOTEF_TIEDOWN = (1<<3), /* tie direction is DOWN */ |
||
− | NOTEF_GRACE = (1<<4), /* display as grace note */ |
||
− | NOTEF_CUE = (1<<5), /* display as cue note */ |
||
− | NOTEF_DRUM = (1<<6), /* note has a drum head */ |
||
− | NOTEF_STEMSET = (1<<7), /* Stem direction fixed by user */ |
||
− | |||
− | NOTEF_RES1 = (1<<12), /* reserved by DMCS for play */ |
||
− | NOTEF_RES2 = (1<<13), /* styles (sorry :-) */ |
||
− | NOTEF_RES3 = (1<<14), |
||
− | NOTEF_RES4 = (1<<15), |
||
− | }; |
||
− | |||
− | /* ========================================================================= * |
||
− | Filler item |
||
− | * ========================================================================= */ |
||
− | |||
− | /* This item is used for supporting sparse clips. The fillerDuration |
||
− | field contains the total of the formal durations of the missing |
||
− | items between the previous event and the next one. |
||
− | */ |
||
− | |||
− | typedef struct { |
||
− | CM_ItemHeader fillerItem; /* item header */ |
||
− | UWORD fillerDuration; /* formal size of items left out*/ |
||
− | } CM_Filler; |
||
− | |||
− | /* ========================================================================= * |
||
− | Dynamic Item |
||
− | * ========================================================================= */ |
||
− | |||
− | /* This item specifies a MIDI volume. Note that the relationship between |
||
− | Volume and dynamic markings (such as fff, pp, etc) is defined |
||
− | elsewhere. |
||
− | */ |
||
− | |||
− | typedef struct { |
||
− | CM_ItemHeader dynItem; /* item header */ |
||
− | BYTE dynLevelPos; /* vertical position in leveks */ |
||
− | UBYTE dynVolume; /* midi pressure number (0..127)*/ |
||
− | BYTE dynSymbol; /* dynamic symbol, see below */ |
||
− | UBYTE dynPad; |
||
− | } CM_Dynamic; |
||
− | |||
− | /* Dynamic symbols: |
||
− | |||
− | 0 = symbol not specified, derive from MIDI volume. |
||
− | +1 = mf -1 = mp |
||
− | +2 = f -2 = p |
||
− | +3 = ff -3 = pp |
||
− | +4 = fff -4 = ppp |
||
− | (etc) |
||
− | */ |
||
− | |||
− | /* ========================================================================= * |
||
− | Instrument item |
||
− | * ========================================================================= */ |
||
− | |||
− | /* Rather than embedding the instrument names in the actual score, a |
||
− | seperate "instrument table" chunk will be defined. |
||
− | */ |
||
− | |||
− | typedef struct { |
||
− | CM_ItemHeader instItem; /* instrument item */ |
||
− | UBYTE instNumber; /* instrument number from table */ |
||
− | UBYTE instPad; |
||
− | } CM_Instrument; |
||
− | |||
− | /* ========================================================================= * |
||
− | Tempo Item |
||
− | * ========================================================================= */ |
||
− | |||
− | /* For compatibility with Standard MIDI files, tempo is represented as |
||
− | microseconds per quarter note, rather than the more commonly used |
||
− | quarter notes per minute. To convert from one to the other, the |
||
− | following formula works both ways: |
||
− | |||
− | T = 60,000,000 / t; |
||
− | |||
− | For accuracy, you may want to round: |
||
− | |||
− | T = (60,000,000 + t/2) / t; |
||
− | |||
− | Of course, the user interface of the program should not use units |
||
− | like this. |
||
− | */ |
||
− | |||
− | typedef struct { |
||
− | CM_ItemHeader tempoItem; /* item header */ |
||
− | ULONG tempoValue; /* new tempo value */ |
||
− | } CM_Tempo; |
||
− | |||
− | /* ========================================================================= * |
||
− | Repeat Item |
||
− | * ========================================================================= */ |
||
− | |||
− | /* This is a general category of items for jumping around in the |
||
− | score in a non-sequential fashion. It includes things like |
||
− | begin/end repeat bars, repeat measure, Da Capo, etc. |
||
− | |||
− | "repeatCount" is the number of times that the jump should occur, |
||
− | not the total number of times a passage should be played. For example, |
||
− | an begin/end repeat which is to play twice (once through, and then |
||
− | prepeated once) should have a repeatCount of "1". |
||
− | |||
− | In addition, repeatCount should be associated with the jump rather |
||
− | than the label. This imples that the count should go with the |
||
− | "end" of a begin/end block rather than the "begin". |
||
− | */ |
||
− | |||
− | typedef struct { |
||
− | CM_ItemHeader repeatItem; /* item header */ |
||
− | UBYTE repeatType; /* subtype of group */ |
||
− | UBYTE repeatCount; /* number of times to jump */ |
||
− | } CM_Repeat; |
||
− | |||
− | enum repeat_types { |
||
− | REPEAT_BLOCK_BEGIN=0, /* defines a repeat block */ |
||
− | REPEAT_BLOCK_END, |
||
− | |||
− | REPEAT_LAST_MEASURE, /* jumps back 1 measure */ |
||
− | REPEAT_LAST_TWO_MEASURES, /* jumps back 2 measures */ |
||
− | |||
− | REPEAT_MEASURE_REST, /* rest for N measures */ |
||
− | /* (not really a jump) */ |
||
− | /* labels to go to */ |
||
− | |||
− | REPEAT_LABEL_SEGNO, /* The "sign" D.S. refers to */ |
||
− | REPEAT_LABEL_CODA, /* The Coda symbol */ |
||
− | |||
− | /* goto operators */ |
||
− | |||
− | REPEAT_DC, /* D.C. */ |
||
− | REPEAT_DC_AL_FINE, /* D.C. al fine */ |
||
− | REPEAT_DS, /* D.S. */ |
||
− | REPEAT_DS_AL_FINE, /* D.S. al fine */ |
||
− | REPEAT_DS_AL_CODA, /* D.S. al coda */ |
||
− | }; |
||
− | |||
− | /* ========================================================================= * |
||
− | Group Item |
||
− | * ========================================================================= */ |
||
− | |||
− | /* A "Group" Item is defined as a Slur, Crescendo, or Octave Raiser. |
||
− | In general, groups can apply to any contiguous range of notes |
||
− | on a track, and groups of the same type can note overlap. |
||
− | |||
− | Note that in some cases, such as for example a crecendo, although |
||
− | the modification is technically "attached" to a particular |
||
− | track, it affects all the tracks on that staff. |
||
− | */ |
||
− | |||
− | typedef struct { |
||
− | CM_ItemHeader groupItem; /* item header */ |
||
− | UBYTE groupType; /* subtype of group */ |
||
− | |||
− | /* To even out the structure, we'll add an extra byte which means |
||
− | different things based on the group type. Right now it is |
||
− | only defined in the case of a crescendo / decrescendo in which |
||
− | case it means the final volume. |
||
− | |||
− | For all others, it should be set to zero. |
||
− | */ |
||
− | |||
− | UBYTE groupVal; |
||
− | } CM_Group; |
||
− | |||
− | /* Types of group items supported */ |
||
− | |||
− | enum group_types { |
||
− | GROUPTYPE_SLUR_UP=0, |
||
− | GROUPTYPE_SLUR_DOWN, |
||
− | GROUPTYPE_CRESCENDO, |
||
− | GROUPTYPE_DECRESCENDO, |
||
− | GROUPTYPE_OCTAVE_UP, /* "8va" symbol */ |
||
− | GROUPTYPE_OCTAVE_DOWN, /* "8vb" symbol */ |
||
− | GROUPTYPE_GLISSANDO_UP, |
||
− | GROUPTYPE_GLISSANDO_DOWN, |
||
− | |||
− | GROUPTYPE_TUPLET, /* see below */ |
||
− | GROUPTYPE_TRILL, /* the one with the wavy line */ |
||
− | GROUPTYPE_TREMOLO, /* Slashes below a beam */ |
||
− | }; |
||
− | |||
− | /* Tuplets are a subtype of group items, and as such have an extended |
||
− | structure. Unlike other group types, tuplet group items can be nested. |
||
− | |||
− | Note that for ending a tuplet, the extra fields are not required |
||
− | and a normal "Group" structure can be used. Each tuplet ending |
||
− | item matches the nearest previous unmatched tuplet item. |
||
− | */ |
||
− | |||
− | typedef struct { |
||
− | CM_ItemHeader tupletItem; /* item header */ |
||
− | UBYTE tupletType; /* subtype of group */ |
||
− | |||
− | /* tupletNumber indicates how many notes can fit in the space of |
||
− | 'tupletSpace'. For example, a triplet, i.e. "3 in the space of 2", |
||
− | or 2/3 duration, can be represented as tupletNumber = 3, |
||
− | tupletSpace = 2. |
||
− | */ |
||
− | |||
− | UBYTE tupletNumber, /* How manu items */ |
||
− | tupletSpace; /* in the space of how many */ |
||
− | |||
− | /* tupletDigits represents the binary number which should be |
||
− | displayed above the tuplet; For example, for a triplet this |
||
− | should be 3. |
||
− | */ |
||
− | |||
− | UBYTE tupletDigits; /* number to display */ |
||
− | |||
− | /* tupletFlags is for later use when we want tuplets combined with |
||
− | slurs / brackets. Currently there are no flags defined, so the |
||
− | field should be all zeroes. |
||
− | */ |
||
− | |||
− | UBYTE tupletFlags, /* various flags */ |
||
− | tupletPad; |
||
− | } CM_Tuplet; |
||
− | |||
− | /* ========================================================================= * |
||
− | Tablature Item |
||
− | * ========================================================================= */ |
||
− | |||
− | /* The Tablature item is used for guitar, banjo or other fretted |
||
− | instruments. It's a two-dimensional array of bits, which is drawn |
||
− | as a grid indicating the exact placement of fingers. |
||
− | |||
− | In addition, most tablatures have the name of the chord placed above |
||
− | the grid. This can be quite complex, looking something like this: |
||
− | |||
− | 7+6 |
||
− | C min |
||
− | |||
− | Which means: "C minor, with an added seventh and a raised sixth". |
||
− | */ |
||
− | |||
− | typedef struct { |
||
− | CM_ItemHeader tabItem; /* item header */ |
||
− | |||
− | /* tabRoot is used to indicate the name of the chord placed above |
||
− | the tablature. Note that the root can have superscripts, which |
||
− | are defined elsewhere. |
||
− | |||
− | unsigned int rootLetter : 3, -- A, B, C, etc. |
||
− | rootAccidental : 2, -- accidental of root |
||
− | rootType : 3, -- major, minor, etc. |
||
− | */ |
||
− | |||
− | UBYTE tabRoot; /* describes root of chord */ |
||
− | |||
− | /* tabDimensions is a field of two 4 bit values, representing the |
||
− | width and height of the tablature array. A dimension of (0,0) |
||
− | indicates that only the chord symbol should be used. |
||
− | */ |
||
− | |||
− | UBYTE tabDimensions; /* width/height of tab array */ |
||
− | |||
− | /* tabIntervals is an optional field -- if it's zero, it means that |
||
− | the writing program wasn't sophisticated enough to set it. |
||
− | (This is generally true for programs that are typographical |
||
− | rather than musical in orientation). |
||
− | |||
− | The field used to exactly describe the intervals in the |
||
− | chord above the root. Each interval may be: |
||
− | |||
− | 0 - missing ( no interval) |
||
− | 1 - lowered ( one half-step below major chord position ) |
||
− | 2 - normal ( in the normal position for a major chord ) |
||
− | 3 - raised ( one half-step above major chord position ) |
||
− | |||
− | unsigned int chordThird : 2, -- (missing, -1, 0, +1) |
||
− | chordFifth : 2, -- (missing, -1, 0, +1) |
||
− | chordSeventh : 2, -- (missing, -1, 0, +1) |
||
− | chordNinth : 2, -- (missing, -1, 0, +1) |
||
− | chordEleventh : 2, -- (missing, -1, 0, +1) |
||
− | chordThirteenth : 2, -- (missing, -1, 0, +1) |
||
− | chordFifteenth : 2, -- (missing, -1, 0, +1) |
||
− | chordValid : 1, -- TRUE if field valid |
||
− | chordPad : 1; |
||
− | */ |
||
− | |||
− | UWORD tabIntervals; /* describes exact chord intervals*/ |
||
− | |||
− | /* tabArray is a byte array of finger positions. |
||
− | |||
− | Each byte represents a string. The value of the byte |
||
− | can be from 0 (representing an open string), or 1-16 |
||
− | (representing a finger placed above the Nth fret). The high |
||
− | 4 bits are reserved for now, but may be used later to indicate |
||
− | special placement of the fingers. |
||
− | |||
− | Note that the tabArray can be longer or shorter than 6 bytes, |
||
− | up to a maximum of 16 strings. In such cases, the event length |
||
− | stored in the CM_ItemHeader would be adjusted accordingly. |
||
− | */ |
||
− | |||
− | UBYTE tabArray[6]; /* tablature array */ |
||
− | |||
− | /* Following the tabArray field is an optional variable-length |
||
− | ASCII string which is the actual text of the superscript, |
||
− | such as "maj6+7". |
||
− | |||
− | The length of the string can be computed comparing the end of |
||
− | the event with the end of the tab-array. Null termination is |
||
− | not required. |
||
− | */ |
||
− | |||
− | }; |
||
− | |||
− | enum chord_accidentals { |
||
− | CHORD_ACC_NONE=0, |
||
− | CHORD_ACC_FLAT, |
||
− | CHORD_ACC_NATURAL, |
||
− | CHORD_ACC_SHARP |
||
− | }; |
||
− | |||
− | enum chord_types { |
||
− | CHORD_TYPE_MAJOR, |
||
− | CHORD_TYPE_MINOR, |
||
− | CHORD_TYPE_DIMINISHED, |
||
− | CHORD_TYPE_AUGMENTED, |
||
− | CHORD_TYPE_SUSPENDED |
||
− | }; |
||
− | |||
− | enum chord_letters { |
||
− | CHORD_LETTER_A=0, |
||
− | CHORD_LETTER_B, |
||
− | CHORD_LETTER_C, |
||
− | CHORD_LETTER_D, |
||
− | CHORD_LETTER_E, |
||
− | CHORD_LETTER_F, |
||
− | CHORD_LETTER_G |
||
− | }; |
||
− | |||
− | /* ========================================================================= * |
||
− | Lyric Font Chunk (LFON) |
||
− | |||
− | This section describes the data structures which are used in the CMUS |
||
− | 'LFON' Chunk. |
||
− | |||
− | LFON chunks are used to store the font table for the document. Embedded |
||
− | within the Lyric, Annotation and title chunks are font specifiers which |
||
− | refer to a given font by number. That number is an index into this table. |
||
− | |||
− | There is one LFON chunk per font. Each LFON chunk consists of the following |
||
− | header, and then the name of the font. The terminating NULL should be |
||
− | included in the font name. |
||
− | |||
− | * ========================================================================= */ |
||
− | |||
− | typedef struct { |
||
− | UWORD fontNumber; /* number assigned to font */ |
||
− | UWORD fontHeight; /* height of font in points */ |
||
− | |||
− | /* fontName follows */ |
||
− | |||
− | } CM_FontEntry; |
||
− | |||
− | /* ========================================================================= * |
||
− | Lyric Chunk (LYRC) |
||
− | |||
− | This section describes the data structures which are used in the CMUS |
||
− | 'LYRC' Chunk. |
||
− | |||
− | Each lyric is associated with a particular track, and a particular measure |
||
− | within that track. The reason for this is because certain elements within |
||
− | the lyrics can be "attached" to notes within a track, so that syllables |
||
− | of the lyric can properly appear under the notes. |
||
− | |||
− | Lyrics associated with a particular track are written immediately after |
||
− | that track. In other words, when reading a lyric, it should be associated |
||
− | with the previously read track. |
||
− | |||
− | * ========================================================================= */ |
||
− | |||
− | /* This is the header structure for a lyric. It is followed by the actual |
||
− | text of the lyric. No terminating NUL is used. |
||
− | |||
− | Attaching syllables to notes: This is an optional feature which need |
||
− | not be supported by all readers. Basically, the TAB character is used |
||
− | to specify a block of text to align with the next note. Essentially, |
||
− | each chord on the track acts as a center-justified tab-stop. This is |
||
− | similar to the way tab stops work on medium- to high-end word |
||
− | processors: All the text between a tab, and the next tab (or the end |
||
− | of the line) is "centered" at the tab-stop position. Readers |
||
− | which don't wish to deal with this level of complexity can just |
||
− | treat the tab as a space. |
||
− | */ |
||
− | |||
− | typedef struct { |
||
− | UWORD lyricMeasure; /* starting measure of lyric */ |
||
− | |||
− | /* Position of the upper-left coordinate of the lyric. |
||
− | This can be positive or negative, and is interpreted just like |
||
− | the 'itemXPos' field for track events. |
||
− | */ |
||
− | |||
− | WORD lyricXPos; /* position relative to measure */ |
||
− | |||
− | /* lyricLevel is the position, in micrometers, of the upper- |
||
− | left corner of the lyric's extent box. |
||
− | |||
− | lyricHeight is also in micrometers. |
||
− | */ |
||
− | |||
− | Micrometers lyricLevel, /* distance from center of staff*/ |
||
− | lyricHeight; /* height of lyric extent */ |
||
− | |||
− | /* Width is in micrometers. */ |
||
− | |||
− | Micrometers lyricWidth; |
||
− | |||
− | /* lyric text string follows */ |
||
− | |||
− | } CM_Lyric; |
||
− | |||
− | /* Codes for specification of fonts and text styles. The "newfont" code |
||
− | is followed by the font number. If no font is specified, font #0 is |
||
− | the default. |
||
− | */ |
||
− | |||
− | enum { |
||
− | LSTYLE_BOLD_ON=0x80, |
||
− | LSTYLE_BOLD_OFF, |
||
− | LSTYLE_ITALIC_ON, |
||
− | LSTYLE_ITALIC_OFF, |
||
− | LSTYLE_UNDER_ON, |
||
− | LSTYLE_UNDER_OFF, |
||
− | LSTYLE_NEWFONT, /* font number follows */ |
||
− | }; |
||
− | |||
− | /* ========================================================================= * |
||
− | Annotation chunks (ANOT) |
||
− | |||
− | This section describes the data structures which are used in the CMUS |
||
− | 'ANOT' Chunk. Note that there is a standard IFF chunk called 'ANNO' |
||
− | which can be added to any file to annotate the file. The 'ANOT' is |
||
− | used to specify annotations to the music, not to the file. |
||
− | |||
− | * ========================================================================= */ |
||
− | |||
− | /* Annotation chunks are specified exactly like Lyric chunks. The only |
||
− | reason for distinguishing between the two is that a "stripper" program |
||
− | might want to strip out one or the other. |
||
− | */ |
||
− | |||
− | /* ========================================================================= * |
||
− | Title Chunk (TITL) |
||
− | |||
− | This section describes the data structures which are used in the CMUS 'TITL' |
||
− | Chunk. Unlike Lyrics, Titles are placed at fixed positions on the page |
||
− | (generally at the top) and are are not adjusted based on the positioning |
||
− | of any particular measure. |
||
− | |||
− | * ========================================================================= */ |
||
− | |||
− | /* Title chunks are specified exactly like Lyric chunks, except that the |
||
− | lyricMeasure field is ignored and should be set to 0. |
||
− | |||
− | In particular, the lyricXPos field is no longer based on measure width, |
||
− | but is now a fractional width of the document. Similarly, the |
||
− | lyricLevel field is the number of levels from the top of the page. |
||
− | (Or should that be an absolute measure?) |
||
− | */ |
||
− | |||
− | /* ========================================================================= * |
||
− | CMUS Instrument Table (FORM INST) |
||
− | |||
− | The instrument table fo the CMUS form is stored as an embedded FORM |
||
− | called 'INST'. Each instrument in the table is one INST form. |
||
− | |||
− | Instruments can be configured for MIDI, internal audio, or both. |
||
− | When using internal sounds, samples can be sepcified using an embedded |
||
− | FORM 8SVX, or any other IFF sampled sound FORM that the program wishes |
||
− | to support. Sampled sounds can be embedded in the file, or external |
||
− | sample files can be referenced from within the file, by pathname. |
||
− | |||
− | Here's a summary of the chunks which can be included in an INST |
||
− | form: |
||
− | |||
− | 'INHD': This is the instrument header. It contains the instrument |
||
− | number, and the various MIDI-related parameters. The chunk |
||
− | format is defined below. |
||
− | |||
− | 'FORM 8SVX': This is an embedded sampled sound file. The sampled |
||
− | sound is to be associated with the instrument. |
||
− | |||
− | 'SFIL': This is a reference to a sampled sound in a different file, |
||
− | and can be used instead of an embedded sample. The chunk format |
||
− | is simply the name of the file. If the file contains more than |
||
− | one sample, only the first is used. (A different chunk can be |
||
− | defined to select the Nth sample, if it turns out that this |
||
− | feature might be desired). |
||
− | |||
− | 'SHAR': This allows a instrument to share a sampled sound with |
||
− | another instrument. This would be used instead of either and |
||
− | embedded sample or an 'SFIL' chunk. The chunk format is simple |
||
− | a UWORD of the instrument number to share with; This |
||
− | instrument must have been previously loaded. |
||
− | |||
− | 'ATAK': Identical with the ATAK chunk in FORM 8SVX, this allows |
||
− | the instrument have a different envelope than the one in |
||
− | the sampled sound file. |
||
− | |||
− | 'RLSE': Identical with the RLSE chunk in FORM 8SVX, this allows the |
||
− | instrument have a different envelope than the one in the |
||
− | sampled sound file. |
||
− | |||
− | 'NAME': is a standard chunk which can be added to any IFF FORM. |
||
− | In this case, it is used to store the instrument name. Other |
||
− | standard chunks which can be added are "AUTH" (author name), |
||
− | "VERS" (version string), "ANNO" (Annotations) and "(C) " |
||
− | (copyright notice). |
||
− | |||
− | Note: If there is no sampled sound specified, either through an |
||
− | embedded sample or SFIL or SHAR chunks, then this instrument is |
||
− | a MIDI-only instrument. |
||
− | |||
− | * ========================================================================= */ |
||
− | |||
− | /* Instrument header chunk -- INHD */ |
||
− | |||
− | typedef struct { |
||
− | |||
− | /* 'instNumber' corresponds to the instrument number used |
||
− | in the "instrument event" in the TRCK chunk. |
||
− | */ |
||
− | |||
− | UBYTE instNumber; |
||
− | |||
− | UBYTE instFlags; /* various flags */ |
||
− | WORD instTune; /* tuning, in 1/100 semitones */ |
||
− | WORD instVolume; /* overall volume, 0-0xffff */ |
||
− | |||
− | /* "Pan" can be used by both MIDI and sampled sound instruments, and |
||
− | indicates a preferences for left or right. It ranges from 0 to |
||
− | 127 (same as MIDI), with 0 being ?? and 127 being ??. |
||
− | */ |
||
− | |||
− | UBYTE instPan; |
||
− | |||
− | /* MIDI-related variables */ |
||
− | |||
− | UBYTE instMidiChannel; /* MIDI channel to use */ |
||
− | UBYTE instMidiPreset; /* MIDI Preset for this channel */ |
||
− | UBYTE instMidiPort; /* Hardware port #, if applies */ |
||
− | |||
− | } InstrumentHeader; |
||
− | |||
− | #define INST_MAXVOL 0x0ffff |
||
− | #define INST_MAXPAN 127 |
||
− | |||
− | /* various flags for instFlags */ |
||
− | |||
− | #define INSTF_MIDI (1<<0) /* MIDI is enabled */ |
||
− | #define INSTF_MIDIVOL (1<<1) /* use MIDI volume, not velocity*/ |
||
− | |||
− | #endif |
||
− | </pre> |
||
− | |||
− | === DEEP === |
||
− | |||
− | <pre> |
||
− | Chunky pixel image files (Used in TV Paint) |
||
− | |||
− | IFF FORM / CHUNK DESCRIPTION |
||
− | ============================ |
||
− | |||
− | Form/Chunk ID: FORM DEEP (DEEP pixels) |
||
− | Chunk DGBL (Deep GloBaL information) |
||
− | Chunk DPEL (Deep Pixel ELements) |
||
− | Chunk DLOC (Deep display LOCation) |
||
− | Chunk DBOD (Deep data BODy) |
||
− | Chunk DCHG (Deep CHanGe buffer) |
||
− | |||
− | Date Submitted: 10-Sep-91 |
||
− | Submitted by: Amiga Centre Scotland |
||
− | |||
− | |||
− | FORM |
||
− | ==== |
||
− | |||
− | FORM ID: DEEP (DEEP pixels) |
||
− | |||
− | FORM Purpose: |
||
− | |||
− | To allow faster loading and saving of images when pixels are |
||
− | stored in consecutive memory locations and provide support for |
||
− | common extensions implemented on advanced graphics cards. |
||
− | |||
− | FORM Description: |
||
− | |||
− | This form is designed to provide support for a variety of deep |
||
− | pixels, including 24 bits images. A deep pixel is one in which |
||
− | the pixel value is used to directly produce the output colour |
||
− | without the use of a colour look-up table and also where the |
||
− | pixel is stored in consecutive memory locations. The format |
||
− | allows additional bits to be stored along with the colour bits |
||
− | to provide support for additional features such as masks, |
||
− | Z-buffers, linear keys, etc. |
||
− | |||
− | The format is designed to allow different colour formats to be |
||
− | stored such as RGB, RGBA, YCM and YCMB with varying depths |
||
− | supported. Bit ordering will be most significant bit first. |
||
− | |||
− | |||
− | CHUNKS |
||
− | ====== |
||
− | |||
− | Chunk ID: DGBL (Deep GloBaL information) |
||
− | |||
− | Chunk Purpose: |
||
− | |||
− | Provide global information of relevance to all the data contained |
||
− | in the file. DGBL will always be the first chunk in the file. |
||
− | |||
− | Chunk Description: |
||
− | |||
− | Used to provide information that is constant for all contents of |
||
− | the file. One chunk is mandatory at the start of the file. When |
||
− | the file is used to store a group of images it may, in |
||
− | exceptional circumstances, be necessary to add additional DGBL |
||
− | chunks. The contents of a DGBL chunk remain valid until another |
||
− | DGBL chunk is encountered. |
||
− | |||
− | |||
− | Chunk ID: DPEL (Deep Pixel Elements) |
||
− | |||
− | Chunk Purpose: |
||
− | |||
− | Defines the contents of each pixel. Enables the data content to |
||
− | be identified and handled. Data that is unknown or not required |
||
− | can be discarded. |
||
− | |||
− | Chunk Description: |
||
− | |||
− | This chunk is best described by an example: |
||
− | |||
− | Original data = RGBA 8:8:8:4 |
||
− | |||
− | DPEL = |
||
− | 4 (number of elements) |
||
− | RED (first element) |
||
− | 8 (bits in element) |
||
− | GREEN (second element) |
||
− | 8 (bits in second element) |
||
− | BLUE (third element) |
||
− | 8 (bits in third element) |
||
− | ALPHA (fourth element) |
||
− | 4 (bits in fourth element) |
||
− | |||
− | Stored data (binary) = rrrrrrrr gggggggg bbbbbbbb aaaa0000 |
||
− | |||
− | Note: The pixel has been padded to the next byte boundary. |
||
− | |||
− | The elements must be defined in the order in which they are |
||
− | stored, with the most significant bit first. |
||
− | |||
− | |||
− | Chunk ID: DLOC (Deep display LOCation) |
||
− | |||
− | Chunk Purpose: |
||
− | |||
− | Provides information specific to the following DBOD section. |
||
− | Enables image sections to be located within the screen area |
||
− | individually & allows images with a size different to |
||
− | DisplayWidth & DisplayHeight to be stored. |
||
− | |||
− | Chunk Description: |
||
− | |||
− | Specifies the width, height and where to place the following Deep |
||
− | data BODy. If no DLOC is encountered before a DBOD, the |
||
− | DisplayWidth & DisplayHeight parameters will be used as the DBOD |
||
− | image data dimensions. The contents of a DLOC chunk remain valid |
||
− | until another DLOC chunk is encountered. |
||
− | |||
− | |||
− | Chunk ID: DBOD (Deep BODy) |
||
− | |||
− | Chunk Purpose: |
||
− | |||
− | Contains the image data. |
||
− | |||
− | Chunk Description: |
||
− | |||
− | Contains image data compressed by the method defined in DGBL. |
||
− | The image size and the location where it is to be displayed is |
||
− | provided by a DLOC chunk. If no DLOC chunk has been read the |
||
− | data will be displayed in the upper left corner and will be |
||
− | DisplayWidth wide and DisplayHeight high. |
||
− | |||
− | |||
− | Chunk ID: DCHG (Deep CHanGe buffer) |
||
− | |||
− | Chunk Purpose: |
||
− | |||
− | Informs the IFF reader that a complete frame has been read. Only |
||
− | required when multiple images are stored for cell animation. |
||
− | |||
− | Chunk Description: |
||
− | |||
− | When a DCHG chunk is encounter the IFF reader knows that a |
||
− | complete frame has been read. The chunk gives the time *from the |
||
− | last frame change* before the frame should be changed again. If |
||
− | the time has already elapsed the frame should be changed |
||
− | immediately. A FrameRate of 0 will cause the frame changes to |
||
− | occur as fast as possible. A FrameRate of -1 is used to indicate |
||
− | the end of the data for one frame and the start of the next in |
||
− | cases where multiple frames are stored but are not intended for |
||
− | animation. A DCHG chunk is not required when only a single frame |
||
− | is stored. |
||
− | |||
− | |||
− | |||
− | // |
||
− | //FORM DEEP |
||
− | //========= |
||
− | // |
||
− | // Chunk DGBL |
||
− | // ---------- |
||
− | // |
||
− | struct DGBL = { |
||
− | // |
||
− | // Size of source display |
||
− | // |
||
− | UWORD DisplayWidth,DisplayHeight; |
||
− | // |
||
− | // Type of compression |
||
− | // |
||
− | UWORD Compression; |
||
− | // |
||
− | // Pixel aspect, a ration w:h |
||
− | // |
||
− | UBYTE xAspect,yAspect; |
||
− | }; |
||
− | |||
− | // |
||
− | // Chunk DPEL |
||
− | // ---------- |
||
− | struct DPEL = { |
||
− | // |
||
− | // Number of pixel components |
||
− | // |
||
− | ULONG nElements; |
||
− | // |
||
− | // The TypeDepth structure is repeated nElement times to identify |
||
− | // the content of every pixel. Pixels will always be padded to |
||
− | // byte boundaries. The DBOD chunk will be padded to an even |
||
− | // longword boundary. |
||
− | // |
||
− | struct TypeDepth = { |
||
− | // |
||
− | // Type of data |
||
− | // |
||
− | UWORD cType; |
||
− | // |
||
− | // Bit depth of this type |
||
− | // |
||
− | UWORD cBitDepth; |
||
− | } typedepth[Nelements]; |
||
− | }; |
||
− | |||
− | // |
||
− | // Chunk DLOC |
||
− | // ---------- |
||
− | // |
||
− | struct DLOC = { |
||
− | // |
||
− | // Body width & height in pixels |
||
− | // |
||
− | UWORD w,h |
||
− | // |
||
− | // Pixel position for this image |
||
− | // |
||
− | WORD x,y |
||
− | }; |
||
− | |||
− | // |
||
− | // Chunk DBOD |
||
− | // ---------- |
||
− | // |
||
− | pixel[0], pixel[2], pixel[3], ...., pixel[w-1] |
||
− | pixel[((h-1)*w)], ...,pixel[h*w-1] |
||
− | |||
− | // |
||
− | // Chunk DCHG |
||
− | // ---------- |
||
− | // |
||
− | struct DCHG = { |
||
− | // |
||
− | // Animation control (When multiple images are stored) |
||
− | // FrameRate - milli-seconds between frames changes |
||
− | // |
||
− | LONG FrameRate; |
||
− | }; |
||
− | |||
− | Compressions currently defined: |
||
− | |||
− | NOCOMPRESSION = 0 |
||
− | RUNLENGTH = 1 |
||
− | HUFFMAN = 2 |
||
− | DYNAMICHUFF = 3 |
||
− | JPEG = 4 |
||
− | |||
− | Ctype currently defined: |
||
− | |||
− | RED = 1 |
||
− | GREEN = 2 |
||
− | BLUE = 3 |
||
− | ALPHA = 4 (no precise definition of use) |
||
− | YELLOW = 5 |
||
− | CYAN = 6 |
||
− | MAGENTA = 7 |
||
− | BLACK = 8 |
||
− | MASK = 9 |
||
− | ZBUFFER = 10 |
||
− | OPACITY = 11 |
||
− | LINEARKEY = 12 |
||
− | BINARYKEY = 13 |
||
− | |||
− | ---------------------------------------------------------------------- |
||
− | |||
− | Addendum |
||
− | ======== |
||
− | |||
− | The following information is an extension to the DEEP format |
||
− | proposed by TecSoft and used in their 24 bit paint application, |
||
− | TVPaint. The extension provides an additional compression method |
||
− | and its associated chunk. |
||
− | |||
− | Additional compression type: |
||
− | |||
− | TVDC = 5 |
||
− | |||
− | Chunk ID: TVDC (TVPaint Deep Compression) |
||
− | |||
− | Chunk Purpose: |
||
− | |||
− | Provides the table of values required to enable decompression of |
||
− | the image data. |
||
− | |||
− | Chunk Description: |
||
− | |||
− | TVDC is a modified version of Delta compression, using a 16 word |
||
− | lookup table of delta values and also incorporates Run Length |
||
− | Limiting compression for short runs. |
||
− | |||
− | Note that the compression is made line by line for each element |
||
− | of the chunk DPEL. For RGBA for example we have a Red line, a |
||
− | Green line, and so on. |
||
− | |||
− | CDepackTVDC(source,dest,table,size) |
||
− | UBYTE *source; |
||
− | UBYTE *dest; |
||
− | WORD *table; |
||
− | int size; |
||
− | { |
||
− | int i; |
||
− | int d; |
||
− | int pos=0; |
||
− | UBYTE v=0; |
||
− | |||
− | for(i=0;i<size;i++) |
||
− | { |
||
− | d=source[pos>>1]; |
||
− | if(pos++&1) d&=0xf; |
||
− | else d>>=4; |
||
− | v+=table[d]; |
||
− | dest[i]=v; |
||
− | if(!table[d]) |
||
− | { |
||
− | d=source[pos>>1]; |
||
− | if(pos++&1) d&=0xf; |
||
− | else d>>=4; |
||
− | while(d--) dest[++i]=v; |
||
− | } |
||
− | } |
||
− | return((pos+1)/2); |
||
− | } |
||
− | </pre> |
||
− | |||
− | === DTYP === |
||
− | |||
− | DataTypes Identification |
||
− | |||
− | <pre> |
||
− | #ifndef LIBRARIES_DATATYPES_H |
||
− | #define LIBRARIES_DATATYPES_H |
||
− | /* |
||
− | ** $Id: datatypes.h,v 39.1 91/12/13 10:17:52 davidj Exp $ |
||
− | ** |
||
− | ** (C) Copyright 1991-1999 Amiga, Inc. |
||
− | ** All Rights Reserved |
||
− | */ |
||
− | #ifndef EXEC_TYPES_H |
||
− | #include <exec/types.h> |
||
− | #endif |
||
− | #ifndef EXEC_LISTS_H |
||
− | #include <exec/lists.h> |
||
− | #endif |
||
− | #ifndef EXEC_NODES_H |
||
− | #include <exec/nodes.h> |
||
− | #endif |
||
− | #ifndef EXEC_LIBRARIES_H |
||
− | #include <exec/libraries.h> |
||
− | #endif |
||
− | #ifndef LIBRARIES_IFFPARSE_H |
||
− | #include <libraries/iffparse.h> |
||
− | #endif |
||
− | |||
− | /*****************************************************************************/ |
||
− | |||
− | #define ID_DTYP MAKE_ID('D','T','Y','P') |
||
− | |||
− | /*****************************************************************************/ |
||
− | |||
− | #define ID_DTHD MAKE_ID('D','T','H','D') |
||
− | |||
− | struct DataTypeHeader |
||
− | { |
||
− | STRPTR dth_Name; /* Descriptive name of the data type */ |
||
− | STRPTR dth_BaseName; /* Base name of the data type */ |
||
− | STRPTR dth_Pattern; /* Match pattern for file name. */ |
||
− | WORD *dth_Mask; /* Comparision mask */ |
||
− | ULONG dth_GroupID; /* Group that the DataType is in */ |
||
− | ULONG dth_ID; /* ID for DataType (same as IFF FORM type) */ |
||
− | WORD dth_MaskLen; /* Length of comparision mask */ |
||
− | WORD dth_Pad; /* Unused at present (must be 0) */ |
||
− | UWORD dth_Flags; /* Flags */ |
||
− | UWORD dth_Priority; /* Priority */ |
||
− | }; |
||
− | |||
− | #define DTHSIZE sizeof(struct DataTypeHeader) |
||
− | |||
− | /*****************************************************************************/ |
||
− | |||
− | /* Basic file type */ |
||
− | #define DTF_TYPE_MASK 0x000F |
||
− | #define DTF_BINARY 0x0000 |
||
− | #define DTF_ASCII 0x0001 |
||
− | #define DTF_IFF 0x0002 |
||
− | #define DTF_MISC 0x0003 |
||
− | |||
− | /* Set if case is important */ |
||
− | #define DTF_CASE 0x0010 |
||
− | |||
− | /* Reserved for system use */ |
||
− | #define DTF_SYSTEM1 0x1000 |
||
− | |||
− | /***************************************************************************** |
||
− | * |
||
− | * GROUP ID and ID |
||
− | * |
||
− | * This is used for filtering out objects that you don't want. For |
||
− | * example, you could make a filter for the ASL file requester so |
||
− | * that it only showed the files that were pictures, or even to |
||
− | * narrow it down to only show files that were ILBM pictures. |
||
− | * |
||
− | * Note that the Group ID's are in lower case, and always the first |
||
− | * four characters of the word. |
||
− | * |
||
− | * For ID's; If it is an IFF file, then the ID is the same as the |
||
− | * FORM type. If it isn't an IFF file, then the ID would be the |
||
− | * first four characters of name for the file type. |
||
− | * |
||
− | *****************************************************************************/ |
||
− | |||
− | /* System file, such as; directory, executable, library, device, font, etc. */ |
||
− | #define GID_SYSTEM MAKE_ID ('s','y','s','t') |
||
− | |||
− | /* Formatted or unformatted text */ |
||
− | #define GID_TEXT MAKE_ID ('t','e','x','t') |
||
− | |||
− | /* Formatted text with graphics or other DataTypes */ |
||
− | #define GID_DOCUMENT MAKE_ID ('d','o','c','u') |
||
− | |||
− | /* Sound */ |
||
− | #define GID_SOUND MAKE_ID ('s','o','u','n') |
||
− | |||
− | /* Musical instruments used for musical scores */ |
||
− | #define GID_INSTRUMENT MAKE_ID ('i','n','s','t') |
||
− | |||
− | /* Musical score */ |
||
− | #define GID_MUSIC MAKE_ID ('m','u','s','i') |
||
− | |||
− | /* Still picture */ |
||
− | #define GID_PICTURE MAKE_ID ('p','i','c','t') |
||
− | |||
− | /* Animated picture */ |
||
− | #define GID_ANIMATION MAKE_ID ('a','n','i','m') |
||
− | |||
− | /* Animation with audio track */ |
||
− | #define GID_MOVIE MAKE_ID ('m','o','v','i') |
||
− | |||
− | /*****************************************************************************/ |
||
− | |||
− | /* A DTCD chunk contains an embedded executable that can be loaded |
||
− | * with InternalLoadSeg. */ |
||
− | #define ID_CODE MAKE_ID('D','T','C','D') |
||
− | |||
− | /* DataTypes comparision hook context (Read-Only). This is the |
||
− | * argument that is passed to a custom comparision routine. */ |
||
− | struct DTHookContext |
||
− | { |
||
− | /* Libraries that are already opened for your use */ |
||
− | struct Library *dthc_SysBase; |
||
− | struct Library *dthc_DOSBase; |
||
− | struct Library *dthc_IFFParseBase; |
||
− | struct Library *dthc_UtilityBase; |
||
− | |||
− | /* File context */ |
||
− | BPTR dthc_Lock; |
||
− | struct FileInfoBlock *dthc_FIB; |
||
− | BPTR dthc_FileHandle; |
||
− | struct IFFHandle *dthc_IFF; |
||
− | STRPTR dthc_Buffer; /* Buffer */ |
||
− | ULONG dthc_BufferLength; /* Length of the buffer */ |
||
− | }; |
||
− | |||
− | /*****************************************************************************/ |
||
− | |||
− | #define ID_DTTL MAKE_ID('D','T','T','L') |
||
− | |||
− | struct Tool |
||
− | { |
||
− | UWORD tn_Which; /* Which tool is this */ |
||
− | UWORD tn_Flags; /* Flags */ |
||
− | STRPTR tn_Program; /* Application to use */ |
||
− | }; |
||
− | |||
− | #define TSIZE sizeof(struct Tool) |
||
− | |||
− | /* defines for tn_Which */ |
||
− | #define TW_INFO 1 |
||
− | #define TW_BROWSE 2 |
||
− | #define TW_EDIT 3 |
||
− | #define TW_PRINT 4 |
||
− | #define TW_MAIL 5 |
||
− | |||
− | /* defines for tn_Flags */ |
||
− | #define TF_LAUNCH_MASK 0x000F |
||
− | #define TF_SHELL 0x0001 |
||
− | #define TF_WORKBENCH 0x0002 |
||
− | #define TF_RX 0x0003 |
||
− | |||
− | /*****************************************************************************/ |
||
− | |||
− | #ifndef DATATYPE |
||
− | #define DATATYPE |
||
− | struct DataType |
||
− | { |
||
− | struct Node dtn_Node1; /* Reserved for system use */ |
||
− | struct Node dtn_Node2; /* Reserved for system use */ |
||
− | struct DataTypeHeader *dtn_Header; /* Pointer to the DataTypeHeader */ |
||
− | struct List dtn_ToolList; /* List of tool nodes */ |
||
− | STRPTR dtn_FunctionName; /* Name of comparision routine */ |
||
− | ULONG dtn_Length; /* Length of the memory block */ |
||
− | }; |
||
− | #endif |
||
− | |||
− | #define DTNSIZE sizeof(struct DataType) |
||
− | |||
− | /*****************************************************************************/ |
||
− | |||
− | struct ToolNode |
||
− | { |
||
− | struct Node tn_Node; /* Embedded node */ |
||
− | struct Tool tn_Tool; /* Embedded tool */ |
||
− | ULONG tn_Length; /* Length of the memory block */ |
||
− | }; |
||
− | |||
− | #define TNSIZE sizeof(struct ToolNode) |
||
− | |||
− | /*****************************************************************************/ |
||
− | |||
− | #ifndef ID_NAME |
||
− | #define ID_NAME MAKE_ID('N','A','M','E') |
||
− | #endif |
||
− | |||
− | #endif /* LIBRARIES_DATATYPES_H */ |
||
− | </pre> |
||
− | |||
− | === HEAD === |
||
− | |||
− | <pre> |
||
− | TITLE: HEAD (FORM used by Flow - New Horizons Software, Inc.) |
||
− | |||
− | IFF FORM / CHUNK DESCRIPTION |
||
− | ============================ |
||
− | |||
− | Form/Chunk ID: FORM HEAD, Chunks NEST, TEXT, FSCC |
||
− | |||
− | Date Submitted: 03/87 |
||
− | Submitted by: James Bayless - New Horizons Software, Inc. |
||
− | |||
− | |||
− | FORM |
||
− | ==== |
||
− | |||
− | FORM ID: HEAD |
||
− | |||
− | FORM Description: |
||
− | |||
− | FORM HEAD is the file storage format of the Flow idea processor |
||
− | by New Horizons Software, Inc. Currently only the TEXT and NEST |
||
− | chunks are used. There are plans to incorporate FSCC and some |
||
− | additional chunks for headers and footers. |
||
− | |||
− | |||
− | CHUNKS |
||
− | ====== |
||
− | |||
− | CHUNK ID: NEST |
||
− | |||
− | This chunk consists of only of a word (two byte) value that gives |
||
− | the new current nesting level of the outline. The initial nesting level |
||
− | (outermost level) is zero. It is necessary to include a NEST chunk only |
||
− | when the nesting level changes. Valid changes to the nesting level are |
||
− | either to decrease the current value by any amount (with a minimum of 0) |
||
− | or to increase it by one (and not more than one). |
||
− | |||
− | |||
− | CHUNK ID: TEXT |
||
− | |||
− | This chunk is the actual text of a heading. Each heading has a TEXT |
||
− | chunk (even if empty). The text is not NULL terminated - the chunk |
||
− | size gives the length of the heading text. |
||
− | |||
− | |||
− | CHUNK ID: FSCC |
||
− | |||
− | This chunk gives the Font/Style/Color changes in the heading from the |
||
− | most recent TEXT chunk. It should occur immediately after the TEXT chunk |
||
− | it modifies. The format is identical to the FSCC chunk for the IFF |
||
− | form type 'WORD' (for compatibility), except that only the 'Location' |
||
− | and 'Style' values are used (i.e., there can be currently only be style |
||
− | changes in an outline heading). The structure definition is: |
||
− | |||
− | typedef struct { |
||
− | UWORD Location; /* Char location of change */ |
||
− | UBYTE FontNum; /* Ignored */ |
||
− | UBYTE Style; /* Amiga style bits */ |
||
− | UBYTE MiscStyle; /* Ignored */ |
||
− | UBYTE Color; /* Ignored */ |
||
− | UWORD pad; /* Ignored */ |
||
− | } FSCChange; |
||
− | |||
− | The actual chunk consists of an array of these structures, one entry |
||
− | for each Style change in the heading text.</pre> |
||
− | === Numerical data storage === |
||
− | |||
− | <pre>Numerical data storage (MathVision - Seven Seas) |
||
− | |||
− | MTRX FORM, for matrix data storage 19-July-1990 |
||
− | |||
− | Submitted by: Doug Houck |
||
− | Seven Seas Software |
||
− | (address, etc) |
||
− | |||
− | INTRODUCTION: |
||
− | |||
− | Numerical data, as it comes from the real world, is an ill-mannered beast. |
||
− | Often much is assumed about the data, such as the number of dimensions, |
||
− | formatting, compression, limits, and sizes. As such, data is not portable. |
||
− | The MTRX FORM will both store the data, and completely describe its |
||
− | format, such that programs no longer need to guess the parameters of |
||
− | a data file. There needs to be but one program to read ascii files and |
||
− | output MTRX IFF files. |
||
− | |||
− | A matrix, by our definition, is composed of three types of things. |
||
− | Firstly, the atomic data, such as an integer, or floating point number. |
||
− | Secondly, arrays, which are simply lists of things which are all the same. |
||
− | Thirdly, structures, which are lists of things which are different. |
||
− | Both arrays and structures may be composed of things besides atomic data - |
||
− | they may contain other structures and arrays as well. This concept |
||
− | of nesting structures may be repeated to any desired depth. |
||
− | |||
− | For example, a list of data pairs could be encoded as an array of structures, |
||
− | where each structure contains two numbers. A two-dimensional array is |
||
− | simply an array of arrays. |
||
− | |||
− | Since space conservation is often desirable, there is provision for |
||
− | representing each number with fewer bits, and compressing the bits together. |
||
− | |||
− | |||
− | CHUNKS |
||
− | |||
− | The MTRX FORM is composed of the definition of the structure, followed |
||
− | by the BODY which contains the data which is defined. Usually, there |
||
− | is only one set of data, but a smarter IFF read could use the definition |
||
− | as a PROPerty, with identically formatted data sets (BODYs) in a LIST. |
||
− | |||
− | FORM MTRX |
||
− | definition (ARRY | STRU | DTYP) |
||
− | BODY |
||
− | |||
− | ARRY: The array chunk defines a counted list of similar items. |
||
− | The first (required) chunk in an ARRY is ELEM, which gives the number |
||
− | of elements in the array. Optionally, there may be limits given, (LOWR |
||
− | and UPPR), which could be used in scaling during sampling of the data. |
||
− | Lastly is the definition of an element of the array, which may be a |
||
− | nested definition like everything else. |
||
− | |||
− | ARRY ::= "ARRY" #{ ELEM [LOWR] [UPPR] [PACK] ARRY|STRU|DTYP } |
||
− | |||
− | STRU: The structure chunk defines a counted list of dissimilar things. |
||
− | The first (required) chunk in a STRU is FLDS, which gives the number |
||
− | of fields in the structure. Lastly are definitions of each field |
||
− | in the structure. Again, each field may have a nested definition like |
||
− | everything else. |
||
− | |||
− | STRU ::= "STRU" #{ FLDS ([PACK] ARRY|STRU|DTYP)* } |
||
− | |||
− | VALU: The value contains a datatype, and then a constant of that type. |
||
− | The datatype contains the size of the constant, so this chunk has variable |
||
− | size. VALU is used in the ARRY chunk to give the scaling limits of the array. |
||
− | |||
− | BODY: This is the actual data we went to so much effort to describe. |
||
− | It is stored in "row-first" format, that is, items at the bottom of the |
||
− | nested description are stored next to each other. In most cases, it |
||
− | should be sufficient to simply block-read the whole chunk from disk, |
||
− | unless the reader needs to adjust byte-ordering or store in a more |
||
− | time-efficient format in memory. Data is assumed to be byte-aligned. |
||
− | |||
− | PACK: The PACK chunk is necessary when the bit length of the data is |
||
− | not a multiple of 8, that is, not byte-aligned, and the user wishes |
||
− | to conserve space by packing data items together. PACK is simply a |
||
− | number - the number of items to bit-pack before aligning on a byte. |
||
− | A PACK is in effect for the remainder of its nested scope, or until |
||
− | overridden by a new specification. A STRU or ARRY is assumed to have |
||
− | a PACK of 1 by default - it is not affected by PACKs in definitions above. |
||
− | A PACK of 0 means to byte-align before processing the next definition. |
||
− | The PACK specifier should be normalized. For example, when packing a large |
||
− | array of 3-bit numbers, PACK should be 8 since 3*8 = 24. In this case 8 is |
||
− | the smallest PACK number which aligns on a byte naturally. |
||
− | |||
− | DTYP: The DataType is the most interesting chunk, as it attempts to define |
||
− | every conceivable type of numeric data with 32 bits. The 32 bits are broken |
||
− | down into three fields, 1) the size in bits, 2) the Class, and 3) SubClass. |
||
− | The Class makes the most major distinction, separating integers from floating |
||
− | point numbers from Binary Coded Decimal and etc. Within each class is a |
||
− | SubClass, which gives the specific encoding used. Finally, the Size tells |
||
− | what how much room the data occupies. The basic division of datatypes is |
||
− | given in the tree structure below. |
||
− | |||
− | Class SubClass Size Final Specific Type |
||
− | ===== ======== ==== =================== |
||
− | | |
||
− | Binary Unsigned - 0 ------------ 8 UByte |
||
− | | 16 UWord |
||
− | | 32 ULong |
||
− | | |
||
− | Binary Signed --- 0 ------------ 8 Byte |
||
− | | 16 Word |
||
− | | 32 ULong |
||
− | | |
||
− | Real ------------Ieee38 -------- 32 Ieee Single Precision |
||
− | | | |
||
− | | Ieee308 ------- 64 Double Precision |
||
− | | | 32 Truncated Double Precision |
||
− | | | |
||
− | | FFP ----------- 32 Motorola Fast Floating Point |
||
− | | |
||
− | Text ----------- Text0 --------- ?? Null-terminated text |
||
− | | | |
||
− | | CText --------- ?? Number of characters in first byte |
||
− | | | |
||
− | | FText --------- ?? Fixed length, space padded |
||
− | | |
||
− | BCD ------------ Nibble -------- ?? |
||
− | | |
||
− | Character ----- ?? |
||
− | |||
− | A design goal was to create a classification system which other people |
||
− | can easily plug into. Many data types are simply size variations on |
||
− | existing data types. For example, a 4-bit integer can be specified by |
||
− | giving the size as four bits in the Signed Binary class. Be aware that |
||
− | not all MTRX readers may support your new type, but there will not be |
||
− | any type clashes or ambiguities by following these rules. If you have |
||
− | a truly unique Class or SubClass, you will need to register it with |
||
− | the AmigaOS development team to prevent clashes. |
||
− | |||
− | A second design goal was to create a format which is easily decoded |
||
− | by software. By aligning fields on bytes, you have the option of redefining |
||
− | the datatype as a structure, so as to avoid shifting when accessing the |
||
− | fields. Since the numbers are sequentially assigned, they are suitable |
||
− | as array indicies, and may be optimized in a C switch statement. |
||
− | |||
− | A third design goal was allowing for naive and sophisticated readers. |
||
− | In checking for a certain datatype, a naive reader can simply compare |
||
− | the whole datatype with a small set of known types, which assumes that |
||
− | each different Size defines a unique datatype. Sophisticated readers |
||
− | will consider the Class, SubClass and Size separately, so as to support |
||
− | arbitrary size integers, and truncated Floating Point numbers, for example. |
||
− | |||
− | * |
||
− | * MTRX ::= "FORM" #{ "MTRX" ARRY|STRU|DTYP BODY } Matrix |
||
− | * ARRY ::= "ARRY" #{ ELEM [LOWR] [UPPR] [PACK] ARRY|STRU|DTYP } Array |
||
− | * STRU ::= "STRU" #{ FLDS ([PACK] ARRY|STRU|DTYP)* } Structure |
||
− | * ELEM ::= "ELEM" #{ elements } Array elements |
||
− | * LOWR ::= "LOWR" { VALU } Minimum limit |
||
− | * UPPR ::= "UPPR" { VALU } Maximum limit |
||
− | * VALU ::= #{ dtyp value } Value (in union) |
||
− | * dtyp ::= { size, subclass, class } Data Type (scalar) |
||
− | * DTYP ::= "DTYP" #{ dtyp } |
||
− | * FLDS ::= "FLDS" #{ number of fields } Number of Fields |
||
− | * PACK ::= "PACK" #{ units packed b4 byte alignment } Packing |
||
− | * BODY ::= "BODY" #{ inner-first binary dump } Data |
||
− | * |
||
− | * [] means optional |
||
− | * # means the size of the unit following |
||
− | * * means one or more of |
||
− | *</pre> |
||
− | |||
− | === Program traceback === |
||
− | |||
− | <pre>Program traceback (SAS Institute) |
||
− | |||
− | FORM PGTB |
||
− | |||
− | Proposal: |
||
− | New IFF chunk type, to be named PGTB, meaning ProGram TraceBack. |
||
− | |||
− | Format: |
||
− | |||
− | 'PGTB' - chunk identifier |
||
− | length - longword for length of chunk |
||
− | |||
− | 'FAIL' - subfield giving environment at time of crash |
||
− | length - longword length of subfield |
||
− | NameLen - length of program name in longwords (BSTR) |
||
− | Name - program name packed in longwords |
||
− | Environment - copy of AttnFlags field from ExecBase, |
||
− | gives type of processor, and existence of |
||
− | math chip |
||
− | VBlankFreq - copy of VBlankFrequency field from ExecBase |
||
− | PowerSupFreq - copy of PowerSupplyFrequency field from ExecBase |
||
− | above fields may be used to determine whether |
||
− | machine was PAL or NTSC |
||
− | Starter - non-zero = CLI, zero = WorkBench |
||
− | GURUNum - exception number of crash |
||
− | SegCount - number of segments for program |
||
− | SegList - copy of seglist for program |
||
− | (Includes all seglist pointers, paired with |
||
− | sizes of the segments) |
||
− | |||
− | 'REGS' - register dump subfield |
||
− | length - length of subfield in longwords |
||
− | GURUAddr - PC at time of crash |
||
− | Flags - copy of Condition Code Register |
||
− | DDump - dump of data registers |
||
− | ADump - dump of address registers |
||
− | |||
− | 'VERS' - revision of program which created this file |
||
− | length - length of subfield in longwords |
||
− | version - main version of writing program |
||
− | revision - minor revision level of writing program |
||
− | TBNameLen - length of name of writing program |
||
− | TBName - name of writing program packed in longwords (BSTR) |
||
− | |||
− | 'STAK' - stack dump subfield |
||
− | length - length of subfield in longwords |
||
− | (type) - tells type of stack subfield, which can be any of |
||
− | the following: |
||
− | ----------------------------------------------------------- |
||
− | Info - value 0 |
||
− | StackTop - address of top of stack |
||
− | StackPtr - stack pointer at time of crash |
||
− | StackLen - number of longwords on stack |
||
− | |||
− | ----------------------------------------------------------- |
||
− | Whole stack - value 1 |
||
− | only used if total stack to be dumped is 8k |
||
− | or less in size |
||
− | Stack - dump of stack from current to top |
||
− | |||
− | ----------------------------------------------------------- |
||
− | Top 4k - value 2 |
||
− | if stack used larger than 8k, this part |
||
− | is a dump of the top 4k |
||
− | Stack - dump of stack from top - 4k to top |
||
− | |||
− | ----------------------------------------------------------- |
||
− | Bottom 4k - value 3 |
||
− | if stack used larger than 8k, this part |
||
− | is a dump of the bottom 4k |
||
− | Stack - dump of stack from current to current + 4k |
||
− | |||
− | In other words, we will dump a maximum of 8k of stack data. This |
||
− | does NOT mean the stack must be less than 8k in size to dump the |
||
− | entire stack, just that the amount of stack USED be less than 8k. |
||
− | |||
− | 'UDAT' - Optional User DATa chunk. If the user assigns |
||
− | a function pointer to the label "_ONGURU", the |
||
− | catcher will call this routine prior to closing |
||
− | the SnapShot file, passing one parameter on the |
||
− | stack - an AmigaDOS file pointer to the SnapShot |
||
− | file. Spec for the _ONGURU routine: |
||
− | |||
− | void <function name>(fp) |
||
− | long fp; |
||
− | |||
− | In other words, your routine must be of type 'void' |
||
− | and must take one parameter, an AmigaDOS file |
||
− | handle (which AmigaDOS wants to see as a LONG). |
||
− | length - length of the UserDATa chunk, calculated after the |
||
− | user routine terminates.</pre> |
||
− | === PRSP === |
||
− | |||
− | DPaint IV perspective move. |
||
− | |||
− | <pre> |
||
− | /* ----------------------------------------------------------------------- |
||
− | IFF Information: |
||
− | PRSP ::= "FORM" # {"PSRP" MOVE } |
||
− | MOVE ::= "MOVE" # { MoveState } |
||
− | * ---------------------------------------------------------------------- */ |
||
− | typedef struct { |
||
− | BYTE reserved; /* initialize to 0 */ |
||
− | BYTE moveDir; /* 0 = from point 1 = to point */ |
||
− | BYTE recordDir; /* 0 = FORWARD, 1 = STILL, 2 = BACKWARD */ |
||
− | BYTE rotationType; /* 0 = SCREEN_RELATIVE, 1 = BRUSH_RELATIVE */ |
||
− | BYTE translationType; /* 0 = SCREEN_RELATIVE, 1 = BRUSH_RELATIVE */ |
||
− | BYTE cyclic; /* 0 = NO, 1 = YES */ |
||
− | SHORT distance[3]; /* x,y,z distance displacement */ |
||
− | SHORT angle[3]; /* x,y,z rotation angles */ |
||
− | SHORT nframes; /* number of frames to move */ |
||
− | SHORT easeout; /* number of frames to ease out */ |
||
− | SHORT easein; /* number of frames to ease in */ |
||
− | } MoveState; |
||
− | </pre> |
||
− | |||
− | === RGB image === |
||
− | |||
− | |||
− | |||
− | <pre>FORM RGBN and FORM RGB8 |
||
− | ----------------------- |
||
− | |||
− | RGBN and RGB8 files are used in Impulse's Turbo Silver and Imagine. |
||
− | They are almost identical to FORM ILBM's except for the BODY chunk |
||
− | and slight differences in the BMHD chunk. |
||
− | |||
− | A CAMG chunk IS REQUIRED. |
||
− | |||
− | The BMHD chunk specfies the number of bitplanes as 13 for type RGBN |
||
− | and 25 for type RGB8, and the compression type as 4. |
||
− | |||
− | The FORM RGBN uses 12 bit RGB values, and the FORM RGB8 uses |
||
− | 24 bit RGB values. |
||
− | |||
− | The BODY chunk contains RGB values, a "genlock" bit, and repeat |
||
− | counts. In Silver, when "genlock" bit is set, a "zero color" is |
||
− | written into the bitplanes for genlock video to show through. |
||
− | In Diamond and Light24 (Impulse 12 & 24 bit paint programs), |
||
− | the genlock bit is ignored if the file is loaded as a picture |
||
− | (and the RGB color is used instead), and if the file is loaded |
||
− | as a brush the genlock bit marks pixels that are not part of |
||
− | the brush. |
||
− | |||
− | For both RGBN and RGB8 body chunks, each RGB value always has a |
||
− | repeat count. The values are written in different formats depending |
||
− | on the magnitude of the repeat count. |
||
− | |||
− | For the RGBN BODY chunk: |
||
− | |||
− | For each RGB value, a WORD (16-bits) is written: with the |
||
− | 12 RGB bits in the MSB (most significant bit) positions; |
||
− | the "genlock" bit next; and then a 3 bit repeat count. |
||
− | If the repeat count is greater than 7, the 3-bit count is |
||
− | zero, and a BYTE repeat count follows. If the repeat count |
||
− | is greater than 255, the BYTE count is zero, and a WORD |
||
− | repeat count follows. Repeat counts greater than 65536 are |
||
− | not supported. |
||
− | |||
− | For the RGB8 body chunk: |
||
− | |||
− | For each RGB value, a LONG-word (32 bits) is written: |
||
− | with the 24 RGB bits in the MSB positions; the "genlock" |
||
− | bit next, and then a 7 bit repeat count. |
||
− | |||
− | In a previous version of this document, there appeared the |
||
− | following line: |
||
− | |||
− | "If the repeat count is greater than 127, the same rules apply |
||
− | as in the RGBN BODY." |
||
− | |||
− | But Impulse has never written more than a 7 bit repeat count, |
||
− | and when Imagine and Light24 were written, they didn't support |
||
− | reading anything but 7 bit counts. |
||
− | |||
− | Sample BODY code: |
||
− | |||
− | if(!count) { |
||
− | if (Rgb8) { |
||
− | fread (&w, 4, 1, RGBFile); |
||
− | lock = w & 0x00000080; |
||
− | rgb = w >> 8; |
||
− | count = w & 0x0000007f; |
||
− | } else { |
||
− | w = (UWORD) getw (RGBFile); |
||
− | lock = w & 8; |
||
− | rgb = w >> 4; |
||
− | count = w & 7; |
||
− | } |
||
− | if (!count) |
||
− | if (!(count = (UBYTE) getc (RGBFile))) |
||
− | count = (UWORD) getw (RGBFile); |
||
− | } |
||
− | |||
− | The pixels are scanned from left to right across horizontal |
||
− | lines, processing from top to bottom. The (12 or 24 bit) RGB |
||
− | values are stored with the red bits as the MSB's, the green |
||
− | bits next, and the blue bits as the LSB's. |
||
− | |||
− | Special note: As of this writing (Sep 88), Silver does NOT |
||
− | support anything but black for color zero.</pre> |
||
− | |||
− | === Sampled sound === |
||
− | |||
− | <pre> IFF FORM "SAMP" Sampled Sound |
||
− | |||
− | Date: Dec 3,1989 |
||
− | From: Jim Fiore and Jeff Glatt, dissidents |
||
− | |||
− | The form "SAMP" is a file format used to store sampled sound data in some |
||
− | ways like the current standard, "8SVX". Unlike "8SVX", this new format is not |
||
− | restricted to 8 bit sample data. There can be more than one waveform per |
||
− | octave, and the lengths of different waveforms do not have to be factors of |
||
− | 2. In fact, the lengths (waveform size) and playback mapping (which musical |
||
− | notes each waveform will "play") are independently determined for each wave- |
||
− | form. Furthermore, this format takes into account the MIDI sample dump stan- |
||
− | dard (the defacto standard for musical sample storage), while also incorpo- |
||
− | rating the ability to store Amiga specific info (for example, the sample data |
||
− | that might be sent to an audio channel which is modulating another channel). |
||
− | Although this form can be used to store "sound effects" (typically oneShot |
||
− | sounds played at a set pitch), it is primarily intended to correct the many |
||
− | deficiencies of the "8SVX" form in regards to musical sampling. Because the |
||
− | emphasis is on musical sampling, this format relies on the MIDI (Musical |
||
− | Instrument Digital Interface) method of describing "sound events" as does |
||
− | virtually all currently manufactured, musical samplers. In addition, it at- |
||
− | tempts to incorporate features found on many professional music samplers, in |
||
− | anticipation that future Amiga models will implement 16 bit sampling, and |
||
− | thus be able to achieve this level of performance. Because this format is |
||
− | more complex than "8SVX", programming examples to demonstrate the use of this |
||
− | format have been included in both C and assembly. Also, a library of func- |
||
− | tions to read and write SAMP files is available, with example applications. |
||
− | |||
− | SEMANTICS: When MIDI literature talks about a sample, usually it means a |
||
− | collection of many sample points that make up what we call a "wave". |
||
− | |||
− | |||
− | =====SIMILARITIES AND DIFFERENCES FROM THE "8SVX" FORM======= |
||
− | |||
− | Like "8SVX", this new format uses headers to separate the various sections |
||
− | of the sound file into chunks. Some of the chunks are exactly the same since |
||
− | there wasn't a need to improve them. The chunks that remain unchanged are as |
||
− | follows: |
||
− | |||
− | "(c) " |
||
− | "AUTH" |
||
− | "ANNO" |
||
− | |||
− | Since these properties are all described in the original "8SVX" document, |
||
− | please refer to that for a description of these chunks and their uses. Like |
||
− | the "8SVX" form, none of these chunks are required to be in a sound file. |
||
− | If they do appear, they must be padded out to an even number of bytes. |
||
− | |||
− | Furthermore, two "8SVX" chunks no longer exist as they have been incorpo- |
||
− | rated into the "BODY" chunk. They are: |
||
− | |||
− | "ATAK" |
||
− | "RLSE" |
||
− | |||
− | Since each wave can be completely different than the other waves in the |
||
− | sound file (one wave might be middle C on a piano, and another might be a |
||
− | snare drum hit), it is necessary for each wave to have its own envelope de- |
||
− | scription, and name. |
||
− | |||
− | The major changes from the "8SVX" format are in the "MHDR", "NAME", and |
||
− | "BODY" chunks. |
||
− | |||
− | |||
− | =================THE "SAMP" HEADER================ |
||
− | |||
− | At the very beginning of a sound file is the "SAMP" header. This is used to |
||
− | determine if the disk file is indeed a SAMP sound file. It's attributes are |
||
− | as follows: |
||
− | |||
− | #define ID_SAMP MakeID('S','A','M','P') |
||
− | |||
− | In assembly, this looks like: |
||
− | |||
− | CNOP 0,2 ;word-align |
||
− | |||
− | SAMP dc.b 'SAMP' |
||
− | sizeOfChunks dc.l [sizes of all subsequent chunks summed] |
||
− | |||
− | |||
− | =================THE "MHDR" CHUNK================= |
||
− | |||
− | The required "MHDR" chunk immediately follows the "SAMP" header and consists |
||
− | of the following components: |
||
− | |||
− | #define ID_MHDR MakeID('M','H','D','R') |
||
− | |||
− | /* MHDR size is dependant on the size of the imbedded PlayMap. */ |
||
− | |||
− | typedef struct{ |
||
− | UBYTE NumOfWaves, /* The number of waves in this file */ |
||
− | Format, /* # of ORIGINAL significant bits from 8-28 */ |
||
− | Flags, /* Various bits indicate various functions */ |
||
− | PlayMode, /* determines play MODE of the PlayMap */ |
||
− | NumOfChans, |
||
− | Pad, |
||
− | PlayMap[128*4], /* a map of which wave numbers to use for |
||
− | each of 128 possible Midi Notes. Default to 4 */ |
||
− | } MHDRChunk; |
||
− | |||
− | The PlayMap is an array of bytes representing wave numbers. There can be a |
||
− | total of 255 waves in a "SAMP" file. They are numbered from 1 to 255. A wave |
||
− | number of 0 is reserved to indicate "NO WAVE". The Midi Spec 1.0 designates |
||
− | that there are 128 possible note numbers (pitches), 0 to 127. The size of an |
||
− | MHDR's PlayMap is determined by (NumOfChans * 128). For example, if NumOfChans |
||
− | = 4, then an MHDR's PlayMap is 512 bytes. There are 4 bytes in the PlayMap |
||
− | for EACH of the 128 Midi Note numbers. For example, the first 4 bytes |
||
− | in PlayMap pertain to Midi Note #0. Of those 4 bytes, the first byte is the |
||
− | wave number to play back on Amiga audio channel 0. The second byte is the |
||
− | wave number to play back on Amiga audio channel 1, etc. In this way, a single |
||
− | Midi Note Number could simultaneously trigger a sound event on each of the 4 |
||
− | Amiga audio channels. If NumOfChans is 1, then the PlayMap is 128 bytes and |
||
− | each midi note has only 1 byte in the PlayMap. The first byte pertains to midi |
||
− | note #0, the second pertains to midi note #1, etc. In this case, a player |
||
− | program might elect to simply play back the PlayMap wave number on any |
||
− | available amiga audio channel. If NumOfChans = 0, then there is no imbedded |
||
− | PlayMap in the MHDR, no midi note assignments for the waves, and an application |
||
− | should play back waves on any channel at their default sampleRates. |
||
− | In effect, the purpose of the PlayMap array is to determine which (if any) |
||
− | waves are to be played back for each of the 128 possible Midi Note Numbers. |
||
− | Usually, the MHDR's NumOfChans will be set to 4 since the Amiga has 4 audio |
||
− | channels. For the rest of this document, the NumOfChans is assumed to be 4. |
||
− | As mentioned, there can be a total of 255 waves in a "SAMP" file, numbered |
||
− | from 1 to 255. A PlayMap wave number of 0 is reserved to indicate that NO WAVE |
||
− | number should be played back. Consider the following example: |
||
− | |||
− | The first 4 bytes of PlayMap are 1,3,0,200. |
||
− | |||
− | If a sample playing program receives (from the serial port or another task |
||
− | perhaps) Midi Note Number 0, the following should occur: |
||
− | |||
− | 1) The sampler plays back wave 1 on Amiga audio channel |
||
− | number 0 (because the first PlayMap byte is 1). |
||
− | 2) The sampler plays back wave 3 on Amiga audio channel |
||
− | number 1 (because the second PlayMap byte is 3). |
||
− | 3) The sampler does not effect Amiga audio channel 2 in |
||
− | any way (because the third PlayMap byte is a 0). |
||
− | 4) The sampler plays back wave 200 on Amiga audio channel |
||
− | number 4 (because the fourth PlayMap byte is 200). |
||
− | |||
− | (This assumes INDEPENDANT CHANNEL play MODE to be discussed later in this |
||
− | document.) |
||
− | |||
− | All four of the PlayMap bytes could even be the same wave number. This would |
||
− | cause that wave to be output of all 4 Amiga channels simultaneously. |
||
− | |||
− | NumOfWaves is simply the number of waves in the sound file. |
||
− | |||
− | Format is the number of significant bits in every sample of a wave. |
||
− | For example, if Format = 8, then this means that the sample data is an |
||
− | 8 bit format, and that every sample of the wave can be expressed by a single |
||
− | BYTE. (A 16 bit sample would need a WORD for every sample point). |
||
− | |||
− | Each bit of the Flags byte, when set, means the following: |
||
− | |||
− | Bit #0 - File continued on another disc. This might occur if the SAMP file |
||
− | was too large to fit on 1 floppy. The accepted practice (as incor- |
||
− | porated by Yamaha's TX sampler and Casio's FZ-1 for example) is to |
||
− | dump as much as possible onto one disc and set a flag to indicate |
||
− | that more is on another disc's file. The name of the files must |
||
− | be the related. The continuation file should have its own SAMP header |
||
− | MHDR, and BODY chunks. This file could even have its continuation |
||
− | bit set, etc. Never chop a sample wave in half. Always close the |
||
− | file on 1 disc after the last wave which can be completely saved. |
||
− | Resume with the next wave within the BODY of the continuation file. |
||
− | Also, the NumOfWaves in each file's BODY should be the number saved |
||
− | on that disc (not the total number in all combined disk files). |
||
− | See the end of this document for filename conventions. |
||
− | |||
− | In C, here is how the PlayMap is used when receiving a midi note-on event: |
||
− | |||
− | MapOffset = (UBYTE) MidiNoteNumber * numOfChans; |
||
− | /* MidiNoteNumber is the received note number (i.e. the second byte of a |
||
− | midi note-on event. numOfChans is from the SAMP MHDR. */ |
||
− | chan0waveNum = (UBYTE) playMap[MapOffset]; |
||
− | chan1waveNum = (UBYTE) playMap[MapOffset+1]; |
||
− | chan2waveNum = (UBYTE) playMap[MapOffset+2]; |
||
− | chan3waveNum = (UBYTE) playMap[MapOffset+3]; |
||
− | |||
− | if (chan0waveNum != 0) |
||
− | { /* get the pointer to wave #1's data, determine the values |
||
− | that need to be passed to the audio device, and play this |
||
− | wave on Amiga audio channel #0 (if INDEPENDANT PlayMode) */ |
||
− | } |
||
− | |||
− | /* do the same with the other 3 channel's wave numbers */ |
||
− | |||
− | In assembly, the "MHDR" structure looks like this: |
||
− | |||
− | CNOP 0,2 |
||
− | MHDR dc.b 'MHDR' |
||
− | sizeOfMHDR dc.l [this is 6 + (NumOfChans * 128) ] |
||
− | NumOfWaves dc.b [a byte count of the # of waves in the file] |
||
− | Format dc.b [a byte count of the # of significant bits in a sample point] |
||
− | Flags dc.b [bit mask] |
||
− | PlayMode dc.b [play MODE discussed later] |
||
− | NumOfChans dc.b [# of bytes per midi note for PlayMap] |
||
− | PlayMap ds.b [128 x NumOfChans bytes of initialized values] |
||
− | |||
− | and a received MidiNoteNumber is interpreted as follows: |
||
− | |||
− | moveq #0,d0 |
||
− | move.b MidiNoteNumber,d0 ;this is the received midi note # |
||
− | bmi.s Illegal_Number ;exit, as this is an illegal midi note # |
||
− | moveq #0,d1 |
||
− | move.b NumOfChans,d1 |
||
− | mulu.w d1,d0 ;MidiNoteNumber x NumOfChans |
||
− | lea PlayMap,a0 |
||
− | adda.l d0,a0 |
||
− | move.b (a0)+,chan0waveNum |
||
− | move.b (a0)+,chan1waveNum |
||
− | move.b (a0)+,chan2waveNum |
||
− | move.b (a0),chan3waveNum |
||
− | |||
− | tst.b chan0waveNum |
||
− | beq.s Chan1 |
||
− | ;Now get the address of this wave number's sample data, determine the |
||
− | ;values that need to be passed to the audio device, and output the wave's |
||
− | ;data on Amiga chan 0 (assuming INDEPENDANT PlayMode). |
||
− | |||
− | Chan1 tst.b chan1waveNum |
||
− | beq.s Chan2 |
||
− | ;do the same for the other wave numbers, etc. |
||
− | |||
− | |||
− | =====================THE "NAME" CHUNK========================= |
||
− | |||
− | #define ID_NAME MakeID('N','A','M','E') |
||
− | |||
− | If a NAME chunk is included in the file, then EVERY wave must have a name. |
||
− | Each name is NULL-terminated. The first name is for the first wave, and it |
||
− | is immediately followed by the second wave's name, etc. It is legal for a |
||
− | wave's name to be simply a NULL byte. For example, if a file contained 4 |
||
− | waves and a name chunk, the chunk might look like this: |
||
− | |||
− | CNOP 0,2 |
||
− | |||
− | Name dc.b 'NAME' |
||
− | sizeOfName dc.l 30 |
||
− | dc.b 'Snare Drum',0 ;wave 1 |
||
− | dc.b 'Piano 1',0 ;wave 2 |
||
− | dc.b 'Piano A4',0 ;wave 3 |
||
− | dc.b 0 ;wave 4 |
||
− | dc.b 0 |
||
− | |||
− | NAME chunks should ALWAYS be padded out to an even number of bytes. (Hence |
||
− | the extra NULL byte in this example). The chunk's size should ALWAYS be even |
||
− | consequently. DO NOT USE the typical IFF method of padding a chunk out to an |
||
− | even number of bytes, but allowing an odd number size in the header. |
||
− | |||
− | |||
− | ==============THE "BODY" CHUNK=============== |
||
− | |||
− | The "BODY" chunk is CONSIDERABLY different than the "8SVX" form. Like all |
||
− | chunks it has an ID. |
||
− | |||
− | #define ID_BODY MakeID('B','O','D','Y') |
||
− | |||
− | Every wave has an 80 byte waveHeader, followed by its data. The waveHeader |
||
− | structure is as follows: |
||
− | |||
− | typedef struct { |
||
− | ULONG WaveSize; /* total # of BYTES in the wave (MUST be even) */ |
||
− | UWORD MidiSampNum; /* ONLY USED for Midi Dumps */ |
||
− | UBYTE LoopType, /* ONLY USED for Midi Dumps */ |
||
− | InsType; /* Used for searching for a certain instrument */ |
||
− | ULONG Period, /* in nanoseconds at original pitch */ |
||
− | Rate, /* # of samples per second at original pitch */ |
||
− | LoopStart, /* an offset in BYTES (from the beginning of the |
||
− | of the wave) where the looping portion of the |
||
− | wave begins. Set to WaveSize if no loop. */ |
||
− | LoopEnd; /* an offset in BYTES (from the beginning of the |
||
− | of the wave) where the looping portion of the |
||
− | wave ends. Set to WaveSize if no loop. */ |
||
− | UBYTE RootNote, /* the Midi Note # that plays back original pitch */ |
||
− | VelStart; /* 0 = NO velocity effect, 128 = |
||
− | negative direction, 64 = positive |
||
− | direction (it must be one of these 3) */ |
||
− | UWORD VelTable[16]; /* contains 16 successive offset values |
||
− | in BYTES from the beginning of the wave */ |
||
− | |||
− | /* The ATAK and RLSE segments contain an EGPoint[] piece-wise |
||
− | linear envelope just like 8SVX. The structure of an EGPoint[] |
||
− | is the same as 8SVX. See that document for details. */ |
||
− | |||
− | ULONG ATAKsize, /* # of BYTES in subsequent ATAK envelope. |
||
− | If 0, then no ATAK data for this wave. */ |
||
− | RLSEsize, /* # of BYTES in subsequent RLSE envelope |
||
− | If 0, then no RLSE envelope follows */ |
||
− | |||
− | /* The FATK and FRLS segments contain an EGPoint[] piece-wise |
||
− | linear envelope for filtering purposes. This is included in |
||
− | the hope that future Amiga audio will incorporate a VCF |
||
− | (Voltage Controlled Filter). Until then, if you are doing any |
||
− | non-realtime digital filtering, you could store info here. */ |
||
− | |||
− | sizeOfFATK, /* # of BYTES in FATK segment */ |
||
− | sizeOfFRLS, /* # of BYTES in FRLS segment */ |
||
− | |||
− | USERsize; /* # of BYTES in the following data |
||
− | segment (not including USERtype). |
||
− | If zero, then no user data */ |
||
− | UWORD USERtype; /* See explanation below. If USERsize |
||
− | = 0, then ignore this. */ |
||
− | |||
− | /* End of the waveHeader. */ |
||
− | |||
− | /* The data for any ATAK, RLSE, FATK, FRLS, USER, and the actual wave |
||
− | data for wave #1 follows in this order: |
||
− | Now list each EGPoint[] (if any) for the VCA's (Voltage Controlled Amp) |
||
− | attack portion. |
||
− | Now list each EGPoint[] for the VCA's (Voltage Controlled Amp) |
||
− | release portion. |
||
− | List EGPoints[] (if any) for FATK. |
||
− | List EGPoints[] if any for FRLS */ |
||
− | Now include the user data here if there is any. Just pad it out |
||
− | to an even number of bytes and have USERsize reflect that. |
||
− | Finally, here is the actual sample data for the wave. The size (in BYTES) |
||
− | of this data is WaveSize. It MUST be padded out to an even number of bytes. */ |
||
− | |||
− | } WaveFormInfo; |
||
− | |||
− | /* END OF WAVE #1 */ |
||
− | |||
− | /* The waveHeader and data for the next wave would now follow. It is |
||
− | the same form as the first wave */ |
||
− | |||
− | |||
− | In assembly, the BODY chunk looks like this: |
||
− | |||
− | CNOP 0,2 |
||
− | BodyHEADER dc.b 'BODY' |
||
− | sizeOfBody dc.l [total bytes in the BODY chunk not counting 8 byte header] |
||
− | |||
− | ; Now for the first wave |
||
− | WaveSize dc.l ;[total # of BYTES in this wave (MUST be even)] |
||
− | MidiSampNum dc.w ;[from Midi Sample Dump] ; ONLY USED for Midi Dumps |
||
− | LoopType dc.b ;[0 or 1] ; ONLY USED for Midi Dumps |
||
− | InsType dc.b 0 |
||
− | Period dc.l ;[period in nanoseconds at original pitch] |
||
− | Rate dc.l ;[# of samples per second at original pitch] |
||
− | LoopStart dc.l ;[an offset in BYTES (from the beginning of the |
||
− | ; of the wave) to where the looping |
||
− | ; portion of the wave begins.] |
||
− | LoopEnd dc.l ;[an offset in BYTES (from the beginning of the |
||
− | ; of the wave) to where the looping |
||
− | ; portion of the wave ends] |
||
− | RootNote dc.b ;[the Midi Note # that plays back original pitch] |
||
− | VelStart dc.b ;[0, 64, or 128] |
||
− | VelTable dc.w ;[first velocity offset] |
||
− | dc.w ;[second velocity offset]...etc |
||
− | ds.w 14 ;...for a TOTAL of 16 velocity offsets |
||
− | |||
− | ATAKsize dc.l ;# of BYTES in subsequent ATAK envelope. |
||
− | ;If 0, then no ATAK data for this wave. |
||
− | RLSEsize dc.l ;# of BYTES in subsequent RLSE envelope |
||
− | ;If 0, then no RLSE data |
||
− | FATKsize dc.l ;# of BYTES in FATK segment |
||
− | FRLSsize dc.l ;# of BYTES in FRLS segment |
||
− | USERsize dc.l ;# of BYTES in the following User data |
||
− | ;segment (not including USERtype). |
||
− | ;If zero, then no user data |
||
− | USERtype dc.w ; See explanation below. If USERsize |
||
− | ; = 0, then ignore this. |
||
− | |||
− | ;Now include the EGpoints[] (data) for the ATAK if any |
||
− | ;Now the EGpoints for the RLSE |
||
− | ;Now the EGpoints for the FATK |
||
− | ;Now the EGpoints for the FLSR |
||
− | ;Now include the user data here if there is any. Just pad |
||
− | ;it out to an even number of bytes. |
||
− | ;After the userdata (if any) is the actual sample data for |
||
− | ;the wave. The size (in BYTES) of this segment is WaveSize. |
||
− | ;It MUST be padded out to an even number of bytes. |
||
− | |||
− | ; END OF WAVE #1 |
||
− | |||
− | |||
− | =============STRUCTURE OF AN INDIVIDUAL SAMPLE POINT============= |
||
− | |||
− | Even though the next generation of computers will probably have 16 bit |
||
− | audio, and 8 bit sampling will quickly disappear, this spec has sizes expressed |
||
− | in BYTES. (ie LoopStart, WaveSize, etc.) This is because each successive |
||
− | address in RAM is a byte to the 68000, and so calculating address offsets |
||
− | will be much easier with all sizes in BYTES. The Midi sample dump, on the |
||
− | other hand, has sizes expressed in WORDS. What this means is that if you |
||
− | have a 16 bit wave, for example, the WaveSize is the total number of BYTES, |
||
− | not WORDS, in the wave. |
||
− | Also, there is no facility for storing a compression type. This is because |
||
− | sample data should be stored in linear format (as per the MIDI spec). Currently, |
||
− | all music samplers, regardless of their internal method of playing sample data |
||
− | must transmit and expect to receive sample dumps in a linear format. It is |
||
− | up to each device to translate the linear format into its own compression |
||
− | scheme. For example, if you are using an 8 bit compression scheme that yields |
||
− | a 14 bit linear range, you should convert each sample data BYTE to a decom- |
||
− | pressed linear WORD when you save a sound file. Set the MHDR's Format |
||
− | to 14. It is up to the application to do its own compression upon loading |
||
− | a file. The midi spec was set up this way because musical samplers need to |
||
− | pass sample data between each other, and computers (via a midi interface). |
||
− | Since there are almost as many data compression schemes on the market as |
||
− | there are musical products, it was decided that all samplers should expect |
||
− | data received over midi to be in LINEAR format. It seems logical to store it |
||
− | this way on disc as well. Therefore, any software program "need not know" how |
||
− | to decompress another software program's SAMP file. When 16 bit sampling is |
||
− | eventually implemented there won't be much need for compression on playback |
||
− | anyway. The continuation Flag solves the problem of disc storage as well. |
||
− | Since the 68000 can only perform math on BYTES, WORDS, or LONGS, it has |
||
− | been decided that a sample point should be converted to one of these sizes |
||
− | when saved in SAMP as follows: |
||
− | |||
− | ORIGINAL significant bits SAMP sample point size |
||
− | |
||
− | 8 BYTE |
||
− | 9 to 16 WORD |
||
− | 17 to 28 LONG |
||
− | |||
− | Furthermore, the significant bits should be left-justified since it is |
||
− | easier to perform math on the samples. |
||
− | |||
− | So, for example, an 8 bit sample point (like 8SVX) would be saved as a |
||
− | BYTE with all 8 bits being significant. The MHDR's Format = 8. No |
||
− | conversion is necessary. |
||
− | |||
− | A 12 bit sample point should be stored as a WORD with the significant bits |
||
− | being numbers 4 to 15. (i.e shift the 12-bit WORD 4 places to the left). Bits |
||
− | 0, 1, 2 and 3 may be zero (unless some 16-bit math was performed and you wish to |
||
− | save these results). The MHDR's Format = 12. In this way, the sample |
||
− | may be loaded and manipulated as a 16-bit wave, but when transmitted via |
||
− | midi, it can be converted back to 12 bits (rounded and shifted right by 4). |
||
− | |||
− | A 16 bit sample point would be saved as a WORD with all 16 bits being |
||
− | significant. The MHDR's Format = 16. No conversion is necessary. |
||
− | |||
− | |||
− | ============== The waveHeader explained ============== |
||
− | |||
− | The WaveSize is, as stated, the number of BYTES in the wave's sample table. |
||
− | If your sample data consisted of the following 8 bit samples: |
||
− | |||
− | BYTE 100,-90,80,-60,30,35,40,-30,-35,-40,00,12,12,10 |
||
− | |||
− | then WaveSize = 14. (PAD THE DATA OUT TO AN EVEN NUMBER OF BYTES!) |
||
− | |||
− | The MidiSampNum is ONLY used to hold the sample number received from a MIDI |
||
− | Sample Dump. It has no bearing on where the wave should be placed in a SAMP |
||
− | file. Also, the wave numbers in the PlayMap are between 1 to 255, with 1 being |
||
− | the number of the first wave in the file. Remember that a wave number of 0 is |
||
− | reserved to mean "no wave to play back". Likewise, the LoopType is only used |
||
− | to hold info from a MIDI sample dump. |
||
− | |||
− | The InsType is explained at the end of this document. Often it will be set |
||
− | to 0. |
||
− | |||
− | The RootNote is the Midi Note number that will play the wave back at it's |
||
− | original, recorded pitch. For example, consider the following excerpt of a |
||
− | PlayMap: |
||
− | |||
− | PlayMap {2,0,0,4 /* Midi Note #0 channel assignment */ |
||
− | 4,100,1,0 /* Midi Note #1 " " */ |
||
− | 1,4,0,0 /* Midi Note #2 " " */ |
||
− | 60,2,1,1...} /* Midi Note #3 " " */ |
||
− | |||
− | Notice that Midi Notes 0, 1, and 2 are all set to play wave number 4 (on |
||
− | Amiga channels 3, 0, and 1 respectively). If we set wave 4's RootNote = 1, |
||
− | then receiving Midi Note number 1 would play back wave 4 (on Amiga channel 0) |
||
− | at it's original pitch. If we receive a Midi Note number 0, then wave 4 would |
||
− | be played back on channel 3) a half step lower than it's original pitch. If we |
||
− | receive Midi Note number 2, then wave 4 would be played (on channel 1) a half |
||
− | step higher than it's original pitch. If we receive Midi Note number 3, then |
||
− | wave 4 would not be played at all because it isn't specified in the PlayMap |
||
− | bytes for Midi Note number 3. |
||
− | |||
− | The Rate is the number of samples per second of the original pitch. |
||
− | For example, if Rate = 20000, then to play the wave at it's original |
||
− | pitch, the sampling period would be: |
||
− | |||
− | (1/20000)/.279365 = .000178977 |
||
− | |||
− | #define AUDIO_HARDWARE_FUDGE .279365 |
||
− | |||
− | where .279365 is the Amiga Fudge Factor (a hardware limitation). Since the |
||
− | amiga needs to see the period in terms of microseconds, move the decimal place |
||
− | to the right 6 places and our sampling period = 179 (rounded to an integer). |
||
− | In order to play the wave at higher or lower pitches, one would need to |
||
− | "transpose" this period value. By specifying a higher period value, the Amiga |
||
− | will play back the samples slower, and a lower pitch will be achieved. By |
||
− | specifying a lower period value, the amiga will play back the sample faster, |
||
− | and a higher pitch will be achieved. By specifying this exact period, the wave |
||
− | will be played back exactly "as it was recorded (sampled)". ("This period is |
||
− | JUST RIGHT!", exclaimed GoldiLocks.) Later, a method of transposing pitch will |
||
− | be shown using a "look up" table of periods. This should prove to be the |
||
− | fastest way to transpose pitch, though there is nothing in the SAMP format |
||
− | that compels you to do it this way. |
||
− | |||
− | The LoopStart is a BYTE offset from the beginning of the wave to where |
||
− | the looping portion of the wave begins. For example, if SampleData points to |
||
− | the start of the wave, then SampleData + LoopStart is the start address |
||
− | of the looping portion. In 8SVX, the looping portion was referred to as |
||
− | repeatHiSamples. The data from the start of the wave up to the start of the |
||
− | looping portion is the oneShot portion of the wave. LoopEnd is a BYTE |
||
− | offset from the beginning of the wave to where the looping portion ends. This |
||
− | might be the very end of the wave in memory, or perhaps there might be still |
||
− | more data after this point. You can choose to ignore this "trailing" data and |
||
− | play back the two other portions of the wave just like an 8SVX file (except |
||
− | that there are no other interpolated octaves of this wave). |
||
− | |||
− | VelTable contains 16 BYTE offsets from the beginning of the wave. Each |
||
− | successive value should be greater (or equal to) the preceding value. If |
||
− | VelStart = POSITIVE (64), then for each 8 increments in Midi Velocity |
||
− | above 0, you move UP in the table, add this offset to the wave's beginning |
||
− | address (start of oneShot), and start playback at that address. Here is a |
||
− | table relating received midi note-on velocity vs. start playback address for |
||
− | POSITIVE VelStart. SamplePtr points to the beginning of the sample. |
||
− | |||
− | If midi velocity = 0, then don't play a sample, this is a note off |
||
− | If midi velocity = 1 to 7, then start play at SamplePtr + VelTable[0] |
||
− | If midi velocity = 8 to 15, then start at SamplePtr + VelTable[1] |
||
− | If midi velocity = 16 to 23, then start at SamplePtr + VelTable[2] |
||
− | If midi velocity = 24 to 31, then start at SamplePtr + VelTable[3] |
||
− | If midi velocity = 32 to 39, then start at SamplePtr + VelTable[4] |
||
− | If midi velocity = 40 to 47, then start at SamplePtr + VelTable[5] |
||
− | If midi velocity = 48 to 55, then start at SamplePtr + VelTable[6] |
||
− | If midi velocity = 56 to 63, then start at SamplePtr + VelTable[7] |
||
− | If midi velocity = 64 to 71, then start at SamplePtr + VelTable[8] |
||
− | If midi velocity = 72 to 79, then start at SamplePtr + VelTable[9] |
||
− | If midi velocity = 80 to 87, then start at SamplePtr + VelTable[10] |
||
− | If midi velocity = 88 to 95, then start at SamplePtr + VelTable[11] |
||
− | If midi velocity = 96 to 103, then start at SamplePtr + VelTable[12] |
||
− | If midi velocity = 104 to 111, then start at SamplePtr + VelTable[13] |
||
− | If midi velocity = 112 to 119, then start at SamplePtr + VelTable[14] |
||
− | If midi velocity = 120 to 127, then start at SamplePtr + VelTable[15] |
||
− | |||
− | We don't want to specify a scale factor and use integer division to find the |
||
− | sample start. This would not only be slow, but also, it could never be certain |
||
− | that the resulting sample would be a zero crossing if the start point is calcu- |
||
− | lated "on the fly". The reason for having a table is so that the offsets can be |
||
− | be initially set on zero crossings via an editor. This way, no audio "clicks" |
||
− | guaranteed. This table should provide enough resolution. |
||
− | |||
− | If VelStart = NEGATIVE (128), then for each 8 increments in midi |
||
− | velocity, you start from the END of VelTable, and work backwards. Here |
||
− | is a table for NEGATIVE velocity start. |
||
− | |||
− | If midi velocity = 0, then don't play a sample, this is a note off |
||
− | If midi velocity = 1 to 7, then start play at SamplePtr + VelTable[15] |
||
− | If midi velocity = 8 to 15, then start at SamplePtr + VelTable[14] |
||
− | If midi velocity = 16 to 23, then start at SamplePtr + VelTable[13] |
||
− | If midi velocity = 24 to 31, then start at SamplePtr + VelTable[12] |
||
− | If midi velocity = 32 to 39, then start at SamplePtr + VelTable[11] |
||
− | If midi velocity = 40 to 47, then start at SamplePtr + VelTable[10] |
||
− | If midi velocity = 48 to 55, then start at SamplePtr + VelTable[9] |
||
− | If midi velocity = 56 to 63, then start at SamplePtr + VelTable[8] |
||
− | If midi velocity = 64 to 71, then start at SamplePtr + VelTable[7] |
||
− | If midi velocity = 72 to 81, then start at SamplePtr + VelTable[6] |
||
− | If midi velocity = 80 to 87, then start at SamplePtr + VelTable[5] |
||
− | If midi velocity = 88 to 95, then start at SamplePtr + VelTable[4] |
||
− | If midi velocity = 96 to 103, then start at SamplePtr + VelTable[3] |
||
− | If midi velocity = 104 to 111, then start at SamplePtr + VelTable[2] |
||
− | If midi velocity = 112 to 119, then start at SamplePtr + VelTable[1] |
||
− | If midi velocity = 120 to 127, then start at SamplePtr + VelTable[0] |
||
− | |||
− | In essence, increasing midi velocity starts playback "farther into" the wave |
||
− | for POSITIVE VelStart. Increasing midi velocity "brings the start point |
||
− | back" toward the beginning of the wave for NEGATIVE VelStart. |
||
− | |||
− | If VelStart is set to NONE (0), then the wave's playback start should |
||
− | not be affected by the table of offsets. |
||
− | |||
− | What is the use of this feature? As an example, when a snare drum is hit with |
||
− | a soft volume, its initial attack is less pronounced than when it is struck |
||
− | hard. You might record a snare being hit hard. By setting VelStart to a |
||
− | NEGATIVE value and setting up the offsets in the Table, a lower midi velocity |
||
− | will "skip" the beginning samples and thereby tend to soften the initial |
||
− | attack. In this way, one wave yields a true representation of its instrument |
||
− | throughout its volume range. Furthermore, stringed and plucked instruments |
||
− | (violins, guitars, pianos, etc) exhibit different attacks at different |
||
− | volumes. VelStart makes these kinds of waves more realistic via a software |
||
− | implementation. Also, an application program can allow the user to enable/ |
||
− | disable this feature. See the section "Making the Velocity Table" for info on |
||
− | how to best choose the 16 table values. |
||
− | |||
− | |||
− | =========MIDI VELOCITY vs. AMIGA CHANNEL VOLUME============ |
||
− | |||
− | The legal range for Midi Velocity bytes is 0 to 127. (A midi velocity of 0 |
||
− | should ALWAYS be interpreted as a note off). |
||
− | |||
− | The legal range for Amiga channel volume is 0 to 64. Since this is half of |
||
− | the midi range, a received midi velocity should be divided by 2 and add 1 |
||
− | (but only AFTER checking for a received midi velocity of 0). |
||
− | |||
− | An example of how to implement a received midi velocity in C: |
||
− | |||
− | If ( ReceivedVelocity != 0 && ReceivedVelocity < 128 ) |
||
− | { /* the velocity byte of a midi message */ |
||
− | If (velStart != 0) |
||
− | { |
||
− | tableEntry = ReceivedVelocity / 8; |
||
− | If (velStart == 64) |
||
− | { /* Is it POSITIVE */ |
||
− | startOfWave = SamplePtr + velTable[tableEntry]; |
||
− | /* ^where to find the sample start point */ |
||
− | } |
||
− | If (velStart == 128) |
||
− | { /* Is it NEGATIVE */ |
||
− | startOfWave = SamplePtr + velTable[15 - tableEntry]; |
||
− | } |
||
− | volume = (receivedVelocity/2 + 1; /* playback volume */ |
||
− | /* Now playback the wave */ |
||
− | } |
||
− | } |
||
− | |||
− | In assembly, |
||
− | |||
− | lea SampleData,a0 ;the start addr of the sample data |
||
− | moveq #0,d0 |
||
− | move.b ReceivedVelocity,d0 ;the velocity byte of a midi message |
||
− | beq A_NoteOff ;If zero, branch to a routine to |
||
− | ;process a note-off message. |
||
− | |||
− | bmi Illegal_Vol ;exit if received velocity > 127 |
||
− | ;---Check for velocity start feature ON, and direction |
||
− | move.b VelStart,d1 |
||
− | beq.s Volume ;skip the velocity offset routine if 0 |
||
− | bmi.s NegativeVel ;is it NEGATIVE? (128) |
||
− | |||
− | ;---Positive velocity offset |
||
− | move.l d0,d1 ;duplicate velocity |
||
− | lsr.b #3,d1 ;divide by 8 |
||
− | add.b d1,d1 ;x 2 because we need to fetch a word |
||
− | lea VelTable,a1 ;start at table's HEAD |
||
− | adda.l d1,a1 ;go forward |
||
− | move.w (a1),d1 ;get the velocity offet |
||
− | adda.l d1,a0 ;where to start actual playback |
||
− | bra.s Volume |
||
− | |||
− | NegativeVel: |
||
− | ;---Negative velocity offset |
||
− | move.l d0,d1 ;duplicate velocity |
||
− | lsr.b #3,d1 ;divide by 8 |
||
− | add.b d1,d1 ;x 2 because we need to fetch a word |
||
− | lea VelTable+30,a1 ;start at table's END |
||
− | suba.l d1,a1 ;go backwards |
||
− | move.w (a1),d1 ;get the velocity offset |
||
− | adda.l d1,a0 ;where to start actual playback |
||
− | |||
− | ;---Convert Midi velocity to an Amiga volume |
||
− | Volume lsr.b #1,d0 ;divide by 2 |
||
− | addq.b #1,d0 ;an equivalent Amiga volume |
||
− | |||
− | ;---Now a0 and d0 are the address of sample start, and volume |
||
− | |||
− | |||
− | ================= AN EGpoint (envelope generator) ================ |
||
− | |||
− | A single EGpoint is a 6 byte structure as follows: |
||
− | |||
− | EGpoint1: dc.w ;[the duration in milliseconds] |
||
− | dc.l ;[the volume factor - fixed point, 16 bits to the left of the |
||
− | ;decimal point and 16 to the right.] |
||
− | |||
− | The volume factor is a fixed point where 1.0 ($00010000) represents the |
||
− | MAXIMUM volume possible. (i.e. No volume factor should exceed this value.) |
||
− | The last EGpoint in the ATAK is always the sustain point. Each EG's volume |
||
− | is determined from 0.0, not as a difference from the previous EG's volume. |
||
− | I hope that this clears up the ambiguity in the original 8SVX document. |
||
− | So, to recreate an amplifier envelope like this: |
||
− | |||
− | /\ |
||
− | / \____ |
||
− | / \ |
||
− | / \ |
||
− | |||
− | | | | | | |
||
− | 1 2 3 4 |
||
− | |||
− | Stages 1, 2, and 3 would be in the ATAK data, like so: |
||
− | |||
− | ;Stage 1 |
||
− | dc.w 100 ;take 100ms |
||
− | dc.l $00004000 ;go to this volume |
||
− | dc.w 100 |
||
− | dc.l $00008000 |
||
− | dc.w 100 |
||
− | dc.l $0000C000 |
||
− | dc.w 100 |
||
− | dc.l $00010000 ;the "peak" of our attack is full volume |
||
− | ;Stage 2 |
||
− | dc.w 100 |
||
− | dc.l $0000C000 ;back off to this level |
||
− | dc.l 100 |
||
− | dc.l $00008000 ;this is where we hold (SUSTAIN) until the note is turned |
||
− | ;off. (We are now holding at stage 3) |
||
− | |||
− | Now the RLSE data would specify stage 4 as follows: |
||
− | dc.w 100 |
||
− | dc.l $00004000 |
||
− | dc.w 100 |
||
− | dc.l $00000000 ;the volume is 0 |
||
− | |||
− | |||
− | ===============ADDITIONAL USER DATA SECTION================= |
||
− | |||
− | There is a provision for storing user data for each wave. This is where an |
||
− | application can store Amiga hardware info, or other, application specific info. |
||
− | The waveHeader's USERtype tells what kind of data is stored. The current |
||
− | types are: |
||
− | |||
− | #define SPECIFIC 0 |
||
− | #define VOLMOD 1 |
||
− | #define PERMOD 2 |
||
− | #define LOOPING 3 |
||
− | |||
− | SPECIFIC (0) - application specific data. It should be stored |
||
− | in a format that some application can immediately |
||
− | recognize. (i.e. a "format within" the SAMP format) |
||
− | If the USERtype is SPECIFIC, and an application |
||
− | doesn't find some sort of header that it can re- |
||
− | cognize, it should conclude that this data was |
||
− | put there by "someone else", and ignore the data. |
||
− | |||
− | VOLMOD (1) - This data is for volume modulation of an Amiga |
||
− | channel as described by the ADKCON register. This |
||
− | data will be sent to the modulator channel of the |
||
− | channel set to play the wave. |
||
− | |||
− | PERMOD (2) - This data is for period modulation of an Amiga |
||
− | channel as described by the ADKCON register. This |
||
− | data will be sent to the modulator channel of the |
||
− | channel set to play the wave. |
||
− | |||
− | LOOPING (3) - This contains more looping points for the sample. |
||
− | There are some samplers that allow more than just |
||
− | one loop (Casio products primarily). Additional |
||
− | looping info can be stored in this format: |
||
− | |||
− | UWORD numOfLoops; /* number of loop points to follow */ |
||
− | |||
− | ULONG StartLoop1, /* BYTE offset from the beginning of |
||
− | the sample to the start of loop1 */ |
||
− | EndLoop1, /* BYTE offset from the beginning of |
||
− | the sample to the end of loop1 */ |
||
− | |||
− | StartLoop2, /* ...etc */ |
||
− | |||
− | |||
− | =========Converting Midi Sample Dump to SAMP========= |
||
− | |||
− | SEMANTICS: When MIDI literature talks about a sample, usually it means a |
||
− | collection of many sample points that make up what we call "a wave". |
||
− | Therefore, a Midi Sample Dump sends all the sample data that makes up ONE |
||
− | wave. A SAMP file is designed to hold up to 255 of these waves (midi dumps). |
||
− | |||
− | The Midi Sample Dump specifies playback rate only in terms of a sample |
||
− | PERIOD in nanoseconds. SAMP also expresses playback in terms of samples per |
||
− | second (frequency). The Amiga needs to see its period rounded to the nearest |
||
− | microsecond. If you take the sample period field of a Midi sample Dump (the |
||
− | 8th, 9th, and 10th bytes of the Dump Header LSB first) which we will call |
||
− | MidiSamplePer, and the Rate of a SAMP file, here is the relationship: |
||
− | |||
− | Rate = (1/MidiSamplePer) x 10E9 |
||
− | |||
− | Also the number of samples (wave's length) in a Midi Sample Dump (the 11th, |
||
− | 12th, and 13th bytes of the Dump header) is expressed in WORDS. SAMP's |
||
− | WaveSize is expressed in the number of BYTES. (For the incredibly stupid), |
||
− | the relationship is: |
||
− | |||
− | WaveSize = MidiSampleLength x 2 |
||
− | |||
− | A Midi sample dump's LoopStart point and LoopEnd point are also in WORDS as |
||
− | versus the SAMP equivalents expressed in BYTES. |
||
− | |||
− | A Midi sample dump's sample number can be 0 to 65535. A SAMP file can hold |
||
− | up to 255 waves, and their numbers in the playmap must be 1 to 255. (A single, |
||
− | Midi Sample Dump only sends info on one wave.) When recieving a Midi Sample |
||
− | Dump, just store the sample number (5th and 6th bytes of the Dump Header LSB |
||
− | first) in SAMP's MidiSampNum field. Then forget about this number until you |
||
− | need to send the wave back to the Midi instrument from whence it came. |
||
− | |||
− | A Midi Dump's loop type can be forward, or forward/backward. Amiga hardware |
||
− | supports forward only. You should store the Midi Dump's LoopType byte here, |
||
− | but ignore it otherwise until/unless Amiga hardware supports "reading audio |
||
− | data" in various ways. If so, then the looptype is as follows: |
||
− | |||
− | forward = 0, backward/forward = 1 |
||
− | |||
− | A Midi Dump's sample format byte is the same as SAMP's. |
||
− | |||
− | |||
− | ===================== INTERPRETING THE PLAYMODE ========================== |
||
− | |||
− | PlayMode specifies how the bytes in the PlayMap are to be interpreted. |
||
− | Remember that a PlayMap byte of 0 means "No Wave to Play". |
||
− | |||
− | #define INDEPENDANT 0 |
||
− | #define MULTI 1 |
||
− | #define STEREO 2 |
||
− | #define PAN 3 |
||
− | |||
− | PlayMode types: |
||
− | |||
− | INDEPENDANT (0) - The wave #s for a midi note are to be output on |
||
− | Amiga audio channels 0, 1, 2, and 3 respectively. |
||
− | If the NumOfChans is < 4, then only use that many channels. |
||
− | |||
− | MULTI (1) - The first wave # (first of the PlayMap bytes) for a |
||
− | midi note is to be output on any free channel. The other |
||
− | wave numbers are ignored. If all four channels are in |
||
− | play, the application can decide whether to "steal" a |
||
− | channel. |
||
− | |||
− | STEREO (2) - The first wave # (first of the PlayMap bytes) is to be |
||
− | output of the Left stereo jack (channel 1 or 3) and if |
||
− | there is a second wave number (the second of the PlayMap |
||
− | bytes), it is to be output the Right jack (channel 2 or 4). |
||
− | The other wave numbers are ignored. |
||
− | |||
− | PAN (3) - This is just like STEREO except that the volume of wave 1 |
||
− | should start at its initial volume (midi velocity) and |
||
− | fade to 0. At the same rate, wave 2 should start at 0 |
||
− | volume and rise to wave #1's initial level. The net |
||
− | effect is that the waves "cross" from Left to Right in |
||
− | the stereo field. This is most effective when the wave |
||
− | numbers are the same. (ie the same wave) The application |
||
− | program should set the rate. Also, the application can |
||
− | reverse the stereo direction (ie Right to Left fade). |
||
− | |||
− | The most important wave # to be played back by a midi note should be the |
||
− | first of the PlayMap bytes. If the NumOfChans > 1, the second PlayMap byte |
||
− | should be a defined wave number as well (even if it is deliberately set to the |
||
− | same value as the first byte). This insures that all 4 PlayModes will have some |
||
− | effect on a given SAMP file. Also, an application should allow the user to |
||
− | change the PlayMode at will. The PlayMode stored in the SAMP file is only a |
||
− | default or initial set-up condition. |
||
− | |||
− | |||
− | =================== MAKING A TRANSPOSE TABLE ===================== |
||
− | |||
− | In order to allow a wave to playback over a range of musical notes, (+/- |
||
− | semitones), its playback rate must be raised or lowered by a set amount. |
||
− | From one semitone to the next, this set amount is by a factor of the 12th |
||
− | root of 2 (assuming a western, equal-tempered scale). Here is a table that |
||
− | shows what factor would need to be multiplied by the sampling rate in order |
||
− | to transpose the wave's pitch. |
||
− | |||
− | Pitch in relation to the Root Multiply Rate by this amount |
||
− | ------------------------------- ------------------------------ |
||
− | DOWN 6 semitones 0.5 |
||
− | DOWN 5 1/2 semitones 0.529731547 |
||
− | DOWN 5 semitones 0.561231024 |
||
− | DOWN 4 1/2 semitones 0.594603557 |
||
− | DOWN 4 semitones 0.629960525 |
||
− | DOWN 3 1/2 semitones 0.667419927 |
||
− | DOWN 3 semitones 0.707106781 |
||
− | DOWN 2 1/2 semitones 0.749153538 |
||
− | DOWN 2 semitones 0.793700526 |
||
− | DOWN 1 1/2 semitones 0.840896415 |
||
− | DOWN 1 semitones 0.890898718 |
||
− | DOWN 1/2 semitone 0.943874312 |
||
− | ORIGINAL_PITCH 1.0 /* rootnote's pitch */ |
||
− | UP 1/2 semitone 1.059463094 |
||
− | UP 1 semitones 1.122562048 |
||
− | UP 1 1/2 semitones 1.189207115 |
||
− | UP 2 semitones 1.259921050 |
||
− | UP 2 1/2 semitones 1.334839854 |
||
− | UP 3 semitones 1.414213562 |
||
− | UP 3 1/2 semitones 1.498307077 |
||
− | UP 4 semitones 1.587401052 |
||
− | UP 4 1/2 semitones 1.681792830 |
||
− | UP 5 semitones 1.781797436 |
||
− | UP 5 1/2 semitones 1.887748625 |
||
− | UP 6 semitones 2 |
||
− | |||
− | For example, if the wave's Rate is 18000 hz, and you wish to play |
||
− | the wave UP 1 semitone, then the playback rate is: |
||
− | |||
− | 18000 x 1.122562048 = 20206.11686 hz |
||
− | |||
− | The sampling period for the Amiga is therefore: |
||
− | |||
− | (1/20206.11686)/.279365 = .000177151 |
||
− | |||
− | and to send it to the Audio Device, it is rounded and expressed in micro- |
||
− | seconds: 177 |
||
− | |||
− | Obviously, this involves floating point math which can be time consuming |
||
− | and impractical for outputing sound in real-time. A better method is to con- |
||
− | struct a transpose table that contains the actual periods already calculated |
||
− | for every semitone. The drawback of this method is that you need a table for |
||
− | EVERY DIFFERENT Rate in the SAMP file. If all the Rates in the |
||
− | file happened to be the same, then only one table would be needed. Let's |
||
− | assume that this is the case, and that the Rate = 18000 hz. Here is a |
||
− | table containing enough entries to transpose the waves +/- 6 semitones. |
||
− | |||
− | Pitch in relation to the Root The Amiga Period (assuming rate = 18000 hz) |
||
− | ------------------------------- ------------------------------ |
||
− | Transposition_table[TRANS_TABLE_SIZE]={ |
||
− | /* DOWN 6 semitones */ 398, |
||
− | /* DOWN 5 1/2 semitones */ 375, |
||
− | /* DOWN 5 semitones */ 354, |
||
− | /* DOWN 4 1/2 semitones */ 334, |
||
− | /* DOWN 4 semitones */ 316, |
||
− | /* DOWN 3 1/2 semitones */ 298, |
||
− | /* DOWN 3 semitones */ 281, |
||
− | /* DOWN 2 1/2 semitones */ 265, |
||
− | /* DOWN 2 semitones */ 251, |
||
− | /* DOWN 1 1/2 semitones */ 236, |
||
− | /* DOWN 1 semitones */ 223, |
||
− | /* DOWN 1/2 semitone */ 211, |
||
− | /* ORIGINAL_PITCH */ 199, /* rootnote's pitch */ |
||
− | /* UP 1/2 semitone */ 187, |
||
− | /* UP 1 semitones */ 177, |
||
− | /* UP 1 1/2 semitones */ 167, |
||
− | /* UP 2 semitones */ 157, |
||
− | /* UP 2 1/2 semitones */ 148, |
||
− | /* UP 3 semitones */ 141, |
||
− | /* UP 3 1/2 semitones */ 133, |
||
− | /* Since the minimum Amiga period = 127 the following |
||
− | are actually out of range. */ |
||
− | /* UP 4 semitones */ 125, |
||
− | /* UP 4 1/2 semitones */ 118, |
||
− | /* UP 5 semitones */ 112, |
||
− | /* UP 5 1/2 semitones */ 105, |
||
− | /* UP 6 semitones */ 99 }; |
||
− | |||
− | |||
− | Let's assume that (according to the PlayMap) midi note #40 is set to play |
||
− | wave number 3. Upon examining wave 3's structure, we discover that the |
||
− | Rate = 18000, and the RootNote = 38. Here is how the Amiga sampling |
||
− | period is calulated using the above 18000hz "transpose chart" in C: |
||
− | /* MidiNoteNumber is the received midi note's number (here 40) */ |
||
− | |||
− | #define ORIGINAL_PITCH TRANS_TABLE_SIZE/2 + 1 |
||
− | /* TRANS_TABLE_SIZE is the number of entries in the transposition table |
||
− | (dynamic, ie this can change with the application) */ |
||
− | |||
− | transposeAmount = (LONG) (MidiNoteNumber - rootNote); /* make it a SIGNED LONG */ |
||
− | amigaPeriod = Transposition_table[ORIGINAL_PITCH + transposeAmount]; |
||
− | |||
− | |||
− | In assembly, the 18000hz transpose chart and above example would be: |
||
− | |||
− | Table dc.w 398 |
||
− | dc.w 375 |
||
− | dc.w 354 |
||
− | dc.w 334 |
||
− | dc.w 316 |
||
− | dc.w 298 |
||
− | dc.w 281 |
||
− | dc.w 265 |
||
− | dc.w 251 |
||
− | dc.w 236 |
||
− | dc.w 223 |
||
− | dc.w 211 |
||
− | ORIGINAL_PITCH dc.w 199 ; rootnote's pitch |
||
− | dc.w 187 |
||
− | dc.w 177 |
||
− | dc.w 167 |
||
− | dc.w 157 |
||
− | dc.w 148 |
||
− | dc.w 141 |
||
− | dc.w 133 |
||
− | ; Since the minimum Amiga period = 127, the following |
||
− | ; are actually out of range. |
||
− | dc.w 125 |
||
− | dc.w 118 |
||
− | dc.w 112 |
||
− | dc.w 105 |
||
− | dc.w 99 |
||
− | |||
− | lea ORIGINAL_PITCH,a0 |
||
− | move.b MidiNoteNumber,d0 ;the received note number |
||
− | sub.b RootNote,d0 ;subtract the wave's root note |
||
− | ext.w d0 |
||
− | ext.l d0 ;make it a signed LONG |
||
− | add.l d0,d0 ;x 2 in order to fetch a WORD |
||
− | adda.l d0,a0 |
||
− | move.w (a0),d0 ;the Amiga Period (WORD) |
||
− | |||
− | Note that these examples don't check to see if the transpose amount is |
||
− | beyond the number of entries in the transpose table. Nor do they check if |
||
− | the periods in the table are out of range of the Amiga hardware. |
||
− | |||
− | |||
− | ===================== MAKING THE VELOCITY TABLE ====================== |
||
− | |||
− | The 16 entries in the velocity table should be within the oneShot portion of |
||
− | the sample (ie not in the looping portion). THe first offset, VelTable[0] |
||
− | should be set to zero (in order to play back from the beginning of the data). |
||
− | The subsequent values should be increasing numbers. If you are using a graphic |
||
− | editor, try choosing offsets that will keep you within the initial attack |
||
− | portion of the wave. In practice, these values will be relatively close |
||
− | together within the wave. Always set the offsets so that when they are added |
||
− | to the sample start point, the resulting address points to a sample value of |
||
− | zero (a zero crossing point). This will eliminate pops and clicks at the |
||
− | beginning of the playback. |
||
− | |||
− | In addition, the start of the wave should be on a sample with a value of |
||
− | zero. The last sample of the oneShot portion and the first sample of the |
||
− | looping portion should be approximately equal, (or zero points). The same is |
||
− | true of the first and last samples of the looping portion. Finally, try to |
||
− | keep the slopes of the end of the oneShot, the beginning of the looping, and |
||
− | the end of the looping section, approximately equal. All this will eliminate |
||
− | noise on the audio output and provide "seamless" looping. |
||
− | |||
− | |||
− | ======================== THE INSTRUMENT TYPE ========================== |
||
− | |||
− | Many SMUS players search for certain instruments by name. Not only is this |
||
− | slow (comparing strings), but if the exact name can't be found, then it is |
||
− | very difficult and time-consuming to search for a suitable replacement. For |
||
− | this reason, many SMUS players resort to "default" instruments even if these |
||
− | are nothing like the desired instruments. The InsType byte in each |
||
− | waveHeader is meant to be a numeric code which will tell an SMUS player |
||
− | exactly what the instrument is. In this way, the SMUS player can search for |
||
− | the correct "type" of instrument if it can't find the desired name. The type |
||
− | byte is divided into 2 nibbles (4 bits for you C programmers) with the low |
||
− | 4 bits representing the instrument "family" as follows: |
||
− | |||
− | 1 = STRING, 2 = WOODWIND, 3 = KEYBOARD, 4 = GUITAR, 5 = VOICE, 6 = DRUM1, |
||
− | 7 = DRUM2, 8 = PERCUSSION1, 9 = BRASS1, A = BRASS2, B = CYMBAL, C = EFFECT1, |
||
− | D = EFFECT2, E = SYNTH, F is undefined at this time |
||
− | |||
− | Now, the high nibble describes the particular type within that family. |
||
− | |||
− | For the STRING family, the high nibble is as follows: |
||
− | |||
− | 1 = VIOLIN BOW, 2 = VIOLIN PLUCK, 3 = VIOLIN GLISSANDO, 4 = VIOLIN TREMULO, |
||
− | 5 = VIOLA BOW, 6 = VIOLA PLUCK, 7 = VIOLA GLIS, 8 = VIOLA TREM, 9 = CELLO |
||
− | BOW, A = CELLO PLUCK, B = CELLO GLIS, C = CELLO TREM, D = BASS BOW, E = |
||
− | BASS PLUCK (jazz bass), F = BASS TREM |
||
− | |||
− | For the BRASS1 family, the high nibble is as follows: |
||
− | |||
− | 1 = BARITONE SAX, 2 = BARI GROWL, 3 = TENOR SAX, 4 = TENOR GROWL, 5 = ALTO |
||
− | SAX, 6 = ALTO GROWL, 7 = SOPRANO SAX, 8 = SOPRANO GROWL, 9 = TRUMPET, A = |
||
− | MUTED TRUMPET, B = TRUMPET DROP, C = TROMBONE, D = TROMBONE SLIDE, E = |
||
− | TROMBONE MUTE |
||
− | |||
− | For the BRASS2 family, the high nibble is as follows: |
||
− | |||
− | 1 = FRENCH HORN, 2 = TUBA, 3 = FLUGAL HORN, 4 = ENGLISH HORN |
||
− | |||
− | For the WOODWIND family, the high nibble is as follows: |
||
− | |||
− | 1 = CLARINET, 2 = FLUTE, 3 = PAN FLUTE, 4 = OBOE, 5 = PICCOLO, 6 = RECORDER, |
||
− | 7 = BASSOON, 8 = BASS CLARINET, 9 = HARMONICA |
||
− | |||
− | For the KEYBOARD family, the high nibble is as follows: |
||
− | |||
− | 1 = GRAND PIANO, 2 = ELEC. PIANO, 3 = HONKYTONK PIANO, 4 = TOY PIANO, 5 = |
||
− | HARPSICHORD, 6 = CLAVINET, 7 = PIPE ORGAN, 8 = HAMMOND B-3, 9 = FARFISA |
||
− | ORGAN, A = HARP |
||
− | |||
− | For the DRUM1 family, the high nibble is as follows: |
||
− | |||
− | 1 = KICK, 2 = SNARE, 3 = TOM, 4 = TIMBALES, 5 = CONGA HIT, 6 = CONGA SLAP, |
||
− | 7 = BRUSH SNARE, 8 = ELEC SNARE, 9 = ELEC KICK, A = ELEC TOM, B = RIMSHOT, |
||
− | C = CROSS STICK, D = BONGO, E = STEEL DRUM, F = DOUBLE TOM |
||
− | |||
− | For the DRUM2 family, the high nibble is as follows: |
||
− | |||
− | 1 = TIMPANI, 2 = TIMPANI ROLL, 3 = LOG DRUM |
||
− | |||
− | For the PERCUSSION1 family, the high nibble is as follows: |
||
− | |||
− | 1 = BLOCK, 2 = COWBELL, 3 = TRIANGLE, 4 = TAMBOURINE, 5 = WHISTLE, 6 = |
||
− | MARACAS, 7 = BELL, 8 = VIBES, 9 = MARIMBA, A = XYLOPHONE, B = TUBULAR BELLS, |
||
− | C = GLOCKENSPEIL |
||
− | |||
− | For the CYMBAL family, the high nibble is as follows: |
||
− | |||
− | 1 = CLOSED HIHAT, 2 = OPEN HIHAT, 3 = STEP HIHAT, 4 = RIDE, 5 = BELL CYMBAL, |
||
− | 6 = CRASH, 7 = CHOKE CRASH, 8 = GONG, 9 = BELL TREE, A = CYMBAL ROLL |
||
− | |||
− | For the GUITAR family, the high nibble is as follows: |
||
− | |||
− | 1 = ELECTRIC, 2 = MUTED ELECTRIC, 3 = DISTORTED, 4 = ACOUSTIC, 5 = 12-STRING, |
||
− | 6 = NYLON STRING, 7 = POWER CHORD, 8 = HARMONICS, 9 = CHORD STRUM, A = BANJO, |
||
− | B = ELEC. BASS, C = SLAPPED BASS, D = POPPED BASS, E = SITAR, F = MANDOLIN |
||
− | (Note that an acoustic picked bass is found in the STRINGS - Bass Pluck) |
||
− | |||
− | For the VOICE family, the high nibble is as follows: |
||
− | |||
− | 1 = MALE AHH, 2 = FEMALE AHH, 3 = MALE OOO, 4 = FEMALE OOO, 5 = FEMALE |
||
− | BREATHY, 6 = LAUGH, 7 = WHISTLE |
||
− | |||
− | For the EFFECTS1 family, the high nibble is as follows: |
||
− | |||
− | 1 = EXPLOSION, 2 = GUNSHOT, 3 = CREAKING DOOR OPEN, 4 = DOOR SLAM, 5 = DOOR |
||
− | CLOSE, 6 = SPACEGUN, 7 = JET ENGINE, 8 = PROPELLER, 9 = HELOCOPTER, A = |
||
− | BROKEN GLASS, B = THUNDER, C = RAIN, D = BIRDS, E = JUNGLE NOISES, F = |
||
− | FOOTSTEP |
||
− | |||
− | For the EFFECTS2 family, the high nibble is as follows: |
||
− | |||
− | 1 = MACHINE GUN, 2 = TELEPHONE, 3 = DOG BARK, 4 = DOG GROWL, 5 = BOAT |
||
− | WHISTLE, 6 = OCEAN, 7 = WIND, 8 = CROWD BOOS, 9 = APPLAUSE, A = ROARING |
||
− | CROWDS, B = SCREAM, C = SWORD CLASH, D = AVALANCE, E = BOUNCING BALL, |
||
− | F = BALL AGAINST BAT OR CLUB |
||
− | |||
− | For the SYNTH family, the high nibble is as follows: |
||
− | |||
− | 1 = STRINGS, 2 = SQUARE, 3 = SAWTOOTH, 4 = TRIANGLE, 5 = SINE, 6 = NOISE |
||
− | |||
− | So, for example if a wave's type byte was 0x26, this would be a SNARE DRUM. |
||
− | If a wave's type byte is 0, then this means "UNKNOWN" instrument. |
||
− | |||
− | |||
− | ===================== THE ORDER OF THE CHUNKS ========================= |
||
− | |||
− | The SAMP header obviously must be first in the file, followed by the MHDR |
||
− | chunk. After this, the ANNO, (c), AUTH and NAME chunks may follow in any |
||
− | order, though none of these need appear in the file at all. The BODY chunk |
||
− | must be last. |
||
− | |||
− | |||
− | ================= FILENAME CONVENTIONS ================= |
||
− | |||
− | For when it becomes necessary to split a SAMP file between floppies using |
||
− | the Continuation feature, the filenames should be related. The method is the |
||
− | following: |
||
− | |||
− | The "root" file has the name that the user chose to save under. Subsequent |
||
− | files have an ascii number appended to the name to indicate what sublevel the |
||
− | file is in. In this way, a program can reload the files in the proper order. |
||
− | |||
− | For example, if a user saved a file called "Gurgle", the first continuation |
||
− | file should be named "Gurgle1", etc. |
||
− | |||
− | |||
− | ============ WHY DOES ANYONE NEED SUCH A COMPLICATED FILE? ============== |
||
− | (or "What's wrong with 8SVX anyway?") |
||
− | |||
− | In a nutshell, 8SVX is not adequate for professional music sampling. First |
||
− | of all, it is nearly impossible to use multi-sampling (utilizing several, |
||
− | different samples of any instrument throughout its musical range). This very |
||
− | reason alone makes it impossible to realistically reproduce a musical in- |
||
− | strument, as none in existance (aside from an electronic organ) uses inter- |
||
− | polations of a single wave to create its musical note range. |
||
− | Also, stretching a sample out over an entire octave range does grotesque |
||
− | (and VERY unmusical) things to such elements as the overtone structure, |
||
− | wind/percussive noises, the instrument's amplitude envelope, etc. The 8SVX |
||
− | format is designed to stretch the playback in exactly this manner. |
||
− | 8SVX ignores MIDI which is the de facto standard of musical data transmission. |
||
− | 8SVX does not allow storing data for features that are commonplace to pro- |
||
− | fessional music samplers. Such features are: velocity sample start, separate |
||
− | filter and envelopes for each sample, separate sampling rates, and various |
||
− | playback modes like stereo sampling and panning. |
||
− | SAMP attempts to remedy all of these problems with a format that can be |
||
− | used by a program that simulates these professional features in software. The |
||
− | format was inspired by the capabilities of the following musical products: |
||
− | |||
− | EMU's EMAX, EMULATOR |
||
− | SEQUENTIAL CIRCUIT's PROPHET 2000, STUDIO 440 |
||
− | ENSONIQ's MIRAGE |
||
− | CASIO's FZ-1 |
||
− | OBERHEIM's DPX |
||
− | YAMAHA TX series |
||
− | |||
− | So why does the Amiga need the SAMP format? Because professional musician's |
||
− | are buying computers. With the firm establishment of MIDI, musician's are |
||
− | buying and using a variety of sequencers, patch editors, and scoring programs. |
||
− | It is now common knowledge amoung professional musicians that the Amiga |
||
− | lags far behind IBM clones, Macintosh, and Atari ST computers in both music |
||
− | software and hardware support. It is important for music software to exploit whatever capabili- |
||
− | ties the Amiga offers before the paint and animation programs, genlocks, |
||
− | frame-grabbers, and video breadboxes are the only applications selling |
||
− | for the Amiga. Hopefully, this format, with the SAMP disk I/O library will |
||
− | make it possible for Amiga software to attain the level of professionalism |
||
− | that the other machines now boast, and the Amiga lacks.</pre> |
||
− | |||
− | === 3-D rendering data === |
||
− | |||
− | <pre>FORM TDDD is used by Impulse's Turbo Silver 3.0 for 3D rendering |
||
− | data. TDDD stands for "3D data description". The files contain |
||
− | object and (optionally) observer data. |
||
− | |||
− | Turbo Silver's successor, "Imagine", uses an upgraded FORM TDDD |
||
− | when it reads/writes object data. |
||
− | |||
− | Currently, in "standard IFF" terms, a FORM TDDD has only two chunk |
||
− | types: an INFO chunk describing observer data; and an OBJ chunk |
||
− | describing an object heirarchy. The INFO chunk appears only in |
||
− | Turbo Silver's "cell" files, and the OBJ chunk appears in both |
||
− | "cell" files and "object" files. |
||
− | |||
− | The FORM has an (optional) INFO chunk followed by some number of |
||
− | OBJ chunks. (Note: OBJ is followed by a space -- ckID = "OBJ ") |
||
− | |||
− | The INFO and OBJ chunks, in turn, are made up of smaller chunks with |
||
− | the standard IFF structure: <ID> <data-size> <data>. |
||
− | |||
− | The INFO "sub-chunks" are relatively straightforward to interpret. |
||
− | |||
− | The OBJ "sub-chunks" support object heirarchies, and are slightly |
||
− | more difficult to interpret. Currently, there are 3 types of OBJ |
||
− | sub-chunks: an EXTR chunk, describing an "external" object in a |
||
− | seperate file; a DESC chunk, describing one node of a heirarchy; |
||
− | and a TOBJ chunk marking the end of a heirarchy chain. For each |
||
− | DESC chunk, there must be a corresponding TOBJ chunk. And an |
||
− | EXTR chunk is equivalent to a DESC/TOBJ pair. |
||
− | |||
− | In Turbo Silver and Imagine, the structure of the object heirarchy |
||
− | is as follows. There is a head object, and its (sexist) brothers. |
||
− | Each brother may have child objects. The children may have |
||
− | grandchildren, and so on. The brother nodes are kept in a doubly |
||
− | linked list, and each node has a (possibly NULL) pointer to a |
||
− | doubly linked "child" list. The children point to the "grandchildren" |
||
− | lists, and so on. (In addition, each node has a "back" pointer to |
||
− | its parent). |
||
− | |||
− | Each of the "head" brothers is written in a seperate OBJ chunk, |
||
− | along with all its descendants. The descendant heirarchy is |
||
− | supported as follows: |
||
− | |||
− | for each node of a doubly linked list, |
||
− | |||
− | 1) A DESC chunk is written, describing its object. |
||
− | 2) If it has children, steps 1) to 3) are performed |
||
− | for each child. |
||
− | 3) A TOBJ chunk is written, marking the end of the children. |
||
− | |||
− | For "external" objects, steps 1) to 3) are not performed, but |
||
− | an EXTR chunk is written instead. (This means that an external |
||
− | object cannot have children unless they are stored in the same |
||
− | "external" file). |
||
− | |||
− | The TOBJ sub-chunks have zero size -- and no data. The DESC |
||
− | and EXTR sub-chunks are made up of "sub-sub-chunks", again, |
||
− | with the standard IFF structure: <ID> <data-size> <data>. |
||
− | |||
− | ( "External" objects were used by Turbo Silver to allow a its |
||
− | "cell" data files to refer to an "object" data file that is |
||
− | "external" to the cell file. Imagine abandons the idea of |
||
− | individual cell files, and deals only in TDDD "object" files. |
||
− | Currently, Imagine does not support EXTR chunks in TDD files.) |
||
− | |||
− | Reader software WILL FOLLOW the standard IFF procedure of |
||
− | skipping over any un-recognized chunks -- and "sub-chunks" |
||
− | or "sub-sub-chunks". The <data-size> field indicates how many |
||
− | bytes to skip. In addition it WILL OBSERVE the IFF rule that |
||
− | an odd <data-size> may appear, in which case the corredponding |
||
− | <data> field will be padded at the end with one extra byte to |
||
− | give it an even size. |
||
− | |||
− | |||
− | Now, on with the details. |
||
− | |||
− | First, there are several numerical fields appearing in the data, |
||
− | describing object positions, rotation angles, scaling factors, etc. |
||
− | They are stored as "32-bit fractional" numbers, such that the true |
||
− | number is the 32-bit number divided by 65536. So as an example, |
||
− | the number 3.14159 is stored as (hexadecimal) $0003243F. This |
||
− | allows the data to be independant of any particular floating point |
||
− | format. And it (actually) is the internal format used in the |
||
− | "integer" version of Turbo Silver. Numbers stored in this format |
||
− | are called as "FRACT"s below. |
||
− | |||
− | Second, there are several color (or RGB) fields in the data. |
||
− | They are always stored as three UBYTEs representing the red, |
||
− | green and blue components of the color. Red is always first, |
||
− | followed by green, and then blue. For some of the data chunks, |
||
− | Turbo Silver reads the color field into the 24 LSB's of a |
||
− | LONGword. In such cases, the 3 RGB bytes are preceded by a |
||
− | zero byte in the file. |
||
− | |||
− | |||
− | The following "typedef"s are used below: |
||
− | |||
− | typedef LONG FRACT; /* 4 bytes */ |
||
− | typedef UBYTE COLOR[3]; /* 3 bytes */ |
||
− | |||
− | typedef struct vectors { |
||
− | FRACT X; /* 4 bytes */ |
||
− | FRACT Y; /* 4 bytes */ |
||
− | FRACT Z; /* 4 bytes */ |
||
− | } VECTOR; /* 12 bytes total */ |
||
− | |||
− | typedef struct matrices { |
||
− | VECTOR I; /* 12 bytes */ |
||
− | VECTOR J; /* 12 bytes */ |
||
− | VECTOR K; /* 12 bytes */ |
||
− | } MATRIX; /* 36 bytes total */ |
||
− | |||
− | typedef struct _tform { |
||
− | VECTOR r; /* 12 bytes - position */ |
||
− | VECTOR a; /* 12 bytes - x axis */ |
||
− | VECTOR b; /* 12 bytes - y axis */ |
||
− | VECTOR c; /* 12 bytes - z axis */ |
||
− | VECTOR s; /* 12 bytes - size */ |
||
− | } TFORM; /* 60 bytes total */ |
||
− | |||
− | The following structure is used in generating animated cells |
||
− | from a single cell. It can be attached to an object or to the |
||
− | camera. It is also used for Turbo Silver's "extrude along a |
||
− | path" feature. (It is ignored & forgotten by Imagine) |
||
− | |||
− | typedef struct story { |
||
− | UBYTE Path[18]; /* 18 bytes */ |
||
− | VECTOR Translate; /* 12 bytes */ |
||
− | VECTOR Rotate; /* 12 bytes */ |
||
− | VECTOR Scale; /* 12 bytes */ |
||
− | UWORD info; /* 2 bytes */ |
||
− | } STORY; /* 56 bytes total */ |
||
− | |||
− | The Path[] name refers to a named object in the cell data. |
||
− | The path object should be a sequence of points connected |
||
− | with edges. The object moves from the first point of the |
||
− | first edge, to the last point of the last edge. The edge |
||
− | ordering is important. The path is interpolated so that |
||
− | the object always moves an equal distance in each frame of |
||
− | the animation. If there is no path the Path[] field should |
||
− | be set to zeros. |
||
− | The Translate vector is not currently used. |
||
− | The Rotate "vector" specifies rotation angles about the |
||
− | X, Y, and Z axes. |
||
− | The Scale vector specfies X,Y, and Z scale factors. |
||
− | The "info" word is a bunch of bit flags: |
||
− | |||
− | ABS_TRA 0x0001 - translate in world coorinates (not used) |
||
− | ABS_ROT 0x0002 - rotation in world coorinates |
||
− | ABS_SCL 0x0004 - scaling in world coorinates |
||
− | LOC_TRA 0x0010 - translate in local coorinates (not used) |
||
− | LOC_ROT 0x0020 - rotation in local coorinates |
||
− | LOC_SCL 0x0040 - scaling in local coorinates |
||
− | X_ALIGN 0x0100 - (not used) |
||
− | Y_ALIGN 0x0200 - align Y axis to path's direction |
||
− | Z_ALIGN 0x0400 - (not used) |
||
− | FOLLOW_ME 0x1000 - children follow parent on path |
||
− | |||
− | DESC sub-sub-chunks |
||
− | ------------------- |
||
− | |||
− | NAME - size 18 |
||
− | |||
− | BYTE Name[18]; ; a name for the object. |
||
− | |||
− | Used for camera tracking, specifying story paths, etc. |
||
− | |||
− | SHAP - size 4 |
||
− | |||
− | WORD Shape; ; number indicating object type |
||
− | WORD Lamp; ; number indicating lamp type |
||
− | |||
− | Lamp numbers are composed of several bit fields: |
||
− | |||
− | Bits 0-1: |
||
− | 0 - not a lamp |
||
− | 1 - like sunlight |
||
− | 2 - like a lamp - intensity falls off with distance. |
||
− | 3 - unused/reserved |
||
− | |||
− | Bits 2: |
||
− | 0 - non-shadow-casting light |
||
− | 4 - shadow-casting light |
||
− | |||
− | Bits 3-4: |
||
− | 0 - Spherical light source |
||
− | 8 - Cylindrical light source. |
||
− | 16 - Conical light source. |
||
− | 24 - unused/reserved |
||
− | |||
− | Shape numbers are: |
||
− | |||
− | 0 - Sphere |
||
− | 1 - Stencil ; not supported by Imagine |
||
− | 2 - Axis ; custom objects with points/triangles |
||
− | 3 - Facets ; illegal - for internal use only |
||
− | 4 - Surface ; not supported by Imagine |
||
− | 5 - Ground |
||
− | |||
− | Spheres have thier radius set by the X size parameter. |
||
− | Stencils and surfaces are plane-parallelograms, with one |
||
− | point at the object's position vector; one side lying along |
||
− | the object's X axis with a length set by the X size; and |
||
− | another side starting from the position vector and going |
||
− | "Y size" units in the Y direction and "Z size" units in |
||
− | the X direction. A ground object is an infinte plane |
||
− | perpendicular to the world Z axis. Its Z coordinate sets |
||
− | its height, and the X and Y coordinates are only relevant |
||
− | to the position of the "hot point" used in selecting the |
||
− | object in the editor. Custom objects have points, edges |
||
− | and triangles associated with them. The size fields are |
||
− | relevant only for drawing the object axes in the editor. |
||
− | Shape number 3 is used internally for triangles of custom |
||
− | objects, and should never appear in a data file. |
||
− | |||
− | POSI - size 12 |
||
− | |||
− | VECTOR Position; ; the object's position. |
||
− | |||
− | Legal coordinates are in the range -32768 to 32767 and 65535/65536. |
||
− | Currently, the ray-tracer only sees objects in the -1024 to 1024 |
||
− | range. Light sources, and the camera may be placed outside that |
||
− | range, however. |
||
− | |||
− | AXIS - size 36 |
||
− | |||
− | VECTOR XAxis; |
||
− | VECTOR YAxis; |
||
− | VECTOR ZAxis; |
||
− | |||
− | These are direction vectors for the object coordinate system. |
||
− | They must be "orthogonal unit vectors" - i.e. the sum of the |
||
− | squares of the vevtor components must equal one (or close to it), |
||
− | and the vectors must be perpendicular. |
||
− | |||
− | SIZE - size 12 |
||
− | |||
− | VECTOR Size; |
||
− | |||
− | See SHAP chunk above. The sizes are used in a variety of ways |
||
− | depending on the object shape. For custom objects, they are |
||
− | the lengths of the coordinate axes drawn in the editor. If the |
||
− | object has its "Quickdraw" flag set, the axes lengths are also |
||
− | used to set the size of a rectangular solid that is drawn rather |
||
− | than drawing all the points and edges. |
||
− | |||
− | PNTS - size 2 + 12 * point count |
||
− | |||
− | UWORD PCount; ; point count |
||
− | VECTOR Points[]; ; points |
||
− | |||
− | This chunk has all the points for custom objects. The are |
||
− | refered to by thier position in the array. |
||
− | |||
− | EDGE - size 4 + 4 * edge cout |
||
− | |||
− | UWORD ECount; ; edge count |
||
− | UWORD Edges[][2]; ; edges |
||
− | |||
− | This chunk contins the edge list for custom objects. |
||
− | The Edges[][2] array is pairs of point numbers that |
||
− | are connected by the edges. Edges are refered to by thier |
||
− | position in the Edges[] array. |
||
− | |||
− | FACE - size 2 + 6 * face count |
||
− | |||
− | UWORD TCount; ; face count |
||
− | UWORD Connects[][3]; ; faces |
||
− | |||
− | This chunk contains the triangle (face) list for custom objects. |
||
− | The Connects[][3] array is triples of edge numbers that are |
||
− | connected by triangles. |
||
− | |||
− | PTHD - size 2 + 6 * axis count - Imagine only |
||
− | |||
− | UWORD ACount; ; axis count |
||
− | TFORM PData[][3]; ; axis data |
||
− | |||
− | This chunk contains the axis data for Imagine "path" objects. |
||
− | The PData array contains a TFORM structure for each point along |
||
− | the path. The "Y size" item for the last point on the path tells |
||
− | whether the path is closed or not. Zero means closed, non-zero |
||
− | means open. Otherwise the Y size field is the distance along |
||
− | the path to the next path point/axis. |
||
− | |||
− | COLR - size 4 |
||
− | REFL - size 4 |
||
− | TRAN - size 4 |
||
− | SPC1 - size 4 - Imagine only |
||
− | |||
− | BYTE pad; ; pad byte - must be zero |
||
− | COLOR col; ; RGB color |
||
− | |||
− | These are the main object RGB color, and reflection, transmission |
||
− | and specularity coefficients. |
||
− | |||
− | CLST - size 2 + 3 * count |
||
− | RLST - size 2 + 3 * count |
||
− | TLST - size 2 + 3 * count |
||
− | |||
− | UWORD count; ; count of colors |
||
− | COLOR colors[]; ; colors |
||
− | |||
− | These are the color, reflection and transmission coefficients |
||
− | for each face in custom objects. The count should match the |
||
− | face count in the FACE chunk. The ordering corresponds to the |
||
− | face order. |
||
− | |||
− | TPAR - size 64 - not written by Imagine - see TXT1 below |
||
− | |||
− | FRACT Params[16]; ; texture parameters |
||
− | |||
− | This is the list of parameters for texture modules when |
||
− | texture mapping is used. |
||
− | |||
− | TXT1 - variable size - Imagine only |
||
− | |||
− | This chunk contains texture data when texture mapping is used. |
||
− | |||
− | UWORD Flags; ; texture flags: |
||
− | ; 1 - TXTR_CHILDREN - apply to child objs |
||
− | TFORM TForm; ; local coordinates of texture axes. |
||
− | FRACT Params[16]; ; texture parameters |
||
− | UBYTE PFlags[16]; ; parameter flags (currently unused) |
||
− | UBYTE Length; ; length of texture file name |
||
− | UBYTE Name[Length]; ; texture file name (not NULL terminated) |
||
− | UBYTE pad; ; (if necessary to make an even length) |
||
− | |||
− | BRS1 - variable size - Imagine only (version 1.0) |
||
− | BRS2 - variable size - Imagine only (version 1.1) |
||
− | |||
− | UWORD Flags; ; brush type: |
||
− | ; 0 - Color |
||
− | ; 1 - Reflection |
||
− | ; 2 - Filter |
||
− | ; 3 - Altitude |
||
− | UWORD WFlags; ; brush wrapping flags: |
||
− | ; 1 WRAP_X - wrap type |
||
− | ; 2 WRAP_Z - wrap type |
||
− | ; 4 WRAP_CHILDREN - apply to children |
||
− | ; 8 WRAP_REPEAT - repeating brush |
||
− | ; 16 WRAP_FLIP - flip with repeats |
||
− | TFORM TForm; ; local coordinates of brush axes. |
||
− | (UWORD FullScale;) ; full scale value |
||
− | (UWORD MaxSeq;) ; highest number for sequenced brushes |
||
− | UBYTE Length; ; length of brush file name |
||
− | UBYTE Name[Length]; ; brush file name (not NULL terminated) |
||
− | UBYTE pad; ; (if necessary to make an even length) |
||
− | |||
− | The FullScale and MaxSeq items are in BRS2 chunks only. |
||
− | |||
− | SURF - size 5 - not written by Imagine |
||
− | |||
− | BYTE SProps[5]; ; object properties |
||
− | |||
− | This chunk contains object (surface) properties used |
||
− | by Turbo Silver. |
||
− | |||
− | SProps[0] - PRP_SURFACE ; surface type |
||
− | ; 0 - normal |
||
− | ; 4 - genlock |
||
− | ; 5 - IFF brush |
||
− | SProps[1] - PRP_BRUSH ; brush number (if IFF mapped) |
||
− | SProps[2] - PRP_WRAP ; IFF brush wrapping type |
||
− | ; 0 - no wrapping |
||
− | ; 1 - wrap X |
||
− | ; 2 - wrap Z |
||
− | ; 3 - wrap X and Z |
||
− | SProps[3] - PRP_STENCIL ; stencil number for stencil objects |
||
− | SProps[4] - PRP_TEXTURE ; texture number if texture mapped |
||
− | |||
− | MTTR - size 2 - not written by Imagine - see PRP1 chunk. |
||
− | |||
− | UBYTE Type; ; refraction type (0-4) |
||
− | UBYTE Index; ; custom index of refraction |
||
− | |||
− | This chunk contains refraction data for transparent or |
||
− | glossy objects. If the refraction type is 4, the object |
||
− | has a "custom" refractive index stored in the Index field. |
||
− | The Index field is 100 * (true index of refraction - 1.00) |
||
− | -- so it must be in the range of 1.00 to 3.55. The |
||
− | refraction types is 0-3 specify 0) Air - 1.00, 1) Water - 1.33, |
||
− | 2) Glass - 1.67 or 3) Crystal 2.00. |
||
− | |||
− | SPEC - size 2 - not written by Imagine - see SPC1 above. |
||
− | |||
− | UBYTE Specularity; ; range of 0-255 |
||
− | UBYTE Hardness; ; specular exponent (0-31) |
||
− | |||
− | This chunk contains specular information. The Specularity |
||
− | field is the amount of specular reflection -- 0 is none, |
||
− | 255 is fully specular. The "specular exponent" controls |
||
− | the "tightness" of the specular spots. A value of zero |
||
− | gives broad specular spots and a value of 31 gives smaller |
||
− | spots. |
||
− | |||
− | PRP0 - size 6 - not written by Imagine |
||
− | |||
− | UBYTE Props[6]; ; more object properties |
||
− | |||
− | This chunk contains object properties that programs other |
||
− | than Turbo Silver might support. |
||
− | |||
− | Props[0] - PRP_BLEND ; blending factor (0-255) |
||
− | Props[1] - PRP_SMOOTH ; roughness factor |
||
− | Props[2] - PRP_SHADE ; shading on/off flag |
||
− | Props[3] - PRP_PHONG ; phong shading on/off flag |
||
− | Props[4] - PRP_GLOSSY ; glossy on/off flag |
||
− | Props[5] - PRP_QUICK ; Quickdraw on/off flag |
||
− | |||
− | The blending factor controls the amount of dithering used |
||
− | on the object - 255 is fully dithered. |
||
− | The roughness factor controls how rough the object should |
||
− | appear - 0 is smooth, 255 is max roughness. |
||
− | The shading flag is interpreted differently depending on |
||
− | whether the object is a light source or not. For light |
||
− | sources, it sets the light to cast shadows or not. For |
||
− | normal objects, if the flag is set, the object is always |
||
− | considered as fully lit - i.e. it's color is read directly |
||
− | from the object (or IFF brush), and is not affected by light |
||
− | sources. |
||
− | The phong shading is on by default - a non-zero value turns |
||
− | it off. |
||
− | The glossy flag sets the object to be glossy or not. If |
||
− | the object is glossy, the "transmit" colors and the index |
||
− | of refraction control the amount of "sheen". The glossy |
||
− | feature is meant to simulate something like a wax coating |
||
− | on the object with the specified index of refraction. The |
||
− | trasmission coefficients control how much light from the |
||
− | object makes it through the wax coating. |
||
− | The Quickdraw flag, if set, tells the editor not to draw |
||
− | all the points and edges for the object, but to draw a |
||
− | rectanglular solid centered at the object position, and |
||
− | with sizes detemined by the axis lengths. |
||
− | |||
− | PRP1 - size 8 - Imagine only |
||
− | |||
− | UBYTE IProps[8]; ; more object properties |
||
− | |||
− | This chunk contains object properties that programs other |
||
− | than Imagine might support. |
||
− | |||
− | IProps[0] - IPRP_DITHER ; blending factor (0-255) |
||
− | IProps[1] - IPRP_HARD ; hardness factor (0-255) |
||
− | IProps[2] - IPRP_ROUGH ; roughness factor (0-255) |
||
− | IProps[3] - IPRP_SHINY ; shinyness factor (0-255) |
||
− | IProps[4] - IPRP_INDEX ; index of refraction |
||
− | IProps[5] - IPRP_QUICK ; flag - Quickdraw on/off |
||
− | IProps[6] - IPRP_PHONG ; flag - Phong shading on/off |
||
− | IProps[7] - IPRP_GENLOCK ; flag - Genlock on/off |
||
− | |||
− | The blending factor controls the amount of dithering used |
||
− | on the object - 255 is fully dithered. |
||
− | The hardness factor controls how tight the specular spot |
||
− | should be - 0 is a big soft spot, 255 is a tight hot spot |
||
− | The roughness factor controls how rough the object should |
||
− | appear - 0 is smooth, 255 is max roughness. |
||
− | The shiny factor in interaction with the object's filter |
||
− | values controls how shiny the object appears. Setting it |
||
− | to anything but zero forces the object to be non-transparent |
||
− | since then the filter values are used in the shiny (reflection) |
||
− | calculations. A value of 255 means maximum shinyness. |
||
− | |||
− | INTS - size 4 - not written by Imagine |
||
− | |||
− | FRACT Intensity; ; light intensity |
||
− | |||
− | This is the intensity field for light source objects. |
||
− | an intensity of 255 for a sun-like light fully lights |
||
− | object surfaces which are perpendicular to the direction |
||
− | to the light source. For lamp-like light sources, the |
||
− | necessary intensity will depend on the distance to the light. |
||
− | |||
− | INT1 - size 12 - Imagine only |
||
− | |||
− | VECTOR Intensity; ; light intensity |
||
− | |||
− | This is like INTS above, but has seperate R, G & B intensities. |
||
− | |||
− | STRY - size 56 - not written by Imagine |
||
− | |||
− | STORY story; ; a story structure for the object. |
||
− | |||
− | The story structure is described above. |
||
− | |||
− | ANID - size 64 - Imagine only |
||
− | |||
− | LONG Cellno; ; cell number |
||
− | TFORM TForm; ; object position/axes/size in that cell. |
||
− | |||
− | For Imagine's "Cycle" objects, within EACH DESC chunk in the |
||
− | file - that is, for each object of the group, there will be |
||
− | a series of ANID chunks. The cell number sequences of each |
||
− | part of the must agree with the sequence for the head object, |
||
− | and the first cell number must be zero. |
||
− | |||
− | FORD - size 56 + 12 * PC - Imagine only |
||
− | |||
− | WORD NumC; ; number of cross section points |
||
− | WORD NumF; ; number of slices |
||
− | WORD Flags; ; orientation flag |
||
− | WORD pad; ; reserved |
||
− | MATRIX TForm; ; object rotation/scaling transformation |
||
− | VECTOR Shift; ; object translation |
||
− | VECTOR Points[PC]; ; "Forms" editor points |
||
− | |||
− | For Imagine's "Forms" objects, the "PNTS" chunk above is not |
||
− | written out, but this structure is written instead. The point |
||
− | count is PC = NumC + 4 * NumF. The object's real points are |
||
− | then calculated from these using a proprietary algorithm. |
||
− | The tranformation parameters above allow the axes of the |
||
− | real object be moved around relative to the "Forms" points. |
||
− | |||
− | |||
− | DESC notes |
||
− | ---------- |
||
− | |||
− | Again, most of these fields are optional, and defaults are supplied. |
||
− | However, if there is a FACE chunk, there must also be a CLST chunk, |
||
− | an RLST chunk and a TLST chunk -- all with matching "count" fields. |
||
− | The SHAP chunk is not optional. |
||
− | |||
− | Defaults are: Colors set to (240,240,240); reflection and |
||
− | transmission coefficients set to zero; illegal shape; no story or |
||
− | special surface types; position at (0,0,0); axes aligned to the |
||
− | world axes; size fields all 32.0; intensity at 300; no name; |
||
− | no points/edges or faces; texture parameters set to zero; refraction |
||
− | type 0 with index 1.00; specular, hardness and roughness set to zero; |
||
− | blending at 255; glossy off; phong shading on; not a light source; |
||
− | not brightly lit; |
||
− | |||
− | In Imagine, defaults are the same, but with colors (255,255,255). |
||
− | |||
− | |||
− | INFO sub-chunks |
||
− | --------------- |
||
− | |||
− | BRSH - size 82 |
||
− | |||
− | WORD Number; ; Brush number (between 0 and 7) |
||
− | CHAR Filename[80]; ; IFF ILBM filename |
||
− | |||
− | There may be more than one of these. |
||
− | |||
− | STNC - size 82 |
||
− | |||
− | Same format as BRSH chunk. |
||
− | |||
− | TXTR - size 82 |
||
− | |||
− | Same format as BRSH chunk. The Filename field is the name of |
||
− | a code module that can be loaded with LoadSeg(). |
||
− | |||
− | OBSV - size 28 |
||
− | |||
− | VECTOR Camera; ; Camera position |
||
− | VECTOR Rotate; ; Camera rotation angles |
||
− | FRACT Focal; ; Camera focal length |
||
− | |||
− | This tells where the camera is, how it is aimed, and its |
||
− | focal length. The rotation angles are in degrees, and specify |
||
− | rotations around the X, Y, and Z axes. The camera looks down |
||
− | its own Y axis, with the top of the picture in the direction of |
||
− | the Z axis. If the rotation angles are all zero, its axes |
||
− | are aligned with the world coordinate axes. The rotations are |
||
− | performed in the order ZXY about the camera axes. A positive |
||
− | angle rotates Y toward Z, Z toward X, and X toward Y for |
||
− | rotations about the X, Y, and Z axes respectively. To |
||
− | understand the focal length, imagine a 320 x 200 pixel |
||
− | rectangle perpendicular to, and centered on the camera's |
||
− | Y axis. Any objects in the infinite rectangular cone defined |
||
− | by the camera position and the 4 corners of the rectangle will |
||
− | appear in the picture. |
||
− | |||
− | OTRK - size 18 |
||
− | |||
− | BYTE Trackname[18]; |
||
− | |||
− | This chunk specifies the name of an object that the camera |
||
− | is "tracked" to. If the name is NULL, the camera doesn't |
||
− | track. Otherwise, if the object is moved inside Turbo Silver, |
||
− | the camera will follow it. |
||
− | |||
− | OSTR - size 56 |
||
− | |||
− | STORY CStory; ; a STORY structure for the camera |
||
− | |||
− | The story structure is defined above. |
||
− | |||
− | FADE - size 12 |
||
− | |||
− | FRACT FadeAt; ; distance to start fade |
||
− | FRACT FadeBy; ; distance of total fade |
||
− | BYTE pad; ; pad byte - must be zero |
||
− | COLOR FadeTo; ; RGB color to fade to |
||
− | |||
− | SKYC - size 8 |
||
− | |||
− | BYTE pad; ; pad byte - must be zero |
||
− | COLOR Horizon; ; horizon color |
||
− | BYTE pad; ; pad byte - must be zero |
||
− | COLOR Zenith; ; zenith color |
||
− | |||
− | AMBI - size 4 |
||
− | |||
− | BYTE pad; ; pad byte - must be zero |
||
− | COLOR Ambient; ; abmient light color |
||
− | |||
− | GLB0 - size 8 |
||
− | |||
− | BYTE Props[8]; ; an array of 8 "global properties" used |
||
− | ; by Turbo Silver. |
||
− | |||
− | Props[0] - GLB_EDGING ; edge level (globals requester) |
||
− | Props[1] - GLB_PERTURB ; perturbance (globals requester) |
||
− | Props[2] - GLB_SKY_BLEND ; sky blending factor (0-255) |
||
− | Props[3] - GLB_LENS ; lens type (see below) |
||
− | Props[4] - GLB_FADE ; flag - Sharp/Fuzzy focus (globals) |
||
− | Props[5] - GLB_SIZE ; "apparant size" (see below) |
||
− | Props[6] - GLB_RESOLVE ; resolve depth (globals requester) |
||
− | Props[7] - GLB_EXTRA ; flag - genlock sky on/off |
||
− | |||
− | The edging and perturbance values control the heuristics in |
||
− | ray tracing. The sky blending factor is zero for no blending, |
||
− | and 255 for full blending. The lens type is a number from 0 |
||
− | 4, corresponding to the boxes in the "camera" requester, and |
||
− | correspond to 0) Manual, 1) Wide angle, 2) Normal, 3) Telephoto, |
||
− | and 4) Custom. It is used in setting the camera's focal length |
||
− | if the camera is tracked to an object. The Sharp/Fuzzy flag |
||
− | turns the "fade" feature on and off - non-zero means on. |
||
− | The "apparant size" parameter is 100 times the "custom size" |
||
− | parameter in the camera requester. And is used to set the |
||
− | focal length for a custom lens. The "resolve depth" controls |
||
− | the number of rays the ray tracer will shoot for a single pixel. |
||
− | Each reflective/refractive ray increments the depth counter, and |
||
− | the count is never allowed to reach the "resolve depth". If both |
||
− | a reflective and a refractive ray are traced, each ray gets its |
||
− | own version of the count - so theoretically, a resolve depth of |
||
− | 4 could allow much more than 4 rays to be traced. The "genlock |
||
− | sky" flag controls whether the sky will be colored, or set to |
||
− | the genlock color (color 0 - black) in the final picture. |
||
− | |||
− | |||
− | All of the INFO sub-chunks are optional, as is the INFO chunk. |
||
− | Default values are supplied if the chunks are not present. The |
||
− | defaults are: no brushes, stencils, or textures defined; no story |
||
− | for the camera; horizon and zenith and ambient light colors set |
||
− | to black; fade color set to (80,80,80); un-rotated, un-tracked |
||
− | camera at (-100, -100, 100); and global properties array set to |
||
− | [30, 0, 0, 0, 0, 100, 8, 0]. |
||
− | |||
− | |||
− | EXTR sub-sub-chunks |
||
− | ------------------- |
||
− | |||
− | MTRX - size 60 |
||
− | |||
− | VECTOR Translate; ; translation vector |
||
− | VECTOR Scale; ; X,Y and Z scaling factors |
||
− | MATRIX Rotate; ; rotation matrix |
||
− | |||
− | The translation vector is i world coordinates. |
||
− | The scaling factors are with respect to local axes. |
||
− | The rotation matrix is with respect to the world axes, |
||
− | and it should be a "unit matrix". |
||
− | The rotation is such that a rotated axis's X,Y, and Z |
||
− | components are the dot products of the MATRIX's I,J, |
||
− | and K vectors with the un-rotated axis vector. |
||
− | |||
− | LOAD - size 80 |
||
− | |||
− | BYTE Filename[80]; ; the name of the external file |
||
− | |||
− | This chunk contains the name of an external object file. |
||
− | The external file should be a FORM TDDD file. It may contain |
||
− | an any number of objects possibly grouped into heirarchy(ies). |
||
− | |||
− | Both of these chunks are required.</pre> |
||
− | === ProWrite document format === |
||
− | |||
− | <pre>IFF FORM / CHUNK DESCRIPTION |
||
− | ============================ |
||
− | |||
− | Form/Chunk IDs: |
||
− | FORM WORD |
||
− | Chunks FONT,COLR,DOC,HEAD,FOOT,PCTS,PARA,TABS,PAGE,TEXT,FSCC,PINF |
||
− | |||
− | Date Submitted: 03/87 |
||
− | Submitted by: James Bayless - New Horizons Software, Inc. |
||
− | |||
− | |||
− | FORM |
||
− | ==== |
||
− | |||
− | FORM ID: WORD |
||
− | |||
− | FORM Purpose: Document storage (supports color, fonts, pictures) |
||
− | |||
− | FORM Description: |
||
− | |||
− | This include file describes FORM WORD and its Chunks |
||
− | |||
− | /* |
||
− | * IFF Form WORD structures and defines |
||
− | * Copyright (c) 1987 New Horizons Software, Inc. |
||
− | * |
||
− | * Permission is hereby granted to use this file in any and all |
||
− | * applications. Modifying the structures or defines included |
||
− | * in this file is not permitted without written consent of |
||
− | * New Horizons Software, Inc. |
||
− | */ |
||
− | |||
− | #include ":IFF/ILBM.h" /* Makes use of ILBM defines */ |
||
− | |||
− | #define ID_WORD MakeID('W','O','R','D') /* Form type */ |
||
− | |||
− | #define ID_FONT MakeID('F','O','N','T') /* Chunks */ |
||
− | #define ID_COLR MakeID('C','O','L','R') |
||
− | #define ID_DOC MakeID('D','O','C',' ') |
||
− | #define ID_HEAD MakeID('H','E','A','D') |
||
− | #define ID_FOOT MakeID('F','O','O','T') |
||
− | #define ID_PCTS MakeID('P','C','T','S') |
||
− | #define ID_PARA MakeID('P','A','R','A') |
||
− | #define ID_TABS MakeID('T','A','B','S') |
||
− | #define ID_PAGE MakeID('P','A','G','E') |
||
− | #define ID_TEXT MakeID('T','E','X','T') |
||
− | #define ID_FSCC MakeID('F','S','C','C') |
||
− | #define ID_PINF MakeID('P','I','N','F') |
||
− | |||
− | /* |
||
− | * Special text characters for page number, date, and time |
||
− | * Note: ProWrite currently supports only PAGENUM_CHAR, and only in |
||
− | * headers and footers |
||
− | */ |
||
− | |||
− | #define PAGENUM_CHAR 0x80 |
||
− | #define DATE_CHAR 0x81 |
||
− | #define TIME_CHAR 0x82 |
||
− | |||
− | /* |
||
− | * Chunk structures follow |
||
− | */ |
||
− | |||
− | /* |
||
− | * FONT - Font name/number table |
||
− | * There are one of these for each font/size combination |
||
− | * These chunks should appear at the top of the file (before document data) |
||
− | */ |
||
− | |||
− | typedef struct { |
||
− | UBYTE Num; /* 0 .. 255 */ |
||
− | UWORD Size; |
||
− | /* UBYTE Name[]; */ /* NULL terminated, without ".font" */ |
||
− | } FontID; |
||
− | |||
− | /* |
||
− | * COLR - Color translation table |
||
− | * Translates from color numbers used in file to ISO color numbers |
||
− | * Should be at top of file (before document data) |
||
− | * Note: Currently ProWrite only checks these values to be its current map, |
||
− | * it does no translation as it does for FONT chunks |
||
− | */ |
||
− | |||
− | typedef struct { |
||
− | UBYTE ISOColors[8]; |
||
− | } ISOColors; |
||
− | |||
− | /* |
||
− | * DOC - Begin document section |
||
− | * All text and paragraph formatting following this chunk and up to a |
||
− | * HEAD, FOOT, or PICT chunk belong to the document section |
||
− | */ |
||
− | |||
− | #define PAGESTYLE_1 0 /* 1, 2, 3 */ |
||
− | #define PAGESTYLE_I 1 /* I, II, III */ |
||
− | #define PAGESTYLE_i 2 /* i, ii, iii */ |
||
− | #define PAGESTYLE_A 3 /* A, B, C */ |
||
− | #define PAGESTYLE_a 4 /* a, b, c */ |
||
− | |||
− | typedef struct { |
||
− | UWORD StartPage; /* Starting page number */ |
||
− | UBYTE PageNumStyle; /* From defines above */ |
||
− | UBYTE pad1; |
||
− | LONG pad2; |
||
− | } DocHdr; |
||
− | |||
− | /* |
||
− | * HEAD/FOOT - Begin header/footer section |
||
− | * All text and paragraph formatting following this chunk and up to a |
||
− | * DOC, HEAD, FOOT, or PICT chunk belong to this header/footer |
||
− | * Note: This format supports multiple headers and footers, but currently |
||
− | * ProWrite only allows a single header and footer per document |
||
− | */ |
||
− | |||
− | #define PAGES_NONE 0 |
||
− | #define PAGES_LEFT 1 |
||
− | #define PAGES_RIGHT 2 |
||
− | #define PAGES_BOTH 3 |
||
− | |||
− | typedef struct { |
||
− | UBYTE PageType; /* From defines above */ |
||
− | UBYTE FirstPage; /* 0 = Not on first page */ |
||
− | LONG pad; |
||
− | } HeadHdr; |
||
− | |||
− | /* |
||
− | * PCTS - Begin picture section |
||
− | * Note: ProWrite currently requires NPlanes to be three (3) |
||
− | */ |
||
− | |||
− | typedef struct { |
||
− | UBYTE NPlanes; /* Number of planes used in picture bitmaps */ |
||
− | UBYTE pad; |
||
− | } PictHdr; |
||
− | |||
− | /* |
||
− | * PARA - New paragraph format |
||
− | * This chunk should be inserted first when a new section is started (DOC, |
||
− | * HEAD, or FOOT), and again whenever the paragraph format changes |
||
− | */ |
||
− | |||
− | #define SPACE_SINGLE 0 |
||
− | #define SPACE_DOUBLE 0x10 |
||
− | |||
− | #define JUSTIFY_LEFT 0 |
||
− | #define JUSTIFY_CENTER 1 |
||
− | #define JUSTIFY_RIGHT 2 |
||
− | #define JUSTIFY_FULL 3 |
||
− | |||
− | #define MISCSTYLE_NONE 0 |
||
− | #define MISCSTYLE_SUPER 1 /* Superscript */ |
||
− | #define MISCSTYLE_SUB 2 /* Subscript */ |
||
− | |||
− | typedef struct { |
||
− | UWORD LeftIndent; /* In decipoints (720 dpi) */ |
||
− | UWORD LeftMargin; |
||
− | UWORD RightMargin; |
||
− | UBYTE Spacing; /* From defines above */ |
||
− | UBYTE Justify; /* From defines above */ |
||
− | UBYTE FontNum; /* FontNum, Style, etc. for first char in para*/ |
||
− | UBYTE Style; /* Standard Amiga style bits */ |
||
− | UBYTE MiscStyle; /* From defines above */ |
||
− | UBYTE Color; /* Internal number, use COLR to translate */ |
||
− | LONG pad; |
||
− | } ParaFormat; |
||
− | |||
− | /* |
||
− | * TABS - New tab stop types/locations |
||
− | * Use an array of values in each chunk |
||
− | * Like the PARA chunk, this should be inserted whenever the tab settings |
||
− | * for a paragraph change |
||
− | * Note: ProWrite currently does not support TAB_CENTER |
||
− | */ |
||
− | |||
− | #define TAB_LEFT 0 |
||
− | #define TAB_CENTER 1 |
||
− | #define TAB_RIGHT 2 |
||
− | #define TAB_DECIMAL 3 |
||
− | |||
− | typedef struct { |
||
− | UWORD Position; /* In decipoints */ |
||
− | UBYTE Type; |
||
− | UBYTE pad; |
||
− | } TabStop; |
||
− | |||
− | /* |
||
− | * PAGE - Page break |
||
− | * Just a marker -- this chunk has no data |
||
− | */ |
||
− | |||
− | /* |
||
− | * TEXT - Paragraph text (one block per paragraph) |
||
− | * Block is actual text, no need for separate structure |
||
− | * If the paragraph is empty, this is an empty chunk -- there MUST be |
||
− | * a TEXT block for every paragraph |
||
− | * Note: The only ctrl characters ProWrite can currently handle in TEXT |
||
− | * chunks are Tab and PAGENUM_CHAR, ie no Return's, etc. |
||
− | */ |
||
− | |||
− | /* |
||
− | * FSCC - Font/Style/Color changes in previous TEXT block |
||
− | * Use an array of values in each chunk |
||
− | * Only include this chunk if the previous TEXT block did not have |
||
− | * the same Font/Style/Color for all its characters |
||
− | */ |
||
− | |||
− | typedef struct { |
||
− | UWORD Location; /* Character location in TEXT chunk of change */ |
||
− | UBYTE FontNum; |
||
− | UBYTE Style; |
||
− | UBYTE MiscStyle; |
||
− | UBYTE Color; |
||
− | UWORD pad; |
||
− | } FSCChange; |
||
− | |||
− | /* |
||
− | * PINF - Picture info |
||
− | * This chunk must only be in a PCTS section |
||
− | * Must be followed by ILBM BODY chunk |
||
− | * Pictures are treated independently of the document text (like a |
||
− | * page-layout system), this chunk includes information about what |
||
− | * page and location on the page the picture is at |
||
− | * Note: ProWrite currently only supports mskTransparentColor and |
||
− | * mskHasMask masking |
||
− | */ |
||
− | |||
− | typedef struct { |
||
− | UWORD Width, Height; /* In pixels */ |
||
− | UWORD Page; /* Which page picture is on (0..max) */ |
||
− | UWORD XPos, YPos; /* Location on page in decipoints */ |
||
− | Masking Masking; /* Like ILBM format */ |
||
− | Compression Compression; /* Like ILBM format */ |
||
− | UBYTE TransparentColor; /* Like ILBM format */ |
||
− | UBYTE pad; |
||
− | } PictInfo; |
||
− | |||
− | /* end */</pre> |
||
− | |||
− | == Additional documents == |
||
− | |||
− | === Intro to IFF Amiga ILBM Files and Amiga Viewmodes === |
||
− | |||
− | The IFF (Interchange File Format) for graphic images on the Amiga is called FORM ILBM (InterLeaved BitMap). It follows a standard parsable IFF format. |
||
− | |||
− | ==== Sample hex dump of beginning of an ILBM ==== |
||
− | |||
− | Important note! You can NOT ever depend on any particular ILBM chunk being at any particular offset into the file! IFF files are composed, in their simplest form, of chunks within a FORM. Each chunk starts starts with a 4-letter chunkID, followed by a 32-bit length of the rest of the chunk. You PARSE IFF files, skipping past unneeded or unknown chunks by seeking their length (+1 if odd length) to the next 4-letter chunkID. |
||
− | |||
− | <pre>0000: 464F524D 00016418 494C424D 424D4844 FORM..d.ILBMBMHD |
||
− | 0010: 00000014 01400190 00000000 06000100 .....@.......... |
||
− | 0020: 00000A0B 01400190 43414D47 00000004 .....@..CAMG.... |
||
− | 0030: 00000804 434D4150 00000030 001100EE ....CMAP...0.... |
||
− | 0040: EEEE0000 22000055 33333355 55550033 .... ..P000PPP.0 |
||
− | 0050: 99885544 77777711 66EE2266 EE6688DD ..P@ppp.`. `.`.. |
||
− | 0060: AAAAAAAA 99EECCCC CCDDAAEE 424F4459 ............BODY |
||
− | 0070: 000163AC F8000F80 148A5544 2ABDEFFF ..c.......UD*... etc.</pre> |
||
− | Interpretation: |
||
− | |||
− | <pre> 'F O R M' length 'I L B M''B M H D'<-start of BitMapHeader chunk |
||
− | 0000: 464F524D 00016418 494C424D 424D4844 FORM..d.ILBMBMHD |
||
− | |||
− | length WideHigh XorgYorg PlMkCoPd <- Planes Mask Compression Pad |
||
− | 0010: 00000014 01400190 00000000 06000100 .....@.......... |
||
− | |||
− | start of C-AMiGa |
||
− | TranAspt PagwPagh 'C A M G' length <- View modes chunk |
||
− | 0020: 00000A0B 01400190 43414D47 00000004 .....@..CAMG.... |
||
− | |||
− | Viewmode 'C M A P' length R g b R <- Viewmode 800=HAM | 4=LACE |
||
− | 0030: 00000804 434D4150 00000030 001100EE ....CMAP...0.... |
||
− | |||
− | g b R g b R g b R g b R g b R g <- Rgb's are for reg0 thru regN |
||
− | 0040: EEEE0000 22000055 33333355 55550033 .... ..P000PPP.0 |
||
− | |||
− | b R g b R g b R g b R g b R g b |
||
− | 0050: 99885544 77777711 66EE2266 EE6688DD ..P@ppp.`. `.`.. |
||
− | |||
− | R g b R g b R g b R g b 'B O D Y' |
||
− | 0060: AAAAAAAA 99EECCCC CCDDAAEE 424F4459 ............BODY |
||
− | |||
− | Compacted |
||
− | length start of body data <- (Compression=1 above) |
||
− | 0070: 000163AC F8000F80 148A5544 2ABDEFFF ..c.......UD*... |
||
− | 0080: FFBFF800 0F7FF7FC FF04F85A 77AD5DFE ...........Zw.]. etc. |
||
− | |||
− | Notes on CAMG Viewmodes: HIRES=0x8000 LACE=0x4 HAM=0x800 HALFBRITE=0x80</pre> |
||
− | === Interpreting ILBMs === |
||
− | |||
− | ILBM is a fairly simple IFF FORM. All you really need to deal with to extract the image are the following chunks: |
||
− | |||
− | <pre>(Note - Also watch for AUTH Author chunks and (c) Copyright chunks |
||
− | and preserve any copyright information if you rewrite the ILBM) |
||
− | |||
− | BMHD - info about the size, depth, compaction method |
||
− | (See interpreted hex dump above) |
||
− | |||
− | CAMG - optional Amiga viewmodes chunk |
||
− | Most HAM and HALFBRITE ILBMs should have this chunk. If no |
||
− | CAMG chunk is present, and image is 6 planes deep, assume |
||
− | HAM and you'll probably be right. Some Amiga viewmodes |
||
− | flags are HIRES=0x8000, LACE=0x4, HAM=0x800, HALFBRITE=0x80. |
||
− | Note that new Amiga 2.0 ILBMs may have more complex 32-bit |
||
− | numbers (modeid) stored in the CAMG. However, the bits |
||
− | described above should get you a compatible old viewmode. |
||
− | |||
− | CMAP - RGB values for color registers 0 to n |
||
− | (each component left justified in a byte) |
||
− | If a deep ILBM (like 12 or 24 planes), there should be no CMAP |
||
− | and instead the BODY planes are interpreted as the bits of RGB |
||
− | in the order R0...Rn G0...Gn B0...Bn |
||
− | |||
− | BODY - The pixel data, stored in an interleaved fashion as follows: |
||
− | (each line individually compacted if BMHD Compression = 1) |
||
− | plane 0 scan line 0 |
||
− | plane 1 scan line 0 |
||
− | plane 2 scan line 0 |
||
− | ... |
||
− | plane n scan line 0 |
||
− | plane 0 scan line 1 |
||
− | plane 1 scan line 1 |
||
− | etc.</pre> |
||
− | === Body Compression === |
||
− | |||
− | The BODY contains pixel data for the image. Width, Height, and depth (Planes) is specified in the BMHD. |
||
− | |||
− | If the BMHD Compression byte is 0, then the scan line data is not compressed. If Compression=1, then each scan line is individually compressed as follows: |
||
− | |||
− | More than 2 bytes the same stored as BYTE code value n from -1 to -127 followed by byte to be repeated (-n) + 1 times. Varied bytes stored as BYTE code n from 0 to 127 followed by n+1 bytes of data. |
||
− | |||
− | The byte code -128 is a NOP. |
||
− | |||
− | === Interpreting the Scan Line Data === |
||
− | |||
− | If the ILBM is not HAM or HALFBRITE, then after parsing and uncompacting if necessary, you will have N planes of pixel data. Color register used for each pixel is specified by looking at each pixel thru the planes. I.e., if you have 5 planes, and the bit for a particular pixel is set in planes 0 and 3: |
||
− | |||
− | <pre>PLANE 4 3 2 1 0 |
||
− | PIXEL 0 1 0 0 1</pre> |
||
− | then that pixel uses color register binary 01001 = 9 |
||
− | |||
− | The RGB value for each color register is stored in the CMAP chunk of the ILBM, starting with register 0, with each register’s RGB value stored as one byte of R, one byte G, and one byte of B, with each component scaled to 8-bits. (ie. 4-bit Amiga R, G, and B components are each stored in the high nibble of a byte. The low nibble may also contain valid data if the color was stored with 8-bit-per-gun color resolution). |
||
− | |||
− | BUT - if the picture is '''HAM''' or '''HALFBRITE''', it is interpreted differently. |
||
− | |||
− | Hopefully, if the picture is HAM or HALFBRITE, the package that saved it properly saved a CAMG chunk (look at a hex dump of your file with ACSII interpretation - you will see the chunks - they all start with a 4-ASCII- character chunk ID). If the picture is 6 planes deep and has no CAMG chunk, it is probably HAM. If you see a CAMG chunk, the "CAMG" is followed by the 32-bit chunk length, and then the 32-bit Amiga Viewmode flags. |
||
− | |||
− | HAM pics with a 16-bit CAMG will have the 0x800 bit set in CAMG ViewModes. HALBRITE pics will have the 0x80 bit set. |
||
− | |||
− | To transport a HAM or HALFBRITE picture to another machine, you must understand how HAM and HALFBRITE work on the Amiga. |
||
− | |||
− | ==== How Amiga HAM mode works ==== |
||
− | |||
− | Amiga HAM (Hold and Modify) mode lets the Amiga display all 4096 RGB values. In HAM mode, the bits in the two last planes describe an R G or B modification to the color of the previous pixel on the line to create the color of the current pixel. So a 6-plane HAM picture has 4 planes for specifying absolute color pixels giving up to 16 absolute colors which would be specified in the ILBM CMAP chunk. The bits in the last two planes are color modification bits which cause the Amiga, in HAM mode, to take the RGB value of the previous pixel (Hold and), substitute the 4 bits in planes 0-3 for the previous color’s R G or B component (Modify) and display the result for the current pixel. If the first pixel of a scan line is a modification pixel, it modifies the RGB value of the border color (register 0). The color modification bits in the last two planes (planes 4 and 5) are interpreted as follows: |
||
− | |||
− | <pre> 00 - no modification. Use planes 0-3 as normal color register index |
||
− | 10 - hold previous, replacing Blue component with bits from planes 0-3 |
||
− | 01 - hold previous, replacing Red component with bits from planes 0-3 |
||
− | 11 - hold previous. replacing Green component with bits from planes 0-3</pre> |
||
− | ==== How Amiga HALFBRITE mode works ==== |
||
− | |||
− | This one is simpler. In HALFBRITE mode, the Amiga interprets the bit in the last plane as HALFBRITE modification. The bits in the other planes are treated as normal color register numbers (RGB values for each color register is specified in the CMAP chunk). If the bit in the last plane is set (1), then that pixel is displayed at half brightness. This can provide up to 64 absolute colors. |
||
− | |||
− | === Other Notes === |
||
− | |||
− | Amiga ILBMs images must be a even number of bytes wide. Smaller images (such as brushes) are padded to an even byte width. |
||
− | |||
− | ILBMs created with Electronic Arts IBM and Amiga “DPaintII” packages are compatible (though you may have to use a ’.lbm’ filename extension on an IBM). The ILBM graphic files may be transferred between the machines (or between the Amiga and IBM sides your Amiga if you have a CBM Bridgeboard card installed) and loaded into either package. |
Latest revision as of 20:49, 17 April 2014
IFF FORM and Chunk Registry
Last Updated: June 8, 2012
This section contains the official list of registered FORM and Chunk names that are reserved and in use. This list is often referred to as the 3rd party registry since these are FORM and Chunk types created by application developers and not part of the original IFF specification.
For all FORM and Chunk types that are public, the official specifications from the third party company are listed (in alphabetical order). At the end of this section are additional documents describing how the ILBM FORM type works on the Amiga.
New chunks and FORMS should be registered with the AmigaOS development team. Please make all submissions via the AmigaOS web site contact form.
Developing New IFF FORMs and Chunks
IFF has been one of the keys to the Amiga's superiority in multimedia applications, allowing interchange of media elements between packages. The wealth of standard IFF FORMs and chunks gives the Amiga user data-sharing capabilities that are virtually unequaled on other systems. The Amiga's ability to render an image, touch it up, convert it to a different display mode, and load it into in another package is something that is a chore on other platforms, simply because the format of the image file may be different from one application to the next. IFF files lessen the need for "conversion" software, because most Amiga applications can read and write them.
Since its introduction as an open standard in 1985, IFF has widened to encompass data of many sorts-and the need for new IFF types continues to grow. To satisfy these growing needs, developers will continue to define and support new IFF types.
When developing a new IFF type, there are several steps you should follow:
- Discuss needs and specifications within the developer community and with the AmigaOS development team.
- The most important thing about designing IFF FORMs and chunks is that they meet the data storage and transfer needs of multiple applications. When more than one product uses the same IFF type, the market widens for all products that use that IFF type. Users are not forced to use one product or another, but can buy as many as they need to get the job done, fully utilizing all the features that each product has to offer. This step helps to ensure that a proposed IFF form or chunk type is flexible and isn't redundant.
- Implement the new type and conduct feasibility tests.
- Before settling on a format, set up prototype code to test the proposed format. This will help to prove that the idea is sound and can be implemented in software before others try to use it.
- Submit specifications to the AmigaOS development team.
- Coming up with a new kind of IFF FORM or chunk is easy--almost too easy. Just about anyone can follow the IFF guidelines and define their own FORM or chunk. If every application used a different IFF FORM, one application would be unable to share data with another because it can't read the other application's IFF FORM. It's like making up a new word for something that everyone sees every day. You may understand what the word means, but when you try to use your new word to communicate with others, they won't understand you. Further, deciding to use a pre-existing FORM or chunk in a new and different way is a lot like making up your own meaning for a pre-existing word. Confusion results when programs try to read FORMs or chunks whose meaning was altered by a non-conforming program.
- To avoid the problem of incompatible IFF types, register your new IFF types with the AmigaOS development team. The AmigaOS development team acts as a "dictionary" of IFF types. By submitting your proposals for FORM or chunk types to Amigan Software, you help prevent duplication of an existing data type. Also, if you register your new IFF type, it is more likely that it will be adopted as an IFF standard that other applications will use. For example, the ANIM form came from third party developers who proposed and refined the format. Now ANIM is the de facto standard for animation files.
- For an excellent example of a third party FORM specification, see the WORD FORM. For an example of chunk descriptions, examine the 8SVX FORM's SEQN and FADE chunks.
- Note that even you don't plan to release the specifications of your FORM or chunk, you must still register the name with the AmigaOS development team. This is the only way to prevent name conflicts in IFF files. You should register your FORM and chunk names before finalizing your product and its documentation in case there is a name conflict with an existing IFF type.
- Distribute final specifications to the developer community.
- Once you have registered your FORM or chunk with the AmigaOS development team, you should release the specifications of the chunk to the developer community. Although the AmigaOS development team publishes FORMs and chunks online developers should not rely on this method to distribute their IFF type specification. One of the most efficient ways to distribute your specification is to include it in your application's documentation. Distributing the specification will increase the probability of your FORM or chunk becoming a standard.
Third party FORMs
- The following is an alphabetical list of registered FORMs, generic chunks (shown as (any).chunkname), and registered new chunks for existing FORMs (shown as formname.chunkname). The center column describes where additional information on the FORM or chunk may be found. Items marked “EA IFF” are described in the main chapters of the EA IFF specs. Those marked “IFF TP” are described in the third-party specifications section. Items marked “propos” are submitted proposals, some of which are private. And items marked with “—” are private or yet unreleased specifications.
Chunk ID | Reference | Description |
---|---|---|
(any).ANNO | IFF Standard | EA IFF 85 generic annotation chunk |
(any).AUTH | IFF Standard | EA IFF 85 generic author chunk |
(any).CHRS | IFF Standard | EA IFF 85 generic character string chunk |
(any).CSET | IFF_TP | chunk for specifying character set |
(any).FRED | -- | Private ASDG global chunk |
(any).FVER | IFF_TP | chunk for 2.0 VERSION string of an IFF file |
(any).HLID | IFF_TP | HotLink IDentification (Soft-Logik) |
(any).INFO | propos | This chunk contains data usually found in a file's .info file |
(any).JUNK | IFF_TP | Always ignore this chunk |
(any).UTF8 | IFF_TP | UTF-8 character text |
(any).NAME | IFF Standard | EA IFF 85 generic name of art, music, etc. chunk |
(any).TEXT | IFF Standard | EA IFF 85 generic unformatted ASCII text chunk |
(any).(c) | IFF Standard | EA IFF 85 generic copyright text chunk |
8SVX | EA_IFF | EA IFF 85 8-bit sound sample form |
8SVX.CHAN.PAN | IFF_TP | Stereo chunks for 8SVX form |
8SVX.SEQN.FADE | IFF_TP | Looping chunks for 8SVX form |
ACBM | IFF_TP | Amiga Contiguous Bitmap form |
AHAM | ---- | unregistered (???) |
AHIM | private | AHI Modes |
AHIM.AUDN | private | AUDio driver Name |
AHIM.AUDD | private | AUDio driver Data |
AHIM.AUDM | private | AUDio Mode |
AIFF | IFF_TP | Audio 1-32 bit samples (Mac, Apple II, Synthia Pro) |
AIFF.COMM | IFF_TP | Describes fundamental parameters of the sampled sound |
AIFF.SSND | IFF_TP | Contains the actual sample frames |
ANBM | IFF_TP | Animated bitmap form (Framer, Deluxe Video) |
ANIM | IFF_TP | Cel animation form |
ANIM.brush | IFF_TP | ANIM brush format |
ANIM.op6 | IFF_TP | Stereo (3D) animations |
ANIM.op7 | IFF_TP | Maximum playback speed and acceptable packing rates |
ANIM.op8 | IFF_TP | Maximum playback speed and acceptable packing rates. Easier to use than ANIM.op7 |
ARC | propos | archive format proposal (old) |
ARES | ---- | unregistered (???) |
ATXT | ---- | temporarily reserved |
AVCF | private | AmigaVision Flow format (currently private) |
BANK | ---- | Soundquest Editor/Librarian MIDI Sysex dump |
BBSD | ---- | BBS Database, F. Patnaude, Jr., Phalanx Software |
C100 | ---- | Cloanto Italia private format |
CAT | IFF Standard | EA IFF 85 group identifier |
CELP | propos | For storage of compressed ZyXEL voice data (reserved) |
CHBM | ---- | Chunky bitmap (name reserved by Eric Lavitsky) |
CLIP | ---- | CAT CLIP to hold various formats in clipboard |
CMUS | propos | Common MUsical Score |
CPFM | ---- | Cloanto Personal FontMaker (doc in their manual) |
DCCL | ---- | DCTV paint clip |
DCPA | ---- | DCTV paint palette |
DCTV | ---- | DCTV raw picture file |
DECK | ---- | private format for Inovatronics CanDo |
DEEP | IFF_TP | Chunky pixel image files (used in TV Paint) |
DOC | ---- | unregistered (PageStream) |
DR2D | IFF_TP | 2D object standard format |
DSDR | ---- | unregistered (DrawStudio) |
DRAW | ---- | reserved by Jim Bayless, 12/90 |
DTYP | IFF_TP | DataTypes identification |
EXEC | propos | Proposed form for executable (loadseg-able) code |
FANT | IFF_TP | Fantavision movie format |
FAX3 | ---- | private GPSoftware FAX format, no longer used |
FAXX.GPHD | IFF_TP | Additional header info for FAXX forms |
FAXX | IFF_TP | Facsimile image form |
FIGR | ---- | Deluxe Video - reserved |
FILM | ---- | LIST FILM - For storing ILBMs with interleaved 8SVX audio |
FNTR | IFF Standard | EA IFF 85 reserved for raster font |
FNTV | IFF Standard | EA IFF 85 reserved for vector font |
FORM | IFF Standard | EA IFF 85 group identifier |
FTXT | IFF Standard | EA IFF 85 formatted text form |
GRYP | propos | byteplane storage proposal (copyrighted) |
GSCR | IFF Standard | EA IFF 85 reserved general music score |
GMS | IFF_TP | Gesture and Motion Signal GMS Web Site |
GUI | propos | user interface storage proposal (private) |
HEAD | IFF_TP | Flow - New Horizons Software |
ILBM | EA_IFF | EA IFF 85 raster bitmap form |
ILBM.3DCM | ---- | reserved by Haitex |
ILBM.3DPA | ---- | reserved by Haitex |
ILBM.ASDG | ---- | private ASDG application chunk |
ILBM.BHBA | ---- | private Photon Paint chunk (brushes) |
ILBM.BHCP | ---- | private Photon Paint chunk (screens) |
ILBM.BHSM | ---- | private Photon Paint chunk |
ILBM.CLUT | IFF_TP | Color Lookup Table chunk |
ILBM.CMYK | IFF_TP | Cyan, Magenta, Yellow, & Black color map (Soft-Logik) |
ILBM.CNAM | IFF_TP | Color naming chunk (Soft-Logik) |
ILBM.CTBL.DYCP | IFF_TP | Newtek Dynamic HAM color chunks |
ILBM.DCTV | ---- | reserved |
ILBM.DGVW | ---- | private Newtek DigiView chunk |
ILBM.DPI | IFF_TP | Dots per inch chunk |
ILBM.DPPV | IFF_TP | DPaint perspective chunk (EA) |
ILBM.DRNG | IFF_TP | DPaint IV enhanced color cycle chunk (EA) |
ILBM.EPSF | IFF_TP | Encapsulated Postscript chunk |
ILBM.PCHG | IFF_TP | Line by line palette control information (Sebastiano Vigna) |
ILBM.PRVW | propos | A mini duplicate ILBM used for preview (Gary Bonham) |
ILBM.TMAP | ---- | Transparency map (temporarily reserved) |
VTAG | propos | Viewmode tags chunk suggestion |
ILBM.XBMI | IFF_TP | eXtended BitMap Information (Soft-Logik) |
ILBM.XSSL | IFF_TP | Identifier chunk for 3D X-Specs image (Haitex) |
IOBJ | ---- | reserved by Seven Seas Software |
IODK | ---- | reserved for Jean-Marc Porchet at Merging Technologies |
ITRF | ---- | reserved |
JMOV | ---- | reserved for Merging Technologies |
LIST | IFF Standard | EA IFF 85 group identifier |
MFAX | ---- | reserved for TKR GmbH & Co. |
MIDI | ---- | Circum Design |
MOVI | ---- | LIST MOVI - private format |
MSCX | ---- | private Music-X format |
MSMP | ---- | temporarily reserved |
MTRX | IFF_TP | Numerical data storage (MathVision - Seven Seas) |
NSEQ | ---- | Numerical sequence (Stockhausen GmbH) |
OB3D | propos | Proposal for a standard 3D object format |
OCMP | IFF Standard | EA IFF 85 reserved computer prop |
OCPU | IFF Standard | EA IFF 85 reserved processor prop |
OPGM | IFF Standard | EA IFF 85 reserved program prop |
OSN | IFF Standard | EA IFF 85 reserved serial num. prop |
PGTB | IFF_TP | Program traceback (SAS Institute) |
PICS | IFF Standard | EA IFF 85 reserved Macintosh picture |
PLBM | IFF Standard | EA IFF 85 reserved obsolete name |
PMBC | propos | reserved for Black Belt Systems 91.12.01 |
PREF | ---- | Reserved by the AmigaOS Development Team for user preferences data, currently private |
PREF.AHIG | private | AHI Global preferences |
PREF.AHIU | private | AHI Unit preferences |
PROP | IFF Standard | EA IFF 85 group identifier |
PRSP | IFF_TP | DPaint IV perspective move form (EA) |
PTCH | ---- | Patch file format (SAS Institute) |
PTXT | ---- | temporarily reserved |
RGB4 | ---- | 4-bit RGB (format not available) |
RGBN and RGB8 | IFF_TP | RGB image forms, Turbo Silver (Impulse) |
RGBX | ---- | temporarily reserved |
ROXN | ---- | private animation form |
SAMP | IFF_TP | Sampled sound format |
SC3D | ---- | private scene format (Sculpt-3D) |
SHAK | ---- | private Shakespeare format |
SHO1 | ---- | reserved by Gary Bonham (private) |
SHOW | ---- | reserved by Gary Bonham (private) |
SMUS | EA_IFF | EA IFF 85 simple music score form |
SPLT | IFF_TP | ASDG's file SPLiTting system |
SSRE | ---- | reserved for Merging Technologies 92.05.04 |
SWRT | ---- | unregistered (???) |
SYTH | ---- | SoundQuest Master Librarian MIDI System driver |
TCDE | ---- | reserved by Merging Technologies |
TDDD | IFF_TP | 3D rendering data, Turbo Silver (Impulse) |
TERM | ---- | unregistered (???) |
TMUI | IFF_TP | Toolmaker IFF project file format (ToolMaker V1.19) |
TREE | IFF_TP | Storage of arbitrary data structures as trees (or nested lists) |
TRKR | propos | TRacKeR style music module format proposal |
UNAM | IFF Standard | EA IFF 85 reserved user name prop |
USCR | IFF Standard | EA IFF 85 reserved Uhuru score |
UVOX | IFF Standard | EA IFF 85 reserved Uhuru Mac voice |
VDEO | ---- | private Deluxe Video format |
WORD | IFF_TP | ProWrite document format (New Horizons) |
WOWO | ---- | unregistered (Wordworth) |
YAFA | ---- | unregistered animation format (Wildfire) |
YUVN | IFF_TP | For storage of Y:U:V image data (MacroSystems) |