summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/sound/spu.h
diff options
context:
space:
mode:
author Miodrag Milanovic <mmicko@gmail.com>2015-09-13 08:41:44 +0200
committer Miodrag Milanovic <mmicko@gmail.com>2015-09-13 08:41:44 +0200
commitf88cefad27a1737c76e09d99c9fb43e173506081 (patch)
tree2d8167d03579c46e226471747eb4407bd00ed6fa /src/devices/sound/spu.h
parente92ac9e0fa8e99869894bea00589bbb526be30aa (diff)
Move all devices into separate part of src tree (nw)
Diffstat (limited to 'src/devices/sound/spu.h')
-rw-r--r--src/devices/sound/spu.h255
1 files changed, 255 insertions, 0 deletions
diff --git a/src/devices/sound/spu.h b/src/devices/sound/spu.h
new file mode 100644
index 00000000000..8a6727e4833
--- /dev/null
+++ b/src/devices/sound/spu.h
@@ -0,0 +1,255 @@
+// license:BSD-3-Clause
+// copyright-holders:pSXAuthor, R. Belmont
+#pragma once
+
+#ifndef __SPU_H__
+#define __SPU_H__
+
+#include "spureverb.h"
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_SPU_IRQ_HANDLER(_devcb) \
+ devcb = &spu_device::set_irq_handler(*device, DEVCB_##_devcb);
+
+#define MCFG_SPU_ADD(_tag, _clock) \
+ MCFG_DEVICE_MODIFY( "maincpu" ) \
+ MCFG_PSX_SPU_READ_HANDLER(DEVREAD16(_tag, spu_device, read)) \
+ MCFG_PSX_SPU_WRITE_HANDLER(DEVWRITE16(_tag, spu_device, write)) \
+ MCFG_DEVICE_ADD(_tag, SPU, _clock) \
+ MCFG_SPU_IRQ_HANDLER(DEVWRITELINE("maincpu:irq", psxirq_device, intin9)) \
+ MCFG_PSX_DMA_CHANNEL_READ( "maincpu", 4, psx_dma_read_delegate( FUNC( spu_device::dma_read ), (spu_device *) device ) ) \
+ MCFG_PSX_DMA_CHANNEL_WRITE( "maincpu", 4, psx_dma_write_delegate( FUNC( spu_device::dma_write ), (spu_device *) device ) )
+
+// ======================> spu_device
+
+const unsigned int spu_base_frequency_hz=44100;
+
+class stream_buffer;
+
+class spu_device : public device_t, public device_sound_interface
+{
+ struct sample_cache;
+ struct sample_loop_cache;
+ struct cache_pointer;
+ struct voiceinfo;
+
+ enum
+ {
+ dirtyflag_voice_mask=0x00ffffff,
+ dirtyflag_reverb=0x01000000,
+ dirtyflag_ram=0x02000000,
+ dirtyflag_irq=0x04000000
+ };
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_post_load();
+ virtual void device_stop();
+
+ virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
+
+ // internal state
+ devcb_write_line m_irq_handler;
+
+ unsigned char *spu_ram;
+ reverb *rev;
+ unsigned int taddr, sample_t;
+
+ stream_buffer *xa_buffer, *cdda_buffer;
+ unsigned int xa_cnt,cdda_cnt,
+ xa_freq,cdda_freq,
+ xa_channels,
+ xa_spf,
+ xa_out_ptr,
+ cur_frame_sample,
+ cur_generate_sample,
+ dirty_flags;
+
+ UINT16 m_cd_out_ptr;
+
+ signed short xa_last[4];
+ bool status_enabled,
+ xa_playing,
+ cdda_playing;
+ int xa_voll,xa_volr,
+ changed_xa_vol;
+ voiceinfo *voice;
+ sample_cache **cache;
+ float samples_per_frame,
+ samples_per_cycle;
+
+ static float freq_multiplier;
+
+ unsigned char *output_buf[4];
+ unsigned int output_head,
+ output_tail,
+ output_size,
+ cur_qsz;
+
+ unsigned int noise_t;
+ signed short noise_cur;
+ int noise_seed;
+
+ #pragma pack(push,spureg,1)
+
+ struct voicereg
+ {
+ unsigned short vol_l, // 0
+ vol_r, // 2
+ pitch, // 4
+ addr, // 6
+ adsl, // 8
+ srrr, // a
+ curvol, // c
+ repaddr; // e
+ };
+
+ union
+ {
+ unsigned char reg[0x200];
+ struct
+ {
+ voicereg voice[24];
+ unsigned short mvol_l,mvol_r,
+ rvol_l,rvol_r;
+ unsigned int keyon,
+ keyoff,
+ fm,
+ noise,
+ reverb,
+ chon;
+ unsigned short _unknown,
+ reverb_addr,
+ irq_addr,
+ trans_addr,
+ data,
+ ctrl;
+ unsigned int status;
+ signed short cdvol_l,cdvol_r,
+ exvol_l,exvol_r;
+ } spureg;
+ };
+
+ #pragma pack(pop,spureg)
+
+ struct reverb_preset
+ {
+ const char *name;
+ unsigned short param[32];
+ reverb_params cfg;
+ };
+
+ reverb_preset *cur_reverb_preset;
+
+ static reverb_preset reverb_presets[];
+
+ void key_on(const int v);
+ void key_off(const int v);
+ bool update_envelope(const int v);
+ void write_data(const unsigned short data);
+ void generate(void *ptr, const unsigned int sz);
+ void generate_voice(const unsigned int v,
+ void *ptr,
+ void *noiseptr,
+ void *outxptr,
+ const unsigned int sz);
+ void generate_noise(void *ptr, const unsigned int num);
+ bool process_voice(const unsigned int v,
+ const unsigned int sz,
+ void *ptr,
+ void *fmnoise_ptr,
+ void *outxptr,
+ unsigned int *tleft);
+ void process();
+ void process_until(const unsigned int tsample);
+ void update_voice_loop(const unsigned int v);
+ bool update_voice_state(const unsigned int v);
+ void update_voice_state();
+ void update_voice_events(voiceinfo *vi);
+ void update_irq_event();
+ unsigned int get_irq_distance(const voiceinfo *vi);
+ void generate_xa(void *ptr, const unsigned int sz);
+ void generate_cdda(void *ptr, const unsigned int sz);
+ void decode_xa_mono(const unsigned char *xa, unsigned char *ptr);
+ void decode_xa_stereo(const unsigned char *xa, unsigned char *ptr);
+ void update_key();
+ void update_reverb();
+ void update_timing();
+
+ bool translate_sample_addr(const unsigned int addr, cache_pointer *cp);
+ sample_cache *get_sample_cache(const unsigned int addr);
+ void flush_cache(sample_cache *sc,
+ const unsigned int istart,
+ const unsigned int iend);
+ void invalidate_cache(const unsigned int st, const unsigned int en);
+
+ void set_xa_format(const float freq, const int channels);
+
+ void init_stream();
+ void kill_stream();
+
+ void update_vol(const unsigned int addr);
+
+ void flush_output_buffer();
+
+ sample_loop_cache *get_loop_cache(sample_cache *cache,
+ const unsigned int lpen,
+ sample_cache *lpcache,
+ const unsigned int lpst);
+#if 0
+ void write_cache_pointer(outfile *fout,
+ cache_pointer *cp,
+ sample_loop_cache *lc=NULL);
+ void read_cache_pointer(infile *fin,
+ cache_pointer *cp,
+ sample_loop_cache **lc=NULL);
+#endif
+ static float get_linear_rate(const int n);
+ static float get_linear_rate_neg_phase(const int n);
+ static float get_pos_exp_rate(const int n);
+ static float get_pos_exp_rate_neg_phase(const int n);
+ static float get_neg_exp_rate(const int n);
+ static float get_neg_exp_rate_neg_phase(const int n);
+ static float get_decay_rate(const int n);
+ static float get_sustain_level(const int n);
+ static float get_linear_release_rate(const int n);
+ static float get_exp_release_rate(const int n);
+ static reverb_preset *find_reverb_preset(const unsigned short *param);
+
+public:
+ spu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // static configuration helpers
+ template<class _Object> static devcb_base &set_irq_handler(device_t &device, _Object object) { return downcast<spu_device &>(device).m_irq_handler.set_callback(object); }
+
+ void dma_read( UINT32 *ram, UINT32 n_address, INT32 n_size );
+ void dma_write( UINT32 *ram, UINT32 n_address, INT32 n_size );
+
+ void reinit_sound();
+ void kill_sound();
+
+ void update();
+
+ void start_dma(UINT8 *mainram, bool to_spu, UINT32 size);
+ bool play_xa(const unsigned int sector, const unsigned char *sec);
+ bool play_cdda(const unsigned int sector, const unsigned char *sec);
+ void flush_xa(const unsigned int sector=0);
+ void flush_cdda(const unsigned int sector=0);
+
+ sound_stream *m_stream;
+
+ DECLARE_READ16_MEMBER( read );
+ DECLARE_WRITE16_MEMBER( write );
+};
+
+extern reverb_params *spu_reverb_cfg;
+
+// device type definition
+extern const device_type SPU;
+
+#endif