1 // license:BSD-3-Clause
2 // copyright-holders:Mike Balfour
3 /*************************************************************************
4
5 audio\avalnche.c
6
7 *************************************************************************/
8
9 #include "emu.h"
10 #include "includes/avalnche.h"
11 #include "sound/discrete.h"
12 #include "speaker.h"
13
14
15 /* Avalanche Discrete Sound Input Nodes */
16 #define AVALNCHE_AUD0_EN NODE_01
17 #define AVALNCHE_AUD1_EN NODE_02
18 #define AVALNCHE_AUD2_EN NODE_03
19 #define AVALNCHE_SOUNDLVL_DATA NODE_04
20 #define AVALNCHE_ATTRACT_EN NODE_05
21
22
23 /***************************************************************************
24 Avalanche memory audio output handlers
25 ***************************************************************************/
26
avalnche_noise_amplitude_w(uint8_t data)27 void avalnche_state::avalnche_noise_amplitude_w(uint8_t data)
28 {
29 m_discrete->write(AVALNCHE_SOUNDLVL_DATA, data & 0x3f);
30 }
31
32
33 /***************************************************************************
34 Avalanche sound system analog emulation
35 ***************************************************************************/
36
37 static const discrete_lfsr_desc avalnche_lfsr={
38 DISC_CLK_IS_FREQ,
39 16, /* Bit Length */
40 0, /* Reset Value */
41 0, /* Use Bit 0 as XOR input 0 */
42 14, /* Use Bit 14 as XOR input 1 */
43 DISC_LFSR_XNOR, /* Feedback stage1 is XNOR */
44 DISC_LFSR_OR, /* Feedback stage2 is just stage 1 output OR with external feed */
45 DISC_LFSR_REPLACE, /* Feedback stage3 replaces the shifted register contents */
46 0x000001, /* Everything is shifted into the first bit only */
47 0, /* Output is already inverted by XNOR */
48 15 /* Output bit */
49 };
50
51 /* Nodes - Sounds */
52 #define AVALNCHE_NOISE NODE_10
53 #define AVALNCHE_AUD1_SND NODE_11
54 #define AVALNCHE_AUD2_SND NODE_12
55 #define AVALNCHE_SOUNDLVL_AUD0_SND NODE_13
56
57 static DISCRETE_SOUND_START(avalnche_discrete)
58 /************************************************/
59 /* avalnche Effects Relataive Gain Table */
60 /* */
61 /* Effect V-ampIn Gain ratio Relative */
62 /* Aud0 3.8 50/(50+33+39) 725.6 */
63 /* Aud1 3.8 50/(50+68) 750.2 */
64 /* Aud2 3.8 50/(50+68) 750.2 */
65 /* Soundlvl 3.8 50/(50+33+.518) 1000.0 */
66 /************************************************/
67
68 /************************************************/
69 /* Input register mapping for avalnche */
70 /************************************************/
71 /* NODE GAIN OFFSET INIT */
DISCRETE_INPUT_LOGIC(AVALNCHE_AUD0_EN)72 DISCRETE_INPUT_LOGIC (AVALNCHE_AUD0_EN)
73 DISCRETE_INPUT_LOGIC (AVALNCHE_AUD1_EN)
74 DISCRETE_INPUT_LOGIC (AVALNCHE_AUD2_EN)
75 DISCRETE_INPUTX_DATA (AVALNCHE_SOUNDLVL_DATA, 500.0/63, 0, 0.0)
76 DISCRETE_INPUT_NOT (AVALNCHE_ATTRACT_EN)
77
78 /************************************************/
79 /* Aud0 = 2V = HSYNC/4 = 15750/4 */
80 /* Aud1 = 32V = HSYNC/64 = 15750/64 */
81 /* Aud2 = 8V = HSYNC/16 = 15750/16 */
82 /************************************************/
83 DISCRETE_SQUAREWFIX(NODE_20, AVALNCHE_AUD0_EN, 15750.0/4, 725.6, 50.0, 0, 0.0) // Aud0
84 DISCRETE_SQUAREWFIX(AVALNCHE_AUD1_SND, AVALNCHE_AUD1_EN, 15750.0/64, 750.2, 50.0, 0, 0.0)
85 DISCRETE_SQUAREWFIX(AVALNCHE_AUD2_SND, AVALNCHE_AUD2_EN, 15750.0/16, 750.2, 50.0, 0, 0.0)
86
87 /************************************************/
88 /* Soundlvl is variable amplitude, filtered */
89 /* random noise. */
90 /* LFSR clk = 16V = 15750.0Hz/16/2 */
91 /************************************************/
92 DISCRETE_LFSR_NOISE(AVALNCHE_NOISE, AVALNCHE_ATTRACT_EN, AVALNCHE_ATTRACT_EN, 15750.0, AVALNCHE_SOUNDLVL_DATA, 0, 0, &avalnche_lfsr)
93 DISCRETE_ADDER2(NODE_30, 1, NODE_20, AVALNCHE_NOISE)
94 DISCRETE_RCFILTER(AVALNCHE_SOUNDLVL_AUD0_SND, NODE_30, 556.7, 1e-7)
95
96 /************************************************/
97 /* Final mix and output. */
98 /************************************************/
99 DISCRETE_ADDER3(NODE_90, AVALNCHE_ATTRACT_EN, AVALNCHE_AUD1_SND, AVALNCHE_AUD2_SND, AVALNCHE_SOUNDLVL_AUD0_SND)
100
101 DISCRETE_OUTPUT(NODE_90, 65534.0/(725.6+750.2+750.2+1000.0))
102 DISCRETE_SOUND_END
103
104
105 void avalnche_state::avalnche_sound(machine_config &config)
106 {
107 SPEAKER(config, "mono").front_center();
108
109 DISCRETE(config, m_discrete, avalnche_discrete).add_route(ALL_OUTPUTS, "mono", 1.0);
110
111 m_latch->q_out_cb<1>().set(m_discrete, FUNC(discrete_device::write_line<AVALNCHE_ATTRACT_EN>));
112 m_latch->q_out_cb<4>().set(m_discrete, FUNC(discrete_device::write_line<AVALNCHE_AUD0_EN>));
113 m_latch->q_out_cb<5>().set(m_discrete, FUNC(discrete_device::write_line<AVALNCHE_AUD1_EN>));
114 m_latch->q_out_cb<6>().set(m_discrete, FUNC(discrete_device::write_line<AVALNCHE_AUD2_EN>));
115 }
116
117
acatch_sound(machine_config & config)118 void avalnche_state::acatch_sound(machine_config &config)
119 {
120 // just a stub here...
121 m_latch->q_out_cb<1>().set_nop(); // It is attract_enable just like avalnche, but not hooked up yet.
122 m_latch->q_out_cb<4>().set(FUNC(avalnche_state::catch_aud0_w));
123 m_latch->q_out_cb<5>().set(FUNC(avalnche_state::catch_aud1_w));
124 m_latch->q_out_cb<6>().set(FUNC(avalnche_state::catch_aud2_w));
125 }
126
127
128 /***************************************************************************
129 Catch memory audio output handlers
130 ***************************************************************************/
131
WRITE_LINE_MEMBER(avalnche_state::catch_aud0_w)132 WRITE_LINE_MEMBER(avalnche_state::catch_aud0_w)
133 {
134 /* Different from avalnche, it plays a sound (offset 0/1/2) on data bit 0 rising edge.
135 There's no indication that the game silences sound, it's probably done automatically. */
136 }
137
WRITE_LINE_MEMBER(avalnche_state::catch_aud1_w)138 WRITE_LINE_MEMBER(avalnche_state::catch_aud1_w)
139 {
140 }
141
WRITE_LINE_MEMBER(avalnche_state::catch_aud2_w)142 WRITE_LINE_MEMBER(avalnche_state::catch_aud2_w)
143 {
144 }
145