1 // license:BSD-3-Clause
2 // copyright-holders:Juergen Buchmueller, Derrick Renaud
3 /****************************************************************************
4  *
5  * Phoenix sound hardware simulation - still very ALPHA!
6  *
7  * If you find errors or have suggestions, please mail me.
8  * Juergen Buchmueller <pullmoll@t-online.de>
9  *
10  ****************************************************************************/
11 
12 
13 #include "emu.h"
14 #include "audio/phoenix.h"
15 
16 /****************************************************************************
17  * 4006
18  * Dual 4-bit and dual 5-bit serial-in serial-out shift registers.
19  *
20  *          +----------+
21  *      1D5 |1  +--+ 14| VCC
22  *     /1Q4 |2       13| 1Q1
23  *      CLK |3       12| 2Q0
24  *      2D4 |4  4006 11| 2Q0
25  *      3D4 |5       10| 3Q0
26  *      4D5 |6        9| 4Q0
27  *      GND |7        8| 4Q1
28  *          +----------+
29  *
30  * [This information is part of the GIICM]
31  *
32  * Pin 8 and 9 are connected to an EXOR gate and the inverted
33  * output (EXNOR) is fed back to pin 1 (and the pseudo polynomial output).
34  *
35  *      1D5          1Q1  2D4       2Q0  3D4       3Q0  4D5      4Q1 4Q0
36  *      +--+--+--+--+--+  +--+--+--+--+  +--+--+--+--+  +--+--+--+--+--+
37  *   +->| 0| 1| 2| 3| 4|->| 5| 6| 7| 8|->| 9|10|11|12|->|13|14|15|16|17|
38  *   |  +--+--+--+--+--+  +--+--+--+--+  +--+--+--+--+  +--+--+--+--+--+
39  *   |                                           ____             |  |
40  *   |                                          /    |------------+  |
41  *   +-----------------------------------------|EXNOR|               |
42  *                                              \____|---------------+
43  *
44  ****************************************************************************/
45 
46 #define VMIN    0
47 #define VMAX    32767
48 
49 
50 
51 DEFINE_DEVICE_TYPE(PHOENIX_SOUND, phoenix_sound_device, "phoenix_sound", "Phoenix Custom Sound")
52 
phoenix_sound_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)53 phoenix_sound_device::phoenix_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
54 	: device_t(mconfig, PHOENIX_SOUND, tag, owner, clock)
55 	, device_sound_interface(mconfig, *this)
56 	, m_discrete(*this, ":discrete")
57 	, m_tms(*this, ":tms")
58 {
59 }
60 
61 //-------------------------------------------------
62 //  device_start - device-specific startup
63 //-------------------------------------------------
64 
device_start()65 void phoenix_sound_device::device_start()
66 {
67 	int i, j;
68 	uint32_t shiftreg;
69 
70 	m_sound_latch_a = 0;
71 	memset(&m_c24_state, 0, sizeof(m_c24_state));
72 	memset(&m_c25_state, 0, sizeof(m_c25_state));
73 	memset(&m_noise_state, 0, sizeof(m_noise_state));
74 
75 	m_poly18 = std::make_unique<uint32_t[]>(1ul << (18-5));
76 
77 	shiftreg = 0;
78 	for( i = 0; i < (1ul << (18-5)); i++ )
79 	{
80 		uint32_t bits = 0;
81 		for( j = 0; j < 32; j++ )
82 		{
83 			bits = (bits >> 1) | (shiftreg << 31);
84 			if( ((shiftreg >> 16) & 1) == ((shiftreg >> 17) & 1) )
85 				shiftreg = (shiftreg << 1) | 1;
86 			else
87 				shiftreg <<= 1;
88 		}
89 		m_poly18[i] = bits;
90 	}
91 
92 	m_channel = stream_alloc(0, 1, machine().sample_rate());
93 
94 	save_item(NAME(m_sound_latch_a));
95 	save_item(NAME(m_c24_state.counter));
96 	save_item(NAME(m_c24_state.level));
97 	save_item(NAME(m_c25_state.counter));
98 	save_item(NAME(m_c25_state.level));
99 	save_item(NAME(m_noise_state.counter));
100 	save_item(NAME(m_noise_state.polybit));
101 	save_item(NAME(m_noise_state.polyoffs));
102 	save_item(NAME(m_noise_state.lowpass_counter));
103 	save_item(NAME(m_noise_state.lowpass_polybit));
104 }
105 
update_c24(int samplerate)106 int phoenix_sound_device::update_c24(int samplerate)
107 {
108 	/*
109 	 * Noise frequency control (Port B):
110 	 * Bit 6 lo charges C24 (6.8u) via R51 (330) and when
111 	 * bit 6 is hi, C24 is discharged through R52 (20k)
112 	 * in approx. 20000 * 6.8e-6 = 0.136 seconds
113 	 */
114 	#define C24 6.8e-6
115 	#define R49 1000
116 	#define R51 330
117 	#define R52 20000
118 
119 	if( m_sound_latch_a & 0x40 )
120 	{
121 		if (m_c24_state.level > VMIN)
122 		{
123 			m_c24_state.counter -= (int)((m_c24_state.level - VMIN) / (R52 * C24));
124 			if( m_c24_state.counter <= 0 )
125 			{
126 				int n = -m_c24_state.counter / samplerate + 1;
127 				m_c24_state.counter += n * samplerate;
128 				if( (m_c24_state.level -= n) < VMIN)
129 					m_c24_state.level = VMIN;
130 			}
131 		}
132 	}
133 	else
134 	{
135 		if (m_c24_state.level < VMAX)
136 		{
137 			m_c24_state.counter -= (int)((VMAX - m_c24_state.level) / ((R51+R49) * C24));
138 			if( m_c24_state.counter <= 0 )
139 			{
140 				int n = -m_c24_state.counter / samplerate + 1;
141 				m_c24_state.counter += n * samplerate;
142 				if( (m_c24_state.level += n) > VMAX)
143 					m_c24_state.level = VMAX;
144 			}
145 		}
146 	}
147 	return VMAX - m_c24_state.level;
148 }
149 
update_c25(int samplerate)150 int phoenix_sound_device::update_c25(int samplerate)
151 {
152 	/*
153 	 * Bit 7 hi charges C25 (6.8u) over a R50 (1k) and R53 (330) and when
154 	 * bit 7 is lo, C25 is discharged through R54 (47k)
155 	 * in about 47000 * 6.8e-6 = 0.3196 seconds
156 	 */
157 	#define C25 6.8e-6
158 	#define R50 1000
159 	#define R53 330
160 	#define R54 47000
161 
162 	if( m_sound_latch_a & 0x80 )
163 	{
164 		if (m_c25_state.level < VMAX)
165 		{
166 			m_c25_state.counter -= (int)((VMAX - m_c25_state.level) / ((R50+R53) * C25));
167 			if( m_c25_state.counter <= 0 )
168 			{
169 				int n = -m_c25_state.counter / samplerate + 1;
170 				m_c25_state.counter += n * samplerate;
171 				if( (m_c25_state.level += n) > VMAX )
172 					m_c25_state.level = VMAX;
173 			}
174 		}
175 	}
176 	else
177 	{
178 		if (m_c25_state.level > VMIN)
179 		{
180 			m_c25_state.counter -= (int)((m_c25_state.level - VMIN) / (R54 * C25));
181 			if( m_c25_state.counter <= 0 )
182 			{
183 				int n = -m_c25_state.counter / samplerate + 1;
184 				m_c25_state.counter += n * samplerate;
185 				if( (m_c25_state.level -= n) < VMIN )
186 					m_c25_state.level = VMIN;
187 			}
188 		}
189 	}
190 	return m_c25_state.level;
191 }
192 
193 
noise(int samplerate)194 int phoenix_sound_device::noise(int samplerate)
195 {
196 	int vc24 = update_c24(samplerate);
197 	int vc25 = update_c25(samplerate);
198 	int sum = 0, level, frequency;
199 
200 	/*
201 	 * The voltage levels are added and control I(CE) of transistor TR1
202 	 * (NPN) which then controls the noise clock frequency (linearily?).
203 	 * level = voltage at the output of the op-amp controlling the noise rate.
204 	 */
205 	if( vc24 < vc25 )
206 		level = vc24 + (vc25 - vc24) / 2;
207 	else
208 		level = vc25 + (vc24 - vc25) / 2;
209 
210 	frequency = 588 + 6325 * level / 32768;
211 
212 	/*
213 	 * NE555: Ra=47k, Rb=1k, C=0.05uF
214 	 * minfreq = 1.44 / ((47000+2*1000) * 0.05e-6) = approx. 588 Hz
215 	 * R71 (2700 Ohms) parallel to R73 (47k Ohms) = approx. 2553 Ohms
216 	 * maxfreq = 1.44 / ((2553+2*1000) * 0.05e-6) = approx. 6325 Hz
217 	 */
218 	m_noise_state.counter -= frequency;
219 	if( m_noise_state.counter <= 0 )
220 	{
221 		int n = (-m_noise_state.counter / samplerate) + 1;
222 		m_noise_state.counter += n * samplerate;
223 		m_noise_state.polyoffs = (m_noise_state.polyoffs + n) & 0x3ffff;
224 		m_noise_state.polybit = (m_poly18[m_noise_state.polyoffs>>5] >> (m_noise_state.polyoffs & 31)) & 1;
225 	}
226 	if (!m_noise_state.polybit)
227 		sum += vc24;
228 
229 	/* 400Hz crude low pass filter: this is only a guess!! */
230 	m_noise_state.lowpass_counter -= 400;
231 	if( m_noise_state.lowpass_counter <= 0 )
232 	{
233 		m_noise_state.lowpass_counter += samplerate;
234 		m_noise_state.lowpass_polybit = m_noise_state.polybit;
235 	}
236 	if (!m_noise_state.lowpass_polybit)
237 		sum += vc25;
238 
239 	return sum;
240 }
241 
242 
243 /************************************************************************/
244 /* phoenix Sound System Analog emulation                                */
245 /*                                                                      */
246 /* NOTE: Sample Rate must be at least 44100 for proper emulation.       */
247 /*                                                                      */
248 /* April 2005, DR.                                                      */
249 /************************************************************************/
250 
251 static const discrete_555_desc phoenix_effect1_555 =
252 {
253 	DISC_555_OUT_COUNT_F_X,
254 	5,      // B+ voltage of 555
255 	DEFAULT_555_VALUES
256 };
257 
258 static const discrete_555_desc phoenix_effect2_555 =
259 {
260 	DISC_555_OUT_ENERGY,
261 	5,      // B+ voltage of 555
262 	DEFAULT_555_CHARGE,
263 	4.0     // loaded output voltage
264 };
265 
266 static const discrete_comp_adder_table phoenix_effect2_cap_sel =
267 {
268 	DISC_COMP_P_CAPACITOR,
269 	CAP_U(0.01),    // C18
270 	2,
271 	{CAP_U(0.47), CAP_U(1)} // C16, C17
272 };
273 
274 static const discrete_mixer_desc phoenix_effect2_mixer1 =
275 {
276 	DISC_MIXER_IS_RESISTOR,
277 	{RES_K(10), RES_K(5.1) + RES_K(5.1), RES_K(5)}, // R42, R45+R46, internal 555 R
278 	{0},            // No variable resistor nodes
279 	{0},            // No caps
280 	0,              // No rI
281 	RES_K(10),      // internal 555
282 	0,0,            // No Filter
283 	0,              // not used in resistor network
284 	1   // final gain
285 };
286 
287 static const discrete_mixer_desc phoenix_effect2_mixer2 =
288 {
289 	DISC_MIXER_IS_RESISTOR,
290 	{RES_K(5.1), RES_K(5.1)},   // R45, R46
291 	{0},            // No variable resistor nodes
292 	{0},            // No caps
293 	0,              // No rI
294 	0,              // No rF
295 	0,0,            // No Filter
296 	0,              // not used in resistor network
297 	1   // final gain
298 };
299 
300 static const discrete_mixer_desc phoenix_effect2_mixer3 =
301 {
302 	DISC_MIXER_IS_RESISTOR,
303 	{RES_K(10), RES_K(5.1), RES_K(5)},  // R42, R46, internal 555 R
304 	{0},            // No variable resistor nodes
305 	{0},            // No caps
306 	0,              // No rI
307 	RES_K(10),      // internal 555
308 	0,0,            // No Filter
309 	0,              // not used in resistor network
310 	1   // final gain
311 };
312 
313 static const discrete_mixer_desc phoenix_mixer =
314 {
315 	DISC_MIXER_IS_RESISTOR,
316 	{RES_K(10+47), RES_K(10+20), RES_K(20), RES_K(20)}, // R19+R21, R38+R47, R67, R68
317 	{0},            // No variable resistor nodes
318 	{CAP_U(10), CAP_U(10), CAP_U(.1), CAP_U(10)},       // C6, C31, C29, C30
319 	0,              // No rI
320 	RES_K(10),      // VR1
321 	0,              // No Filter
322 	CAP_U(10),      // C32
323 	0,              // not used in resistor network
324 	40000   // final gain
325 };
326 
327 /* Nodes - Inputs */
328 #define PHOENIX_EFFECT_1_DATA       NODE_01
329 #define PHOENIX_EFFECT_1_FREQ       NODE_02
330 #define PHOENIX_EFFECT_1_FILT       NODE_03
331 #define PHOENIX_EFFECT_2_DATA       NODE_04
332 #define PHOENIX_EFFECT_2_FREQ       NODE_05
333 #define PHOENIX_EFFECT_3_EN         NODE_06
334 #define PHOENIX_EFFECT_4_EN         NODE_07
335 /* Nodes - Sounds */
336 #define PHOENIX_EFFECT_1_SND        NODE_10
337 #define PHOENIX_EFFECT_2_SND        NODE_11
338 #define PHOENIX_EFFECT_3_SND        0
339 #define PHOENIX_EFFECT_4_SND        0
340 
341 
342 DISCRETE_SOUND_START(phoenix_discrete)
343 	/************************************************/
344 	/* Input register mapping for phoenix           */
345 	/************************************************/
DISCRETE_INPUT_DATA(PHOENIX_EFFECT_1_DATA)346 	DISCRETE_INPUT_DATA (PHOENIX_EFFECT_1_DATA)
347 	DISCRETE_INPUT_LOGIC(PHOENIX_EFFECT_1_FREQ)
348 	DISCRETE_INPUT_LOGIC(PHOENIX_EFFECT_1_FILT)
349 	DISCRETE_INPUT_DATA (PHOENIX_EFFECT_2_DATA)
350 	DISCRETE_INPUT_DATA (PHOENIX_EFFECT_2_FREQ)
351 	DISCRETE_INPUT_LOGIC(PHOENIX_EFFECT_3_EN)
352 	DISCRETE_INPUT_LOGIC(PHOENIX_EFFECT_4_EN)
353 
354 	/************************************************/
355 	/* Effect 1                                     */
356 	/* - shield, bird explode, level 3&4 siren,     */
357 	/* - level 5 spaceship                          */
358 	/************************************************/
359 	/* R22 has been confirmed on real boards as 470 ohm, not 47k in schematics  */
360 	DISCRETE_RCDISC4(NODE_20,                   /* IC52 output pin 7 */
361 						1,                          /* ENAB */
362 						PHOENIX_EFFECT_1_FREQ,      /* Input to O.C. inverter */
363 						470,                        /* R22 */
364 						RES_K(100),             /* R23 */
365 						RES_K(33),                  /* R24 */
366 						CAP_U(6.8),             /* C7 */
367 						12,                     /* 12V supply */
368 						1)                          /* Circuit type 1 */
369 	DISCRETE_555_ASTABLE_CV(NODE_21,            /* IC20 pin 6 */
370 							1,                  /* ENAB */
371 							RES_K(47),          /* R25 */
372 							RES_K(47),          /* R26 */
373 							CAP_U(.001),        /* C8 */
374 							NODE_20,            /* IC48 pin 5 input */
375 							&phoenix_effect1_555)
376 	/* LS163 counts rising edge, but the LS14 inverts that */
377 	DISCRETE_NOTE(NODE_22,                      /* IC21 pin 5 output */
378 					1,                          /* ENAB */
379 					NODE_21,                        /* IC13 pin 2 clock input */
380 					PHOENIX_EFFECT_1_DATA,      /* Pre-load data */
381 					0x0f,                           /* Maximum count of first counter 0-15 (IC13) */
382 					1,                          /* Maximum count of second counter 0-1 (IC21) */
383 					DISC_CLK_BY_COUNT | DISC_OUT_IS_ENERGY) /* Module is clocked externally and we anti-alias output */
384 	/* When FILT is enabled, the effect is filtered.
385 	 * While the R20 does decrease the amplitude a little, its main purpose
386 	 * is to discharge C5 when the filter is disabled. */
387 	DISCRETE_SWITCH(NODE_23,
388 					1,                          /* ENAB */
389 					PHOENIX_EFFECT_1_FILT,
390 					DEFAULT_TTL_V_LOGIC_1,
391 					DEFAULT_TTL_V_LOGIC_1 * RES_K(100) / (RES_K(10) + RES_K(100)))  /* R20, R19 */
392 	DISCRETE_MULTIPLY(NODE_24,
393 						NODE_22,
394 						NODE_23)
395 	DISCRETE_RCFILTER(NODE_25,
396 						NODE_24,
397 						1.0/(1.0/RES_K(10) + 1.0/RES_K(100)),   /* R19, R20 */
398 						CAP_U(.047))                            /* C5 */
399 	DISCRETE_SWITCH(PHOENIX_EFFECT_1_SND,
400 					1,                          /* ENAB */
401 					PHOENIX_EFFECT_1_FILT,
402 					NODE_24,                    /* non-filtered */
403 					NODE_25)                    /* filtered */
404 
405 	/************************************************/
406 	/* Effect 2                                     */
407 	/* - bird flying, bird/phoenix/spaceship hit    */
408 	/* - phoenix wing hit                           */
409 	/************************************************/
410 	DISCRETE_COMP_ADDER(NODE_30,                /* total capacitance of selected capacitors */
411 						PHOENIX_EFFECT_2_FREQ,  /* passed selection bits */
412 						&phoenix_effect2_cap_sel)
413 	/* Part of the frequency select also effects the gain */
414 	DISCRETE_TRANSFORM2(NODE_31,                /* 0/1 state of PHOENIX_EFFECT_2_FREQ high bit */
415 						PHOENIX_EFFECT_2_FREQ, 2, "01&1/") // get bit 0x02
416 	DISCRETE_SWITCH(NODE_32,                    /* voltage level */
417 					1,                          /* ENAB */
418 					NODE_31,                    /* PHOENIX_EFFECT_2_FREQ high bit determines voltage level */
419 					DEFAULT_TTL_V_LOGIC_1,
420 					DEFAULT_TTL_V_LOGIC_1 / 2)
421 	DISCRETE_555_ASTABLE(NODE_33,               /* pin 3 output of IC44 */
422 							1,                      /* ENAB */
423 							RES_K(47),              /* R40 */
424 							RES_K(100),         /* R41 */
425 							NODE_30,                /* C16, C17, C18 combined */
426 							&phoenix_effect2_555)
427 	/* C20 has been confirmed on real boards as 1uF, not 10uF in schematics  */
428 	DISCRETE_555_ASTABLE(NODE_34,               /* pin 3 output of IC51 */
429 							1,                      /* ENAB */
430 							RES_K(510),         /* R23 */
431 							RES_K(510),         /* R24 */
432 							CAP_U(1),               /* C20 */
433 							&phoenix_effect2_555)
434 	/* R45 & R46 have been confirmed on real boards as 5.1k, not 51k in schematics  */
435 	/* We need to work backwards here and calculate the voltage at the junction of R42 & R46 */
436 	/* If you remove C22 from the real PCB, you can WAVELOG NODE_35 with a gain of 1000 and compare
437 	 * it against the junction of R42 & R46 on a real PCB. */
438 	DISCRETE_MIXER3(NODE_35,                    /* Voltage at junction of R42 & R46 with C22 removed */
439 					1,                          /* ENAB */
440 					NODE_33,                    /* output from IC44 */
441 					NODE_34,                    /* output from IC51 */
442 					5,                          /* B+ connected internally to pin 5 of 555 */
443 					&phoenix_effect2_mixer1)
444 	/* Then calculate the voltage going to C22 */
445 	/* If you remove C22 from the real PCB, you can WAVELOG NODE_36 with a gain of 1000 and compare
446 	 * it against the junction of R45 & R46 on a real PCB. */
447 	DISCRETE_MIXER2(NODE_36,                    /* Voltage at junction of R45 & R46 with C22 removed */
448 					1,                          /* ENAB */
449 					NODE_34,                    /* pin 3 output of IC51 */
450 					NODE_35,                    /* Voltage at junction of R42 & R46 with C22 removed */
451 					&phoenix_effect2_mixer2)
452 	/* C22 charging is R45 in parallel with R46, R42 and the 555 CV internal resistance */
453 	DISCRETE_RCFILTER(NODE_37,
454 						NODE_36,
455 						1.0/ (1.0/RES_K(5.1) + (1.0/(RES_K(5.1) + 1.0/(1.0/RES_K(10) + 1.0/RES_K(5) + 1.0/RES_K(10)) ))),
456 						CAP_U(100)) /* R45, R46, R42, internal 555 Rs, C22 */
457 	/* Now mix from C22 on */
458 	/* You can WAVELOG NODE_38 with a gain of 1000 and compare it against IC50 pin 5 on a real PCB. */
459 	DISCRETE_MIXER3(NODE_38,                    /* control voltage to pin 5 of IC50 */
460 					1,                          /* ENAB */
461 					NODE_33,                    /* pin 3 output of IC44 */
462 					NODE_37,                    /* voltage on C22 */
463 					5,                          /* IC50 internally connected to B+ */
464 					&phoenix_effect2_mixer3)
465 	DISCRETE_555_ASTABLE_CV(NODE_39,            /* IC20 pin 8 output */
466 							1,                  /* ENAB */
467 							RES_K(20),          /* R47 */
468 							RES_K(20),          /* R48 */
469 							CAP_U(0.001),       /* C23 */
470 							NODE_38,            /* IC50 pin 5 input */
471 							&phoenix_effect1_555)
472 	DISCRETE_NOTE(NODE_40,                      /* IC21 pin 9 output */
473 					1,                          /* ENAB */
474 					NODE_39,                        /* IC14 pin 2 clock input */
475 					PHOENIX_EFFECT_2_DATA,      /* Pre-load data */
476 					0x0f,                           /* Maximum count of first counter 0-15 (IC14) */
477 					1,                          /* Maximum count of second counter 0-1 (IC21) */
478 					DISC_CLK_BY_COUNT | DISC_OUT_IS_ENERGY)
479 	DISCRETE_MULTIPLY(PHOENIX_EFFECT_2_SND,
480 						NODE_40,                    /* IC21 pin 9 output */
481 						NODE_32)                    /* voltage level selected by high bit of PHOENIX_EFFECT_2_FREQ */
482 
483 	/************************************************/
484 	/* Combine all sound sources.                   */
485 	/************************************************/
486 	DISCRETE_MIXER4(NODE_90,
487 					1,                          /* ENAB */
488 					PHOENIX_EFFECT_1_SND,
489 					PHOENIX_EFFECT_2_SND,
490 					PHOENIX_EFFECT_3_SND,
491 					PHOENIX_EFFECT_4_SND,
492 					&phoenix_mixer)
493 
494 	DISCRETE_OUTPUT(NODE_90, 1)
495 DISCRETE_SOUND_END
496 
497 void phoenix_sound_device::control_a_w(uint8_t data)
498 {
499 	m_discrete->write(PHOENIX_EFFECT_2_DATA, data & 0x0f);
500 	m_discrete->write(PHOENIX_EFFECT_2_FREQ, (data & 0x30) >> 4);
501 #if 0
502 	/* future handling of noise sounds */
503 	m_discrete->write(PHOENIX_EFFECT_3_EN  , data & 0x40);
504 	m_discrete->write(PHOENIX_EFFECT_4_EN  , data & 0x80);
505 #endif
506 	m_channel->update();
507 	m_sound_latch_a = data;
508 }
509 
control_b_w(uint8_t data)510 void phoenix_sound_device::control_b_w(uint8_t data)
511 {
512 	m_discrete->write(PHOENIX_EFFECT_1_DATA, data & 0x0f);
513 	m_discrete->write(PHOENIX_EFFECT_1_FILT, data & 0x20);
514 	m_discrete->write(PHOENIX_EFFECT_1_FREQ, data & 0x10);
515 
516 	/* update the tune that the MM6221AA is playing */
517 	m_tms->mm6221aa_tune_w(data >> 6);
518 }
519 
520 
521 //-------------------------------------------------
522 //  sound_stream_update - handle a stream update
523 //-------------------------------------------------
524 
sound_stream_update(sound_stream & stream,std::vector<read_stream_view> const & inputs,std::vector<write_stream_view> & outputs)525 void phoenix_sound_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
526 {
527 	auto &buffer = outputs[0];
528 	int samplerate = buffer.sample_rate();
529 
530 	for (int sampindex = 0; sampindex < buffer.samples(); sampindex++)
531 	{
532 		int sum = 0;
533 		sum = noise(samplerate) / 2;
534 		buffer.put_int_clamp(sampindex, sum, 32768);
535 	}
536 }
537