summaryrefslogblamecommitdiffstatshomepage
path: root/src/emu/sound.h
blob: 37c3492588adca87f49e9a6dac0c524f822c595d (plain) (tree)
1
2
3
4
5
6
7
8

                                





                                                                            



                                                                            



                                                              

                        
 
 
                                                                            


                                                                            
                                                                                                      
                                                                                                                        

                                                                            

                                                                            
 
                                                                                                                                 
 


                                                                            
 
 

                                        
 


                                                                           


  
                                       
 
                  
 
                                   
 
                                                                                                                                                                  
 

                              
         


                                           
                                                                                                   
 
                                 
                                                                            
                                                                          
                                                                                   
                                                                                          

          





                                           
                                                                                                 
 
                                 
                                                                                                          
                                                                                                              
                                                                                                               

                                                                                                        
          
 
                    



                                                                     
 
       
                                   
                                                                                                                  
 




                                                                                                        
                                                                                        

                                                            
                                                   



                                                          


                                               
                                                                                                       




                                                                                        
                                                     

                                                        
 



                                                      
 
                           




                                           

                                                                                      

                              

                                                                                     

                              

                                                                                                 
                                                                                                                  

                             
                                                                                             
                                                                                       
                                                                                                 

                            

                                                                                                      

                                      
                                                                                                   

                             

                                                                                                        

                                    



                                                                                                                              

                               
                                                                                  
  
 
 
                                        
 
                   
 
                                  
 
                             



                                                        
 

                                                      
 
       
                                                           
 


                                                
 
                  
                                                              
                                                         
                                                                                                   

                                                                                 
 
                          
                                                                                                                                                           
 
                          

                               




                                                                                          
 
                             
                                                                     
 

                           
                                        


                      

                                                                                       
 
                                                        
 
                         

                                                                                      
 



                                                
 
                                    

                                           
 
                                      
 
                       
                                                                                       

                                                                                         
  
 
 
                          
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************

    sound.h

    Core sound interface functions and definitions.

***************************************************************************/

#pragma once

#ifndef __EMU_H__
#error Dont include this file directly; include emu.h instead.
#endif

#ifndef MAME_EMU_SOUND_H
#define MAME_EMU_SOUND_H


//**************************************************************************
//  CONSTANTS
//**************************************************************************

constexpr int STREAM_SYNC   = -1;       // special rate value indicating a one-sample-at-a-time stream
										// with actual rate defined by its input

//**************************************************************************
//  MACROS
//**************************************************************************

typedef delegate<void (sound_stream &, stream_sample_t **inputs, stream_sample_t **outputs, int samples)> stream_update_delegate;

//**************************************************************************
//  TYPE DEFINITIONS
//**************************************************************************


// structure describing an indexed mixer
struct mixer_input
{
	device_mixer_interface *mixer;          // owning device interface
	sound_stream *          stream;         // stream within the device
	int                     inputnum;       // input on the stream
};


// ======================> sound_stream

class 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();
		stream_output &operator=(const stream_output &rhs) { assert(false); return *this; }

		// internal state
		sound_stream *      m_stream;               // owning stream
		std::vector<stream_sample_t> m_buffer;    // output buffer
		int                 m_dependents;           // number of dependents
		s16                 m_gain;                 // gain to apply to the output
	};

	// stream input class
	class stream_input
	{
	public:
		// construction/destruction
		stream_input();
		stream_input &operator=(const stream_input &rhs) { assert(false); return *this; }

		// internal state
		stream_output *     m_source;               // pointer to the sound_output for this source
		std::vector<stream_sample_t> m_resample;  // buffer for resampling to the stream's sample rate
		attoseconds_t       m_latency_attoseconds;  // latency between this stream and the input stream
		s16               m_gain;                 // gain to apply to this input
		s16               m_user_gain;            // user-controlled gain to apply to this input
	};

	// constants
	static constexpr int OUTPUT_BUFFER_UPDATES  = 5;
	static constexpr u32 FRAC_BITS              = 22;
	static constexpr u32 FRAC_ONE               = 1 << FRAC_BITS;
	static constexpr u32 FRAC_MASK              = FRAC_ONE - 1;

public:
	// construction/destruction
	sound_stream(device_t &device, int inputs, int outputs, int sample_rate, stream_update_delegate callback);

	// 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_input.size(); }
	int output_count() const { return m_output.size(); }
	std::string input_name(int inputnum) const;
	device_t *input_source_device(int inputnum) const;
	int input_source_outputnum(int inputnum) const;
	float user_gain(int inputnum) const;
	float input_gain(int inputnum) 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_user_gain(int inputnum, float gain);
	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
	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, u32 numsamples);
	void sync_update(void *, s32);

	// linking information
	device_t &          m_device;                     // owning device
	sound_stream *      m_next;                       // next stream in the chain

	// general information
	u32                 m_sample_rate;                // sample rate of this stream
	u32                 m_new_sample_rate;            // newly-set sample rate for the stream
	bool                m_synchronous;                // synchronous stream that runs at the rate of its input

	// timing information
	attoseconds_t       m_attoseconds_per_sample;     // number of attoseconds per sample
	s32                 m_max_samples_per_update;     // maximum samples per update
	emu_timer *         m_sync_timer;                 // update timer for synchronous streams

	// input information
	std::vector<stream_input> m_input;              // list of streams we directly depend upon
	std::vector<stream_sample_t *> m_input_array;   // array of inputs for passing to the callback

	// resample buffer information
	u32                 m_resample_bufalloc;          // allocated size of each resample buffer

	// output information
	std::vector<stream_output> m_output;            // list of streams which directly depend upon us
	std::vector<stream_sample_t *> m_output_array;  // array of outputs for passing to the callback

	// output buffer information
	u32                 m_output_bufalloc;            // allocated size of each output buffer
	s32                 m_output_sampindex;           // current position within each output buffer
	s32                 m_output_update_sampindex;    // position at time of last global update
	s32                 m_output_base_sampindex;      // sample at base of buffer, relative to the current emulated second

	// callback information
	stream_update_delegate  m_callback;                   // callback function
};


// ======================> sound_manager

class sound_manager
{
	friend class sound_stream;

	// reasons for muting
	static constexpr u8 MUTE_REASON_PAUSE = 0x01;
	static constexpr u8 MUTE_REASON_UI = 0x02;
	static constexpr u8 MUTE_REASON_DEBUGGER = 0x04;
	static constexpr u8 MUTE_REASON_SYSTEM = 0x08;

	// stream updates
	static const attotime STREAMS_UPDATE_ATTOTIME;

public:
	static constexpr 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; }
	const std::vector<std::unique_ptr<sound_stream>> &streams() const { return m_stream_list; }
	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, stream_update_delegate callback = stream_update_delegate());

	// global controls
	void start_recording();
	void stop_recording();
	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_mixer_input(int index, mixer_input &info) const;

private:
	// internal helpers
	void mute(bool mute, u8 reason);
	void reset();
	void pause();
	void resume();
	void config_load(config_type cfg_type, util::xml::data_node const *parentnode);
	void config_save(config_type cfg_type, util::xml::data_node *parentnode);

	void update(void *ptr = nullptr, s32 param = 0);

	// internal state
	running_machine &   m_machine;              // reference to our machine
	emu_timer *         m_update_timer;         // timer to drive periodic updates

	u32                 m_finalmix_leftover;
	std::vector<s16>    m_finalmix;
	std::vector<s32>    m_leftmix;
	std::vector<s32>    m_rightmix;

	u8                  m_muted;
	int                 m_attenuation;
	int                 m_nosound_mode;

	wav_file *          m_wavfile;

	// streams data
	std::vector<std::unique_ptr<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 // MAME_EMU_SOUND_H