bool CopyWavChannel(ModSample &sample, const FileReader &file, size_t channelIndex, size_t numChannels, SampleConversion conv = SampleConversion()) { MPT_ASSERT(sample.GetNumChannels() == 1); MPT_ASSERT(sample.GetElementarySampleSize() == sizeof(typename SampleConversion::output_t)); const size_t offset = channelIndex * sizeof(typename SampleConversion::input_t) * SampleConversion::input_inc; if(sample.AllocateSample() == 0 || !file.CanRead(offset)) { return false; } const mpt::byte *inBuf = file.GetRawData<mpt::byte>(); CopySample<SampleConversion>(reinterpret_cast<typename SampleConversion::output_t*>(sample.pSample), sample.nLength, 1, inBuf + offset, file.BytesLeft() - offset, numChannels, conv); return true; }
// Remove DC offset float RemoveDCOffset(ModSample &smp, SmpLength iStart, SmpLength iEnd, const MODTYPE modtype, CSoundFile &sndFile) //--------------------------------------- { if(smp.pSample == nullptr || smp.nLength < 1) return 0; if (iEnd > smp.nLength) iEnd = smp.nLength; if (iStart > iEnd) iStart = iEnd; if (iStart == iEnd) { iStart = 0; iEnd = smp.nLength; } iStart *= smp.GetNumChannels(); iEnd *= smp.GetNumChannels(); const double dMaxAmplitude = (smp.GetElementarySampleSize() == 2) ? GetMaxAmplitude<int16>() : GetMaxAmplitude<int8>(); // step 1: Calculate offset. OffsetData oData = {0,0,0}; if(smp.GetElementarySampleSize() == 2) oData = CalculateOffset(static_cast<int16 *>(smp.pSample) + iStart, iEnd - iStart); else if(smp.GetElementarySampleSize() == 1) oData = CalculateOffset(static_cast<int8*>(smp.pSample) + iStart, iEnd - iStart); double dMin = oData.dMin, dMax = oData.dMax, dOffset = oData.dOffset; const float fReportOffset = (float)dOffset; if((int)(dOffset * dMaxAmplitude) == 0) return 0; // those will be changed... dMax += dOffset; dMin += dOffset; // ... and that might cause distortion, so we will normalize this. const double dAmplify = 1 / MAX(dMax, -dMin); // step 2: centralize + normalize sample dOffset *= dMaxAmplitude * dAmplify; if(smp.GetElementarySampleSize() == 2) RemoveOffsetAndNormalize( static_cast<int16 *>(smp.pSample) + iStart, iEnd - iStart, dOffset, dAmplify); else if(smp.GetElementarySampleSize() == 1) RemoveOffsetAndNormalize( static_cast<int8 *>(smp.pSample) + iStart, iEnd - iStart, dOffset, dAmplify); // step 3: adjust global vol (if available) if((modtype & (MOD_TYPE_IT | MOD_TYPE_MPT)) && (iStart == 0) && (iEnd == smp.nLength * smp.GetNumChannels())) { CriticalSection cs; smp.nGlobalVol = std::min((uint16)(smp.nGlobalVol / dAmplify), uint16(64)); for (CHANNELINDEX i = 0; i < MAX_CHANNELS; i++) { if(sndFile.m_PlayState.Chn[i].pModSample == &smp) { sndFile.m_PlayState.Chn[i].nInsVol = smp.nGlobalVol; if(sndFile.m_PlayState.Chn[i].pModInstrument) { sndFile.m_PlayState.Chn[i].nInsVol = (smp.nGlobalVol * sndFile.m_PlayState.Chn[i].pModInstrument->nGlobalVol) >> 6; } }