Previous 199869 Revisions Next

r23466 Wednesday 5th June, 2013 at 18:34:46 UTC by Fabio Priuli
Modernized Flower sound device. [Osso]
[src/mame/audio]flower.c
[src/mame/drivers]flower.c
[src/mame/includes]flower.h

trunk/src/mame/includes/flower.h
r23465r23466
1#include "devlegcy.h"
2
31class flower_state : public driver_device
42{
53public:
r23465r23466
5149};
5250
5351
54/*----------- defined in audio/flower.c -----------*/
52// ======================> gomoku_sound_device
5553
56DECLARE_WRITE8_DEVICE_HANDLER( flower_sound1_w );
57DECLARE_WRITE8_DEVICE_HANDLER( flower_sound2_w );
5854
55/* this structure defines the parameters for a channel */
56struct flower_sound_channel
57{
58   UINT32 start;
59   UINT32 pos;
60   UINT16 freq;
61   UINT8 volume;
62   UINT8 voltab;
63   UINT8 oneshot;
64   UINT8 active;
65   UINT8 effect;
66   UINT32 ecount;
67
68};
69
5970class flower_sound_device : public device_t,
6071                           public device_sound_interface
6172{
6273public:
6374   flower_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
64   ~flower_sound_device() { global_free(m_token); }
75   ~flower_sound_device() {}
6576
66   // access to legacy token
67   void *token() const { assert(m_token != NULL); return m_token; }
77   enum
78   {
79   TIMER_CLOCK_EFFECT
80   };
81   
82   DECLARE_WRITE8_MEMBER( sound1_w );
83   DECLARE_WRITE8_MEMBER( sound2_w );
84
6885protected:
6986   // device-level overrides
7087   virtual void device_config_complete();
7188   virtual void device_start();
7289   virtual void device_reset();
90   
91   virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
7392
7493   // sound stream update overrides
7594   virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
95
7696private:
97   void make_mixer_table(int voices, int gain);
98   void show_soundregs();
99   
77100   // internal state
78   void *m_token;
101   emu_timer *m_effect_timer;
102
103   /* data about the sound system */
104   flower_sound_channel m_channel_list[8];
105   flower_sound_channel *m_last_channel;
106
107   /* global sound parameters */
108   const UINT8 *m_sample_rom;
109   const UINT8 *m_volume_rom;
110   sound_stream * m_stream;
111
112   /* mixer tables and internal buffers */
113   INT16 *m_mixer_table;
114   INT16 *m_mixer_lookup;
115   short *m_mixer_buffer;
116
117   UINT8 m_soundregs1[0x40];
118   UINT8 m_soundregs2[0x40];
119
79120};
80121
81122extern const device_type FLOWER;
trunk/src/mame/drivers/flower.c
r23465r23466
136136   AM_RANGE(0x4000, 0x4000) AM_WRITE(flower_soundcpu_irq_ack)
137137   AM_RANGE(0x4001, 0x4001) AM_WRITEONLY AM_SHARE("sn_nmi_enable")
138138   AM_RANGE(0x6000, 0x6000) AM_READ(soundlatch_byte_r)
139   AM_RANGE(0x8000, 0x803f) AM_DEVWRITE_LEGACY("flower", flower_sound1_w)
140   AM_RANGE(0xa000, 0xa03f) AM_DEVWRITE_LEGACY("flower", flower_sound2_w)
139   AM_RANGE(0x8000, 0x803f) AM_DEVWRITE("flower", flower_sound_device, sound1_w)
140   AM_RANGE(0xa000, 0xa03f) AM_DEVWRITE("flower", flower_sound_device, sound2_w)
141141   AM_RANGE(0xc000, 0xc7ff) AM_RAM
142142ADDRESS_MAP_END
143143
trunk/src/mame/audio/flower.c
r23465r23466
1919#define MIXER_DEFGAIN       48
2020
2121
22/* this structure defines the parameters for a channel */
23struct sound_channel
24{
25   UINT32 start;
26   UINT32 pos;
27   UINT16 freq;
28   UINT8 volume;
29   UINT8 voltab;
30   UINT8 oneshot;
31   UINT8 active;
32   UINT8 effect;
33   UINT32 ecount;
22const device_type FLOWER = &device_creator<flower_sound_device>;
3423
35};
36
37
38struct flower_sound_state
24flower_sound_device::flower_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
25   : device_t(mconfig, FLOWER, "Flower Custom Sound", tag, owner, clock),
26      device_sound_interface(mconfig, *this)
3927{
40   emu_timer *m_effect_timer;
41
42   /* data about the sound system */
43   sound_channel m_channel_list[8];
44   sound_channel *m_last_channel;
45
46   /* global sound parameters */
47   const UINT8 *m_sample_rom;
48   const UINT8 *m_volume_rom;
49   sound_stream * m_stream;
50
51   /* mixer tables and internal buffers */
52   INT16 *m_mixer_table;
53   INT16 *m_mixer_lookup;
54   short *m_mixer_buffer;
55
56   UINT8 m_soundregs1[0x40];
57   UINT8 m_soundregs2[0x40];
58};
59
60INLINE flower_sound_state *get_safe_token( device_t *device )
61{
62   assert(device != NULL);
63   assert(device->type() == FLOWER);
64
65   return (flower_sound_state *)downcast<flower_sound_device *>(device)->token();
6628}
6729
68/* build a table to divide by the number of voices; gain is specified as gain*16 */
69static void make_mixer_table(device_t *device, int voices, int gain)
70{
71   flower_sound_state *state = get_safe_token(device);
72   int count = voices * 128;
73   int i;
30//-------------------------------------------------
31//  device_config_complete - perform any
32//  operations now that the configuration is
33//  complete
34//-------------------------------------------------
7435
75   /* allocate memory */
76   state->m_mixer_table = auto_alloc_array(device->machine(), INT16, 256 * voices);
77
78   /* find the middle of the table */
79   state->m_mixer_lookup = state->m_mixer_table + (128 * voices);
80
81   /* fill in the table - 16 bit case */
82   for (i = 0; i < count; i++)
83   {
84      int val = i * gain * 16 / voices;
85      if (val > 32767) val = 32767;
86      state->m_mixer_lookup[ i] = val;
87      state->m_mixer_lookup[-i] =-val;
88   }
89}
90
91
92/* generate sound to the mix buffer in mono */
93static STREAM_UPDATE( flower_update_mono )
36void flower_sound_device::device_config_complete()
9437{
95   flower_sound_state *state = get_safe_token(device);
96   stream_sample_t *buffer = outputs[0];
97   sound_channel *voice;
98   short *mix;
99   int i;
100
101   /* zap the contents of the mixer buffer */
102   memset(state->m_mixer_buffer, 0, samples * sizeof(short));
103
104   /* loop over each voice and add its contribution */
105   for (voice = state->m_channel_list; voice < state->m_last_channel; voice++)
106   {
107      int f = voice->freq;
108      int v = voice->volume;
109
110      if (!voice->active)
111         continue;
112
113      // effects
114      // bit 0: volume slide down?
115      if (voice->effect & 1 && !voice->oneshot)
116      {
117         // note: one-shot samples are fixed volume
118         v -= (voice->ecount >> 4);
119         if (v < 0) v = 0;
120      }
121      // bit 1: used often, but hard to figure out what for
122      // bit 2: probably pitch slide
123      if (voice->effect & 4)
124      {
125         f -= (voice->ecount << 7);
126         if (f < 0) f = 0;
127      }
128      // bit 3: not used much, maybe pitch slide the other way?
129
130      v |= voice->voltab;
131      mix = state->m_mixer_buffer;
132
133      for (i = 0; i < samples; i++)
134      {
135         // add sample
136         if (voice->oneshot)
137         {
138            UINT8 sample = state->m_sample_rom[(voice->start + voice->pos) >> 7 & 0x7fff];
139            if (sample == 0xff)
140            {
141               voice->active = 0;
142               break;
143            }
144            else
145               *mix++ += state->m_volume_rom[v << 8 | sample] - 0x80;
146         }
147         else
148         {
149            UINT8 sample = state->m_sample_rom[(voice->start >> 7 & 0x7e00) | (voice->pos >> 7 & 0x1ff)];
150            *mix++ += state->m_volume_rom[v << 8 | sample] - 0x80;
151         }
152
153         // update counter
154         voice->pos += f;
155      }
156   }
157
158   /* mix it down */
159   mix = state->m_mixer_buffer;
160   for (i = 0; i < samples; i++)
161      *buffer++ = state->m_mixer_lookup[*mix++];
16238}
16339
164/* clock sound channel effect counters */
165static TIMER_CALLBACK( flower_clock_effect )
166{
167   flower_sound_state *state = (flower_sound_state *)ptr;
168   sound_channel *voice;
169   state->m_stream->update();
40//-------------------------------------------------
41//  device_start - device-specific startup
42//-------------------------------------------------
17043
171   for (voice = state->m_channel_list; voice < state->m_last_channel; voice++)
172      voice->ecount += (voice->ecount < (1<<22));
173}
174
175
176
177static DEVICE_START( flower_sound )
44void flower_sound_device::device_start()
17845{
179   flower_sound_state *state = get_safe_token(device);
180   running_machine &machine = device->machine();
181   sound_channel *voice;
182   int i;
46   flower_sound_channel *voice;
18347
184   state->m_effect_timer = machine.scheduler().timer_alloc(FUNC(flower_clock_effect), state);
185   state->m_stream = device->machine().sound().stream_alloc(*device, 0, 1, MIXER_SAMPLERATE, 0, flower_update_mono);
186   state->m_mixer_buffer = auto_alloc_array(device->machine(), short, MIXER_SAMPLERATE);
187   make_mixer_table(device, 8, MIXER_DEFGAIN);
48   m_effect_timer = timer_alloc(TIMER_CLOCK_EFFECT);
49   m_stream = machine().sound().stream_alloc(*this, 0, 1, MIXER_SAMPLERATE, this);
50   m_mixer_buffer = auto_alloc_array(machine(), short, MIXER_SAMPLERATE);
51   make_mixer_table(8, MIXER_DEFGAIN);
18852
18953   /* extract globals from the interface */
190   state->m_last_channel = state->m_channel_list + 8;
54   m_last_channel = m_channel_list + 8;
19155
192   state->m_sample_rom = machine.root_device().memregion("sound1")->base();
193   state->m_volume_rom = machine.root_device().memregion("sound2")->base();
56   m_sample_rom = machine().root_device().memregion("sound1")->base();
57   m_volume_rom = machine().root_device().memregion("sound2")->base();
19458
19559   /* register for savestates */
196   for (i = 0; i < 8; i++)
60   for (int i = 0; i < 8; i++)
19761   {
198      voice = &state->m_channel_list[i];
62      voice = &m_channel_list[i];
19963
200      device->save_item(NAME(voice->freq), i+1);
201      device->save_item(NAME(voice->pos), i+1);
202      device->save_item(NAME(voice->volume), i+1);
203      device->save_item(NAME(voice->voltab), i+1);
204      device->save_item(NAME(voice->effect), i+1);
205      device->save_item(NAME(voice->ecount), i+1);
206      device->save_item(NAME(voice->oneshot), i+1);
207      device->save_item(NAME(voice->active), i+1);
208      device->save_item(NAME(voice->start), i+1);
64      save_item(NAME(voice->freq), i+1);
65      save_item(NAME(voice->pos), i+1);
66      save_item(NAME(voice->volume), i+1);
67      save_item(NAME(voice->voltab), i+1);
68      save_item(NAME(voice->effect), i+1);
69      save_item(NAME(voice->ecount), i+1);
70      save_item(NAME(voice->oneshot), i+1);
71      save_item(NAME(voice->active), i+1);
72      save_item(NAME(voice->start), i+1);
20973   }
21074}
21175
212static DEVICE_RESET( flower_sound )
76//-------------------------------------------------
77//  device_reset - device-specific reset
78//-------------------------------------------------
79
80void flower_sound_device::device_reset()
21381{
214   flower_sound_state *state = get_safe_token(device);
215   sound_channel *voice;
82   flower_sound_channel *voice;
21683   attotime period;
217   int i;
21884
21985   /* reset effect timer, period is unknown/guessed */
22086   period = attotime::from_hz(MIXER_SAMPLERATE / 256);
221   state->m_effect_timer->adjust(period, 0, period);
87   m_effect_timer->adjust(period, 0, period);
22288
22389   /* reset all the voices */
224   for (i = 0; i < 8; i++)
90   for (int i = 0; i < 8; i++)
22591   {
226      voice = &state->m_channel_list[i];
92      voice = &m_channel_list[i];
22793
22894      voice->freq = 0;
22995      voice->pos = 0;
r23465r23466
235101      voice->active = 0;
236102      voice->start = 0;
237103   }
104
105   memset(m_soundregs1, 0, 0x40);
106   memset(m_soundregs2, 0, 0x40);
238107}
239108
109/* build a table to divide by the number of voices; gain is specified as gain*16 */
110void flower_sound_device::make_mixer_table(int voices, int gain)
111{
112   int count = voices * 128;
113
114   /* allocate memory */
115   m_mixer_table = auto_alloc_array(machine(), INT16, 256 * voices);
116
117   /* find the middle of the table */
118   m_mixer_lookup = m_mixer_table + (128 * voices);
119
120   /* fill in the table - 16 bit case */
121   for (int i = 0; i < count; i++)
122   {
123      int val = i * gain * 16 / voices;
124      if (val > 32767) val = 32767;
125      m_mixer_lookup[ i] = val;
126      m_mixer_lookup[-i] =-val;
127   }
128}
129
130
131/* clock sound channel effect counters */
132void flower_sound_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
133{
134   switch (id)
135   {
136      case TIMER_CLOCK_EFFECT:
137      flower_sound_channel *voice;
138      m_stream->update();
139
140      for (voice = m_channel_list; voice < m_last_channel; voice++)
141         voice->ecount += (voice->ecount < (1<<22));
142      break;
143     
144      default:
145         assert_always(FALSE, "Unknown id in flower_sound_device::device_timer");
146   }
147}
148
240149/********************************************************************************/
241150
242151#if FLOWER_VERBOSE
243152static int r_numwrites[2][8] = {{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0}};
244static void show_soundregs(device_t *device)
153void flower_sound_device::show_soundregs()
245154{
246   flower_sound_state *state = get_safe_token(device);
247155   int set,reg,chan;
248156   char text[0x100];
249157   char message[0x1000] = {0};
250   UINT8 *base = state->m_soundregs1;
158   UINT8 *base = m_soundregs1;
251159
252160   for (set=0;set<2;set++)
253161   {
r23465r23466
265173         strcat(message,text);
266174      }
267175      strcat(message,"\n");
268      base = state->m_soundregs2;
176      base = m_soundregs2;
269177   }
270178   popmessage("%s",message);
271179}
r23465r23466
301209
302210*/
303211
304WRITE8_DEVICE_HANDLER( flower_sound1_w )
212WRITE8_MEMBER( flower_sound_device::sound1_w )
305213{
306   flower_sound_state *state = get_safe_token(device);
307   sound_channel *voice = &state->m_channel_list[offset >> 3 & 7];
214   flower_sound_channel *voice = &m_channel_list[offset >> 3 & 7];
308215   int c = offset & 0xf8;
309   UINT8 *base1 = state->m_soundregs1;
310//  UINT8 *base2 = state->m_soundregs2;
216   UINT8 *base1 = m_soundregs1;
217//  UINT8 *base2 = m_soundregs2;
311218
312   state->m_stream->update();
219   m_stream->update();
313220   base1[offset] = data;
314221#if FLOWER_VERBOSE
315222   r_numwrites[0][offset & 7]++;
316   show_soundregs(device);
223   show_soundregs();
317224#endif
318225
319226   // recompute voice parameters
r23465r23466
321228   voice->volume = base1[c+7] >> 4;
322229}
323230
324WRITE8_DEVICE_HANDLER( flower_sound2_w )
231WRITE8_MEMBER( flower_sound_device::sound2_w )
325232{
326   flower_sound_state *state = get_safe_token(device);
327   sound_channel *voice = &state->m_channel_list[offset >> 3 & 7];
233   flower_sound_channel *voice = &m_channel_list[offset >> 3 & 7];
328234   int i, c = offset & 0xf8;
329   UINT8 *base1 = state->m_soundregs1;
330   UINT8 *base2 = state->m_soundregs2;
235   UINT8 *base1 = m_soundregs1;
236   UINT8 *base2 = m_soundregs2;
331237
332   state->m_stream->update();
238   m_stream->update();
333239   base2[offset] = data;
334240#if FLOWER_VERBOSE
335241   r_numwrites[1][offset & 7]++;
336   show_soundregs(device);
242   show_soundregs();
337243#endif
338244
339245   // reg 7 is start trigger!
r23465r23466
354260}
355261
356262
357const device_type FLOWER = &device_creator<flower_sound_device>;
358
359flower_sound_device::flower_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
360   : device_t(mconfig, FLOWER, "Flower Custom", tag, owner, clock),
361      device_sound_interface(mconfig, *this)
362{
363   m_token = global_alloc_clear(flower_sound_state);
364}
365
366263//-------------------------------------------------
367//  device_config_complete - perform any
368//  operations now that the configuration is
369//  complete
264//  sound_stream_update - handle a stream update
370265//-------------------------------------------------
371266
372void flower_sound_device::device_config_complete()
267void flower_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
373268{
374}
269   stream_sample_t *buffer = outputs[0];
270   flower_sound_channel *voice;
271   short *mix;
272   int i;
375273
376//-------------------------------------------------
377//  device_start - device-specific startup
378//-------------------------------------------------
274   /* zap the contents of the mixer buffer */
275   memset(m_mixer_buffer, 0, samples * sizeof(short));
379276
380void flower_sound_device::device_start()
381{
382   DEVICE_START_NAME( flower_sound )(this);
383}
277   /* loop over each voice and add its contribution */
278   for (voice = m_channel_list; voice < m_last_channel; voice++)
279   {
280      int f = voice->freq;
281      int v = voice->volume;
384282
385//-------------------------------------------------
386//  device_reset - device-specific reset
387//-------------------------------------------------
283      if (!voice->active)
284         continue;
388285
389void flower_sound_device::device_reset()
390{
391   DEVICE_RESET_NAME( flower_sound )(this);
392}
286      // effects
287      // bit 0: volume slide down?
288      if (voice->effect & 1 && !voice->oneshot)
289      {
290         // note: one-shot samples are fixed volume
291         v -= (voice->ecount >> 4);
292         if (v < 0) v = 0;
293      }
294      // bit 1: used often, but hard to figure out what for
295      // bit 2: probably pitch slide
296      if (voice->effect & 4)
297      {
298         f -= (voice->ecount << 7);
299         if (f < 0) f = 0;
300      }
301      // bit 3: not used much, maybe pitch slide the other way?
393302
394//-------------------------------------------------
395//  sound_stream_update - handle a stream update
396//-------------------------------------------------
303      v |= voice->voltab;
304      mix = m_mixer_buffer;
397305
398void flower_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
399{
400   // should never get here
401   fatalerror("sound_stream_update called; not applicable to legacy sound devices\n");
306      for (i = 0; i < samples; i++)
307      {
308         // add sample
309         if (voice->oneshot)
310         {
311            UINT8 sample = m_sample_rom[(voice->start + voice->pos) >> 7 & 0x7fff];
312            if (sample == 0xff)
313            {
314               voice->active = 0;
315               break;
316            }
317            else
318               *mix++ += m_volume_rom[v << 8 | sample] - 0x80;
319         }
320         else
321         {
322            UINT8 sample = m_sample_rom[(voice->start >> 7 & 0x7e00) | (voice->pos >> 7 & 0x1ff)];
323            *mix++ += m_volume_rom[v << 8 | sample] - 0x80;
324         }
325
326         // update counter
327         voice->pos += f;
328      }
329   }
330
331   /* mix it down */
332   mix = m_mixer_buffer;
333   for (i = 0; i < samples; i++)
334      *buffer++ = m_mixer_lookup[*mix++];
402335}

Previous 199869 Revisions Next


© 1997-2024 The MAME Team