1
0

Load_ams.cpp 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123
  1. /*
  2. * Load_ams.cpp
  3. * ------------
  4. * Purpose: AMS (Extreme's Tracker / Velvet Studio) module loader
  5. * Notes : Extreme was renamed to Velvet Development at some point,
  6. * and thus they also renamed their tracker from
  7. * "Extreme's Tracker" to "Velvet Studio".
  8. * While the two programs look rather similiar, the structure of both
  9. * programs' "AMS" format is significantly different in some places -
  10. * Velvet Studio is a rather advanced tracker in comparison to Extreme's Tracker.
  11. * The source code of Velvet Studio has been released into the
  12. * public domain in 2013: https://github.com/Patosc/VelvetStudio/commits/master
  13. * Authors: OpenMPT Devs
  14. * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
  15. */
  16. #include "stdafx.h"
  17. #include "Loaders.h"
  18. OPENMPT_NAMESPACE_BEGIN
  19. // Read AMS or AMS2 (newVersion = true) pattern. At least this part of the format is more or less identical between the two trackers...
  20. static void ReadAMSPattern(CPattern &pattern, bool newVersion, FileReader &patternChunk)
  21. {
  22. enum
  23. {
  24. emptyRow = 0xFF, // No commands on row
  25. endOfRowMask = 0x80, // If set, no more commands on this row
  26. noteMask = 0x40, // If set, no note+instr in this command
  27. channelMask = 0x1F, // Mask for extracting channel
  28. // Note flags
  29. readNextCmd = 0x80, // One more command follows
  30. noteDataMask = 0x7F, // Extract note
  31. // Command flags
  32. volCommand = 0x40, // Effect is compressed volume command
  33. commandMask = 0x3F, // Command or volume mask
  34. };
  35. // Effect translation table for extended (non-Protracker) effects
  36. static constexpr ModCommand::COMMAND effTrans[] =
  37. {
  38. CMD_S3MCMDEX, // Forward / Backward
  39. CMD_PORTAMENTOUP, // Extra fine slide up
  40. CMD_PORTAMENTODOWN, // Extra fine slide up
  41. CMD_RETRIG, // Retrigger
  42. CMD_NONE,
  43. CMD_TONEPORTAVOL, // Toneporta with fine volume slide
  44. CMD_VIBRATOVOL, // Vibrato with fine volume slide
  45. CMD_NONE,
  46. CMD_PANNINGSLIDE,
  47. CMD_NONE,
  48. CMD_VOLUMESLIDE, // Two times finder volume slide than Axx
  49. CMD_NONE,
  50. CMD_CHANNELVOLUME, // Channel volume (0...127)
  51. CMD_PATTERNBREAK, // Long pattern break (in hex)
  52. CMD_S3MCMDEX, // Fine slide commands
  53. CMD_NONE, // Fractional BPM
  54. CMD_KEYOFF, // Key off at tick xx
  55. CMD_PORTAMENTOUP, // Porta up, but uses all octaves (?)
  56. CMD_PORTAMENTODOWN, // Porta down, but uses all octaves (?)
  57. CMD_NONE,
  58. CMD_NONE,
  59. CMD_NONE,
  60. CMD_NONE,
  61. CMD_NONE,
  62. CMD_NONE,
  63. CMD_NONE,
  64. CMD_GLOBALVOLSLIDE, // Global volume slide
  65. CMD_NONE,
  66. CMD_GLOBALVOLUME, // Global volume (0... 127)
  67. };
  68. ModCommand dummy;
  69. for(ROWINDEX row = 0; row < pattern.GetNumRows(); row++)
  70. {
  71. PatternRow baseRow = pattern.GetRow(row);
  72. while(patternChunk.CanRead(1))
  73. {
  74. const uint8 flags = patternChunk.ReadUint8();
  75. if(flags == emptyRow)
  76. {
  77. break;
  78. }
  79. const CHANNELINDEX chn = (flags & channelMask);
  80. ModCommand &m = chn < pattern.GetNumChannels() ? baseRow[chn] : dummy;
  81. bool moreCommands = true;
  82. if(!(flags & noteMask))
  83. {
  84. // Read note + instr
  85. uint8 note = patternChunk.ReadUint8();
  86. moreCommands = (note & readNextCmd) != 0;
  87. note &= noteDataMask;
  88. if(note == 1)
  89. {
  90. m.note = NOTE_KEYOFF;
  91. } else if(note >= 2 && note <= 121 && newVersion)
  92. {
  93. m.note = note - 2 + NOTE_MIN;
  94. } else if(note >= 12 && note <= 108 && !newVersion)
  95. {
  96. m.note = note + 12 + NOTE_MIN;
  97. }
  98. m.instr = patternChunk.ReadUint8();
  99. }
  100. while(moreCommands)
  101. {
  102. // Read one more effect command
  103. ModCommand origCmd = m;
  104. const uint8 command = patternChunk.ReadUint8(), effect = (command & commandMask);
  105. moreCommands = (command & readNextCmd) != 0;
  106. if(command & volCommand)
  107. {
  108. m.volcmd = VOLCMD_VOLUME;
  109. m.vol = effect;
  110. } else
  111. {
  112. m.param = patternChunk.ReadUint8();
  113. if(effect < 0x10)
  114. {
  115. // PT commands
  116. m.command = effect;
  117. CSoundFile::ConvertModCommand(m);
  118. // Post-fix some commands
  119. switch(m.command)
  120. {
  121. case CMD_PANNING8:
  122. // 4-Bit panning
  123. m.command = CMD_PANNING8;
  124. m.param = (m.param & 0x0F) * 0x11;
  125. break;
  126. case CMD_VOLUME:
  127. m.command = CMD_NONE;
  128. m.volcmd = VOLCMD_VOLUME;
  129. m.vol = static_cast<ModCommand::VOL>(std::min((m.param + 1) / 2, 64));
  130. break;
  131. case CMD_MODCMDEX:
  132. if(m.param == 0x80)
  133. {
  134. // Break sample loop (cut after loop)
  135. m.command = CMD_NONE;
  136. } else
  137. {
  138. m.ExtendedMODtoS3MEffect();
  139. }
  140. break;
  141. }
  142. } else if(effect < 0x10 + mpt::array_size<decltype(effTrans)>::size)
  143. {
  144. // Extended commands
  145. m.command = effTrans[effect - 0x10];
  146. // Post-fix some commands
  147. switch(effect)
  148. {
  149. case 0x10:
  150. // Play sample forwards / backwards
  151. if(m.param <= 0x01)
  152. {
  153. m.param |= 0x9E;
  154. } else
  155. {
  156. m.command = CMD_NONE;
  157. }
  158. break;
  159. case 0x11:
  160. case 0x12:
  161. // Extra fine slides
  162. m.param = static_cast<ModCommand::PARAM>(std::min(uint8(0x0F), m.param) | 0xE0);
  163. break;
  164. case 0x15:
  165. case 0x16:
  166. // Fine slides
  167. m.param = static_cast<ModCommand::PARAM>((std::min(0x10, m.param + 1) / 2) | 0xF0);
  168. break;
  169. case 0x1E:
  170. // More fine slides
  171. switch(m.param >> 4)
  172. {
  173. case 0x1:
  174. // Fine porta up
  175. m.command = CMD_PORTAMENTOUP;
  176. m.param |= 0xF0;
  177. break;
  178. case 0x2:
  179. // Fine porta down
  180. m.command = CMD_PORTAMENTODOWN;
  181. m.param |= 0xF0;
  182. break;
  183. case 0xA:
  184. // Extra fine volume slide up
  185. m.command = CMD_VOLUMESLIDE;
  186. m.param = ((((m.param & 0x0F) + 1) / 2) << 4) | 0x0F;
  187. break;
  188. case 0xB:
  189. // Extra fine volume slide down
  190. m.command = CMD_VOLUMESLIDE;
  191. m.param = (((m.param & 0x0F) + 1) / 2) | 0xF0;
  192. break;
  193. default:
  194. m.command = CMD_NONE;
  195. break;
  196. }
  197. break;
  198. case 0x1C:
  199. // Adjust channel volume range
  200. m.param = static_cast<ModCommand::PARAM>(std::min((m.param + 1) / 2, 64));
  201. break;
  202. }
  203. }
  204. // Try merging commands first
  205. ModCommand::CombineEffects(m.command, m.param, origCmd.command, origCmd.param);
  206. if(ModCommand::GetEffectWeight(origCmd.command) > ModCommand::GetEffectWeight(m.command))
  207. {
  208. if(m.volcmd == VOLCMD_NONE && ModCommand::ConvertVolEffect(m.command, m.param, true))
  209. {
  210. // Volume column to the rescue!
  211. m.volcmd = m.command;
  212. m.vol = m.param;
  213. }
  214. m.command = origCmd.command;
  215. m.param = origCmd.param;
  216. }
  217. }
  218. }
  219. if(flags & endOfRowMask)
  220. {
  221. // End of row
  222. break;
  223. }
  224. }
  225. }
  226. }
  227. /////////////////////////////////////////////////////////////////////
  228. // AMS (Extreme's Tracker) 1.x loader
  229. // AMS File Header
  230. struct AMSFileHeader
  231. {
  232. uint8le versionLow;
  233. uint8le versionHigh;
  234. uint8le channelConfig;
  235. uint8le numSamps;
  236. uint16le numPats;
  237. uint16le numOrds;
  238. uint8le midiChannels;
  239. uint16le extraSize;
  240. };
  241. MPT_BINARY_STRUCT(AMSFileHeader, 11)
  242. // AMS Sample Header
  243. struct AMSSampleHeader
  244. {
  245. enum SampleFlags
  246. {
  247. smp16BitOld = 0x04, // AMS 1.0 (at least according to docs, I yet have to find such a file)
  248. smp16Bit = 0x80, // AMS 1.1+
  249. smpPacked = 0x03,
  250. };
  251. uint32le length;
  252. uint32le loopStart;
  253. uint32le loopEnd;
  254. uint8le panFinetune; // High nibble = pan position, low nibble = finetune value
  255. uint16le sampleRate;
  256. uint8le volume; // 0...127
  257. uint8le flags; // See SampleFlags
  258. // Convert sample header to OpenMPT's internal format.
  259. void ConvertToMPT(ModSample &mptSmp) const
  260. {
  261. mptSmp.Initialize();
  262. mptSmp.nLength = length;
  263. mptSmp.nLoopStart = std::min(loopStart, length);
  264. mptSmp.nLoopEnd = std::min(loopEnd, length);
  265. mptSmp.nVolume = (std::min(uint8(127), volume.get()) * 256 + 64) / 127;
  266. if(panFinetune & 0xF0)
  267. {
  268. mptSmp.nPan = (panFinetune & 0xF0);
  269. mptSmp.uFlags = CHN_PANNING;
  270. }
  271. mptSmp.nC5Speed = 2 * sampleRate;
  272. if(sampleRate == 0)
  273. {
  274. mptSmp.nC5Speed = 2 * 8363;
  275. }
  276. uint32 newC4speed = ModSample::TransposeToFrequency(0, MOD2XMFineTune(panFinetune & 0x0F));
  277. mptSmp.nC5Speed = (mptSmp.nC5Speed * newC4speed) / 8363;
  278. if(mptSmp.nLoopStart < mptSmp.nLoopEnd)
  279. {
  280. mptSmp.uFlags.set(CHN_LOOP);
  281. }
  282. if(flags & (smp16Bit | smp16BitOld))
  283. {
  284. mptSmp.uFlags.set(CHN_16BIT);
  285. }
  286. }
  287. };
  288. MPT_BINARY_STRUCT(AMSSampleHeader, 17)
  289. static bool ValidateHeader(const AMSFileHeader &fileHeader)
  290. {
  291. if(fileHeader.versionHigh != 0x01)
  292. {
  293. return false;
  294. }
  295. return true;
  296. }
  297. static uint64 GetHeaderMinimumAdditionalSize(const AMSFileHeader &fileHeader)
  298. {
  299. return fileHeader.extraSize + 3u + fileHeader.numSamps * (1u + sizeof(AMSSampleHeader)) + fileHeader.numOrds * 2u + fileHeader.numPats * 4u;
  300. }
  301. CSoundFile::ProbeResult CSoundFile::ProbeFileHeaderAMS(MemoryFileReader file, const uint64 *pfilesize)
  302. {
  303. if(!file.CanRead(7))
  304. {
  305. return ProbeWantMoreData;
  306. }
  307. if(!file.ReadMagic("Extreme"))
  308. {
  309. return ProbeFailure;
  310. }
  311. AMSFileHeader fileHeader;
  312. if(!file.ReadStruct(fileHeader))
  313. {
  314. return ProbeWantMoreData;
  315. }
  316. if(!ValidateHeader(fileHeader))
  317. {
  318. return ProbeFailure;
  319. }
  320. return ProbeAdditionalSize(file, pfilesize, GetHeaderMinimumAdditionalSize(fileHeader));
  321. }
  322. bool CSoundFile::ReadAMS(FileReader &file, ModLoadingFlags loadFlags)
  323. {
  324. file.Rewind();
  325. if(!file.ReadMagic("Extreme"))
  326. {
  327. return false;
  328. }
  329. AMSFileHeader fileHeader;
  330. if(!file.ReadStruct(fileHeader))
  331. {
  332. return false;
  333. }
  334. if(!ValidateHeader(fileHeader))
  335. {
  336. return false;
  337. }
  338. if(!file.CanRead(mpt::saturate_cast<FileReader::off_t>(GetHeaderMinimumAdditionalSize(fileHeader))))
  339. {
  340. return false;
  341. }
  342. if(!file.Skip(fileHeader.extraSize))
  343. {
  344. return false;
  345. }
  346. if(loadFlags == onlyVerifyHeader)
  347. {
  348. return true;
  349. }
  350. InitializeGlobals(MOD_TYPE_AMS);
  351. m_SongFlags = SONG_ITCOMPATGXX | SONG_ITOLDEFFECTS;
  352. m_nChannels = (fileHeader.channelConfig & 0x1F) + 1;
  353. m_nSamples = fileHeader.numSamps;
  354. SetupMODPanning(true);
  355. m_modFormat.formatName = U_("Extreme's Tracker");
  356. m_modFormat.type = U_("ams");
  357. m_modFormat.madeWithTracker = MPT_UFORMAT("Extreme's Tracker {}.{}")(fileHeader.versionHigh, fileHeader.versionLow);
  358. m_modFormat.charset = mpt::Charset::CP437;
  359. std::vector<bool> packSample(fileHeader.numSamps);
  360. static_assert(MAX_SAMPLES > 255);
  361. for(SAMPLEINDEX smp = 1; smp <= GetNumSamples(); smp++)
  362. {
  363. AMSSampleHeader sampleHeader;
  364. file.ReadStruct(sampleHeader);
  365. sampleHeader.ConvertToMPT(Samples[smp]);
  366. packSample[smp - 1] = (sampleHeader.flags & AMSSampleHeader::smpPacked) != 0;
  367. }
  368. // Texts
  369. file.ReadSizedString<uint8le, mpt::String::spacePadded>(m_songName);
  370. // Read sample names
  371. for(SAMPLEINDEX smp = 1; smp <= GetNumSamples(); smp++)
  372. {
  373. file.ReadSizedString<uint8le, mpt::String::spacePadded>(m_szNames[smp]);
  374. }
  375. // Read channel names
  376. for(CHANNELINDEX chn = 0; chn < GetNumChannels(); chn++)
  377. {
  378. ChnSettings[chn].Reset();
  379. file.ReadSizedString<uint8le, mpt::String::spacePadded>(ChnSettings[chn].szName);
  380. }
  381. // Read pattern names and create patterns
  382. Patterns.ResizeArray(fileHeader.numPats);
  383. for(PATTERNINDEX pat = 0; pat < fileHeader.numPats; pat++)
  384. {
  385. char name[11];
  386. const bool ok = file.ReadSizedString<uint8le, mpt::String::spacePadded>(name);
  387. // Create pattern now, so name won't be reset later.
  388. if(Patterns.Insert(pat, 64) && ok)
  389. {
  390. Patterns[pat].SetName(name);
  391. }
  392. }
  393. // Read packed song message
  394. const uint16 packedLength = file.ReadUint16LE();
  395. if(packedLength && file.CanRead(packedLength))
  396. {
  397. std::vector<uint8> textIn;
  398. file.ReadVector(textIn, packedLength);
  399. std::string textOut;
  400. textOut.reserve(packedLength);
  401. for(auto c : textIn)
  402. {
  403. if(c & 0x80)
  404. {
  405. textOut.insert(textOut.end(), (c & 0x7F), ' ');
  406. } else
  407. {
  408. textOut.push_back(c);
  409. }
  410. }
  411. textOut = mpt::ToCharset(mpt::Charset::CP437, mpt::Charset::CP437AMS, textOut);
  412. // Packed text doesn't include any line breaks!
  413. m_songMessage.ReadFixedLineLength(mpt::byte_cast<const std::byte*>(textOut.c_str()), textOut.length(), 76, 0);
  414. }
  415. // Read Order List
  416. ReadOrderFromFile<uint16le>(Order(), file, fileHeader.numOrds);
  417. // Read patterns
  418. for(PATTERNINDEX pat = 0; pat < fileHeader.numPats && file.CanRead(4); pat++)
  419. {
  420. uint32 patLength = file.ReadUint32LE();
  421. FileReader patternChunk = file.ReadChunk(patLength);
  422. if((loadFlags & loadPatternData) && Patterns.IsValidPat(pat))
  423. {
  424. ReadAMSPattern(Patterns[pat], false, patternChunk);
  425. }
  426. }
  427. if(loadFlags & loadSampleData)
  428. {
  429. // Read Samples
  430. for(SAMPLEINDEX smp = 1; smp <= GetNumSamples(); smp++)
  431. {
  432. SampleIO(
  433. Samples[smp].uFlags[CHN_16BIT] ? SampleIO::_16bit : SampleIO::_8bit,
  434. SampleIO::mono,
  435. SampleIO::littleEndian,
  436. packSample[smp - 1] ? SampleIO::AMS : SampleIO::signedPCM)
  437. .ReadSample(Samples[smp], file);
  438. }
  439. }
  440. return true;
  441. }
  442. /////////////////////////////////////////////////////////////////////
  443. // AMS (Velvet Studio) 2.0 - 2.02 loader
  444. // AMS2 File Header
  445. struct AMS2FileHeader
  446. {
  447. enum FileFlags
  448. {
  449. linearSlides = 0x40,
  450. };
  451. uint8le versionLow; // Version of format (Hi = MainVer, Low = SubVer e.g. 0202 = 2.02)
  452. uint8le versionHigh; // ditto
  453. uint8le numIns; // Nr of Instruments (0-255)
  454. uint16le numPats; // Nr of Patterns (1-1024)
  455. uint16le numOrds; // Nr of Positions (1-65535)
  456. // Rest of header differs between format revision 2.01 and 2.02
  457. };
  458. MPT_BINARY_STRUCT(AMS2FileHeader, 7)
  459. // AMS2 Instument Envelope
  460. struct AMS2Envelope
  461. {
  462. uint8 speed; // Envelope speed (currently not supported, always the same as current BPM)
  463. uint8 sustainPoint; // Envelope sustain point
  464. uint8 loopStart; // Envelope loop Start
  465. uint8 loopEnd; // Envelope loop End
  466. uint8 numPoints; // Envelope length
  467. // Read envelope and do partial conversion.
  468. void ConvertToMPT(InstrumentEnvelope &mptEnv, FileReader &file)
  469. {
  470. file.ReadStruct(*this);
  471. // Read envelope points
  472. uint8 data[64][3];
  473. file.ReadStructPartial(data, numPoints * 3);
  474. if(numPoints <= 1)
  475. {
  476. // This is not an envelope.
  477. return;
  478. }
  479. static_assert(MAX_ENVPOINTS >= std::size(data));
  480. mptEnv.resize(std::min(numPoints, mpt::saturate_cast<uint8>(std::size(data))));
  481. mptEnv.nLoopStart = loopStart;
  482. mptEnv.nLoopEnd = loopEnd;
  483. mptEnv.nSustainStart = mptEnv.nSustainEnd = sustainPoint;
  484. for(uint32 i = 0; i < mptEnv.size(); i++)
  485. {
  486. if(i != 0)
  487. {
  488. mptEnv[i].tick = mptEnv[i - 1].tick + static_cast<uint16>(std::max(1, data[i][0] | ((data[i][1] & 0x01) << 8)));
  489. }
  490. mptEnv[i].value = data[i][2];
  491. }
  492. }
  493. };
  494. MPT_BINARY_STRUCT(AMS2Envelope, 5)
  495. // AMS2 Instrument Data
  496. struct AMS2Instrument
  497. {
  498. enum EnvelopeFlags
  499. {
  500. envLoop = 0x01,
  501. envSustain = 0x02,
  502. envEnabled = 0x04,
  503. // Flag shift amounts
  504. volEnvShift = 0,
  505. panEnvShift = 1,
  506. vibEnvShift = 2,
  507. vibAmpMask = 0x3000,
  508. vibAmpShift = 12,
  509. fadeOutMask = 0xFFF,
  510. };
  511. uint8le shadowInstr; // Shadow Instrument. If non-zero, the value=the shadowed inst.
  512. uint16le vibampFadeout; // Vib.Amplify + Volume fadeout in one variable!
  513. uint16le envFlags; // See EnvelopeFlags
  514. void ApplyFlags(InstrumentEnvelope &mptEnv, EnvelopeFlags shift) const
  515. {
  516. const int flags = envFlags >> (shift * 3);
  517. mptEnv.dwFlags.set(ENV_ENABLED, (flags & envEnabled) != 0);
  518. mptEnv.dwFlags.set(ENV_LOOP, (flags & envLoop) != 0);
  519. mptEnv.dwFlags.set(ENV_SUSTAIN, (flags & envSustain) != 0);
  520. // "Break envelope" should stop the envelope loop when encountering a note-off... We can only use the sustain loop to emulate this behaviour.
  521. if(!(flags & envSustain) && (flags & envLoop) != 0 && (flags & (1 << (9 - shift * 2))) != 0)
  522. {
  523. mptEnv.nSustainStart = mptEnv.nLoopStart;
  524. mptEnv.nSustainEnd = mptEnv.nLoopEnd;
  525. mptEnv.dwFlags.set(ENV_SUSTAIN);
  526. mptEnv.dwFlags.reset(ENV_LOOP);
  527. }
  528. }
  529. };
  530. MPT_BINARY_STRUCT(AMS2Instrument, 5)
  531. // AMS2 Sample Header
  532. struct AMS2SampleHeader
  533. {
  534. enum SampleFlags
  535. {
  536. smpPacked = 0x03,
  537. smp16Bit = 0x04,
  538. smpLoop = 0x08,
  539. smpBidiLoop = 0x10,
  540. smpReverse = 0x40,
  541. };
  542. uint32le length;
  543. uint32le loopStart;
  544. uint32le loopEnd;
  545. uint16le sampledRate; // Whyyyy?
  546. uint8le panFinetune; // High nibble = pan position, low nibble = finetune value
  547. uint16le c4speed; // Why is all of this so redundant?
  548. int8le relativeTone; // q.e.d.
  549. uint8le volume; // 0...127
  550. uint8le flags; // See SampleFlags
  551. // Convert sample header to OpenMPT's internal format.
  552. void ConvertToMPT(ModSample &mptSmp) const
  553. {
  554. mptSmp.Initialize();
  555. mptSmp.nLength = length;
  556. mptSmp.nLoopStart = std::min(loopStart, length);
  557. mptSmp.nLoopEnd = std::min(loopEnd, length);
  558. mptSmp.nC5Speed = c4speed * 2;
  559. if(c4speed == 0)
  560. {
  561. mptSmp.nC5Speed = 8363 * 2;
  562. }
  563. // Why, oh why, does this format need a c5speed and transpose/finetune at the same time...
  564. uint32 newC4speed = ModSample::TransposeToFrequency(relativeTone, MOD2XMFineTune(panFinetune & 0x0F));
  565. mptSmp.nC5Speed = (mptSmp.nC5Speed * newC4speed) / 8363;
  566. mptSmp.nVolume = (std::min(volume.get(), uint8(127)) * 256 + 64) / 127;
  567. if(panFinetune & 0xF0)
  568. {
  569. mptSmp.nPan = (panFinetune & 0xF0);
  570. mptSmp.uFlags = CHN_PANNING;
  571. }
  572. if(flags & smp16Bit) mptSmp.uFlags.set(CHN_16BIT);
  573. if((flags & smpLoop) && mptSmp.nLoopStart < mptSmp.nLoopEnd)
  574. {
  575. mptSmp.uFlags.set(CHN_LOOP);
  576. if(flags & smpBidiLoop) mptSmp.uFlags.set(CHN_PINGPONGLOOP);
  577. if(flags & smpReverse) mptSmp.uFlags.set(CHN_REVERSE);
  578. }
  579. }
  580. };
  581. MPT_BINARY_STRUCT(AMS2SampleHeader, 20)
  582. // AMS2 Song Description Header
  583. struct AMS2Description
  584. {
  585. uint32le packedLen; // Including header
  586. uint32le unpackedLen;
  587. uint8le packRoutine; // 01
  588. uint8le preProcessing; // None!
  589. uint8le packingMethod; // RLE
  590. };
  591. MPT_BINARY_STRUCT(AMS2Description, 11)
  592. static bool ValidateHeader(const AMS2FileHeader &fileHeader)
  593. {
  594. if(fileHeader.versionHigh != 2 || fileHeader.versionLow > 2)
  595. {
  596. return false;
  597. }
  598. return true;
  599. }
  600. static uint64 GetHeaderMinimumAdditionalSize(const AMS2FileHeader &fileHeader)
  601. {
  602. return 36u + sizeof(AMS2Description) + fileHeader.numIns * 2u + fileHeader.numOrds * 2u + fileHeader.numPats * 4u;
  603. }
  604. CSoundFile::ProbeResult CSoundFile::ProbeFileHeaderAMS2(MemoryFileReader file, const uint64 *pfilesize)
  605. {
  606. if(!file.CanRead(7))
  607. {
  608. return ProbeWantMoreData;
  609. }
  610. if(!file.ReadMagic("AMShdr\x1A"))
  611. {
  612. return ProbeFailure;
  613. }
  614. if(!file.CanRead(1))
  615. {
  616. return ProbeWantMoreData;
  617. }
  618. const uint8 songNameLength = file.ReadUint8();
  619. if(!file.Skip(songNameLength))
  620. {
  621. return ProbeWantMoreData;
  622. }
  623. AMS2FileHeader fileHeader;
  624. if(!file.ReadStruct(fileHeader))
  625. {
  626. return ProbeWantMoreData;
  627. }
  628. if(!ValidateHeader(fileHeader))
  629. {
  630. return ProbeFailure;
  631. }
  632. return ProbeAdditionalSize(file, pfilesize, GetHeaderMinimumAdditionalSize(fileHeader));
  633. }
  634. bool CSoundFile::ReadAMS2(FileReader &file, ModLoadingFlags loadFlags)
  635. {
  636. file.Rewind();
  637. if(!file.ReadMagic("AMShdr\x1A"))
  638. {
  639. return false;
  640. }
  641. std::string songName;
  642. if(!file.ReadSizedString<uint8le, mpt::String::spacePadded>(songName))
  643. {
  644. return false;
  645. }
  646. AMS2FileHeader fileHeader;
  647. if(!file.ReadStruct(fileHeader))
  648. {
  649. return false;
  650. }
  651. if(!ValidateHeader(fileHeader))
  652. {
  653. return false;
  654. }
  655. if(!file.CanRead(mpt::saturate_cast<FileReader::off_t>(GetHeaderMinimumAdditionalSize(fileHeader))))
  656. {
  657. return false;
  658. }
  659. if(loadFlags == onlyVerifyHeader)
  660. {
  661. return true;
  662. }
  663. InitializeGlobals(MOD_TYPE_AMS);
  664. m_songName = songName;
  665. m_nInstruments = fileHeader.numIns;
  666. m_nChannels = 32;
  667. SetupMODPanning(true);
  668. m_modFormat.formatName = U_("Velvet Studio");
  669. m_modFormat.type = U_("ams");
  670. m_modFormat.madeWithTracker = MPT_UFORMAT("Velvet Studio {}.{}")(fileHeader.versionHigh.get(), mpt::ufmt::dec0<2>(fileHeader.versionLow.get()));
  671. m_modFormat.charset = mpt::Charset::CP437;
  672. uint16 headerFlags;
  673. if(fileHeader.versionLow >= 2)
  674. {
  675. uint16 tempo = std::max(uint16(32 << 8), file.ReadUint16LE()); // 8.8 tempo
  676. m_nDefaultTempo.SetRaw((tempo * TEMPO::fractFact) >> 8);
  677. m_nDefaultSpeed = std::max(uint8(1), file.ReadUint8());
  678. file.Skip(3); // Default values for pattern editor
  679. headerFlags = file.ReadUint16LE();
  680. } else
  681. {
  682. m_nDefaultTempo.Set(std::max(uint8(32), file.ReadUint8()));
  683. m_nDefaultSpeed = std::max(uint8(1), file.ReadUint8());
  684. headerFlags = file.ReadUint8();
  685. }
  686. m_SongFlags = SONG_ITCOMPATGXX | SONG_ITOLDEFFECTS | ((headerFlags & AMS2FileHeader::linearSlides) ? SONG_LINEARSLIDES : SongFlags(0));
  687. // Instruments
  688. std::vector<SAMPLEINDEX> firstSample; // First sample of instrument
  689. std::vector<uint16> sampleSettings; // Shadow sample map... Lo byte = Instrument, Hi byte, lo nibble = Sample index in instrument, Hi byte, hi nibble = Sample pack status
  690. enum
  691. {
  692. instrIndexMask = 0xFF, // Shadow instrument
  693. sampleIndexMask = 0x7F00, // Sample index in instrument
  694. sampleIndexShift = 8,
  695. packStatusMask = 0x8000, // If bit is set, sample is packed
  696. };
  697. static_assert(MAX_INSTRUMENTS > 255);
  698. for(INSTRUMENTINDEX ins = 1; ins <= m_nInstruments; ins++)
  699. {
  700. ModInstrument *instrument = AllocateInstrument(ins);
  701. if(instrument == nullptr
  702. || !file.ReadSizedString<uint8le, mpt::String::spacePadded>(instrument->name))
  703. {
  704. break;
  705. }
  706. uint8 numSamples = file.ReadUint8();
  707. uint8 sampleAssignment[120];
  708. MemsetZero(sampleAssignment); // Only really needed for v2.0, where the lowest and highest octave aren't cleared.
  709. if(numSamples == 0
  710. || (fileHeader.versionLow > 0 && !file.ReadArray(sampleAssignment)) // v2.01+: 120 Notes
  711. || (fileHeader.versionLow == 0 && !file.ReadRaw(mpt::span(sampleAssignment + 12, 96)).size())) // v2.0: 96 Notes
  712. {
  713. continue;
  714. }
  715. static_assert(mpt::array_size<decltype(instrument->Keyboard)>::size >= std::size(sampleAssignment));
  716. for(size_t i = 0; i < 120; i++)
  717. {
  718. instrument->Keyboard[i] = sampleAssignment[i] + GetNumSamples() + 1;
  719. }
  720. AMS2Envelope volEnv, panEnv, vibratoEnv;
  721. volEnv.ConvertToMPT(instrument->VolEnv, file);
  722. panEnv.ConvertToMPT(instrument->PanEnv, file);
  723. vibratoEnv.ConvertToMPT(instrument->PitchEnv, file);
  724. AMS2Instrument instrHeader;
  725. file.ReadStruct(instrHeader);
  726. instrument->nFadeOut = (instrHeader.vibampFadeout & AMS2Instrument::fadeOutMask);
  727. const int16 vibAmp = 1 << ((instrHeader.vibampFadeout & AMS2Instrument::vibAmpMask) >> AMS2Instrument::vibAmpShift);
  728. instrHeader.ApplyFlags(instrument->VolEnv, AMS2Instrument::volEnvShift);
  729. instrHeader.ApplyFlags(instrument->PanEnv, AMS2Instrument::panEnvShift);
  730. instrHeader.ApplyFlags(instrument->PitchEnv, AMS2Instrument::vibEnvShift);
  731. // Scale envelopes to correct range
  732. for(auto &p : instrument->VolEnv)
  733. {
  734. p.value = std::min(uint8(ENVELOPE_MAX), static_cast<uint8>((p.value * ENVELOPE_MAX + 64u) / 127u));
  735. }
  736. for(auto &p : instrument->PanEnv)
  737. {
  738. p.value = std::min(uint8(ENVELOPE_MAX), static_cast<uint8>((p.value * ENVELOPE_MAX + 128u) / 255u));
  739. }
  740. for(auto &p : instrument->PitchEnv)
  741. {
  742. #ifdef MODPLUG_TRACKER
  743. p.value = std::min(uint8(ENVELOPE_MAX), static_cast<uint8>(32 + Util::muldivrfloor(static_cast<int8>(p.value - 128), vibAmp, 255)));
  744. #else
  745. // Try to keep as much precision as possible... divide by 8 since that's the highest possible vibAmp factor.
  746. p.value = static_cast<uint8>(128 + Util::muldivrfloor(static_cast<int8>(p.value - 128), vibAmp, 8));
  747. #endif
  748. }
  749. // Sample headers - we will have to read them even for shadow samples, and we will have to load them several times,
  750. // as it is possible that shadow samples use different sample settings like base frequency or panning.
  751. const SAMPLEINDEX firstSmp = GetNumSamples() + 1;
  752. for(SAMPLEINDEX smp = 0; smp < numSamples; smp++)
  753. {
  754. if(firstSmp + smp >= MAX_SAMPLES)
  755. {
  756. file.Skip(sizeof(AMS2SampleHeader));
  757. break;
  758. }
  759. file.ReadSizedString<uint8le, mpt::String::spacePadded>(m_szNames[firstSmp + smp]);
  760. AMS2SampleHeader sampleHeader;
  761. file.ReadStruct(sampleHeader);
  762. sampleHeader.ConvertToMPT(Samples[firstSmp + smp]);
  763. uint16 settings = (instrHeader.shadowInstr & instrIndexMask)
  764. | ((smp << sampleIndexShift) & sampleIndexMask)
  765. | ((sampleHeader.flags & AMS2SampleHeader::smpPacked) ? packStatusMask : 0);
  766. sampleSettings.push_back(settings);
  767. }
  768. firstSample.push_back(firstSmp);
  769. m_nSamples = static_cast<SAMPLEINDEX>(std::min(MAX_SAMPLES - 1, GetNumSamples() + numSamples));
  770. }
  771. // Text
  772. // Read composer name
  773. if(std::string composer; file.ReadSizedString<uint8le, mpt::String::spacePadded>(composer))
  774. {
  775. m_songArtist = mpt::ToUnicode(mpt::Charset::CP437AMS2, composer);
  776. }
  777. // Channel names
  778. for(CHANNELINDEX chn = 0; chn < 32; chn++)
  779. {
  780. ChnSettings[chn].Reset();
  781. file.ReadSizedString<uint8le, mpt::String::spacePadded>(ChnSettings[chn].szName);
  782. }
  783. // RLE-Packed description text
  784. AMS2Description descriptionHeader;
  785. if(!file.ReadStruct(descriptionHeader))
  786. {
  787. return true;
  788. }
  789. if(descriptionHeader.packedLen > sizeof(descriptionHeader) && file.CanRead(descriptionHeader.packedLen - sizeof(descriptionHeader)))
  790. {
  791. const uint32 textLength = descriptionHeader.packedLen - static_cast<uint32>(sizeof(descriptionHeader));
  792. std::vector<uint8> textIn;
  793. file.ReadVector(textIn, textLength);
  794. // In the best case, every byte triplet can decode to 255 bytes, which is a ratio of exactly 1:85
  795. const uint32 maxLength = std::min(textLength, Util::MaxValueOfType(textLength) / 85u) * 85u;
  796. std::string textOut;
  797. textOut.reserve(std::min(maxLength, descriptionHeader.unpackedLen.get()));
  798. size_t readLen = 0;
  799. while(readLen < textLength)
  800. {
  801. uint8 c = textIn[readLen++];
  802. if(c == 0xFF && textLength - readLen >= 2)
  803. {
  804. c = textIn[readLen++];
  805. uint32 count = textIn[readLen++];
  806. textOut.insert(textOut.end(), count, c);
  807. } else
  808. {
  809. textOut.push_back(c);
  810. }
  811. }
  812. textOut = mpt::ToCharset(mpt::Charset::CP437, mpt::Charset::CP437AMS2, textOut);
  813. // Packed text doesn't include any line breaks!
  814. m_songMessage.ReadFixedLineLength(mpt::byte_cast<const std::byte*>(textOut.c_str()), textOut.length(), 74, 0);
  815. }
  816. // Read Order List
  817. ReadOrderFromFile<uint16le>(Order(), file, fileHeader.numOrds);
  818. // Read Patterns
  819. if(loadFlags & loadPatternData)
  820. Patterns.ResizeArray(fileHeader.numPats);
  821. for(PATTERNINDEX pat = 0; pat < fileHeader.numPats && file.CanRead(4); pat++)
  822. {
  823. uint32 patLength = file.ReadUint32LE();
  824. FileReader patternChunk = file.ReadChunk(patLength);
  825. if(loadFlags & loadPatternData)
  826. {
  827. const ROWINDEX numRows = patternChunk.ReadUint8() + 1;
  828. // We don't need to know the number of channels or commands.
  829. patternChunk.Skip(1);
  830. if(!Patterns.Insert(pat, numRows))
  831. {
  832. continue;
  833. }
  834. char patternName[11];
  835. if(patternChunk.ReadSizedString<uint8le, mpt::String::spacePadded>(patternName))
  836. Patterns[pat].SetName(patternName);
  837. ReadAMSPattern(Patterns[pat], true, patternChunk);
  838. }
  839. }
  840. if(!(loadFlags & loadSampleData))
  841. {
  842. return true;
  843. }
  844. // Read Samples
  845. for(SAMPLEINDEX smp = 0; smp < GetNumSamples(); smp++)
  846. {
  847. if((sampleSettings[smp] & instrIndexMask) == 0)
  848. {
  849. // Only load samples that aren't part of a shadow instrument
  850. SampleIO(
  851. (Samples[smp + 1].uFlags & CHN_16BIT) ? SampleIO::_16bit : SampleIO::_8bit,
  852. SampleIO::mono,
  853. SampleIO::littleEndian,
  854. (sampleSettings[smp] & packStatusMask) ? SampleIO::AMS : SampleIO::signedPCM)
  855. .ReadSample(Samples[smp + 1], file);
  856. }
  857. }
  858. // Copy shadow samples
  859. for(SAMPLEINDEX smp = 0; smp < GetNumSamples(); smp++)
  860. {
  861. INSTRUMENTINDEX sourceInstr = (sampleSettings[smp] & instrIndexMask);
  862. if(sourceInstr == 0
  863. || --sourceInstr >= firstSample.size())
  864. {
  865. continue;
  866. }
  867. SAMPLEINDEX sourceSample = ((sampleSettings[smp] & sampleIndexMask) >> sampleIndexShift) + firstSample[sourceInstr];
  868. if(sourceSample > GetNumSamples() || !Samples[sourceSample].HasSampleData())
  869. {
  870. continue;
  871. }
  872. // Copy over original sample
  873. ModSample &sample = Samples[smp + 1];
  874. ModSample &source = Samples[sourceSample];
  875. sample.uFlags.set(CHN_16BIT, source.uFlags[CHN_16BIT]);
  876. sample.nLength = source.nLength;
  877. if(sample.AllocateSample())
  878. {
  879. memcpy(sample.sampleb(), source.sampleb(), source.GetSampleSizeInBytes());
  880. }
  881. }
  882. return true;
  883. }
  884. /////////////////////////////////////////////////////////////////////
  885. // AMS Sample unpacking
  886. void AMSUnpack(const int8 * const source, size_t sourceSize, void * const dest, const size_t destSize, char packCharacter)
  887. {
  888. std::vector<int8> tempBuf(destSize, 0);
  889. size_t depackSize = destSize;
  890. // Unpack Loop
  891. {
  892. const int8 *in = source;
  893. int8 *out = tempBuf.data();
  894. size_t i = sourceSize, j = destSize;
  895. while(i != 0 && j != 0)
  896. {
  897. int8 ch = *(in++);
  898. if(--i != 0 && ch == packCharacter)
  899. {
  900. uint8 repCount = *(in++);
  901. repCount = static_cast<uint8>(std::min(static_cast<size_t>(repCount), j));
  902. if(--i != 0 && repCount)
  903. {
  904. ch = *(in++);
  905. i--;
  906. while(repCount-- != 0)
  907. {
  908. *(out++) = ch;
  909. j--;
  910. }
  911. } else
  912. {
  913. *(out++) = packCharacter;
  914. j--;
  915. }
  916. } else
  917. {
  918. *(out++) = ch;
  919. j--;
  920. }
  921. }
  922. // j should only be non-zero for truncated samples
  923. depackSize -= j;
  924. }
  925. // Bit Unpack Loop
  926. {
  927. int8 *out = tempBuf.data();
  928. uint16 bitcount = 0x80;
  929. size_t k = 0;
  930. uint8 *dst = static_cast<uint8 *>(dest);
  931. for(size_t i = 0; i < depackSize; i++)
  932. {
  933. uint8 al = *out++;
  934. uint16 dh = 0;
  935. for(uint16 count = 0; count < 8; count++)
  936. {
  937. uint16 bl = al & bitcount;
  938. bl = ((bl | (bl << 8)) >> ((dh + 8 - count) & 7)) & 0xFF;
  939. bitcount = ((bitcount | (bitcount << 8)) >> 1) & 0xFF;
  940. dst[k++] |= bl;
  941. if(k >= destSize)
  942. {
  943. k = 0;
  944. dh++;
  945. }
  946. }
  947. bitcount = ((bitcount | (bitcount << 8)) >> dh) & 0xFF;
  948. }
  949. }
  950. // Delta Unpack
  951. {
  952. int8 old = 0;
  953. int8 *out = static_cast<int8 *>(dest);
  954. for(size_t i = depackSize; i != 0; i--)
  955. {
  956. int pos = *reinterpret_cast<uint8 *>(out);
  957. if(pos != 128 && (pos & 0x80) != 0)
  958. {
  959. pos = -(pos & 0x7F);
  960. }
  961. old -= static_cast<int8>(pos);
  962. *(out++) = old;
  963. }
  964. }
  965. }
  966. OPENMPT_NAMESPACE_END