/3rdparty/zlib/msdos/

alue='aaron-pci-cleanup'>aaron-pci-cleanup MAME - Multiple Arcade Machine Emulator
summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/sound/dac.cpp
blob: d6f40cff3ab071ec83ced21ce311576faef7bf0c (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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
// license:BSD-3-Clause
// copyright-holders:smf
/***************************************************************************

    dac.cpp

    Four quadrant multiplying DAC.

    Binary Weighted Resistor Network, R-2R Ladder & PWM

    Binary, Ones Complement, Twos Complement or Sign Magnitude coding

***************************************************************************/

#include "emu.h"

#define DAC_GENERATOR_EPILOG(_dac_type, _dac_class, _dac_description, _dac_shortname) \
DEFINE_DEVICE_TYPE(_dac_type, _dac_class, _dac_shortname, _dac_description)

#include "dac.h"


//-------------------------------------------------
//  dac_mapper_unsigned - map an unsigned value of
//  the given number of bits to a sample value
//-------------------------------------------------

stream_buffer::sample_t dac_mapper_unsigned(u32 input, u8 bits)
{
	stream_buffer::sample_t scale = 1.0 / stream_buffer::sample_t((bits > 1) ? (1 << bits) : 1);
	input &= (1 << bits) - 1;
	return stream_buffer::sample_t(input) * scale;
}


//-------------------------------------------------
//  dac_mapper_signed - map a signed value of
//  the given number of bits to a sample value
//-------------------------------------------------

stream_buffer::sample_t dac_mapper_signed(u32 input, u8 bits)
{
	return dac_mapper_unsigned(input ^ (1 << (bits - 1)), bits);
}


//-------------------------------------------------
//  dac_mapper_ones_complement - map a value where
//  the top bit indicates the lower bits should be
//  treated as a negative 1s complement
//-------------------------------------------------

stream_buffer::sample_t dac_mapper_ones_complement(u32 input, u8 bits)
{
	// this mapping assumes symmetric reference voltages,
	// which is true for all existing cases
	if (BIT(input, bits - 1))
		return 0.5 - 0.5 * dac_mapper_unsigned(~input, bits - 1);
	else
		return 0.5 + 0.5 * dac_mapper_unsigned(input, bits - 1);
}


//-------------------------------------------------
//  dac_mapper_ones_complement - map a value where
//  the top bit is a sign bit and the lower bits
//  are absolute magnitude
//-------------------------------------------------

stream_buffer::sample_t dac_mapper_sign_magnitude(u32 input, u8 bits)
{
	// this mapping assumes symmetric reference voltages,
	// which is true for all existing cases
	if (BIT(input, bits - 1))
		return 0.5 - 0.5 * dac_mapper_unsigned(input, bits - 1);
	else
		return 0.5 + 0.5 * dac_mapper_unsigned(input, bits - 1);
}


//-------------------------------------------------
//  dac_device_base - constructor
//-------------------------------------------------

dac_device_base::dac_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, u8 bits, dac_mapper_callback mapper, stream_buffer::sample_t gain) :
	device_t(mconfig, type, tag, owner, clock),
	device_sound_interface(mconfig, *this),
	m_stream(nullptr),
	m_curval(0),
	m_value_map(1 << bits),
	m_bits(bits),
	m_mapper(mapper),
	m_gain(gain),
	m_vref_base(0),
	m_vref_range(0)
{
}


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

void dac_device_base::device_start()
{
	// precompute all gain-applied values
	for (s32 code = 0; code < m_value_map.size(); code++)
		m_value_map[code] = m_mapper(code, m_bits) * m_gain;

	// determine the number of inputs
	int inputs = 0;
	if (m_vref_range == 0)
		inputs += 2;

	// create the stream
	m_stream = stream_alloc(inputs, 1, 48000 * 4, STREAM_DISABLE_INPUT_RESAMPLING);

	// save data
	save_item(NAME(m_curval));
}


//-------------------------------------------------
//  sound_stream_update - stream updates
//-------------------------------------------------

void dac_device_base::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
{
	auto &out = outputs[0];

	// rails are constant
	if (inputs.size() == 0)
	{
		out.fill(m_vref_base + m_curval * m_vref_range);
		return;
	}

	auto &pos = inputs[DAC_VREF_POS_INPUT];
	auto &neg = inputs[DAC_VREF_NEG_INPUT];

	// rails are streams but effectively constant
	if (pos.sample_rate() == SAMPLE_RATE_MINIMUM && neg.sample_rate() == SAMPLE_RATE_MINIMUM)
		out.fill(neg.get(0) + m_curval * (pos.get(0) - neg.get(0)));

	// rails are streams matching our output rate
	else if (pos.sample_rate() == out.sample_rate() && neg.sample_rate() == out.sample_rate())
	{
		for (int sampindex = 0; sampindex < out.samples(); sampindex++)
			out.put(sampindex, neg.get(sampindex) + m_curval * (pos.get(sampindex) - neg.get(sampindex)));
	}

	// other cases not supported for now
	else
		throw emu_fatalerror("Unsupported case: DAC input rate does not match DAC output rate");
}