// Simple 2-poles resonant filter
void CSoundFile::SetupChannelFilter(MODCHANNEL *pChn, BOOL bReset, int flt_modifier) const
//----------------------------------------------------------------------------------------
{
	float fc = (float)CutOffToFrequency(pChn->nCutOff, flt_modifier);
	float fs = (float)gdwMixingFreq;
	float fg, fb0, fb1;

	fc *= (float)(2.0*3.14159265358/fs);
	float dmpfac = pow(10.0f, -((24.0f / 128.0f)*(float)pChn->nResonance) / 20.0f);
	float d = (1.0f-2.0f*dmpfac)* fc;
	if (d>2.0) d = 2.0;
	d = (2.0f*dmpfac - d)/fc;
	float e = pow(1.0f/fc,2.0);

	fg=1/(1+d+e);
	fb0=(d+e+e)/(1+d+e);
	fb1=-e/(1+d+e);

	pChn->nFilter_A0 = (int)(fg * FILTER_PRECISION);
	pChn->nFilter_B0 = (int)(fb0 * FILTER_PRECISION);
	pChn->nFilter_B1 = (int)(fb1 * FILTER_PRECISION);

	if (bReset)
	{
		pChn->nFilter_Y1 = pChn->nFilter_Y2 = 0;
		pChn->nFilter_Y3 = pChn->nFilter_Y4 = 0;
	}
	pChn->dwFlags |= CHN_FILTER;
}
Ejemplo n.º 2
0
// Simple 2-poles resonant filter
void module_renderer::SetupChannelFilter(modplug::tracker::modchannel_t *pChn, bool bReset, int flt_modifier) const
//----------------------------------------------------------------------------------------
{
    float fs = (float)deprecated_global_mixing_freq;
    float fg, fb0, fb1, fc, dmpfac;

/*    if (pChn->pHeader) {
            fc = (float)CutOffToFrequency(pChn->nCutOff, flt_modifier);
            dmpfac = pow(10.0f, -((24.0f / 128.0f)*(float)pChn->nResonance) / 20.0f);
    } else {*/

            int cutoff = 0;
            if(!GetModFlag(MSF_OLDVOLSWING))
            {
                    if(pChn->nCutSwing)
                    {
                            pChn->nCutOff += pChn->nCutSwing;
                            if(pChn->nCutOff > 127) pChn->nCutOff = 127;
                            if(pChn->nCutOff < 0) pChn->nCutOff = 0;
                            pChn->nCutSwing = 0;
                    }
                    if(pChn->nResSwing)
                    {
                            pChn->nResonance += pChn->nResSwing;
                            if(pChn->nResonance > 127) pChn->nResonance = 127;
                            if(pChn->nResonance < 0) pChn->nResonance = 0;
                            pChn->nResSwing = 0;
                    }
                    cutoff = bad_max( bad_min((int)pChn->nCutOff,127), 0); // cap cutoff
                    fc = (float)CutOffToFrequency(cutoff, flt_modifier);
                    dmpfac = pow(10.0f, -((24.0f / 128.0f)*(float)((pChn->nResonance)&0x7F)) / 20.0f);
            }
            else
            {
                    cutoff = bad_max( bad_min((int)pChn->nCutOff+(int)pChn->nCutSwing,127), 0); // cap cutoff
                    fc = (float)CutOffToFrequency(cutoff, flt_modifier);
                    dmpfac = pow(10.0f, -((24.0f / 128.0f)*(float)((pChn->nResonance+pChn->nResSwing)&0x7F)) / 20.0f);
            }



//    }

    fc *= (float)(2.0*3.14159265358/fs);

    float d = (1.0f-2.0f*dmpfac)* fc;
    if (d>2.0) d = 2.0;
    d = (2.0f*dmpfac - d)/fc;
    float e = pow(1.0f/fc,2.0f);

    fg=1/(1+d+e);
    fb0=(d+e+e)/(1+d+e);
    fb1=-e/(1+d+e);

    switch(pChn->nFilterMode)
    {
    case FLTMODE_HIGHPASS:
            pChn->nFilter_A0 = 1.0f - fg;
            pChn->nFilter_B0 = fb0;
            pChn->nFilter_B1 = fb1;
            pChn->nFilter_HP = 1;
            break;
    default:
            pChn->nFilter_A0 = fg;
            pChn->nFilter_B0 = fb0;
            pChn->nFilter_B1 = fb1;
            pChn->nFilter_HP = 0;
    }

    if (bReset)
    {
            pChn->nFilter_Y1 = pChn->nFilter_Y2 = 0;
            pChn->nFilter_Y3 = pChn->nFilter_Y4 = 0;
    }
    pChn->flags |= CHN_FILTER;
}
Ejemplo n.º 3
0
// Simple 2-poles resonant filter
void CSoundFile::SetupChannelFilter(ModChannel *pChn, bool bReset, int flt_modifier) const
{
	int cutoff = (int)pChn->nCutOff + (int)pChn->nCutSwing;
	int resonance = (int)(pChn->nResonance & 0x7F) + (int)pChn->nResSwing;

	Limit(cutoff, 0, 127);
	Limit(resonance, 0, 127);

	if(!m_playBehaviour[kMPTOldSwingBehaviour])
	{
		pChn->nCutOff = (uint8)cutoff;
		pChn->nCutSwing = 0;
		pChn->nResonance = (uint8)resonance;
		pChn->nResSwing = 0;
	}

	// flt_modifier is in [-256, 256], so cutoff is in [0, 127 * 2] after this calculation.
	const int computedCutoff = cutoff * (flt_modifier + 256) / 256;

	// Filtering is only ever done in IT if either cutoff is not full or if resonance is set.
	if(m_playBehaviour[kITFilterBehaviour] && resonance == 0 && computedCutoff >= 254)
	{
		if(pChn->rowCommand.IsNote() && !pChn->rowCommand.IsPortamento() && !pChn->nMasterChn && m_SongFlags[SONG_FIRSTTICK])
		{
			// Z7F next to a note disables the filter, however in other cases this should not happen.
			// Test cases: filter-reset.it, filter-reset-carry.it, filter-nna.it
			pChn->dwFlags.reset(CHN_FILTER);
		}
		return;
	}

	pChn->dwFlags.set(CHN_FILTER);

	// 2 * damping factor
	const float dmpfac = std::pow(10.0f, -resonance * ((24.0f / 128.0f) / 20.0f));
	const float fc = CutOffToFrequency(cutoff, flt_modifier) * (2.0f * (float)M_PI);
	float d, e;
	if(m_playBehaviour[kITFilterBehaviour] && !m_SongFlags[SONG_EXFILTERRANGE])
	{
		const float r = m_MixerSettings.gdwMixingFreq / fc;

		d = dmpfac * r + dmpfac - 1.0f;
		e = r * r;
	} else
	{
		const float r = fc / m_MixerSettings.gdwMixingFreq;

		d = (1.0f - 2.0f * dmpfac) * r;
		LimitMax(d, 2.0f);
		d = (2.0f * dmpfac - d) / r;
		e = 1.0f / (r * r);
	}

	float fg = 1.0f / (1.0f + d + e);
	float fb0 = (d + e + e) / (1 + d + e);
	float fb1 = -e / (1.0f + d + e);

#if defined(MPT_INTMIXER)
#define FILTER_CONVERT(x) Util::Round<mixsample_t>((x) * (1 << MIXING_FILTER_PRECISION))
#else
#define FILTER_CONVERT(x) (x)
#endif

	switch(pChn->nFilterMode)
	{
	case FLTMODE_HIGHPASS:
		pChn->nFilter_A0 = FILTER_CONVERT(1.0f - fg);
		pChn->nFilter_B0 = FILTER_CONVERT(fb0);
		pChn->nFilter_B1 = FILTER_CONVERT(fb1);
#ifdef MPT_INTMIXER
		pChn->nFilter_HP = -1;
#else
		pChn->nFilter_HP = 1.0f;
#endif // MPT_INTMIXER
		break;

	default:
		pChn->nFilter_A0 = FILTER_CONVERT(fg);
		pChn->nFilter_B0 = FILTER_CONVERT(fb0);
		pChn->nFilter_B1 = FILTER_CONVERT(fb1);
#ifdef MPT_INTMIXER
		if(pChn->nFilter_A0 == 0)
			pChn->nFilter_A0 = 1;	// Prevent silence at low filter cutoff and very high sampling rate
		pChn->nFilter_HP = 0;
#else
		pChn->nFilter_HP = 0;
#endif // MPT_INTMIXER
		break;
	}
#undef FILTER_CONVERT

	if (bReset)
	{
		pChn->nFilter_Y[0][0] = pChn->nFilter_Y[0][1] = 0;
		pChn->nFilter_Y[1][0] = pChn->nFilter_Y[1][1] = 0;
	}

}
Ejemplo n.º 4
0
// Simple 2-poles resonant filter
void CSoundFile::SetupChannelFilter(ModChannel *pChn, bool bReset, int flt_modifier) const
//----------------------------------------------------------------------------------------
{
	int cutoff = (int)pChn->nCutOff + (int)pChn->nCutSwing;
	int resonance = (int)(pChn->nResonance & 0x7F) + (int)pChn->nResSwing;

	Limit(cutoff, 0, 127);
	Limit(resonance, 0, 127);

	if(!GetModFlag(MSF_OLDVOLSWING))
	{
		pChn->nCutOff = (uint8)cutoff;
		pChn->nCutSwing = 0;
		pChn->nResonance = (uint8)resonance;
		pChn->nResSwing = 0;
	}

	float d, e;

	// flt_modifier is in [-256, 256], so cutoff is in [0, 127 * 2] after this calculation.
	const int computedCutoff = cutoff * (flt_modifier + 256) / 256;

	// Filtering is only ever done in IT if either cutoff is not full or if resonance is set.
	if(IsCompatibleMode(TRK_IMPULSETRACKER) && resonance == 0 && computedCutoff >= 254)
	{
		if(pChn->rowCommand.IsNote() && !pChn->dwFlags[CHN_PORTAMENTO] && !pChn->nMasterChn && m_SongFlags[SONG_FIRSTTICK])
		{
			// Z7F next to a note disables the filter, however in other cases this should not happen.
			// Test cases: filter-reset.it, filter-reset-carry.it, filter-nna.it
			pChn->dwFlags.reset(CHN_FILTER);
		}
		return;
	}

	pChn->dwFlags.set(CHN_FILTER);

	if(UseITFilterMode())
	{
		const float freqParameterMultiplier = 128.0f / (24.0f * 256.0f);

		// 2 ^ (i / 24 * 256)
		float frequency = 110.0f * pow(2.0f, 0.25f + (float)computedCutoff * freqParameterMultiplier);
		LimitMax(frequency, (float)(m_MixerSettings.gdwMixingFreq / 2));
		const float r = (float)m_MixerSettings.gdwMixingFreq / (2.0f * (float)M_PI * frequency);

		d = ITResonanceTable[resonance] * r + ITResonanceTable[resonance] - 1.0f;
		e = r * r;
	} else
	{
		float fc = (float)CutOffToFrequency(cutoff, flt_modifier);
		const float dmpfac = pow(10.0f, -((24.0f / 128.0f) * (float)resonance) / 20.0f);

		fc *= (float)(2.0f * (float)M_PI / (float)m_MixerSettings.gdwMixingFreq);

		d = (1.0f - 2.0f * dmpfac) * fc;
		LimitMax(d, 2.0f);
		d = (2.0f * dmpfac - d) / fc;
		e = pow(1.0f / fc, 2.0f);
	}

	float fg = 1.0f / (1.0f + d + e);
	float fb0 = (d + e + e) / (1 + d + e);
	float fb1 = -e / (1.0f + d + e);

	switch(pChn->nFilterMode)
	{
	case FLTMODE_HIGHPASS:
		pChn->nFilter_A0 = 1.0f - fg;
		pChn->nFilter_B0 = fb0;
		pChn->nFilter_B1 = fb1;
		pChn->nFilter_HP = -1;
		break;

	default:
		pChn->nFilter_A0 = fg;
		pChn->nFilter_B0 = fb0;
		pChn->nFilter_B1 = fb1;
		pChn->nFilter_HP = 0;
		break;
	}
	
	if (bReset)
	{
		pChn->nFilter_Y1 = pChn->nFilter_Y2 = 0;
		pChn->nFilter_Y3 = pChn->nFilter_Y4 = 0;
	}

}