// stream creation //------------------------------------------------- // stream_alloc - allocate a new stream //------------------------------------------------- public sound_stream stream_alloc(device_t device, int inputs, int outputs, int sample_rate, stream_update_delegate callback = null) { var stream = new sound_stream(device, inputs, outputs, sample_rate, callback); m_stream_list.push_back(stream); return(stream); }
//float input_gain(int inputnum) const; //float output_gain(int outputnum) const; //void set_input_gain(int inputnum, float gain); //------------------------------------------------- // set_output_gain - set the gain on the given // output index of the device //------------------------------------------------- public void set_output_gain(int outputnum, float gain) { // handle ALL_OUTPUTS as a special case if (outputnum == ALL_OUTPUTS) { foreach (var stream in device().machine().sound().streams()) { if (stream.device() == device()) { for (int num = 0; num < stream.output_count(); num++) { stream.output(num).set_gain(gain); } } } } // look up the stream and stream output index else { int stream_outputnum; sound_stream stream = output_to_stream_output(outputnum, out stream_outputnum); if (stream != null) { stream.output(stream_outputnum).set_gain(gain); } } }
// device_sound_interface overrides //------------------------------------------------- // sound_stream_update - update a sound stream //------------------------------------------------- void device_sound_interface_sound_stream_update(sound_stream stream, std.vector <read_stream_view> inputs, std.vector <write_stream_view> outputs) //virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override; { // find the channel with this stream stream_buffer_sample_t sample_scale = (stream_buffer_sample_t)(1.0 / 32768.0); for (int channel = 0; channel < m_channels; channel++) { if (stream == m_channel[channel].stream) { channel_t chan = m_channel[channel]; var buffer = outputs[0]; // process if we still have a source and we're not paused if (chan.source != null && !chan.paused) { // load some info locally double step = (double)chan.curfreq / (double)buffer.sample_rate(); double endpos = chan.source_len; Pointer <int16_t> sample = new Pointer <int16_t>(chan.source); //const int16_t *sample = chan.source; for (int sampindex = 0; sampindex < buffer.samples(); sampindex++) { // do a linear interp on the sample double pos_floor = std.floor(chan.pos); double frac = chan.pos - pos_floor; int32_t ipos = (int32_t)pos_floor; stream_buffer_sample_t sample1 = (stream_buffer_sample_t)sample[ipos++]; stream_buffer_sample_t sample2 = (stream_buffer_sample_t)sample[(ipos + 1) % (int)chan.source_len]; buffer.put(sampindex, (stream_buffer_sample_t)(sample_scale * ((1.0 - frac) * sample1 + frac * sample2))); // advance chan.pos += step; // handle looping/ending if (chan.pos >= endpos) { if (chan.loop) { chan.pos -= endpos; } else { chan.source = null; chan.source_num = -1; buffer.fill(0, sampindex); break; } } } } else { buffer.fill(0); } break; } } }
void stream_generate(sound_stream stream, ListPointer <stream_sample_t> [] inputs, ListPointer <stream_sample_t> [] outputs, int samples) { ListPointer <stream_sample_t> ptr = new ListPointer <stream_sample_t>(outputs[0]); //stream_sample_t *ptr = outputs[0]; int samplenum = samples; while (samplenum-- > 0) { ptr[0] = m_data; ptr++; } }
std.vector <uint8_t> m_save_blob; // state saving buffer // constructor protected ymfm_device_base(machine_config mconfig, string tag, device_t owner, uint32_t clock, device_type type, Func <ymfm_interface, ChipClass> chip_class_creator) : base(mconfig, tag, owner, clock, type) { m_class_interfaces.Add(new device_sound_interface_ymfm_device_base(mconfig, this)); //device_sound_interface(mconfig, *this); m_disound = GetClassInterface <device_sound_interface_ymfm_device_base>(); m_stream = null; m_chip = chip_class_creator(m_ymfm_interface); //eg, m_chip = new ym2151(this); OUTPUTS = (int)m_chip.OUTPUTS; //static constexpr int OUTPUTS = ChipClass.OUTPUTS; }
// handle device start protected override void device_start() { // let our parent do its startup base.device_start(); // allocate our stream m_stream = m_disound.stream_alloc(0, OUTPUTS, m_chip.sample_rate(clock())); // compute the size of the save buffer by doing an initial save ymfm.ymfm_saved_state state = new ymfm.ymfm_saved_state(m_save_blob, true); m_chip.save_restore(state); // now register the blob for save, on the assumption the size won't change save_item(NAME(new { m_save_blob })); }
// constructor public dac_device_base(machine_config mconfig, device_type type, string tag, device_t owner, uint32_t clock, u8 bits, dac_mapper_callback mapper, stream_buffer_sample_t gain) : base(mconfig, type, tag, owner, clock) { m_class_interfaces.Add(new device_sound_interface_dac_device_base(mconfig, this)); //device_sound_interface(mconfig, *this); m_disound = GetClassInterface <device_sound_interface_dac_device_base>(); m_stream = null; m_curval = 0; m_value_map = new std.vector <stream_buffer_sample_t>(1 << bits); m_bits = bits; m_mapper = mapper; m_gain = gain; m_range_min = (bits == 1) ? (stream_buffer_sample_t)0.0 : (stream_buffer_sample_t)(-1.0); m_range_max = (stream_buffer_sample_t)1.0; }
// device_sound_interface overrides //------------------------------------------------- // sound_stream_update - handle a stream update //------------------------------------------------- void device_sound_interface_sound_stream_update(sound_stream stream, std.vector <read_stream_view> inputs, std.vector <write_stream_view> outputs) //virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override; { var output = outputs[0]; /* if this voice is active */ if (m_signal != 0) { stream_buffer_sample_t sample_scale = (stream_buffer_sample_t)(1.0 / (double)(1 << 12)); int dac_mask = (m_dac_bits >= 12) ? 0 : (1 << (12 - m_dac_bits)) - 1; stream_buffer_sample_t val = (stream_buffer_sample_t)(m_signal & ~dac_mask) * sample_scale; output.fill(val); } else { output.fill(0); } }
// sound interface overrides //------------------------------------------------- // sound_stream_update - mix all inputs to one // output //------------------------------------------------- public override void sound_stream_update(sound_stream stream, std.vector <read_stream_view> inputs, std.vector <write_stream_view> outputs) //virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override; { // special case: single input, single output, same rate if (inputs.size() == 1 && outputs.size() == 1 && inputs[0].sample_rate() == outputs[0].sample_rate()) { outputs[0] = new write_stream_view(inputs[0]); //outputs[0] = inputs[0]; return; } // reset the clear flags std.fill(m_output_clear, false); //std::fill(std::begin(m_output_clear), std::end(m_output_clear), false); // loop over inputs for (int inputnum = 0; inputnum < m_auto_allocated_inputs; inputnum++) { // skip if the gain is 0 var input = inputs[inputnum]; if (input.gain() == 0) { continue; } // either store or accumulate int outputnum = m_outputmap[inputnum]; var output = outputs[outputnum]; if (!m_output_clear[outputnum]) { output.copy(input); } else { output.add(input); } m_output_clear[outputnum] = true; } // clear anything unused for (int outputnum = 0; outputnum < m_outputs; outputnum++) { if (!m_output_clear[outputnum]) { outputs[outputnum].fill(0); } } }
protected ay8910_device(machine_config mconfig, device_type type, string tag, device_t owner, u32 clock, psg_type_t psg_type, int streams, int ioports) : base(mconfig, type, tag, owner, clock) { m_class_interfaces.Add(new device_sound_interface_ay8910(mconfig, this)); // device_sound_interface(mconfig, *this); m_type = psg_type; m_streams = streams; m_ioports = ioports; m_ready = 0; m_channel = null; m_active = false; m_register_latch = 0; m_last_enable = 0; m_prescale_noise = 0; m_count_noise = 0; m_count_env = 0; m_env_step = 0; m_env_volume = 0; m_hold = 0; m_alternate = 0; m_attack = 0; m_holding = 0; m_rng = 0; m_env_step_mask = psg_type == psg_type_t.PSG_TYPE_AY ? (byte)0x0f : (byte)0x1f; m_step = psg_type == psg_type_t.PSG_TYPE_AY ? 2 : 1; m_zero_is_off = psg_type == psg_type_t.PSG_TYPE_AY ? 1 : 0; m_par = psg_type == psg_type_t.PSG_TYPE_AY ? ay8910_param : ym2149_param; m_par_env = psg_type == psg_type_t.PSG_TYPE_AY ? ay8910_param : ym2149_param_env; m_flags = AY8910_LEGACY_OUTPUT; m_port_a_read_cb = new devcb_read8(this); m_port_b_read_cb = new devcb_read8(this); m_port_a_write_cb = new devcb_write8(this); m_port_b_write_cb = new devcb_write8(this); memset(m_regs, (byte)0); memset(m_count, 0); memset(m_output, (byte)0); memset(m_vol_enabled, (byte)0); memset(m_vol_table, 0); memset(m_env_table, 0); m_res_load[0] = m_res_load[1] = m_res_load[2] = 1000; //Default values for resistor loads set_type(psg_type); }
// device startup //------------------------------------------------- // device_start - device startup //------------------------------------------------- protected override void device_start() { // precompute all gain-applied values for (s32 code = 0; code < (int)m_value_map.size(); code++) { m_value_map[code] = m_mapper((u32)code, m_bits) * m_gain; } // determine the number of inputs int inputs = (m_specified_inputs_mask == 0) ? 0 : 2; // create the stream m_stream = stream_alloc(inputs, 1, 48000 * 4); // save data save_item(NAME(new { m_curval })); }
//------------------------------------------------- // interface_post_start - verify that state was // properly set up //------------------------------------------------- public override void interface_post_start() { // iterate over all the sound devices foreach (device_sound_interface sound in new sound_interface_enumerator(device().machine().root_device())) { // scan each route on the device foreach (sound_route route in sound.routes()) { // if we are the target of this route, hook it up device_t target_device = route.m_base.subdevice(route.m_target); if (target_device == device()) { // iterate over all outputs, matching any that apply int inputnum = (int)route.m_input; int numoutputs = sound.outputs(); for (int outputnum = 0; outputnum < numoutputs; outputnum++) { if (route.m_output == outputnum || route.m_output == ALL_OUTPUTS) { // find the output stream to connect from int streamoutputnum; sound_stream outputstream = sound.output_to_stream_output(outputnum, out streamoutputnum); if (outputstream == null) { fatalerror("Sound device '{0}' specifies route for nonexistent output #{1}\n", sound.device().tag(), outputnum); } // find the input stream to connect to int streaminputnum; sound_stream inputstream = input_to_stream_input(inputnum++, out streaminputnum); if (inputstream == null) { fatalerror("Sound device '{0}' targeted output #{1} to nonexistant device '{2}' input {3}\n", sound.device().tag(), outputnum, device().tag(), inputnum - 1); } // set the input inputstream.set_input(streaminputnum, outputstream, streamoutputnum, route.m_gain); } } } } } }
// sound interface overrides //------------------------------------------------- // mixer_update - mix all inputs to one output //------------------------------------------------- public override void sound_stream_update(sound_stream stream, ListPointer <stream_sample_t> [] inputs, ListPointer <stream_sample_t> [] outputs, int samples) { // clear output buffers for (int output = 0; output < m_outputs; output++) { memset(outputs[output], 0, (UInt32)samples); //memset(outputs[output], 0, samples * sizeof(outputs[0][0])); } // loop over samples ListBytesPointer outmap = new ListBytesPointer(m_outputmap); //const u8 *outmap = &m_outputmap[0]; for (int pos = 0; pos < samples; pos++) { // for each input, add it to the appropriate output for (int inp = 0; inp < m_auto_allocated_inputs; inp++) { outputs[outmap[inp]][pos] += inputs[inp][pos]; } } }
// stream generation //------------------------------------------------- // sound_stream_update - stream updates //------------------------------------------------- protected virtual void device_sound_interface_sound_stream_update(sound_stream stream, std.vector <read_stream_view> inputs, std.vector <write_stream_view> outputs) //virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override; { var out_ = outputs[0]; // rails are constant if (inputs.size() == 0) { out_.fill(m_range_min + m_curval * (m_range_max - m_range_min)); return; } var hi = inputs[DAC_INPUT_RANGE_HI]; var lo = inputs[DAC_INPUT_RANGE_LO]; // constant lo, streaming hi if (BIT(m_specified_inputs_mask, DAC_INPUT_RANGE_LO) == 0) { for (int sampindex = 0; sampindex < out_.samples(); sampindex++) { out_.put(sampindex, m_range_min + m_curval * (hi.get(sampindex) - m_range_min)); } } // constant hi, streaming lo else if (BIT(m_specified_inputs_mask, DAC_INPUT_RANGE_HI) == 0) { for (int sampindex = 0; sampindex < out_.samples(); sampindex++) { out_.put(sampindex, lo.get(sampindex) + m_curval * (m_range_max - lo.get(sampindex))); } } // both streams provided else { for (int sampindex = 0; sampindex < out_.samples(); sampindex++) { out_.put(sampindex, lo.get(sampindex) + m_curval * (hi.get(sampindex) - lo.get(sampindex))); } } }
// device_sound_interface overrides //------------------------------------------------- // sound_stream_update - handle a stream update //------------------------------------------------- public override void sound_stream_update(sound_stream stream, ListPointer <stream_sample_t> [] inputs, ListPointer <stream_sample_t> [] outputs, int samples) { msm5205_device pokey = (msm5205_device)device(); ListPointer <stream_sample_t> buffer = outputs[0]; /* if this voice is active */ if (pokey.signal != 0) { short val = (short)(pokey.signal * 16); while (samples != 0) { buffer[0] = val; //*buffer++ = val; buffer++; samples--; } } else { memset(buffer, 0, (UInt32)samples); //memset(buffer, 0, samples * sizeof(*buffer)); } }
// device-level overrides //------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- protected override void device_start() { m_disound = GetClassInterface <device_sound_interface_ay8910>(); int master_clock = (int)clock(); if (m_ioports < 1 && !(m_port_a_read_cb.isnull() && m_port_a_write_cb.isnull())) { fatalerror("Device '{0}' is a {1} and has no port A!", tag(), name()); } if (m_ioports < 2 && !(m_port_b_read_cb.isnull() && m_port_b_write_cb.isnull())) { fatalerror("Device '{0}' is a {1} and has no port B!", tag(), name()); } m_port_a_read_cb.resolve(); m_port_b_read_cb.resolve(); m_port_a_write_cb.resolve(); m_port_b_write_cb.resolve(); if ((m_flags & AY8910_SINGLE_OUTPUT) != 0) { logerror("{0} device using single output!\n", name()); m_streams = 1; } m_vol3d_table = new int[8 * 32 * 32 * 32]; // make_unique_clear<int32_t[]>(8*32*32*32); build_mixer_table(); /* The envelope is pacing twice as fast for the YM2149 as for the AY-3-8910, */ /* This handled by the step parameter. Consequently we use a divider of 8 here. */ m_channel = machine().sound().stream_alloc(this, 0, m_streams, master_clock / 8); ay_set_clock(master_clock); ay8910_statesave(); }
// optional operation overrides //------------------------------------------------- // interface_pre_start - perform startup prior // to the device startup //------------------------------------------------- public override void interface_pre_start() { // call our parent base.interface_pre_start(); // no inputs? that's weird if (m_auto_allocated_inputs == 0) { device().logerror("Warning: mixer \"{0}\" has no inputs\n", device().tag()); return; } // generate the output map m_outputmap.resize((size_t)m_auto_allocated_inputs); // iterate through all routes that point to us and note their mixer output foreach (device_sound_interface sound in new sound_interface_enumerator(device().machine().root_device())) { foreach (sound_route route in sound.routes()) { // see if we are the target of this route device_t target_device = route.m_base.subdevice(route.m_target); if (target_device == device() && route.m_input < m_auto_allocated_inputs) { int count = (route.m_output == ALL_OUTPUTS) ? sound.outputs() : 1; for (int output = 0; output < count; output++) { m_outputmap[(int)(route.m_input + output)] = (u8)route.m_mixoutput; } } } } // keep a small buffer handy for tracking cleared buffers m_output_clear.resize(m_outputs); // allocate the mixer stream m_mixer_stream = stream_alloc(m_auto_allocated_inputs, m_outputs, (u32)device().machine().sample_rate(), sound_stream_flags.STREAM_DEFAULT_FLAGS); }
//void s1_w(int state); //void s2_w(int state); // device-level overrides protected override void device_start() { m_vck_cb.resolve_safe(); m_vck_legacy_cb.resolve(); /* compute the difference tables */ compute_tables(); /* stream system initialize */ m_stream = stream_alloc(0, 1, clock()); m_vck_timer = timer_alloc(TIMER_VCK); m_capture_timer = timer_alloc(TIMER_ADPCM_CAPTURE); /* register for save states */ save_item(NAME(new { m_data })); save_item(NAME(new { m_vck })); save_item(NAME(new { m_reset })); save_item(NAME(new { m_s1 })); save_item(NAME(new { m_s2 })); save_item(NAME(new { m_bitwidth })); save_item(NAME(new { m_signal })); save_item(NAME(new { m_step })); }
//DECLARE_WRITE_LINE_MEMBER(s1_w); //DECLARE_WRITE_LINE_MEMBER(s2_w); // device-level overrides protected override void device_start() { m_vck_cb.resolve_safe(); m_vck_legacy_cb.resolve(); /* compute the difference tables */ compute_tables(); /* stream system initialize */ m_stream = machine().sound().stream_alloc(this, 0, 1, (int)clock()); m_vck_timer = timer_alloc(TIMER_VCK); m_capture_timer = timer_alloc(TIMER_ADPCM_CAPTURE); /* register for save states */ save_item(m_data, "m_data"); save_item(m_vck, "m_vck"); save_item(m_reset, "m_reset"); save_item(m_s1, "m_s1"); save_item(m_s2, "m_s2"); save_item(m_bitwidth, "m_bitwidth"); save_item(m_signal, "m_signal"); save_item(m_step, "m_step"); }
MemoryContainer <int16_t> [] m_waveform = new MemoryContainer <int16_t> [MAX_VOLUME]; //std::unique_ptr<int16_t[]> m_waveform[MAX_VOLUME]; public namco_audio_device(machine_config mconfig, device_type type, string tag, device_t owner, u32 clock) : base(mconfig, type, tag, owner, clock) { m_class_interfaces.Add(new device_sound_interface_namco_audio(mconfig, this)); //device_sound_interface(mconfig, *this), m_disound = GetClassInterface <device_sound_interface_namco_audio>(); m_wave_ptr = new optional_region_ptr <uint8_t>(this, DEVICE_SELF); m_last_channel = null; m_wavedata = null; m_wave_size = 0; m_sound_enable = false; m_stream = null; m_namco_clock = 0; m_sample_rate = 0; m_f_fracbits = 0; m_voices = 0; m_stereo = false; for (int i = 0; i < m_channel_list.Length; i++) { m_channel_list[i] = new sound_channel(); } }
// optional operation overrides //------------------------------------------------- // interface_pre_start - perform startup prior // to the device startup //------------------------------------------------- public override void interface_pre_start() { // call our parent base.interface_pre_start(); // no inputs? that's weird if (m_auto_allocated_inputs == 0) { device().logerror("Warning: mixer \"{0}\" has no inputs\n", device().tag()); return; } // generate the output map m_outputmap.resize(m_auto_allocated_inputs); // iterate through all routes that point to us and note their mixer output foreach (device_sound_interface sound in new sound_interface_iterator(device().machine().root_device())) { foreach (sound_route route in sound.routes()) { // see if we are the target of this route device_t target_device = route.m_base.get().subdevice(route.m_target.c_str()); if ((target_device == device()) && (route.m_input < m_auto_allocated_inputs)) { int count = (route.m_output == ALL_OUTPUTS) ? sound.outputs() : 1; for (int output = 0; output < count; output++) { m_outputmap[(int)(route.m_input + output)] = (byte)route.m_mixoutput; } } } } // allocate the mixer stream m_mixer_stream = stream_alloc(m_auto_allocated_inputs, m_outputs, device().machine().sample_rate()); }
public sound_stream m_mixer_stream; // mixing stream // construction/destruction //------------------------------------------------- // device_mixer_interface - constructor //------------------------------------------------- public device_mixer_interface(machine_config mconfig, device_t device, int outputs = 1) : base(mconfig, device) { m_outputs = (u8)outputs; m_mixer_stream = null; }
public s16 m_gain; // gain to apply to the output // construction/destruction //------------------------------------------------- // stream_output - constructor //------------------------------------------------- public stream_output() { m_stream = null; m_dependents = 0; m_gain = 0x100; }
public override void sound_stream_update(sound_stream stream, std.vector <read_stream_view> inputs, std.vector <write_stream_view> outputs) { ((samples_device)device()).device_sound_interface_sound_stream_update(stream, inputs, outputs); } //virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override
// device_sound_interface overrides //------------------------------------------------- // sound_stream_update - handle a stream update //------------------------------------------------- public override void sound_stream_update(sound_stream stream, ListPointer <stream_sample_t> [] inputs, ListPointer <stream_sample_t> [] outputs, int samples) { ay8910_device ay8910 = (ay8910_device)device(); ListPointer <stream_sample_t> [] buf = new ListPointer <stream_sample_t> [ay8910_device.NUM_CHANNELS]; //stream_sample_t *buf[NUM_CHANNELS]; int chan; buf[0] = new ListPointer <stream_sample_t>(outputs[0]); buf[1] = null; buf[2] = null; if (ay8910.m_streams == ay8910_device.NUM_CHANNELS) { buf[1] = outputs[1]; buf[2] = outputs[2]; } /* hack to prevent us from hanging when starting filtered outputs */ if (ay8910.m_ready == 0) { for (chan = 0; chan < ay8910_device.NUM_CHANNELS; chan++) { if (buf[chan] != null) { memset(buf[chan], 0, (UInt32)samples); //memset(buf[chan], 0, samples * sizeof_(*buf[chan])); } } } /* The 8910 has three outputs, each output is the mix of one of the three */ /* tone generators and of the (single) noise generator. The two are mixed */ /* BEFORE going into the DAC. The formula to mix each channel is: */ /* (ToneOn | ToneDisable) & (NoiseOn | NoiseDisable). */ /* Note that this means that if both tone and noise are disabled, the output */ /* is 1, not 0, and can be modulated changing the volume. */ /* buffering loop */ while (samples != 0) { for (chan = 0; chan < ay8910_device.NUM_CHANNELS; chan++) { ay8910.m_count[chan]++; if (ay8910.m_count[chan] >= ay8910.TONE_PERIOD(chan)) { ay8910.m_output[chan] ^= 1; ay8910.m_count[chan] = 0; } } ay8910.m_count_noise++; if (ay8910.m_count_noise >= ay8910.NOISE_PERIOD()) { /* toggle the prescaler output. Noise is no different to * channels. */ ay8910.m_count_noise = 0; ay8910.m_prescale_noise ^= 1; if (ay8910.m_prescale_noise != 0) { /* The Random Number Generator of the 8910 is a 17-bit shift */ /* register. The input to the shift register is bit0 XOR bit3 */ /* (bit0 is the output). This was verified on AY-3-8910 and YM2149 chips. */ ay8910.m_rng ^= (((ay8910.m_rng & 1) ^ ((ay8910.m_rng >> 3) & 1)) << 17); ay8910.m_rng >>= 1; } } for (chan = 0; chan < ay8910_device.NUM_CHANNELS; chan++) { ay8910.m_vol_enabled[chan] = (byte)((ay8910.m_output[chan] | ay8910.TONE_ENABLEQ(chan)) & (ay8910.NOISE_OUTPUT() | ay8910.NOISE_ENABLEQ(chan))); } /* update envelope */ if (ay8910.m_holding == 0) { ay8910.m_count_env++; if (ay8910.m_count_env >= ay8910.ENVELOPE_PERIOD() * ay8910.m_step) { ay8910.m_count_env = 0; ay8910.m_env_step--; /* check envelope current position */ if (ay8910.m_env_step < 0) { if (ay8910.m_hold != 0) { if (ay8910.m_alternate != 0) { ay8910.m_attack ^= ay8910.m_env_step_mask; } ay8910.m_holding = 1; ay8910.m_env_step = 0; } else { /* if CountEnv has looped an odd number of times (usually 1), */ /* invert the output. */ if (ay8910.m_alternate != 0 && (ay8910.m_env_step & (ay8910.m_env_step_mask + 1)) != 0) { ay8910.m_attack ^= ay8910.m_env_step_mask; } ay8910.m_env_step &= (sbyte)ay8910.m_env_step_mask; } } } } ay8910.m_env_volume = (UInt32)(ay8910.m_env_step ^ ay8910.m_attack); if (ay8910.m_streams == 3) { for (chan = 0; chan < ay8910_device.NUM_CHANNELS; chan++) { if (ay8910.TONE_ENVELOPE(chan) != 0) { if (ay8910.type() == ay8914_device.AY8914) // AY8914 Has a two bit tone_envelope field { buf[chan][0] = ay8910.m_env_table[chan, ay8910.m_vol_enabled[chan] != 0 ? ay8910.m_env_volume >> (3 - ay8910.TONE_ENVELOPE(chan)) : 0]; // *(buf[chan]++) buf[chan]++; } else { buf[chan][0] = ay8910.m_env_table[chan, ay8910.m_vol_enabled[chan] != 0 ? ay8910.m_env_volume : 0]; // *(buf[chan]++) buf[chan]++; } } else { buf[chan][0] = ay8910.m_vol_table[chan, ay8910.m_vol_enabled[chan] != 0 ? ay8910.TONE_VOLUME(chan) : 0]; // *(buf[chan]++) buf[chan]++; } } } else { buf[0][0] = ay8910.mix_3D(); // *(buf[0]++) buf[0]++; } samples--; } }
public static void sound_init() { iRecord = 0; leftmix = new int[0x3c0]; rightmix = new int[0x3c0]; finalmixb = new byte[0xf00]; sound_muted = 0; buf2.Play(0, BufferPlayFlags.Looping); last_update_second = 0; //WavWrite.CreateSoundFile(@"\VS2008\compare1\compare1\bin\Debug\2.wav"); Atime update_frequency = new Atime(0, Attotime.ATTOSECONDS_PER_SECOND / 50); switch (Machine.sBoard) { case "CPS-1": latched_value = new ushort[2]; utempdata = new ushort[2]; sound_update = sound_updateC; sound_update_timer = Timer.timer_alloc_common(sound_update, "sound_update", false); YM2151.ym2151_init(3579545); OKI6295.okim6295_start(); ym2151stream = new sound_stream(55930, 0, 2, YM2151.ym2151_update_one); okistream = new sound_stream(1000000 / 132, 0, 1, OKI6295.okim6295_update); mixerstream = new sound_stream(48000, 3, 0, null); break; case "CPS-1(QSound)": case "CPS2": sound_update = sound_updateQ; sound_update_timer = Timer.timer_alloc_common(sound_update, "sound_update", false); QSound.qsound_start(); qsoundstream = new sound_stream(4000000 / 166, 0, 2, QSound.qsound_update); mixerstream = new sound_stream(48000, 2, 0, null); break; case "Neo Geo": latched_value = new ushort[2]; utempdata = new ushort[2]; sound_update = sound_updateN; sound_update_timer = Timer.timer_alloc_common(sound_update, "sound_update", false); YM2610.ym2610_start(); ay8910stream = new sound_stream(250000, 0, 1, AY8910.ay8910_update); ym2610stream = new sound_stream(111111, 0, 2, FM.ym2610_update_one); mixerstream = new sound_stream(48000, 3, 0, null); break; case "Namco System 1": sound_update = sound_updateNa; sound_update_timer = Timer.timer_alloc_common(sound_update, "sound_update", false); YM2151.ym2151_init(3579580); Namco.namco_start(); DAC.dac_start(); ym2151stream = new sound_stream(55930, 0, 2, YM2151.ym2151_update_one); namcostream = new sound_stream(192000, 0, 2, Namco.namco_update_stereo); dacstream = new sound_stream(192000, 0, 1, DAC.DAC_update); mixerstream = new sound_stream(48000, 5, 0, null); break; case "IGS011": sound_update = sound_updateIGS011; sound_update_timer = Timer.timer_alloc_common(sound_update, "sound_update", false); OKI6295.okim6295_start(); YM3812.ym3812_start(3579545); okistream = new sound_stream(1047600 / 132, 0, 1, OKI6295.okim6295_update); ym3812stream = new sound_stream(49715, 0, 1, FMOpl.ym3812_update_one); mixerstream = new sound_stream(48000, 2, 0, null); break; case "PGM": latched_value = new ushort[3]; utempdata = new ushort[3]; sound_update = sound_updatePGM; sound_update_timer = Timer.timer_alloc_common(sound_update, "sound_update", false); ICS2115.ics2115_start(); ics2115stream = new sound_stream(33075, 0, 2, ICS2115.ics2115_update); mixerstream = new sound_stream(48000, 2, 0, null); break; case "M72": latched_value = new ushort[1]; utempdata = new ushort[1]; sound_update = sound_updateM72; sound_update_timer = Timer.timer_alloc_common(sound_update, "sound_update", false); YM2151.ym2151_init(3579545); DAC.dac_start(); ym2151stream = new sound_stream(55930, 0, 2, YM2151.ym2151_update_one); dacstream = new sound_stream(192000, 0, 1, DAC.DAC_update); mixerstream = new sound_stream(48000, 3, 0, null); break; case "M92": latched_value = new ushort[1]; utempdata = new ushort[1]; sound_update = sound_updateM92; sound_update_timer = Timer.timer_alloc_common(sound_update, "sound_update", false); YM2151.ym2151_init(3579545); Iremga20.iremga20_start(); ym2151stream = new sound_stream(55930, 0, 2, YM2151.ym2151_update_one); iremga20stream = new sound_stream(894886, 0, 2, Iremga20.iremga20_update); mixerstream = new sound_stream(48000, 4, 0, null); break; } Timer.timer_adjust_periodic(sound_update_timer, update_frequency, update_frequency); }
void device_sound_interface_sound_stream_update(sound_stream stream, std.vector <read_stream_view> inputs, std.vector <write_stream_view> outputs) //virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override; { throw new emu_unimplemented(); }
// device_sound_interface overrides //------------------------------------------------- // sound_stream_update - handle a stream update //------------------------------------------------- void device_sound_interface_sound_stream_update(sound_stream stream, std.vector <read_stream_view> inputs, std.vector <write_stream_view> outputs) //virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override; { if (m_stereo) { /* zap the contents of the buffers */ outputs[0].fill(0); outputs[1].fill(0); /* if no sound, we're done */ if (!m_sound_enable) { return; } /* loop over each voice and add its contribution */ for (int voiceIdx = 0; m_channel_list[voiceIdx] != m_last_channel; voiceIdx++) //for (sound_channel *voice = m_channel_list; voice < m_last_channel; voice++) { sound_channel voice = m_channel_list[voiceIdx]; var lmix = outputs[0]; var rmix = outputs[1]; int lv = voice.volume[0]; int rv = voice.volume[1]; if (voice.noise_sw != 0) { int f = (int)(voice.frequency & 0xff); /* only update if we have non-zero volume */ if (lv != 0 || rv != 0) { int hold_time = 1 << (m_f_fracbits - 16); int hold = voice.noise_hold; uint32_t delta = (uint32_t)(f << 4); uint32_t c = voice.noise_counter; int16_t l_noise_data = OUTPUT_LEVEL(0x07 * (lv >> 1)); int16_t r_noise_data = OUTPUT_LEVEL(0x07 * (rv >> 1)); int i; /* add our contribution */ for (i = 0; i < lmix.samples(); i++) { int cnt; if (voice.noise_state != 0) { lmix.add_int(i, l_noise_data, 32768); rmix.add_int(i, r_noise_data, 32768); } else { lmix.add_int(i, -l_noise_data, 32768); rmix.add_int(i, -r_noise_data, 32768); } if (hold != 0) { hold--; continue; } hold = hold_time; c += delta; cnt = (int)(c >> 12); c &= (1 << 12) - 1; for ( ; cnt > 0; cnt--) { if (((voice.noise_seed + 1) & 2) != 0) { voice.noise_state ^= 1; } if ((voice.noise_seed & 1) != 0) { voice.noise_seed ^= 0x28000; } voice.noise_seed >>= 1; } } /* update the counter and hold time for this voice */ voice.noise_counter = c; voice.noise_hold = hold; } } else { /* save the counter for this voice */ uint32_t c = voice.counter; /* only update if we have non-zero left volume */ if (lv != 0) { Pointer <int16_t> lw = new Pointer <int16_t>(m_waveform[lv], voice.waveform_select * 32); //const int16_t *lw = &m_waveform[lv][voice->waveform_select * 32]; /* generate sound into the buffer */ c = namco_update_one(lmix, lw, voice.counter, voice.frequency); } /* only update if we have non-zero right volume */ if (rv != 0) { Pointer <int16_t> rw = new Pointer <int16_t>(m_waveform[rv], voice.waveform_select * 32); //const int16_t *rw = &m_waveform[rv][voice->waveform_select * 32]; /* generate sound into the buffer */ c = namco_update_one(rmix, rw, voice.counter, voice.frequency); } /* update the counter for this voice */ voice.counter = c; } } } else { int voiceIdx; // sound_channel *voice; var buffer = outputs[0]; /* zap the contents of the buffer */ buffer.fill(0); /* if no sound, we're done */ if (!m_sound_enable) { return; } /* loop over each voice and add its contribution */ for (voiceIdx = 0; m_channel_list[voiceIdx] != m_last_channel; voiceIdx++) //for (voice = m_channel_list; voice < m_last_channel; voice++) { sound_channel voice = m_channel_list[voiceIdx]; int v = voice.volume[0]; if (voice.noise_sw != 0) { int f = (int)(voice.frequency & 0xff); /* only update if we have non-zero volume */ if (v != 0) { int hold_time = 1 << (m_f_fracbits - 16); int hold = voice.noise_hold; uint32_t delta = (uint32_t)(f << 4); uint32_t c = voice.noise_counter; int16_t noise_data = OUTPUT_LEVEL(0x07 * (v >> 1)); int i; /* add our contribution */ for (i = 0; i < buffer.samples(); i++) { int cnt; if (voice.noise_state != 0) { buffer.add_int(i, noise_data, 32768); } else { buffer.add_int(i, -noise_data, 32768); } if (hold != 0) { hold--; continue; } hold = hold_time; c += delta; cnt = (int)(c >> 12); c &= (1 << 12) - 1; for ( ; cnt > 0; cnt--) { if (((voice.noise_seed + 1) & 2) != 0) { voice.noise_state ^= 1; } if ((voice.noise_seed & 1) != 0) { voice.noise_seed ^= 0x28000; } voice.noise_seed >>= 1; } } } } else { /* only update if we have non-zero volume */ if (v != 0) { Pointer <int16_t> w = new Pointer <int16_t>(m_waveform[v], voice.waveform_select * 32); //const int16_t *w = &m_waveform[v][voice->waveform_select * 32]; /* generate sound into buffer and update the counter for this voice */ voice.counter = namco_update_one(buffer, w, voice.counter, voice.frequency); } } } } }
// device-level overrides //------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- protected override void device_start() { /* extract globals from the interface */ m_last_channel = m_channel_list[m_voices]; /* build the waveform table */ build_decoded_waveform(m_wave_ptr.op); /* get stream channels */ if (m_stereo) { m_stream = m_disound.stream_alloc(0, 2, 192000); } else { m_stream = m_disound.stream_alloc(0, 1, 192000); } /* start with sound enabled, many games don't have a sound enable register */ m_sound_enable = true; //throw new emu_unimplemented(); #if false if (m_wave_ptr == null) { save_pointer(m_wavedata, "m_wavedata", 0x400); } save_item(m_voices, "m_voices"); save_item(m_sound_enable, "m_sound_enable"); for (int v = 0; v < MAX_VOLUME; v++) { save_pointer(NAME(m_waveform[v]), 32 * 8 * (1 + m_wave_size), v); } #endif /* reset all the voices */ for (int voiceIdx = 0; m_channel_list[voiceIdx] != m_last_channel; voiceIdx++) //for (sound_channel *voice = m_channel_list; voice < m_last_channel; voice++) { sound_channel voice = m_channel_list[voiceIdx]; voice.frequency = 0; voice.volume[0] = voice.volume[1] = 0; voice.waveform_select = 0; voice.counter = 0; voice.noise_sw = 0; voice.noise_state = 0; voice.noise_seed = 1; voice.noise_counter = 0; voice.noise_hold = 0; } //throw new emu_unimplemented(); #if false /* register with the save state system */ save_pointer(STRUCT_MEMBER(m_channel_list, frequency), m_voices); save_pointer(STRUCT_MEMBER(m_channel_list, counter), m_voices); save_pointer(STRUCT_MEMBER(m_channel_list, volume), m_voices); save_pointer(STRUCT_MEMBER(m_channel_list, noise_sw), m_voices); save_pointer(STRUCT_MEMBER(m_channel_list, noise_state), m_voices); save_pointer(STRUCT_MEMBER(m_channel_list, noise_seed), m_voices); save_pointer(STRUCT_MEMBER(m_channel_list, noise_hold), m_voices); save_pointer(STRUCT_MEMBER(m_channel_list, noise_counter), m_voices); save_pointer(STRUCT_MEMBER(m_channel_list, waveform_select), m_voices); #endif }
//device_sound_interface &reset_routes() { m_route_list.clear(); return *this; } // sound stream update overrides //------------------------------------------------- // sound_stream_update - default implementation // that should be overridden //------------------------------------------------- public virtual void sound_stream_update(sound_stream stream, std.vector <read_stream_view> inputs, std.vector <write_stream_view> outputs) //void device_sound_interface::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) { throw new emu_fatalerror("sound_stream_update called but not overridden by owning class"); }