diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/external_dependencies/openmpt-trunk/soundlib/S3MTools.cpp | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-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.cpp | 147 |
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 |