Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2,022 changed files
with
770,863 additions
and
0 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
/*************************************************************************** | ||
PeT mess@utanet.at | ||
main part in video/ | ||
Refined with recording/analysis on MPT-03 (PAL UVI chip) by plgDavid | ||
NTSC UVI sound clock: 15734Hz (arcadia) | ||
PAL UVI sound clock: 15625Hz (Soundic MPT-03 - owned by plgDavid) | ||
***************************************************************************/ | ||
|
||
|
||
#include "includes/arcadia.h" | ||
|
||
//known UVI audio clocks | ||
#define UVI_NTSC 15734 | ||
#define UVI_PAL 15625 | ||
|
||
/* we need to create pulse transitions that sound 'decent' | ||
with the current mess/mame interp scheme | ||
this is not needed anymore with the new trick in streams.c | ||
*/ | ||
|
||
#define OSAMP 1 | ||
|
||
//lfsr is 9 bits long (and same as Atari TIA pure noise) | ||
#define LFSR_MASK (1<<8) | ||
|
||
//makes alien invaders samples noise sync. | ||
#define LFSR_INIT 0x00f0 | ||
|
||
//lfsr states at resynch borders | ||
//0x01c1 | ||
//0x01e0 | ||
//0x00f0 //good synch | ||
//0x0178 | ||
//0x01bc | ||
|
||
|
||
// device type definition | ||
const device_type ARCADIA_SOUND = &device_creator<arcadia_sound_device>; | ||
|
||
//------------------------------------------------- | ||
// arcadia_sound_device - constructor | ||
//------------------------------------------------- | ||
|
||
arcadia_sound_device::arcadia_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) | ||
: device_t(mconfig, ARCADIA_SOUND, "Arcadia Custom Sound", tag, owner, clock), | ||
device_sound_interface(mconfig, *this) | ||
{ | ||
} | ||
|
||
//------------------------------------------------- | ||
// device_start - device-specific startup | ||
//------------------------------------------------- | ||
void arcadia_sound_device::device_start() | ||
{ | ||
m_channel = machine().sound().stream_alloc(*this, 0, 1, UVI_PAL*OSAMP, this); | ||
m_lfsr = LFSR_INIT; | ||
m_tval = 1; | ||
logerror("arcadia_sound start\n"); | ||
} | ||
|
||
//------------------------------------------------- | ||
// sound_stream_update - handle update requests for | ||
// our sound stream | ||
//------------------------------------------------- | ||
|
||
void arcadia_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) | ||
{ | ||
int i; | ||
stream_sample_t *buffer = outputs[0]; | ||
|
||
for (i = 0; i < samples; i++, buffer++) | ||
{ | ||
*buffer = 0; | ||
|
||
//if minimal pitch ? | ||
if (m_reg[1]){ | ||
switch (m_mode){ | ||
//dont play anything | ||
case 0:break; | ||
|
||
//tone only | ||
case 1: | ||
*buffer = m_volume * m_tval; | ||
break; | ||
|
||
//noise only | ||
case 2: | ||
*buffer = m_volume * m_nval; | ||
break; | ||
|
||
//tone AND noise (bitwise and) | ||
case 3: | ||
*buffer = m_volume * (m_tval & m_nval); | ||
break; | ||
} | ||
|
||
//counter | ||
m_pos++; | ||
|
||
if (m_pos >= m_size){ | ||
|
||
//calculate new noise bit ( taps: 0000T000T) | ||
unsigned char newBit = m_lfsr & 1; //first tap | ||
newBit = (newBit ^ ((m_lfsr & 0x10)?1:0) );//xor with second tap | ||
|
||
m_nval = m_lfsr & 1; //taking new output from LSB | ||
m_lfsr = m_lfsr >> 1;//shifting | ||
|
||
//insert new bit at end position (size-1) (only if non null) | ||
if (newBit) | ||
m_lfsr |= LFSR_MASK; | ||
|
||
//invert tone | ||
m_tval = !m_tval; | ||
|
||
m_pos = 0; | ||
} | ||
} | ||
} | ||
} | ||
|
||
|
||
|
||
//------------------------------------------------- | ||
// soundport_w | ||
//------------------------------------------------- | ||
|
||
WRITE8_MEMBER(arcadia_sound_device::write) | ||
{ | ||
m_channel->update(); | ||
m_reg[offset] = data; | ||
|
||
//logerror("arcadia_sound write:%x=%x\n",offset,data); | ||
|
||
switch (offset) | ||
{ | ||
case 1: | ||
//as per Gobbler samples: | ||
//the freq counter is only applied on the next change in the flip flop | ||
m_size = (data & 0x7f)*OSAMP; | ||
//logerror("arcadia_sound write: frq:%d\n",data); | ||
|
||
//reset LFSR | ||
if(!m_size) | ||
m_lfsr = LFSR_INIT; | ||
break; | ||
|
||
case 2: | ||
m_volume = (data & 0x07) * 0x800; | ||
m_mode = (data & 0x18) >> 3; | ||
|
||
//logerror("arcadia_sound write: vol:%d mode:%d\n",m_volume,m_mode ); | ||
|
||
if (m_mode != m_omode){ | ||
//not 100% sure about this, maybe we should not reset anything | ||
//m_pos = 0; | ||
m_tval = 0; | ||
} | ||
m_omode = m_mode; | ||
break; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
#ifndef ARCADIA_SOUND_H_ | ||
#define ARCADIA_SOUND_H_ | ||
|
||
//************************************************************************** | ||
// INTERFACE CONFIGURATION MACROS | ||
//************************************************************************** | ||
|
||
#define MCFG_ARCADIA_SOUND_ADD(_tag) \ | ||
MCFG_SOUND_ADD(_tag, ARCADIA_SOUND, 0) | ||
|
||
//************************************************************************** | ||
// TYPE DEFINITIONS | ||
//************************************************************************** | ||
|
||
// ======================> arcadia_sound_device | ||
|
||
class arcadia_sound_device : public device_t, | ||
public device_sound_interface | ||
{ | ||
public: | ||
// construction/destruction | ||
arcadia_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); | ||
|
||
DECLARE_WRITE8_MEMBER(write); | ||
protected: | ||
// device-level overrides | ||
virtual void device_start(); | ||
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples); | ||
|
||
sound_stream *m_channel; | ||
UINT8 m_reg[3]; | ||
int m_size, m_pos,m_tval,m_nval; | ||
unsigned m_mode, m_omode; | ||
unsigned m_volume; | ||
unsigned m_lfsr; | ||
}; | ||
|
||
// device type definition | ||
extern const device_type ARCADIA_SOUND; | ||
|
||
#endif /* ARCADIA_SOUND_H_ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
#include "includes/channelf.h" | ||
|
||
|
||
static const int max_amplitude = 0x7fff; | ||
|
||
typedef struct _channelf_sound_state channelf_sound_state; | ||
struct _channelf_sound_state | ||
{ | ||
sound_stream *channel; | ||
int sound_mode; | ||
int incr; | ||
float decay_mult; | ||
int envelope; | ||
UINT32 sample_counter; | ||
int forced_ontime; // added for improved sound | ||
int min_ontime; // added for improved sound | ||
}; | ||
|
||
INLINE channelf_sound_state *get_safe_token(device_t *device) | ||
{ | ||
assert(device != NULL); | ||
assert(device->type() == CHANNELF); | ||
return (channelf_sound_state *)downcast<legacy_device_base *>(device)->token(); | ||
} | ||
|
||
void channelf_sound_w(device_t *device, int mode) | ||
{ | ||
channelf_sound_state *state = get_safe_token(device); | ||
if (mode == state->sound_mode) | ||
return; | ||
|
||
state->channel->update(); | ||
state->sound_mode = mode; | ||
|
||
switch(mode) | ||
{ | ||
case 0: | ||
state->envelope = 0; | ||
state->forced_ontime = 0; // added for improved sound | ||
break; | ||
case 1: | ||
case 2: | ||
case 3: | ||
state->envelope = max_amplitude; | ||
state->forced_ontime = state->min_ontime; // added for improved sound | ||
break; | ||
} | ||
} | ||
|
||
|
||
|
||
static STREAM_UPDATE( channelf_sh_update ) | ||
{ | ||
channelf_sound_state *state = get_safe_token(device); | ||
UINT32 mask = 0, target = 0; | ||
stream_sample_t *buffer = outputs[0]; | ||
stream_sample_t *sample = buffer; | ||
|
||
switch( state->sound_mode ) | ||
{ | ||
case 0: /* sound off */ | ||
memset(buffer,0,sizeof(*buffer)*samples); | ||
return; | ||
|
||
case 1: /* high tone (2V) - 1000Hz */ | ||
mask = 0x00010000; | ||
target = 0x00010000; | ||
break; | ||
case 2: /* medium tone (4V) - 500Hz */ | ||
mask = 0x00020000; | ||
target = 0x00020000; | ||
break; | ||
case 3: /* low (weird) tone (32V & 8V) */ | ||
mask = 0x00140000; | ||
target = 0x00140000; | ||
break; | ||
} | ||
|
||
while (samples-- > 0) | ||
{ | ||
if ((state->forced_ontime > 0) || ((state->sample_counter & mask) == target)) // change made for improved sound | ||
*sample++ = state->envelope; | ||
else | ||
*sample++ = 0; | ||
state->sample_counter += state->incr; | ||
state->envelope *= state->decay_mult; | ||
if (state->forced_ontime > 0) // added for improved sound | ||
state->forced_ontime -= 1; // added for improved sound | ||
} | ||
} | ||
|
||
|
||
|
||
static DEVICE_START(channelf_sound) | ||
{ | ||
channelf_sound_state *state = get_safe_token(device); | ||
int rate; | ||
|
||
state->channel = device->machine().sound().stream_alloc(*device, 0, 1, device->machine().sample_rate(), 0, channelf_sh_update); | ||
rate = device->machine().sample_rate(); | ||
|
||
/* | ||
* 2V = 1000Hz ~= 3579535/224/16 | ||
* Note 2V on the schematic is not the 2V scanline counter - | ||
* it is the 2V vertical pixel counter | ||
* 1 pixel = 4 scanlines high | ||
* | ||
* | ||
* This is a convenient way to generate the relevant frequencies, | ||
* using a DDS (Direct Digital Synthesizer) | ||
* | ||
* Essentially, you want a counter to overflow some bit position | ||
* at a fixed rate. So, you figure out a number which you can add | ||
* to the counter at every sample, so that you will achieve this | ||
* | ||
* In this case, we want to overflow bit 16 and the 2V rate, 1000Hz. | ||
* This means we also get bit 17 = 4V, bit 18 = 8V, etc. | ||
*/ | ||
|
||
/* This is the proper value to add per sample */ | ||
state->incr = 65536.0/(rate/1000.0/2.0); | ||
|
||
// added for improved sound | ||
/* This is the minimum forced ontime, in samples */ | ||
state->min_ontime = rate/1000*2; /* approx 2ms - estimated, not verified on HW */ | ||
|
||
/* This was measured, decay envelope with half life of ~9ms */ | ||
/* (this is decay multiplier per sample) */ | ||
state->decay_mult = exp((-0.693/9e-3)/rate); | ||
|
||
/* initial conditions */ | ||
state->envelope = 0; | ||
} | ||
|
||
|
||
DEVICE_GET_INFO( channelf_sound ) | ||
{ | ||
switch (state) | ||
{ | ||
/* --- the following bits of info are returned as 64-bit signed integers --- */ | ||
case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(channelf_sound_state); break; | ||
|
||
/* --- the following bits of info are returned as pointers to data or functions --- */ | ||
case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(channelf_sound); break; | ||
|
||
/* --- the following bits of info are returned as NULL-terminated strings --- */ | ||
case DEVINFO_STR_NAME: strcpy(info->s, "Channel F"); break; | ||
case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break; | ||
} | ||
} | ||
|
||
DEFINE_LEGACY_SOUND_DEVICE(CHANNELF, channelf_sound); |
Oops, something went wrong.