summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/sound/spu.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/sound/spu.cpp')
-rw-r--r--src/devices/sound/spu.cpp169
1 files changed, 90 insertions, 79 deletions
diff --git a/src/devices/sound/spu.cpp b/src/devices/sound/spu.cpp
index d3877ad5bf4..9e3a95b0357 100644
--- a/src/devices/sound/spu.cpp
+++ b/src/devices/sound/spu.cpp
@@ -12,6 +12,7 @@
#include "spu.h"
#include "spureverb.h"
#include "cpu/psx/psx.h"
+#include "corestr.h"
//
//
@@ -272,7 +273,8 @@ public:
invalid_end,
loopaddr,
last_update_end;
- signed short *data,*loop,*dend;
+ std::unique_ptr<signed short []> data;
+ signed short *loop,*dend;
adpcm_decoder decoder, update_decoder;
mutable int ref_count;
bool valid,
@@ -301,8 +303,8 @@ public:
ref_count--;
if (ref_count==0)
{
- cache_size-=(dend-data)<<1;
- global_free(this);
+ cache_size-=(dend-data.get())<<1;
+ delete this;
}
}
@@ -444,7 +446,7 @@ struct spu_device::voiceinfo
//
//
-class stream_buffer
+class spu_stream_buffer
{
public:
struct stream_marker
@@ -466,7 +468,7 @@ public:
stream_marker *marker_head,
*marker_tail;
- stream_buffer(const unsigned int _sector_size,
+ spu_stream_buffer(const unsigned int _sector_size,
const unsigned int _num_sectors)
: head(0),
tail(0),
@@ -481,7 +483,7 @@ public:
memset(&buffer[0], 0, buffer_size);
}
- ~stream_buffer()
+ ~spu_stream_buffer()
{
flush_all();
}
@@ -521,7 +523,7 @@ public:
head=xam->offset;
marker_tail=xam->prev;
if (marker_tail) marker_tail->next=nullptr;
- global_free(xam);
+ delete xam;
}
// Set marker head to nullptr if the list is now empty
@@ -544,7 +546,7 @@ public:
{
stream_marker *m=marker_head;
marker_head=marker_head->next;
- global_free(m);
+ delete m;
}
marker_head=marker_tail=nullptr;
@@ -566,7 +568,7 @@ public:
stream_marker *xam=marker_head;
marker_head=xam->next;
- global_free(xam);
+ delete xam;
if (marker_head) marker_head->prev=nullptr;
}
@@ -606,12 +608,12 @@ static inline int clamp(const int v)
spu_device::sample_cache::~sample_cache()
{
- global_free_array(data);
+ data.reset();
while (loop_cache)
{
sample_loop_cache *lc=loop_cache;
loop_cache=lc->next;
- global_free(lc);
+ delete lc;
}
}
@@ -623,7 +625,7 @@ signed short *spu_device::sample_cache::get_sample_pointer(const unsigned int ad
{
if ((addr>=start) && (addr<end))
{
- return data+(((addr-start)>>4)*28);
+ return &data[((addr-start)>>4)*28];
} else
{
return nullptr;
@@ -668,9 +670,9 @@ bool spu_device::sample_cache::get_loop_pointer(cache_pointer *cp)
unsigned int spu_device::sample_cache::get_sample_address(const signed short *ptr) const
{
- if ((ptr>=data) && (ptr<=dend))
+ if ((ptr>=data.get()) && (ptr<=dend))
{
- return start+(((ptr-data)/28)<<4);
+ return start+(((ptr-data.get())/28)<<4);
} else
{
return -1;
@@ -705,7 +707,7 @@ void spu_device::sample_cache::add_loop_cache(sample_loop_cache *lc)
bool spu_device::sample_cache::is_valid_pointer(signed short *ptr) const
{
- if ((ptr>=data) && (data<=dend)) return true;
+ if ((ptr>=data.get()) && (data.get()<=dend)) return true;
for (sample_loop_cache *slc=loop_cache; slc; slc=slc->next)
if ((ptr>=slc->data) && (ptr<(slc->data+num_loop_cache_samples)))
return true;
@@ -720,7 +722,7 @@ bool spu_device::sample_cache::try_update(spu_device *spu)
{
if ((invalid_start>=start) && (invalid_end<=end))
{
- adpcm_packet *ap=(adpcm_packet *)(spu->spu_ram+start);
+ adpcm_packet *ap=(adpcm_packet *)&spu->spu_ram[start];
unsigned int a;
unsigned int loop=0;
@@ -756,8 +758,8 @@ bool spu_device::sample_cache::try_update(spu_device *spu)
printf("\n");
#endif
- signed short *dp=data+(((invalid_start-start)>>4)*28);
- ap=(adpcm_packet *)(spu->spu_ram+invalid_start);
+ signed short *dp=&data[((invalid_start-start)>>4)*28];
+ ap=(adpcm_packet *)&spu->spu_ram[invalid_start];
for (a=invalid_start; a<invalid_end; a+=16, ap++)
dp=update_decoder.decode_packet(ap,dp);
@@ -779,7 +781,7 @@ bool spu_device::sample_cache::try_update(spu_device *spu)
signed short *dpend=dp+lc->len;
unsigned int adr=lc->loopstart;
for (unsigned int i=0; ((i<num_loop_cache_packets) && (dp<dpend)); i++, adr+=16)
- dp=tmp.decode_packet((adpcm_packet *)(spu->spu_ram+adr),dp);
+ dp=tmp.decode_packet((adpcm_packet *)&spu->spu_ram[adr],dp);
}
}
@@ -847,7 +849,7 @@ bool spu_device::cache_pointer::update(spu_device *spu)
// Cache is invalid, calculate play address offset from start of
// old cache block
- unsigned int off=ptr-cache->data,
+ unsigned int off=ptr-cache->data.get(),
addr=cache->start;
// Release cache block and get updated one
@@ -856,7 +858,7 @@ bool spu_device::cache_pointer::update(spu_device *spu)
// Calculate play address in new cache block
- ptr=cache->data+off;
+ ptr=&cache->data[off];
if (ptr>=cache->dend)
{
@@ -870,7 +872,7 @@ bool spu_device::cache_pointer::update(spu_device *spu)
// Return false if we do not have a cache block or the play address is invalid
- if ((cache) && ((ptr>=cache->data) && (ptr<cache->dend)))
+ if ((cache) && ((ptr>=cache->data.get()) && (ptr<cache->dend)))
{
return true;
} else
@@ -948,6 +950,7 @@ spu_device::spu_device(const machine_config &mconfig, const char *tag, device_t
spu_device::spu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, SPU, tag, owner, clock),
device_sound_interface(mconfig, *this),
+ m_stream_flags(STREAM_DEFAULT_FLAGS),
m_irq_handler(*this),
dirty_flags(-1),
status_enabled(false),
@@ -957,25 +960,26 @@ spu_device::spu_device(const machine_config &mconfig, const char *tag, device_t
{
}
-//-------------------------------------------------
-// static_set_irqf - configuration helper to set
-// the IRQ callback
-//-------------------------------------------------
-
void spu_device::device_start()
{
- m_irq_handler.resolve_safe();
+ spu_base_frequency_hz = clock() / 768.0f;
+ generate_linear_rate_table();
+ generate_pos_exp_rate_table();
+ generate_neg_exp_rate_table();
+ generate_decay_rate_table();
+ generate_linear_release_rate_table();
+ generate_exp_release_rate_table();
voice=new voiceinfo [24];
- spu_ram=new unsigned char [spu_ram_size];
+ spu_ram=std::make_unique<unsigned char []>(spu_ram_size);
- xa_buffer=new stream_buffer(xa_sector_size,xa_buffer_sectors);
- cdda_buffer=new stream_buffer(cdda_sector_size,cdda_buffer_sectors);
+ xa_buffer=new spu_stream_buffer(xa_sector_size,xa_buffer_sectors);
+ cdda_buffer=new spu_stream_buffer(cdda_sector_size,cdda_buffer_sectors);
init_stream();
- cache=new sample_cache *[spu_ram_size>>4];
- memset(cache,0,(spu_ram_size>>4)*sizeof(sample_cache *));
+ cache=std::make_unique<sample_cache * []>(spu_ram_size>>4);
+ std::fill_n(cache.get(), spu_ram_size>>4, nullptr);
// register save state stuff
save_item(NAME(reg)); // this covers all spureg.* plus the reverb parameter block
@@ -1031,16 +1035,16 @@ void spu_device::device_reset()
cdda_playing=false;
m_cd_out_ptr = 0;
- memset(spu_ram,0,spu_ram_size);
+ memset(spu_ram.get(),0,spu_ram_size);
memset(reg,0,0x200);
memset(voice,0,sizeof(voiceinfo)*24);
spureg.status|=(1<<7)|(1<<10);
- memset(cache,0,(spu_ram_size>>4)*sizeof(sample_cache *));
+ std::fill_n(cache.get(), spu_ram_size>>4, nullptr);
for (auto & elem : output_buf)
- elem=new unsigned char [output_buffer_size];
+ elem=std::make_unique<unsigned char []>(output_buffer_size);
output_head=output_tail=output_size=0;
noise_t=0;
@@ -1058,7 +1062,7 @@ void spu_device::device_post_load()
dirty_flags = -1;
// kill and reallocate reverb to avoid artifacts
- global_free(rev);
+ delete rev;
rev = new reverb(44100);
// and do some update processing
@@ -1074,16 +1078,16 @@ void spu_device::device_post_load()
void spu_device::device_stop()
{
for (auto & elem : output_buf)
- global_free_array(elem);
+ elem.reset();
kill_stream();
- global_free_array(spu_ram);
+ spu_ram.reset();
invalidate_cache(0,spu_ram_size);
- global_free_array(cache);
- global_free(xa_buffer);
- global_free(cdda_buffer);
- global_free_array(voice);
+ cache.reset();
+ delete xa_buffer;
+ delete cdda_buffer;
+ delete [] voice;
}
//
//
@@ -1093,12 +1097,13 @@ void spu_device::init_stream()
{
const unsigned int hz=44100;
- m_stream = machine().sound().stream_alloc(*this, 0, 2, hz);
+ // TODO: Rewrite SPU stream update code to work such that Taiko no Tatsujin no longer needs synchronous streams
+ m_stream = stream_alloc(0, 2, hz, m_stream_flags);
rev=new reverb(hz);
cdda_freq=(unsigned int)((44100.0f/(float)hz)*4096.0f);
- freq_multiplier=(float)spu_base_frequency_hz/(float)hz;
+ freq_multiplier=spu_base_frequency_hz/(float)hz;
}
//
@@ -1107,7 +1112,7 @@ void spu_device::init_stream()
void spu_device::kill_stream()
{
- global_free(rev);
+ delete rev;
rev=nullptr;
}
@@ -1136,7 +1141,7 @@ void spu_device::kill_sound()
//
//
-READ16_MEMBER( spu_device::read )
+uint16_t spu_device::read(offs_t offset)
{
unsigned short ret, *rp=(unsigned short *)(reg+((offset*2)&0x1ff));
@@ -1158,7 +1163,7 @@ READ16_MEMBER( spu_device::read )
//
//
-WRITE16_MEMBER( spu_device::write )
+void spu_device::write(offs_t offset, uint16_t data)
{
#ifdef debug_spu_registers
printf("spu: write %08x = %04x [%s]\n",
@@ -1262,7 +1267,7 @@ void spu_device::write_data(const unsigned short data)
assert(taddr<spu_ram_size);
if (cache[taddr>>4]) flush_cache(cache[taddr>>4],taddr,taddr+2);
- *((unsigned short *)(spu_ram+taddr))=data;
+ *((unsigned short *)&spu_ram[taddr])=data;
taddr+=2;
}
@@ -1342,7 +1347,7 @@ spu_device::sample_cache *spu_device::get_sample_cache(const unsigned int addr)
sc->start=addr;
sc->loop=nullptr;
- adpcm_packet *ap=(adpcm_packet *)(spu_ram+sc->start);
+ adpcm_packet *ap=(adpcm_packet *)&spu_ram[sc->start];
unsigned int a;
for (a=addr; a<(512*1024); a+=16, ap++)
{
@@ -1358,13 +1363,13 @@ spu_device::sample_cache *spu_device::get_sample_cache(const unsigned int addr)
sc->end=(std::min)(spu_ram_size,a+16);
unsigned int sz=((sc->end-sc->start)>>4)*28;
- sc->data=new signed short [sz];
+ sc->data=std::make_unique<signed short []>(sz);
sample_cache::cache_size+=sz<<1;
sc->loopaddr=loop;
- if (loop) sc->loop=sc->data+(((loop-sc->start)>>4)*28);
+ if (loop) sc->loop=&sc->data[((loop-sc->start)>>4)*28];
- signed short *dp=sc->data;
- ap=(adpcm_packet *)(spu_ram+sc->start);
+ signed short *dp=sc->data.get();
+ ap=(adpcm_packet *)&spu_ram[sc->start];
for (a=sc->start; a<sc->end; a+=16, ap++)
dp=sc->decoder.decode_packet(ap,dp);
@@ -1389,7 +1394,7 @@ bool spu_device::translate_sample_addr(const unsigned int addr, cache_pointer *c
cp->reset();
if ((cp->cache=get_sample_cache(addr)))
{
- cp->ptr=cp->cache->data+(((addr-cp->cache->start)>>4)*28);
+ cp->ptr=&cp->cache->data[((addr-cp->cache->start)>>4)*28];
cp->cache->add_ref();
return true;
}
@@ -1530,7 +1535,7 @@ spu_device::sample_loop_cache *spu_device::get_loop_cache(sample_cache *cache, c
signed short *dp=lc->data;
for (unsigned int i=0; ((i<num_loop_cache_packets) &&
(adr<lpcache->end)); i++, adr+=16)
- dp=tmp.decode_packet((adpcm_packet *)(spu_ram+adr),dp);
+ dp=tmp.decode_packet((adpcm_packet *)&spu_ram[adr],dp);
#ifdef log_loop_cache
log(log_spu,"spu: add loop cache %08x %08x->%08x (end at %08x)\n",lc,lpen,lpst,adr);
@@ -1572,7 +1577,7 @@ void spu_device::update_voice_loop(const unsigned int v)
{
ra=spureg.voice[v].repaddr<<3;
ra=(ra+0xf)&~0xf;
- const adpcm_packet *ap=ra?(adpcm_packet *)(spu_ram+ra):nullptr;
+ const adpcm_packet *ap=ra?(adpcm_packet *)&spu_ram[ra]:nullptr;
if (ap)
{
@@ -2205,7 +2210,7 @@ bool spu_device::update_envelope(const int v)
break;
case 4: // release
- voice[v].env_level=(std::min)(1.0f,(std::max)(0.0f,voice[v].env_level));
+ voice[v].env_level=std::clamp(voice[v].env_level,0.0f,1.0f);
voice[v].env_delta=voice[v].env_rr;
if (voice[v].env_rr == -0.0f) // 0.0 release means infinite time
{
@@ -2393,8 +2398,8 @@ void spu_device::generate_xa(void *ptr, const unsigned int sz)
// Write to SPU XA buffer (for emulation purposes - some games read this
// back to do analysers, etc...)
- *(signed short *)(spu_ram+xa_out_ptr)=vl;
- *(signed short *)(spu_ram+xa_out_ptr+0x800)=vr;
+ *(signed short *)&spu_ram[xa_out_ptr]=vl;
+ *(signed short *)&spu_ram[xa_out_ptr+0x800]=vr;
xa_out_ptr=(xa_out_ptr+2)&0x7ff;
// Mix samples into output buffer
@@ -2430,7 +2435,7 @@ void spu_device::generate_xa(void *ptr, const unsigned int sz)
{
xa_playing=false;
- memset(spu_ram,0,0x1000);
+ memset(spu_ram.get(),0,0x1000);
xa_out_ptr=0;
}
}
@@ -2465,8 +2470,8 @@ void spu_device::generate_cdda(void *ptr, const unsigned int sz)
int16_t vr = ((sp[1]*volr)>>15);
// if the volume adjusted samples are stored here, vibribbon does nothing
- *(signed short *)(spu_ram+m_cd_out_ptr)=sp[0];
- *(signed short *)(spu_ram+m_cd_out_ptr+0x400)=sp[1];
+ *(signed short *)&spu_ram[m_cd_out_ptr]=sp[0];
+ *(signed short *)&spu_ram[m_cd_out_ptr+0x400]=sp[1];
m_cd_out_ptr=(m_cd_out_ptr+2)&0x3ff;
//if((m_cd_out_ptr == ((spureg.irq_addr << 3) & ~0x400)) && (spureg.ctrl & spuctrl_irq_enable))
@@ -2529,6 +2534,13 @@ void spu_device::update_reverb()
{
if (dirty_flags&dirtyflag_reverb)
{
+ // TODO: Handle cases where reverb present can't be found better
+ // If a save state is loaded and has reverb values that don't match a preset
+ // then spu_reverb_cfg is never set so the reverb settings won't be the same as
+ // when the save state was created.
+ // This only becomes an issue when loading save states from the command line
+ // because if you load a save state from within MAME it will hold the last used
+ // spu_reverb_cfg and reuse that value.
cur_reverb_preset=find_reverb_preset((unsigned short *)&reg[0x1c0]);
if (cur_reverb_preset==nullptr)
@@ -2575,10 +2587,10 @@ void spu_device::generate(void *ptr, const unsigned int sz)
while ((left) && (output_size))
{
unsigned int n=(std::min)((std::min)(left,output_buffer_size-output_head),output_size);
- memcpy(dp,output_buf[0]+output_head,n);
+ memcpy(dp,&output_buf[0][output_head],n);
rev->process((signed short *)dp,
- (signed short *)(output_buf[1]+output_head),
+ (signed short *)&output_buf[1][output_head],
spu_reverb_cfg,
(signed short)spureg.rvol_l,
(signed short)spureg.rvol_r,
@@ -2683,10 +2695,10 @@ void spu_device::process_until(const unsigned int tsample)
process_samples=(std::min)(process_samples,
(output_buffer_size-output_tail)>>2);
- unsigned char *outptr=output_buf[0]+output_tail,
- *reverbptr=output_buf[1]+output_tail,
- *fmptr=output_buf[2]+output_tail,
- *noiseptr=output_buf[3]+output_tail;
+ unsigned char *outptr=&output_buf[0][output_tail],
+ *reverbptr=&output_buf[1][output_tail],
+ *fmptr=&output_buf[2][output_tail],
+ *noiseptr=&output_buf[3][output_tail];
output_tail+=process_samples<<2;
output_tail&=(output_buffer_size-1);
@@ -2761,21 +2773,20 @@ void spu_device::update_timing()
//
//
-void spu_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
+void spu_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
{
- stream_sample_t *outL, *outR;
int16_t temp[44100], *src;
- outL = outputs[0];
- outR = outputs[1];
+ auto &outL = outputs[0];
+ auto &outR = outputs[1];
- generate(temp, samples*4); // second parameter is bytes, * 2 (size of int16_t) * 2 (stereo)
+ generate(temp, outputs[0].samples()*4); // second parameter is bytes, * 2 (size of int16_t) * 2 (stereo)
src = &temp[0];
- for (int i = 0; i < samples; i++)
+ for (int i = 0; i < outputs[0].samples(); i++)
{
- *outL++ = *src++;
- *outR++ = *src++;
+ outL.put_int(i, *src++, 32768);
+ outR.put_int(i, *src++, 32768);
}
}
@@ -2797,13 +2808,13 @@ void spu_device::start_dma(uint8_t *mainram, bool to_spu, uint32_t size)
{
invalidate_cache(st,en);
- memcpy(spu_ram+(spureg.trans_addr<<3), mainram, size);
+ memcpy(&spu_ram[spureg.trans_addr<<3], mainram, size);
dirty_flags|=dirtyflag_ram;
}
else
{
- memcpy(mainram, spu_ram+(spureg.trans_addr<<3), size);
+ memcpy(mainram, &spu_ram[spureg.trans_addr<<3], size);
}
}