aboutsummaryrefslogtreecommitdiff
path: root/Src/external_dependencies/openmpt-trunk/soundlib/S3MTools.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/external_dependencies/openmpt-trunk/soundlib/S3MTools.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/external_dependencies/openmpt-trunk/soundlib/S3MTools.cpp')
-rw-r--r--Src/external_dependencies/openmpt-trunk/soundlib/S3MTools.cpp147
1 files changed, 147 insertions, 0 deletions
diff --git a/Src/external_dependencies/openmpt-trunk/soundlib/S3MTools.cpp b/Src/external_dependencies/openmpt-trunk/soundlib/S3MTools.cpp
new file mode 100644
index 00000000..27be5086
--- /dev/null
+++ b/Src/external_dependencies/openmpt-trunk/soundlib/S3MTools.cpp
@@ -0,0 +1,147 @@
+/*
+ * S3MTools.cpp
+ * ------------
+ * Purpose: Definition of S3M file structures and helper functions
+ * Notes : (currently none)
+ * Authors: OpenMPT Devs
+ * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
+ */
+
+
+#include "stdafx.h"
+#include "Loaders.h"
+#include "S3MTools.h"
+#include "../common/mptStringBuffer.h"
+
+
+OPENMPT_NAMESPACE_BEGIN
+
+// Convert an S3M sample header to OpenMPT's internal sample header.
+void S3MSampleHeader::ConvertToMPT(ModSample &mptSmp, bool isST3) const
+{
+ mptSmp.Initialize(MOD_TYPE_S3M);
+ mptSmp.filename = mpt::String::ReadBuf(mpt::String::maybeNullTerminated, filename);
+
+ if(sampleType == typePCM || sampleType == typeNone)
+ {
+ // Sample Length and Loops
+ if(sampleType == typePCM)
+ {
+ mptSmp.nLength = length;
+ mptSmp.nLoopStart = std::min(static_cast<SmpLength>(loopStart), mptSmp.nLength - 1);
+ mptSmp.nLoopEnd = std::min(static_cast<SmpLength>(loopEnd), mptSmp.nLength);
+ mptSmp.uFlags.set(CHN_LOOP, (flags & smpLoop) != 0);
+ }
+
+ if(mptSmp.nLoopEnd < 2 || mptSmp.nLoopStart >= mptSmp.nLoopEnd || mptSmp.nLoopEnd - mptSmp.nLoopStart < 1)
+ {
+ mptSmp.nLoopStart = mptSmp.nLoopEnd = 0;
+ mptSmp.uFlags.reset();
+ }
+ } else if(sampleType == typeAdMel)
+ {
+ OPLPatch patch;
+ std::memcpy(patch.data() + 0, mpt::as_raw_memory(length).data(), 4);
+ std::memcpy(patch.data() + 4, mpt::as_raw_memory(loopStart).data(), 4);
+ std::memcpy(patch.data() + 8, mpt::as_raw_memory(loopEnd).data(), 4);
+ mptSmp.SetAdlib(true, patch);
+ }
+
+ // Volume / Panning
+ mptSmp.nVolume = std::min(defaultVolume.get(), uint8(64)) * 4;
+
+ // C-5 frequency
+ mptSmp.nC5Speed = c5speed;
+ if(isST3)
+ {
+ // ST3 ignores or clamps the high 16 bits depending on the instrument type
+ if(sampleType == typeAdMel)
+ mptSmp.nC5Speed &= 0xFFFF;
+ else
+ LimitMax(mptSmp.nC5Speed, uint16_max);
+ }
+
+ if(mptSmp.nC5Speed == 0)
+ mptSmp.nC5Speed = 8363;
+ else if(mptSmp.nC5Speed < 1024)
+ mptSmp.nC5Speed = 1024;
+
+}
+
+
+// Convert OpenMPT's internal sample header to an S3M sample header.
+SmpLength S3MSampleHeader::ConvertToS3M(const ModSample &mptSmp)
+{
+ SmpLength smpLength = 0;
+ mpt::String::WriteBuf(mpt::String::maybeNullTerminated, filename) = mptSmp.filename;
+ memcpy(magic, "SCRS", 4);
+
+ if(mptSmp.uFlags[CHN_ADLIB])
+ {
+ memcpy(magic, "SCRI", 4);
+ sampleType = typeAdMel;
+ std::memcpy(mpt::as_raw_memory(length ).data(), mptSmp.adlib.data() + 0, 4);
+ std::memcpy(mpt::as_raw_memory(loopStart).data(), mptSmp.adlib.data() + 4, 4);
+ std::memcpy(mpt::as_raw_memory(loopEnd ).data(), mptSmp.adlib.data() + 8, 4);
+ } else if(mptSmp.HasSampleData())
+ {
+ sampleType = typePCM;
+ length = mpt::saturate_cast<uint32>(mptSmp.nLength);
+ loopStart = mpt::saturate_cast<uint32>(mptSmp.nLoopStart);
+ loopEnd = mpt::saturate_cast<uint32>(mptSmp.nLoopEnd);
+
+ smpLength = length;
+
+ flags = (mptSmp.uFlags[CHN_LOOP] ? smpLoop : 0);
+ if(mptSmp.uFlags[CHN_16BIT])
+ {
+ flags |= smp16Bit;
+ }
+ if(mptSmp.uFlags[CHN_STEREO])
+ {
+ flags |= smpStereo;
+ }
+ } else
+ {
+ sampleType = typeNone;
+ }
+
+ defaultVolume = static_cast<uint8>(std::min(static_cast<uint16>(mptSmp.nVolume / 4), uint16(64)));
+ if(mptSmp.nC5Speed != 0)
+ {
+ c5speed = mptSmp.nC5Speed;
+ } else
+ {
+ c5speed = ModSample::TransposeToFrequency(mptSmp.RelativeTone, mptSmp.nFineTune);
+ }
+
+ return smpLength;
+}
+
+
+// Retrieve the internal sample format flags for this sample.
+SampleIO S3MSampleHeader::GetSampleFormat(bool signedSamples) const
+{
+ if(pack == S3MSampleHeader::pADPCM && !(flags & S3MSampleHeader::smp16Bit) && !(flags & S3MSampleHeader::smpStereo))
+ {
+ // MODPlugin :(
+ return SampleIO(SampleIO::_8bit, SampleIO::mono, SampleIO::littleEndian, SampleIO::ADPCM);
+ } else
+ {
+ return SampleIO(
+ (flags & S3MSampleHeader::smp16Bit) ? SampleIO::_16bit : SampleIO::_8bit,
+ (flags & S3MSampleHeader::smpStereo) ? SampleIO::stereoSplit : SampleIO::mono,
+ SampleIO::littleEndian,
+ signedSamples ? SampleIO::signedPCM : SampleIO::unsignedPCM);
+ }
+}
+
+
+// Calculate the sample position in file
+uint32 S3MSampleHeader::GetSampleOffset() const
+{
+ return (dataPointer[1] << 4) | (dataPointer[2] << 12) | (dataPointer[0] << 20);
+}
+
+
+OPENMPT_NAMESPACE_END