int mixer_sh_start() { /* reset all channels to their defaults */ for (int i = 0; i < mixer_channel.Length; i++) { mixer_channel[i] = new mixer_channel_data(); mixer_channel[i].mixing_level = 0xff; mixer_channel[i].default_mixing_level = 0xff; mixer_channel[i].config_mixing_level = config_mixing_level[i]; mixer_channel[i].config_default_mixing_level = config_default_mixing_level[i]; } /* determine if we're playing in stereo or not */ first_free_channel = 0; is_stereo = ((Machine.drv.sound_attributes & SOUND_SUPPORTS_STEREO) != 0); /* clear the accumulators */ accum_base = 0; for (int i = 0; i < ACCUMULATOR_SAMPLES; i++) { left_accum[i] = 0; right_accum[i] = 0; } samples_this_frame = (uint)osd_start_audio_stream(is_stereo); mixer_sound_enabled = true; return 0; }
static void mix_sample_16(mixer_channel_data channel, int samples_to_generate) { uint step_size, input_frac, output_pos; _ShortPtr source; int source_end; int mixing_volume; /* compute the overall mixing volume */ if (mixer_sound_enabled) mixing_volume = ((channel.volume * channel.mixing_level * 256) << channel.gain) / (100 * 100); else mixing_volume = 0; /* get the initial state */ step_size = channel.step_size; source = new _ShortPtr(channel.data_current); source_end = channel.data_end; input_frac = channel.input_frac; output_pos = (accum_base + channel.samples_available) & ACCUMULATOR_MASK; /* an outer loop to handle looping samples */ while (samples_to_generate > 0) { /* if we're mono or left panning, just mix to the left channel */ if (!is_stereo || channel.pan == MIXER_PAN_LEFT) { while (source.offset < source_end && samples_to_generate > 0) { left_accum[output_pos] += (source.read16(0) * mixing_volume) >> 8; input_frac += step_size; source.offset += (int)(input_frac >> FRACTION_BITS) * 2; input_frac &= FRACTION_MASK; output_pos = (output_pos + 1) & ACCUMULATOR_MASK; samples_to_generate--; } } /* if we're right panning, just mix to the right channel */ else if (channel.pan == MIXER_PAN_RIGHT) { while (source.offset < source_end && samples_to_generate > 0) { right_accum[output_pos] += (source.read16(0) * mixing_volume) >> 8; input_frac += step_size; source.offset += (int)(input_frac >> FRACTION_BITS) * 2; input_frac &= FRACTION_MASK; output_pos = (output_pos + 1) & ACCUMULATOR_MASK; samples_to_generate--; } } /* if we're stereo center, mix to both channels */ else { while (source.offset < source_end && samples_to_generate > 0) { int mixing_value = (source.read16(0) * mixing_volume) >> 8; left_accum[output_pos] += mixing_value; right_accum[output_pos] += mixing_value; input_frac += step_size; source.offset += (int)(input_frac >> FRACTION_BITS) * 2; input_frac &= FRACTION_MASK; output_pos = (output_pos + 1) & ACCUMULATOR_MASK; samples_to_generate--; } } /* handle the end case */ if (source.offset >= source_end) { /* if we're done, stop playing */ if (!channel.is_looping) { channel.is_playing = false; break; } /* if we're looping, wrap to the beginning */ else source.offset-=source_end;// source.offset -= (INT16*)source_end - (INT16*)channel.data_start; } } /* update the final positions */ channel.input_frac = input_frac; channel.data_current = source.offset; }
static void mixer_update_channel(mixer_channel_data channel, int total_sample_count) { int samples_to_generate = (int)(total_sample_count - channel.samples_available); /* don't do anything for streaming channels */ if (channel.is_stream) return; /* if we're all caught up, just return */ if (samples_to_generate <= 0) return; /* if we're playing, mix in the data */ if (channel.is_playing) { if (channel.is_16bit) mix_sample_16(channel, samples_to_generate); else mix_sample_8(channel, samples_to_generate); } /* just eat the rest */ channel.samples_available += (uint)samples_to_generate; }