All files / src/mod types.ts

100% Statements 5/5
100% Branches 0/0
100% Functions 0/0
100% Lines 5/5

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256  1x 1x   1x                                                           1x                                                                                                                                     1x                                                                                                                                                                                                                                                                                                                    
import { Effect } from "../midi/types";
 
// NTSC = 7159090.5 PAL = 7093789.2;
export const PAL_CLOCK = 7093789.2;
// export const SAMPLE_RATE_BASE = 8287;
// export const SEMI_TONE = 1.0595;
 
/**
 * Standard original 4 channel MODs start with M.K.
 * 
 * There are two forms of modules produced by StarTrekker - 4-channel and 8-channel. 
 * 4-channel mods are just the classic Amiga Module format with the ID string "FLT4" instead of "M.K.". 
 * The 8-channel format is slightly different it can be identified by use of the ID string "FLT8". 
 * 
 * M.K. 	Standard 4-channel module
 * 2CHN 	2-channel FastTracker module
 * 6CHN 	6-channel FastTracker module
 * 8CHN 	8-channel FastTracker module
 * CD81 	8-channel Falcon module
 * FLT4 	4-channel Startrekker module
 * FLT8 	8-channel Startrekker module
 * M!K! 	>64 pattern ProTracker module
 * OCTA 	8-channel module
 * TDZx 	1, 2 or 3-channel TakeTracker module
 * xCHN 	5, 7 or 9-channel TakeTracker module
 * xxCH 	10, 12... 32-channel FastTracker module
 * xxCH 	11, 13 or 15-channel TakeTracker module
 * 
 * @see http://fileformats.archiveteam.org/wiki/Amiga_Module
 */
export type ModType = 'M.K.' | '2CHN' | '6CHN' | '8CHN' | 'FLT4' | 'FLT8' | 'CD81' | 'M!K!' | 'OCTA';
 
export type Song = {
  title: string,
  /** The number of patterns in the song 0-0x80 */
  length: number,
  /** 0-127 - each hold a number from 0-63 that tell
   * the tracker what pattern to play at that position
   */
  positions: Array<number>,
  patterns: Pattern[],
  /** 
   * If this position contains 'M.K.','8CHN', '4CHN',
   * '6CHN','FLT4' or 'FLT8' the module 
   * has 31 instruments. */
  type: ModType,
  /** Sample meta data */
  samples: Sample[],
  /** Raw audio data. Can go into channel data to
   * play the actual audio data */
  sampleBuffers: Int8Array[];
}
 
export type Sample = {
  name: string,
  /** In bytes 
   * ProTracker boundaries (including 64kb max sample length), although can save 
   * 2–32 channels */
  length: number,
  /**
   * Only the lower nibble is valid. Fine tune table :
   *  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
   *  0 +1 +2 +3 +4 +5 +6 +7 -8 -7 -6 -5 -4 -3 -2 -1
   */
  fineTune: number,
  /** Range between 0-1 (raw is $00-$40, or 0-64 decimal) */
  volume: number,
  /** In bytes */
  repeatPoint: number,
  /** In bytes */
  repeatLength: number,
}
 
/** 
 * Each Note has four bytes
 *  byte    0-3     4-7    8-11    12-15
 *        Chn #1  Chn #2  Chn #3  Chn #4
 */
export type Note = {
  sample: number,
  note: string,
  effect: Effect,
}
 
/** Each row has from 4 to 8 notes 
 * Assuming a four channel MOD file for now */
export type Row = Array<Note>;
 
/** Each pattern has 64 rows */
export type Pattern = Array<Row>;
 
/*
https://www.fileformat.info/format/mod/corion.htm
 
Protracker 16 note conversion table / MOD Period table (in decimal)
     +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
PT16 : I    1I    2I    3I    4I    5I    6I    7I    8I    9I   10I   11I   12I
MOD  : I 1712I 1616I 1524I 1440I 1356I 1280I 1208I 1140I 1076I 1016I  960I  906I
Note : I  C-0I  C#0I  D-0I  D#0I  E-0I  F-0I  F#0I  G-0I  G#0I  A-0I  A#0I  B-0I
     +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
     I   13I   14I   15I   16I   17I   18I   19I   20I   21I   22I   23I   24I
     I  856I  808I  762I  720I  678I  640I  604I  570I  538I  508I  480I  453I
     I  C-1I  C#1I  D-1I  D#1I  E-1I  F-1I  F#1I  G-1I  G#1I  A-1I  A#1I  B-1I
     +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
     I   25I   26I   27I   28I   29I   30I   31I   32I   33I   34I   35I   36I
     I  428I  404I  381I  360I  339I  320I  302I  285I  269I  254I  240I  226I
     I  C-2I  C#2I  D-2I  D#2I  E-2I  F-2I  F#2I  G-2I  G#2I  A-2I  A#2I  B-2I
     +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
     I   37I   38I   39I   40I   41I   42I   43I   44I   45I   46I   47I   48I
     I  214I  202I  190I  180I  170I  160I  151I  143I  135I  127I  120I  113I
     I  C-3I  C#3I  D-3I  D#3I  E-3I  F-3I  F#3I  G-3I  G#3I  A-3I  A#3I  B-3I
     +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
     I   49I   50I   51I   52I   53I   54I   55I   56I   57I   58I   59I   60I
     I  107I  101I   95I   90I   85I   80I   75I   71I   67I   63I   60I   56I
     I  C-4I  C#4I  D-4I  D#4I  E-4I  F-4I  F#4I  G-4I  G#4I  A-4I  A#4I  B-4I
     +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
*/
 
// NOTE: This table seems correct, based on the documentation, but milkytracker
// seems to export C-1 as C-3 so using the table at the bottom of the file instead.
// (until I can figure out who's doing what wrong :-/)
const NoteTableProper = new Map<number, string>([
  // C-0 (unused in basic MODs?)
  [1712, "C-0"],
  [1616, "C#0"],
  [1524, "D-0"],
  [1440, "D#0"],
  [1356, "E-0"],
  [1280, "F-0"],
  [1208, "F#0"],
  [1140, "G-0"],
  [1076, "G#0"],
  [1016, "A-0"],
  [960, "A#0"],
  [906, "B-0"],
  // C-1 --- C-3
  [856, "C-1"],
  [808, "C#1"],
  [762, "D-1"],
  [720, "D#1"],
  [678, "E-1"],
  [640, "F-1"],
  [604, "F#1"],
  [570, "G-1"],
  [538, "G#1"],
  [508, "A-1"],
  [480, "A#1"],
  [453, "B-1"],
  // C-2 --- C-4
  [428, "C-2"],
  [404, "C#2"],
  [381, "D-2"],
  [360, "D#2"],
  [339, "E-2"],
  [320, "F-2"],
  [302, "F#2"],
  [285, "G-2"],
  [269, "G#2"],
  [254, "A-2"],
  [240, "A#2"],
  [226, "B-2"],
  // C-3 -- C-5
  [214, "C-3"],
  [202, "C#3"],
  [190, "D-3"],
  [180, "D#3"],
  [170, "E-3"],
  [160, "F-3"],
  [151, "F#3"],
  [143, "G-3"],
  [135, "G#3"],
  [127, "A-3"],
  [120, "A#3"],
  [113, "B-3"],
  // C-4 -- (unused in basic MODs?)
  [107, "C-4"],
  [101, "C#4"],
  [95, "D-4"],
  [90, "D#4"],
  [85, "E-4"],
  [80, "F-4"],
  [75, "F#4"],
  [71, "G-4"],
  [67, "G#4"],
  [63, "A-4"],
  [60, "A#4"],
  [56, "B-4"],
]);
 
export const NoteTable = new Map<number, string>([
  // C-3 (need to support....)
  [1712, "C-3"],
  [1616, "C#3"],
  [1524, "D-3"],
  [1440, "D#3"],
  [1356, "E-3"],
  [1280, "F-3"],
  [1208, "F#3"],
  [1140, "G-3"],
  [1076, "G#3"],
  [1016, "A-3"],
  [960, "A#3"],
  [906, "B-3"],
  // C-4 (need to support....)
  [856, "C-4"],
  [808, "C#4"],
  [762, "D-4"],
  [720, "D#4"],
  [678, "E-4"],
  [640, "F-4"],
  [604, "F#4"],
  [570, "G-4"],
  [538, "G#4"],
  [508, "A-4"],
  [480, "A#4"],
  [453, "B-4"],
  // C-5 (need to support....)
  [428, "C-5"],
  [404, "C#5"],
  [381, "D-5"],
  [360, "D#5"],
  [339, "E-5"],
  [320, "F-5"],
  [302, "F#5"],
  [285, "G-5"],
  [269, "G#5"],
  [254, "A-5"],
  [240, "A#5"],
  [226, "B-5"],
  // C-6
  [214, "C-6"],
  [202, "C#6"],
  [190, "D-6"],
  [180, "D#6"],
  [170, "E-6"],
  [160, "F-6"],
  [151, "F#6"],
  [143, "G-6"],
  [135, "G#6"],
  [127, "A-6"],
  [120, "A#6"],
  [113, "B-6"],
  // C-7
  [107, "C-7"],
  [101, "C#7"],
  [95, "D-7"],
  [90, "D#7"],
  [85, "E-7"],
  [80, "F-7"],
  [75, "F#7"],
  [71, "G-7"],
  [67, "G#7"],
  [63, "A-7"],
  [60, "A#7"],
  [56, "B-7"],
]);