summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/sound.h
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/sound.h')
-rw-r--r--trunk/src/emu/sound.h276
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__ */