diff options
Diffstat (limited to 'trunk/src/emu/sound.h')
-rw-r--r-- | trunk/src/emu/sound.h | 276 |
1 files changed, 276 insertions, 0 deletions
diff --git a/trunk/src/emu/sound.h b/trunk/src/emu/sound.h new file mode 100644 index 00000000000..03f6b8ec98c --- /dev/null +++ b/trunk/src/emu/sound.h @@ -0,0 +1,276 @@ +/*************************************************************************** + + sound.h + + Core sound interface functions and definitions. + +**************************************************************************** + + Copyright Aaron Giles + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name 'MAME' nor the names of its contributors may be + used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +***************************************************************************/ + +#pragma once + +#ifndef __EMU_H__ +#error Dont include this file directly; include emu.h instead. +#endif + +#ifndef __SOUND_H__ +#define __SOUND_H__ + + +//************************************************************************** +// MACROS +//************************************************************************** + +#define STREAM_UPDATE(name) void name(device_t *device, sound_stream *stream, void *param, stream_sample_t **inputs, stream_sample_t **outputs, int samples) + + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// forward references +class speaker_device; +typedef struct _wav_file wav_file; + + +// structure describing an indexed speaker +struct speaker_input +{ + speaker_device * speaker; // owning device + sound_stream * stream; // stream within the device + int inputnum; // input on the stream +}; + + +// ======================> sound_stream + +class sound_stream +{ + friend class simple_list<sound_stream>; + friend class sound_manager; + + typedef void (*stream_update_func)(device_t *device, sound_stream *stream, void *param, stream_sample_t **inputs, stream_sample_t **outputs, int samples); + + // stream output class + class stream_output + { + public: + // construction/destruction + stream_output(); + + // internal state + sound_stream * m_stream; // owning stream + stream_sample_t * m_buffer; // output buffer + int m_dependents; // number of dependents + INT16 m_gain; // gain to apply to the output + }; + + // stream input class + class stream_input + { + public: + // construction/destruction + stream_input(); + + // internal state + stream_output * m_source; // pointer to the sound_output for this source + stream_sample_t * m_resample; // buffer for resampling to the stream's sample rate + UINT32 m_bufsize; // size of output buffer, in samples + UINT32 m_bufalloc; // allocated size of output buffer, in samples + attoseconds_t m_latency_attoseconds; // latency between this stream and the input stream + INT16 m_gain; // gain to apply to this input + INT16 m_initial_gain; // initial gain supplied at creation + }; + + // constants + static const int OUTPUT_BUFFER_UPDATES = 5; + static const UINT32 FRAC_BITS = 22; + static const UINT32 FRAC_ONE = 1 << FRAC_BITS; + static const UINT32 FRAC_MASK = FRAC_ONE - 1; + + // construction/destruction + sound_stream(device_t &device, int inputs, int outputs, int sample_rate, void *param = NULL, stream_update_func callback = &sound_stream::device_stream_update_stub); + +public: + // getters + sound_stream *next() const { return m_next; } + device_t &device() const { return m_device; } + int sample_rate() const { return (m_new_sample_rate != 0) ? m_new_sample_rate : m_sample_rate; } + attotime sample_time() const; + attotime sample_period() const { return attotime(0, m_attoseconds_per_sample); } + int input_count() const { return m_inputs; } + int output_count() const { return m_outputs; } + float input_gain(int inputnum) const; + float initial_input_gain(int inputnum) const; + const char *input_name(int inputnum, astring &string) const; + float output_gain(int outputnum) const; + + // operations + void set_input(int inputnum, sound_stream *input_stream, int outputnum = 0, float gain = 1.0f); + void update(); + const stream_sample_t *output_since_last_update(int outputnum, int &numsamples); + + // timing + void set_sample_rate(int sample_rate); + void set_input_gain(int inputnum, float gain); + void set_output_gain(int outputnum, float gain); + +private: + // helpers called by our friends only + void update_with_accounting(bool second_tick); + void apply_sample_rate_changes(); + + // internal helpers + static STREAM_UPDATE( device_stream_update_stub ); + void recompute_sample_rate_data(); + void allocate_resample_buffers(); + void allocate_output_buffers(); + void postload(); + void generate_samples(int samples); + stream_sample_t *generate_resampled_data(stream_input &input, UINT32 numsamples); + + // linking information + device_t & m_device; // owning device + sound_stream * m_next; // next stream in the chain + + // general information + UINT32 m_sample_rate; // sample rate of this stream + UINT32 m_new_sample_rate; // newly-set sample rate for the stream + + // timing information + attoseconds_t m_attoseconds_per_sample;// number of attoseconds per sample + INT32 m_max_samples_per_update;// maximum samples per update + + // input information + int m_inputs; // number of inputs + stream_input * m_input; // list of streams we directly depend upon + stream_sample_t ** m_input_array; // array of inputs for passing to the callback + + // resample buffer information + UINT32 m_resample_bufalloc; // allocated size of each resample buffer + + // output information + int m_outputs; // number of outputs + stream_output * m_output; // list of streams which directly depend upon us + stream_sample_t ** m_output_array; // array of outputs for passing to the callback + + // output buffer information + UINT32 m_output_bufalloc; // allocated size of each output buffer + INT32 m_output_sampindex; // current position within each output buffer + INT32 m_output_update_sampindex;// position at time of last global update + INT32 m_output_base_sampindex;// sample at base of buffer, relative to the current emulated second + + // callback information + stream_update_func m_callback; // callback function + void * m_param; // callback function parameter +}; + + +// ======================> sound_manager + +class sound_manager +{ + friend class sound_stream; + + // reasons for muting + static const UINT8 MUTE_REASON_PAUSE = 0x01; + static const UINT8 MUTE_REASON_UI = 0x02; + static const UINT8 MUTE_REASON_DEBUGGER = 0x04; + static const UINT8 MUTE_REASON_SYSTEM = 0x08; + + // stream updates + static const attotime STREAMS_UPDATE_ATTOTIME; + +public: + static const int STREAMS_UPDATE_FREQUENCY = 50; + + // construction/destruction + sound_manager(running_machine &machine); + ~sound_manager(); + + // getters + running_machine &machine() const { return m_machine; } + int attenuation() const { return m_attenuation; } + sound_stream *first_stream() const { return m_stream_list.first(); } + attotime last_update() const { return m_last_update; } + attoseconds_t update_attoseconds() const { return m_update_attoseconds; } + + // stream creation + sound_stream *stream_alloc(device_t &device, int inputs, int outputs, int sample_rate, void *param = NULL, sound_stream::stream_update_func callback = NULL); + + // global controls + void set_attenuation(int attenuation); + void ui_mute(bool turn_off = true) { mute(turn_off, MUTE_REASON_UI); } + void debugger_mute(bool turn_off = true) { mute(turn_off, MUTE_REASON_DEBUGGER); } + void system_mute(bool turn_off = true) { mute(turn_off, MUTE_REASON_SYSTEM); } + void system_enable(bool turn_on = true) { mute(!turn_on, MUTE_REASON_SYSTEM); } + + // user gain controls + bool indexed_speaker_input(int index, speaker_input &info) const; + +private: + // internal helpers + void mute(bool mute, UINT8 reason); + void reset(); + void pause(); + void resume(); + void config_load(int config_type, xml_data_node *parentnode); + void config_save(int config_type, xml_data_node *parentnode); + + static TIMER_CALLBACK( update_static ) { reinterpret_cast<sound_manager *>(ptr)->update(); } + void update(); + + // internal state + running_machine & m_machine; // reference to our machine + emu_timer * m_update_timer; // timer to drive periodic updates + + UINT32 m_finalmix_leftover; + INT16 * m_finalmix; + INT32 * m_leftmix; + INT32 * m_rightmix; + + UINT8 m_muted; + int m_attenuation; + int m_nosound_mode; + + wav_file * m_wavfile; + + // streams data + simple_list<sound_stream> m_stream_list; // list of streams + attoseconds_t m_update_attoseconds; // attoseconds between global updates + attotime m_last_update; // last update time +}; + + +#endif /* __SOUND_H__ */ |