summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/sound/flt_rc.c
blob: 806792ccc179c389549687703fc01dc22bfa9457 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include "emu.h"
#include "flt_rc.h"


// device type definition
const device_type FILTER_RC = &device_creator<filter_rc_device>;


//**************************************************************************
//  LIVE DEVICE
//**************************************************************************

//-------------------------------------------------
//  filter_rc_device - constructor
//-------------------------------------------------

filter_rc_device::filter_rc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
	: device_t(mconfig, FILTER_RC, "RC Filter", tag, owner, clock, "filter_rc", __FILE__),
		device_sound_interface(mconfig, *this),
		m_stream(NULL),
		m_k(0),
		m_memory(0),
		m_type(FLT_RC_LOWPASS),
		m_R1(1),
		m_R2(1),
		m_R3(1),
		m_C(0)
{
}


//-------------------------------------------------
//  device_start - device-specific startup
//-------------------------------------------------

void filter_rc_device::device_start()
{
	m_stream = stream_alloc(1, 1, machine().sample_rate());
	recalc();
	
	save_item(NAME(m_k));
	save_item(NAME(m_memory));
	save_item(NAME(m_type));
	save_item(NAME(m_R1));
	save_item(NAME(m_R2));
	save_item(NAME(m_R3));
	save_item(NAME(m_C));
}


//-------------------------------------------------
//  sound_stream_update - handle a stream update
//-------------------------------------------------

void filter_rc_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
{
	stream_sample_t *src = inputs[0];
	stream_sample_t *dst = outputs[0];
	int memory = m_memory;

	switch (m_type)
	{
		case FLT_RC_LOWPASS:
			while (samples--)
			{
				memory += ((*src++ - memory) * m_k) / 0x10000;
				*dst++ = memory;
			}
			break;
		case FLT_RC_HIGHPASS:
		case FLT_RC_AC:
			while (samples--)
			{
				*dst++ = *src - memory;
				memory += ((*src++ - memory) * m_k) / 0x10000;
			}
			break;
	}
	m_memory = memory;
}


void filter_rc_device::recalc()
{
	double Req;

	switch (m_type)
	{
		case FLT_RC_LOWPASS:
			if (m_C == 0.0)
			{
				/* filter disabled */
				m_k = 0x10000;
				return;
			}
			Req = (m_R1 * (m_R2 + m_R3)) / (m_R1 + m_R2 + m_R3);
			break;
		case FLT_RC_HIGHPASS:
		case FLT_RC_AC:
			if (m_C == 0.0)
			{
				/* filter disabled */
				m_k = 0x0;
				m_memory = 0x0;
				return;
			}
			Req = m_R1;
			break;
		default:
			fatalerror("filter_rc_setRC: Wrong filter type %d\n", m_type);
	}

	/* Cut Frequency = 1/(2*Pi*Req*C) */
	/* k = (1-(EXP(-TIMEDELTA/RC)))    */
	m_k = 0x10000 - 0x10000 * (exp(-1 / (Req * m_C) / machine().sample_rate()));
}


void filter_rc_device::filter_rc_set_RC(int type, double R1, double R2, double R3, double C)
{
	m_stream->update();
	m_type = type;
	m_R1 = R1;
	m_R2 = R2;
	m_R3 = R3;
	m_C = C;
	recalc();
}

void filter_rc_device::static_set_rc(device_t &device, int type, double R1, double R2, double R3, double C)
{
	downcast<filter_rc_device &>(device).m_type = type;
	downcast<filter_rc_device &>(device).m_R1 = R1;
	downcast<filter_rc_device &>(device).m_R2 = R2;
	downcast<filter_rc_device &>(device).m_R3 = R3;
	downcast<filter_rc_device &>(device).m_C = C;
}