summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/sound/esqpump.c
blob: 0efc4a6d1fafb9c69e3dd11606c2b3b017f7bf0f (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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/***************************************************************************
 
  esqpump.c - Ensoniq 5505/5506 to 5510 interface.
 
  By Christian Brunschen
 
***************************************************************************/

#include "sound/esqpump.h"

const device_type ESQ_5505_5510_PUMP = &device_creator<esq_5505_5510_pump>;

esq_5505_5510_pump::esq_5505_5510_pump(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
	: device_t(mconfig, ESQ_5505_5510_PUMP, "ESQ_5505_5510_PUMP", tag, owner, clock, "esq_5505_5510_pump", __FILE__),
		device_sound_interface(mconfig, *this),
		m_esp_halted(true)
{
}

void esq_5505_5510_pump::device_start()
{
	logerror("Clock = %d\n", clock());

	m_stream = machine().sound().stream_alloc(*this, 8, 2, clock(), this);
	m_timer = timer_alloc(0);
	m_timer->enable(false);

#if PUMP_DETECT_SILENCE
	silent_for = 500;
	was_silence = 1;
#endif
#if !PUMP_FAKE_ESP_PROCESSING
	ticks_spent_processing = 0;
	samples_processed = 0;
#endif
#if PUMP_TRACK_SAMPLES
	last_samples = 0;
	last_ticks = osd_ticks();
	next_report_ticks = last_ticks + osd_ticks_per_second();
#endif

#if !PUMP_FAKE_ESP_PROCESSING && PUMP_REPLACE_ESP_PROGRAM
	memset(e, 0, 0x4000 * sizeof(e[0]));
	ei = 0;
#endif
}

void esq_5505_5510_pump::device_stop()
{
	m_timer->enable(false);
}

void esq_5505_5510_pump::device_reset()
{
	INT64 nsec_per_sample = 100 * 16 * 21;
	attotime sample_time(0, 1000000000 * nsec_per_sample);
	attotime initial_delay(0, 0);

	m_timer->adjust(initial_delay, 0, sample_time);
	m_timer->enable(true);
}

void esq_5505_5510_pump::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
{
	if (samples != 1) {
		logerror("Pump: request for %d samples\n", samples);
	}

	stream_sample_t *left = outputs[0], *right = outputs[1];
	for (int i = 0; i < samples; i++)
	{
#define SAMPLE_SHIFT 4
	    // anything for the 'aux' output?
		INT16 l = inputs[0][i] >> SAMPLE_SHIFT;
		INT16 r = inputs[1][i] >> SAMPLE_SHIFT;

		// push the samples into the ESP
		m_esp->ser_w(0, inputs[2][i] >> SAMPLE_SHIFT);
		m_esp->ser_w(1, inputs[3][i] >> SAMPLE_SHIFT);
		m_esp->ser_w(2, inputs[4][i] >> SAMPLE_SHIFT);
		m_esp->ser_w(3, inputs[5][i] >> SAMPLE_SHIFT);
		m_esp->ser_w(4, inputs[6][i] >> SAMPLE_SHIFT);
		m_esp->ser_w(5, inputs[7][i] >> SAMPLE_SHIFT);

#if PUMP_FAKE_ESP_PROCESSING
		m_esp->ser_w(6, m_esp->ser_r(0) + m_esp->ser_r(2) + m_esp->ser_r(4));
		m_esp->ser_w(7, m_esp->ser_r(1) + m_esp->ser_r(3) + m_esp->ser_r(5));
#else
		if (!m_esp_halted) {
			logerror("passing one sample through ESP\n");
			osd_ticks_t a = osd_ticks();
			m_esp->run_once();
			osd_ticks_t b = osd_ticks();
			ticks_spent_processing += (b - a);
			samples_processed++;
		}
#endif

		// read the processed result from the ESP and add to the saved AUX data
		INT16 ll = m_esp->ser_r(6);
		INT16 rr = m_esp->ser_r(7);
		l += ll;
		r += rr;

#if !PUMP_FAKE_ESP_PROCESSING && PUMP_REPLACE_ESP_PROGRAM
		// if we're processing the fake program through the ESP, the result should just be that of adding the inputs
		INT32 el = (inputs[2][i]) + (inputs[4][i]) + (inputs[6][i]);
		INT32 er = (inputs[3][i]) + (inputs[5][i]) + (inputs[7][i]);
		INT32 e_next = el + er;
		e[(ei + 0x1d0f) % 0x4000] = e_next;
		
		if (l != e[ei]) {
			fprintf(stderr, "expected (%d) but have (%d)\n", e[ei], l);
		}
		ei = (ei + 1) % 0x4000;
#endif

		// write the combined data to the output
		*left++  = l;
		*right++ = r;
	}

#if PUMP_DETECT_SILENCE
	for (int i = 0; i < samples; i++) {
		if (outputs[0][i] == 0 && outputs[1][i] == 0) {
			silent_for++;
		} else {
			silent_for = 0;
		}
	}
	bool silence = silent_for >= 500;
	if (was_silence != silence) {
		if (!silence) {
			fprintf(stderr, ".-*\n");
		} else {
			fprintf(stderr, "*-.\n");
		}
		was_silence = silence;
	}
#endif

#if PUMP_TRACK_SAMPLES
	last_samples += samples;
	osd_ticks_t now = osd_ticks();
	if (now >= next_report_ticks)
	{
		osd_ticks_t elapsed = now - last_ticks;
		osd_ticks_t tps = osd_ticks_per_second();
		fprintf(stderr, "Pump: %d samples in %" I64FMT "d ticks for %f Hz\n", last_samples, elapsed, last_samples * (double)tps / (double)elapsed);
		last_ticks = now;
		while (next_report_ticks <= now) {
			next_report_ticks += tps;
		}
		last_samples = 0;

#if !PUMP_FAKE_ESP_PROCESSING
		fprintf(stderr, "  ESP spent %" I64FMT "d ticks on %d samples, %f ticks per sample\n", ticks_spent_processing, samples_processed, (double)ticks_spent_processing / (double)samples_processed);
		ticks_spent_processing = 0;
		samples_processed = 0;
#endif
	}
#endif
}

void esq_5505_5510_pump::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) {
	// ecery time there's a new sample period, update the stream!
	m_stream->update();
}