// Remove DC offset float RemoveDCOffset(modplug::tracker::modsample_t& smp, SmpLength iStart, SmpLength iEnd, const MODTYPE modtype, module_renderer* const pSndFile) //---------------------------------------------- { if(smp.sample_data == nullptr || smp.length < 1) return 0; modplug::tracker::modsample_t* const pSmp = &smp; if (iEnd > pSmp->length) iEnd = pSmp->length; if (iStart > iEnd) iStart = iEnd; if (iStart == iEnd) { iStart = 0; iEnd = pSmp->length; } iStart *= pSmp->GetNumChannels(); iEnd *= pSmp->GetNumChannels(); const double dMaxAmplitude = (pSmp->GetElementarySampleSize() == 2) ? GetMaxAmplitude<int16_t>() : GetMaxAmplitude<int8_t>(); // step 1: Calculate offset. OffsetData oData = {0,0,0}; if(pSmp->GetElementarySampleSize() == 2) oData = CalculateOffset(reinterpret_cast<int16_t*>(pSmp->sample_data) + iStart, iEnd - iStart); else if(pSmp->GetElementarySampleSize() == 1) oData = CalculateOffset(reinterpret_cast<int8_t*>(pSmp->sample_data) + 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 / bad_max(dMax, -dMin); // step 2: centralize + normalize sample dOffset *= dMaxAmplitude * dAmplify; if(pSmp->GetElementarySampleSize() == 2) RemoveOffsetAndNormalize( reinterpret_cast<int16_t*>(pSmp->sample_data) + iStart, iEnd - iStart, dOffset, dAmplify); else if(pSmp->GetElementarySampleSize() == 1) RemoveOffsetAndNormalize( reinterpret_cast<int8_t*>(pSmp->sample_data) + iStart, iEnd - iStart, dOffset, dAmplify); // step 3: adjust global vol (if available) if((modtype & (MOD_TYPE_IT | MOD_TYPE_MPT)) && (iStart == 0) && (iEnd == pSmp->length * pSmp->GetNumChannels())) { BEGIN_CRITICAL(); pSmp->global_volume = bad_min((uint16_t)(pSmp->global_volume / dAmplify), 64); for (modplug::tracker::chnindex_t i = 0; i < MAX_VIRTUAL_CHANNELS; i++) { if(pSndFile->Chn[i].sample_data == pSmp->sample_data) { pSndFile->Chn[i].nGlobalVol = pSmp->global_volume; } } END_CRITICAL(); } AdjustEndOfSample(smp, pSndFile); return fReportOffset; }
// 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; } }