From 8f54db2902f08ac6341b9c79e25fd81078048785 Mon Sep 17 00:00:00 2001 From: Ilari Liusvaara Date: Sat, 7 Jun 2014 17:33:03 +0300 Subject: [PATCH] Instancefy audioapi core (but not driver) stuff --- include/core/audioapi.hpp | 186 +++++++++++++++++------------- include/core/instance.hpp | 2 + include/core/inthread.hpp | 3 +- src/core/audioapi.cpp | 221 +++++++++++++++++------------------- src/core/dummysound.cpp | 3 +- src/core/instance.cpp | 4 +- src/core/inthread.cpp | 47 ++++---- src/core/window.cpp | 4 +- src/emulation/bsnes-legacy/core.cpp | 2 +- src/emulation/gambatte/core.cpp | 2 +- src/emulation/sky/sky.cpp | 3 +- src/emulation/test/test.cpp | 3 +- src/interface/c-interface.cpp | 3 +- src/platform/libao/sound.cpp | 7 +- src/platform/portaudio/sound.cpp | 21 ++-- src/platform/wxwidgets/vumeter.cpp | 37 +++--- 16 files changed, 290 insertions(+), 258 deletions(-) diff --git a/include/core/audioapi.hpp b/include/core/audioapi.hpp index 3f8b4245..2e8413a9 100644 --- a/include/core/audioapi.hpp +++ b/include/core/audioapi.hpp @@ -1,50 +1,55 @@ #ifndef _audioapi__hpp__included__ #define _audioapi__hpp__included__ +#include "library/threads.hpp" + #include #include #include #include #include +class audioapi_instance +{ +public: /** * Audio API music buffer. */ -struct audioapi_buffer -{ + struct buffer + { /** * The samples. * * Note: May be NULL if no samples are available.. */ - int16_t* samples; + int16_t* samples; /** * Playback pointer in samples structure. */ - size_t pointer; + size_t pointer; /** * Total number of samples in this buffer. */ - size_t total; + size_t total; /** * True if buffer is stereo, false if mono. */ - bool stereo; + bool stereo; /** * The rate in samples per second the buffer is supposed to be played at. */ - double rate; -}; + double rate; + }; /** * Audio API VU calculator. */ -struct audioapi_vumeter -{ + struct vumeter + { /** * Initialize. */ - audioapi_vumeter(); + vumeter(); /** * Submit samples. * @@ -54,38 +59,34 @@ struct audioapi_vumeter * Parameter rate: Sound sampling rate. * Parameter scale: Value to scale the samples by. */ - void operator()(float* samples, size_t count, bool stereo, double rate, double scale); + void operator()(float* samples, size_t count, bool stereo, double rate, double scale); /** * Get VU value in dB. */ - operator float() const throw() { return vu; } -private: - double accumulator; - size_t samples; - float vu; - void update_vu(); -}; - -//VU values. -extern audioapi_vumeter audioapi_vu_mleft; -extern audioapi_vumeter audioapi_vu_mright; -extern audioapi_vumeter audioapi_vu_vout; -extern audioapi_vumeter audioapi_vu_vin; - -//Resampler. -class audioapi_resampler -{ -public: - audioapi_resampler(); - //After call, either insize or outsize is zero. - void resample(float*& in, size_t& insize, float*& out, size_t& outsize, double ratio, bool stereo); -private: - double position; - double vAl, vBl, vCl, vDl, vAr, vBr, vCr, vDr; -}; - + operator float() const throw() { return vu; } + private: + double accumulator; + size_t samples; + float vu; + void update_vu(); + }; + //Resampler. + class resampler + { + public: + resampler(); + //After call, either insize or outsize is zero. + void resample(float*& in, size_t& insize, float*& out, size_t& outsize, double ratio, bool stereo); + private: + double position; + double vAl, vBl, vCl, vDl, vAr, vBr, vCr, vDr; + }; +/** + * Ctor. + */ + audioapi_instance(); + ~audioapi_instance(); //The following are intended to be used by the emulator core. - /** * Submit a buffer for playback on music channel. * @@ -94,114 +95,97 @@ private: * Parameter stereo: If true, the signal is stereo. If false, mono. * Parameter rate: Rate of buffer in samples per second. */ -void audioapi_submit_buffer(int16_t* samples, size_t count, bool stereo, double rate); - + void submit_buffer(int16_t* samples, size_t count, bool stereo, double rate); /** * Get the voice channel playback/record rate. * * Returns: The rate in samples per second (first for recording, then for playback). */ -std::pair audioapi_voice_rate(); - + std::pair voice_rate(); /** * Get the voice channel nominal playback/record rate. * * Returns: The rate in samples per second. */ -unsigned audioapi_orig_voice_rate(); - + unsigned orig_voice_rate(); /** * Get the voice channel playback status register. * * Returns: The number of samples free for playback. */ -unsigned audioapi_voice_p_status(); - + unsigned voice_p_status(); /** * Get the voice channel playback status register2. * * Returns: The number of samples in playback buffer. */ -unsigned audioapi_voice_p_status2(); - + unsigned voice_p_status2(); /** * Get the voice channel record status register. * * Returns: The number of samples in capture buffer. */ -unsigned audioapi_voice_r_status(); - + unsigned voice_r_status(); /** * Play sound on voice channel. * * Parameter samples: The samples to play. * Parameter count: Number of samples to play. Must be less than number of samples free for playback. */ -void audioapi_play_voice(float* samples, size_t count); - + void play_voice(float* samples, size_t count); /** * Capture sound on voice channel. * * Parameter samples: The buffer to store captured samples to. * Parameter count: Number of samples to capture. Must be less than number of samples used for capture. */ -void audioapi_record_voice(float* samples, size_t count); - + void record_voice(float* samples, size_t count); /** * Init the audio. Call on emulator startup. */ -void audioapi_init(); - + void init(); /** * Quit the audio. Call on emulator shutdown. */ -void audioapi_quit(); - + void quit(); /** * Set music volume. * * Parameter volume: The volume (0-1). */ -void audioapi_music_volume(float volume); - + void music_volume(float volume); /** * Get music volume. * * Returns: The music volume. */ -float audioapi_music_volume(); - + float music_volume(); /** * Set voice playback volume. * * Parameter volume: The volume (0-1). */ -void audioapi_voicep_volume(float volume); - + void voicep_volume(float volume); /** * Get voice playback volume. * * Returns: The voice playback volume. */ -float audioapi_voicep_volume(); - + float voicep_volume(); /** * Set voice capture volume. * * Parameter volume: The volume (0-1). */ -void audioapi_voicer_volume(float volume); - + void voicer_volume(float volume); /** * Get voice capture volume. * * Returns: The voice capture volume. */ -float audioapi_voicer_volume(); - + float voicer_volume(); //The following are intended to be used by the driver from the callback - /** * Get mixed music + voice buffer to play (at voice rate). * @@ -209,8 +193,7 @@ float audioapi_voicer_volume(); * Parameter count: Number of samples to generate. * Parameter stereo: If true, return stereo buffer, else mono. */ -void audioapi_get_mixed(int16_t* samples, size_t count, bool stereo); - + void get_mixed(int16_t* samples, size_t count, bool stereo); /** * Get music channel buffer to play. * @@ -219,8 +202,7 @@ void audioapi_get_mixed(int16_t* samples, size_t count, bool stereo); * * Note: This should only be called from the sound driver. */ -struct audioapi_buffer audioapi_get_music(size_t played); - + struct buffer get_music(size_t played); /** * Get voice channel buffer to play. * @@ -229,8 +211,7 @@ struct audioapi_buffer audioapi_get_music(size_t played); * * Note: This should only be called from the sound driver. */ -void audioapi_get_voice(float* samples, size_t count); - + void get_voice(float* samples, size_t count); /** * Put recorded voice channel buffer. * @@ -240,8 +221,7 @@ void audioapi_get_voice(float* samples, size_t count); * Note: Even if audio driver does not support capture, one should send in silence. * Note: This should only be called from the sound driver. */ -void audioapi_put_voice(float* samples, size_t count); - + void put_voice(float* samples, size_t count); /** * Set the voice channel playback/record rate. * @@ -251,7 +231,51 @@ void audioapi_put_voice(float* samples, size_t count); * Note: This should only be called from the sound driver. * Note: Setting rate to 0 enables dummy callbacks. */ -void audioapi_voice_rate(unsigned rate_r, unsigned rate_p); + void voice_rate(unsigned rate_r, unsigned rate_p); + //Vu values. + vumeter vu_mleft; + vumeter vu_mright; + vumeter vu_vout; + vumeter vu_vin; +private: + struct dummy_cb_proc + { + dummy_cb_proc(audioapi_instance& _parent); + int operator()(); + audioapi_instance& parent; + }; + dummy_cb_proc dummyproc; + threads::thread* dummythread; + //3 music buffers is not enough due to huge blocksizes used by SDL. + const static unsigned MUSIC_BUFFERS = 8; + const static unsigned voicep_bufsize = 65536; + const static unsigned voicer_bufsize = 65536; + const static unsigned music_bufsize = 8192; + float voicep_buffer[voicep_bufsize]; + float voicer_buffer[voicer_bufsize]; + int16_t music_buffer[MUSIC_BUFFERS * music_bufsize]; + volatile bool music_stereo[MUSIC_BUFFERS]; + volatile double music_rate[MUSIC_BUFFERS]; + volatile size_t music_size[MUSIC_BUFFERS]; + unsigned music_ptr; + unsigned last_complete_music_seen; + volatile unsigned last_complete_music; + volatile unsigned voicep_get; + volatile unsigned voicep_put; + volatile unsigned voicer_get; + volatile unsigned voicer_put; + volatile unsigned voice_rate_play; + volatile unsigned orig_voice_rate_play; + volatile unsigned voice_rate_rec; + volatile bool dummy_cb_active_record; + volatile bool dummy_cb_active_play; + volatile bool dummy_cb_quit; + volatile float _music_volume; + volatile float _voicep_volume; + volatile float _voicer_volume; +}; + + //All the following need to be implemented by the sound driver itself struct _audioapi_driver diff --git a/include/core/instance.hpp b/include/core/instance.hpp index 52d42a4c..93b9d2aa 100644 --- a/include/core/instance.hpp +++ b/include/core/instance.hpp @@ -25,6 +25,7 @@ class button_mapping; class emulator_dispatch; class slotinfo_cache; class lua_state; +class audioapi_instance; namespace command { class group; } namespace lua { class state; } namespace settingvar { class group; } @@ -117,6 +118,7 @@ struct emulator_instance input_queue* iqueue; master_dumper* mdumper; slotinfo_cache* slotcache; + audioapi_instance* audio; threads::id emu_thread; time_t random_seed_value; dtor_list D; diff --git a/include/core/inthread.hpp b/include/core/inthread.hpp index 2eae5d63..af34bd8f 100644 --- a/include/core/inthread.hpp +++ b/include/core/inthread.hpp @@ -28,7 +28,7 @@ public: uint64_t length; }; - voice_commentary(settingvar::group& _settings, emulator_dispatch& _dispatch); + voice_commentary(settingvar::group& _settings, emulator_dispatch& _dispatch, audioapi_instance& _audio); ~voice_commentary(); void init(); void kill(); @@ -52,6 +52,7 @@ private: void* internal; settingvar::group& settings; emulator_dispatch& edispatch; + audioapi_instance& audio; }; #endif diff --git a/src/core/audioapi.cpp b/src/core/audioapi.cpp index 4a04c7a9..4446a809 100644 --- a/src/core/audioapi.cpp +++ b/src/core/audioapi.cpp @@ -12,65 +12,37 @@ #include #include -//3 music buffers is not enough due to huge blocksizes used by SDL. #define MUSIC_BUFFERS 8 #define MAX_VOICE_ADJUST 200 -namespace +audioapi_instance::dummy_cb_proc::dummy_cb_proc(audioapi_instance& _parent) + : parent(_parent) { - bool paniced = false; - const unsigned voicep_bufsize = 65536; - const unsigned voicer_bufsize = 65536; - const unsigned music_bufsize = 8192; - float voicep_buffer[voicep_bufsize]; - float voicer_buffer[voicer_bufsize]; - int16_t music_buffer[MUSIC_BUFFERS * music_bufsize]; - volatile bool music_stereo[MUSIC_BUFFERS]; - volatile double music_rate[MUSIC_BUFFERS]; - volatile size_t music_size[MUSIC_BUFFERS]; - unsigned music_ptr; - unsigned last_complete_music_seen = MUSIC_BUFFERS + 1; - volatile unsigned last_complete_music = MUSIC_BUFFERS; - volatile unsigned voicep_get = 0; - volatile unsigned voicep_put = 0; - volatile unsigned voicer_get = 0; - volatile unsigned voicer_put = 0; - volatile unsigned voice_rate_play = 40000; - volatile unsigned orig_voice_rate_play = 40000; - volatile unsigned voice_rate_rec = 40000; - volatile bool dummy_cb_active_record = false; - volatile bool dummy_cb_active_play = false; - volatile bool dummy_cb_quit = false; - volatile float music_volume = 1; - volatile float voicep_volume = 32767.0; - volatile float voicer_volume = 1.0/32768; - - struct dummy_cb_proc - { - int operator()() - { - int16_t buf[16384]; - uint64_t last_ts = framerate_regulator::get_utime(); - while(!dummy_cb_quit) { - uint64_t cur_ts = framerate_regulator::get_utime(); - uint64_t dt = cur_ts - last_ts; - last_ts = cur_ts; - unsigned samples = dt / 25; - if(samples > 16384) - samples = 16384; //Don't get crazy. - if(dummy_cb_active_play) - audioapi_get_mixed(buf, samples, false); - if(dummy_cb_active_record) - audioapi_put_voice(NULL, samples); - usleep(10000); - } - return 0; - } - }; +} - dummy_cb_proc* dummy_cb_proc_obj; - threads::thread* dummy_cb_thread; +int audioapi_instance::dummy_cb_proc::operator()() +{ + int16_t buf[16384]; + uint64_t last_ts = framerate_regulator::get_utime(); + while(!parent.dummy_cb_quit) { + uint64_t cur_ts = framerate_regulator::get_utime(); + uint64_t dt = cur_ts - last_ts; + last_ts = cur_ts; + unsigned samples = dt / 25; + if(samples > 16384) + samples = 16384; //Don't get crazy. + if(parent.dummy_cb_active_play) + parent.get_mixed(buf, samples, false); + if(parent.dummy_cb_active_record) + parent.put_voice(NULL, samples); + usleep(10000); + } + return 0; +} +namespace +{ + bool paniced = false; // | -1 1 -1 1 | 1 0 0 0 | // | 0 0 0 1 | 0 1 0 0 | @@ -100,14 +72,15 @@ namespace } } -audioapi_resampler::audioapi_resampler() +audioapi_instance::resampler::resampler() { position = 0; vAl = vBl = vCl = vDl = 0; vAr = vBr = vCr = vDr = 0; } -void audioapi_resampler::resample(float*& in, size_t& insize, float*& out, size_t& outsize, double ratio, bool stereo) +void audioapi_instance::resampler::resample(float*& in, size_t& insize, float*& out, size_t& outsize, double ratio, + bool stereo) { double iratio = 1 / ratio; while(outsize) { @@ -136,18 +109,43 @@ exit: ; } +audioapi_instance::audioapi_instance() + : dummyproc(*this) +{ + music_ptr = 0; + last_complete_music_seen = MUSIC_BUFFERS + 1; + last_complete_music = MUSIC_BUFFERS; + voicep_get = 0; + voicep_put = 0; + voicer_get = 0; + voicer_put = 0; + voice_rate_play = 40000; + orig_voice_rate_play = 40000; + voice_rate_rec = 40000; + dummy_cb_active_record = false; + dummy_cb_active_play = false; + dummy_cb_quit = false; + _music_volume = 1; + _voicep_volume = 32767.0; + _voicer_volume = 1.0/32768; +} + +audioapi_instance::~audioapi_instance() +{ + quit(); +} -std::pair audioapi_voice_rate() +std::pair audioapi_instance::voice_rate() { return std::make_pair(voice_rate_rec, voice_rate_play); } -unsigned audioapi_orig_voice_rate() +unsigned audioapi_instance::orig_voice_rate() { return orig_voice_rate_play; } -void audioapi_voice_rate(unsigned rate_rec, unsigned rate_play) +void audioapi_instance::voice_rate(unsigned rate_rec, unsigned rate_play) { if(rate_rec) voice_rate_rec = rate_rec; @@ -161,7 +159,7 @@ void audioapi_voice_rate(unsigned rate_rec, unsigned rate_play) dummy_cb_active_play = !rate_play; } -unsigned audioapi_voice_p_status() +unsigned audioapi_instance::voice_p_status() { unsigned p = voicep_put; unsigned g = voicep_get; @@ -171,7 +169,7 @@ unsigned audioapi_voice_p_status() return voicep_bufsize - (p - g) - 1; } -unsigned audioapi_voice_p_status2() +unsigned audioapi_instance::voice_p_status2() { unsigned p = voicep_put; unsigned g = voicep_get; @@ -181,7 +179,7 @@ unsigned audioapi_voice_p_status2() return (p - g); } -unsigned audioapi_voice_r_status() +unsigned audioapi_instance::voice_r_status() { unsigned p = voicer_put; unsigned g = voicer_get; @@ -191,7 +189,7 @@ unsigned audioapi_voice_r_status() return (p - g); } -void audioapi_play_voice(float* samples, size_t count) +void audioapi_instance::play_voice(float* samples, size_t count) { unsigned ptr = voicep_put; for(size_t i = 0; i < count; i++) { @@ -202,7 +200,7 @@ void audioapi_play_voice(float* samples, size_t count) voicep_put = ptr; } -void audioapi_record_voice(float* samples, size_t count) +void audioapi_instance::record_voice(float* samples, size_t count) { unsigned ptr = voicer_get; for(size_t i = 0; i < count; i++) { @@ -213,7 +211,7 @@ void audioapi_record_voice(float* samples, size_t count) voicer_get = ptr; } -void audioapi_submit_buffer(int16_t* samples, size_t count, bool stereo, double rate) +void audioapi_instance::submit_buffer(int16_t* samples, size_t count, bool stereo, double rate) { if(stereo) for(unsigned i = 0; i < count; i++) @@ -233,14 +231,14 @@ void audioapi_submit_buffer(int16_t* samples, size_t count, bool stereo, double last_complete_music = bidx; } -struct audioapi_buffer audioapi_get_music(size_t played) +struct audioapi_instance::buffer audioapi_instance::get_music(size_t played) { static bool last_adjust = false; //Adjusting consequtively is too hard. unsigned midx = last_complete_music_seen; unsigned midx2 = last_complete_music; if(midx2 >= MUSIC_BUFFERS) { //Special case: No buffer. - struct audioapi_buffer out; + struct buffer out; out.samples = NULL; out.pointer = 0; //The rest are arbitrary. @@ -281,7 +279,7 @@ struct audioapi_buffer audioapi_get_music(size_t played) } } //Fill the structure. - struct audioapi_buffer out; + struct buffer out; if(music_ptr < music_size[midx]) { out.samples = music_buffer + midx * music_bufsize; out.pointer = music_ptr; @@ -301,14 +299,14 @@ struct audioapi_buffer audioapi_get_music(size_t played) return out; } -void audioapi_get_voice(float* samples, size_t count) +void audioapi_instance::get_voice(float* samples, size_t count) { unsigned g = voicep_get; unsigned p = voicep_put; if(samples) { for(size_t i = 0; i < count; i++) { if(g != p) - samples[i] = voicep_volume * voicep_buffer[g++]; + samples[i] = _voicep_volume * voicep_buffer[g++]; else samples[i] = 0.0; if(g == voicep_bufsize) @@ -325,19 +323,19 @@ void audioapi_get_voice(float* samples, size_t count) voicep_get = g; } -void audioapi_put_voice(float* samples, size_t count) +void audioapi_instance::put_voice(float* samples, size_t count) { unsigned ptr = voicer_put; - audioapi_vu_vin(samples, count, false, voice_rate_rec, voicer_volume); + vu_vin(samples, count, false, voice_rate_rec, _voicer_volume); for(size_t i = 0; i < count; i++) { - voicer_buffer[ptr++] = samples ? voicer_volume * samples[i] : 0.0; + voicer_buffer[ptr++] = samples ? _voicer_volume * samples[i] : 0.0; if(ptr == voicer_bufsize) ptr = 0; } voicer_put = ptr; } -void audioapi_init() +void audioapi_instance::init() { voicep_get = 0; voicep_put = 0; @@ -348,55 +346,56 @@ void audioapi_init() dummy_cb_active_play = true; dummy_cb_active_record = true; dummy_cb_quit = false; - dummy_cb_proc_obj = new dummy_cb_proc; - dummy_cb_thread = new threads::thread(*dummy_cb_proc_obj); + dummythread = new threads::thread(dummyproc); } -void audioapi_quit() +void audioapi_instance::quit() { dummy_cb_quit = true; - dummy_cb_thread->join(); - delete dummy_cb_proc_obj; + if(dummythread) { + dummythread->join(); + dummythread = NULL; + } } -void audioapi_music_volume(float volume) +void audioapi_instance::music_volume(float volume) { - music_volume = volume; + _music_volume = volume; } -float audioapi_music_volume() +float audioapi_instance::music_volume() { - return music_volume; + return _music_volume; } -void audioapi_voicep_volume(float volume) +void audioapi_instance::voicep_volume(float volume) { - voicep_volume = volume * 32767; + _voicep_volume = volume * 32767; } -float audioapi_voicep_volume() +float audioapi_instance::voicep_volume() { - return voicep_volume / 32767; + return _voicep_volume / 32767; } -void audioapi_voicer_volume(float volume) +void audioapi_instance::voicer_volume(float volume) { - voicer_volume = volume / 32768; + _voicer_volume = volume / 32768; } -float audioapi_voicer_volume() +float audioapi_instance::voicer_volume() { - return voicer_volume * 32768; + return _voicer_volume * 32768; } -void audioapi_get_mixed(int16_t* samples, size_t count, bool stereo) +void audioapi_instance::get_mixed(int16_t* samples, size_t count, bool stereo) { - static audioapi_resampler music_resampler; + static resampler music_resampler; const size_t intbuf_size = 256; float intbuf[intbuf_size]; float intbuf2[intbuf_size]; while(count > 0) { - audioapi_buffer b = audioapi_get_music(0); + buffer b = get_music(0); float* in = intbuf; float* out = intbuf2; size_t outdata_used; @@ -407,19 +406,19 @@ void audioapi_get_mixed(int16_t* samples, size_t count, bool stereo) outdata_used = outdata; if(b.samples) for(size_t i = 0; i < 2 * indata; i++) - intbuf[i] = music_volume * b.samples[i + 2 * b.pointer]; + intbuf[i] = _music_volume * b.samples[i + 2 * b.pointer]; else for(size_t i = 0; i < 2 * indata; i++) intbuf[i] = 0; music_resampler.resample(in, indata, out, outdata, (double)voice_rate_play / b.rate, true); indata_used -= indata; outdata_used -= outdata; - audioapi_get_music(indata_used); - audioapi_get_voice(intbuf, outdata_used); + get_music(indata_used); + get_voice(intbuf, outdata_used); - audioapi_vu_mleft(intbuf2, outdata_used, true, voice_rate_play, 1 / 32768.0); - audioapi_vu_mright(intbuf2 + 1, outdata_used, true, voice_rate_play, 1 / 32768.0); - audioapi_vu_vout(intbuf, outdata_used, false, voice_rate_play, 1 / 32768.0); + vu_mleft(intbuf2, outdata_used, true, voice_rate_play, 1 / 32768.0); + vu_mright(intbuf2 + 1, outdata_used, true, voice_rate_play, 1 / 32768.0); + vu_vout(intbuf, outdata_used, false, voice_rate_play, 1 / 32768.0); for(size_t i = 0; i < outdata_used * (stereo ? 2 : 1); i++) intbuf2[i] = max(min(intbuf2[i] + intbuf[i / 2], 32766.0f), -32767.0f); @@ -436,19 +435,19 @@ void audioapi_get_mixed(int16_t* samples, size_t count, bool stereo) outdata_used = outdata; if(b.samples) for(size_t i = 0; i < indata; i++) - intbuf[i] = music_volume * b.samples[i + b.pointer]; + intbuf[i] = _music_volume * b.samples[i + b.pointer]; else for(size_t i = 0; i < indata; i++) intbuf[i] = 0; music_resampler.resample(in, indata, out, outdata, (double)voice_rate_play / b.rate, false); indata_used -= indata; outdata_used -= outdata; - audioapi_get_music(indata_used); - audioapi_get_voice(intbuf, outdata_used); + get_music(indata_used); + get_voice(intbuf, outdata_used); - audioapi_vu_mleft(intbuf2, outdata_used, false, voice_rate_play, 1 / 32768.0); - audioapi_vu_mright(intbuf2, outdata_used, false, voice_rate_play, 1 / 32768.0); - audioapi_vu_vout(intbuf, outdata_used, false, voice_rate_play, 1 / 32768.0); + vu_mleft(intbuf2, outdata_used, false, voice_rate_play, 1 / 32768.0); + vu_mright(intbuf2, outdata_used, false, voice_rate_play, 1 / 32768.0); + vu_vout(intbuf, outdata_used, false, voice_rate_play, 1 / 32768.0); for(size_t i = 0; i < outdata_used; i++) intbuf2[i] = max(min(intbuf2[i] + intbuf[i], 32766.0f), -32767.0f); @@ -466,14 +465,14 @@ void audioapi_get_mixed(int16_t* samples, size_t count, bool stereo) } } -audioapi_vumeter::audioapi_vumeter() +audioapi_instance::vumeter::vumeter() { accumulator = 0; samples = 0; vu = -999.0; } -void audioapi_vumeter::operator()(float* asamples, size_t count, bool stereo, double rate, double scale) +void audioapi_instance::vumeter::operator()(float* asamples, size_t count, bool stereo, double rate, double scale) { size_t limit = rate / 25; //If we already at or exceed limit, cut immediately. @@ -505,7 +504,7 @@ void audioapi_vumeter::operator()(float* asamples, size_t count, bool stereo, do } } -void audioapi_vumeter::update_vu() +void audioapi_instance::vumeter::update_vu() { if(paniced) return; @@ -529,9 +528,3 @@ void audioapi_panicing() throw() { paniced = true; } - -//VU values. -audioapi_vumeter audioapi_vu_mleft; -audioapi_vumeter audioapi_vu_mright; -audioapi_vumeter audioapi_vu_vout; -audioapi_vumeter audioapi_vu_vin; diff --git a/src/core/dummysound.cpp b/src/core/dummysound.cpp index e8258e7b..7d75dee6 100644 --- a/src/core/dummysound.cpp +++ b/src/core/dummysound.cpp @@ -1,4 +1,5 @@ #include "core/audioapi.hpp" +#include "core/instance.hpp" #include #include @@ -7,7 +8,7 @@ namespace { void dummy_init() throw() { - audioapi_voice_rate(0, 0); + lsnes_instance.audio->voice_rate(0, 0); } void dummy_quit() throw() diff --git a/src/core/instance.cpp b/src/core/instance.cpp index d9db912c..ba602665 100644 --- a/src/core/instance.cpp +++ b/src/core/instance.cpp @@ -1,4 +1,5 @@ #include "core/advdumper.hpp" +#include "core/audioapi.hpp" #include "core/command.hpp" #include "core/controllerframe.hpp" #include "core/controller.hpp" @@ -80,7 +81,8 @@ emulator_instance::emulator_instance() D.init(mwatch, *memory, *project, *fbuf); D.init(settings); D.init(setcache, *settings); - D.init(commentary, *settings, *dispatch); + D.init(audio); + D.init(commentary, *settings, *dispatch, *audio); D.init(subtitles, *mlogic, *fbuf, *dispatch); D.init(mbranch, *mlogic, *dispatch); D.init(controls, *project, *mlogic, *buttons, *dispatch); diff --git a/src/core/inthread.cpp b/src/core/inthread.cpp index 98a44ffa..1eb2aaf4 100644 --- a/src/core/inthread.cpp +++ b/src/core/inthread.cpp @@ -74,8 +74,8 @@ namespace struct voicesub_state { - voicesub_state(settingvar::group& _settings, emulator_dispatch& _dispatch) - : settings(_settings), edispatch(_dispatch) + voicesub_state(settingvar::group& _settings, emulator_dispatch& _dispatch, audioapi_instance& _audio) + : settings(_settings), edispatch(_dispatch), audio(_audio) { current_time = 0; time_jump = false; @@ -114,7 +114,7 @@ namespace void start_management_stream(opus_stream& s); void advance_time(uint64_t newtime); void jump_time(uint64_t newtime); - void do_resample(audioapi_resampler& r, float* srcbuf, size_t& srcuse, float* dstbuf, + void do_resample(audioapi_instance::resampler& r, float* srcbuf, size_t& srcuse, float* dstbuf, size_t& dstuse, size_t dstmax, double ratio); void drain_input(); void read_input(float* buf, size_t& use, size_t maxuse); @@ -127,6 +127,7 @@ namespace void handle_tangent_negative_edge(opus_stream*& active_stream, bitrate_tracker& brtrack); settingvar::group& settings; emulator_dispatch& edispatch; + audioapi_instance& audio; }; voicesub_state* get_state(void* ptr) @@ -1397,8 +1398,8 @@ out: } //Resample. - void voicesub_state::do_resample(audioapi_resampler& r, float* srcbuf, size_t& srcuse, float* dstbuf, - size_t& dstuse, size_t dstmax, double ratio) + void voicesub_state::do_resample(audioapi_instance::resampler& r, float* srcbuf, size_t& srcuse, + float* dstbuf, size_t& dstuse, size_t dstmax, double ratio) { if(srcuse == 0 || dstuse >= dstmax) return; @@ -1417,20 +1418,20 @@ out: //Drain the input buffer. void voicesub_state::drain_input() { - while(audioapi_voice_r_status() > 0) { + while(audio.voice_r_status() > 0) { float buf[256]; - unsigned size = min(audioapi_voice_r_status(), 256u); - audioapi_record_voice(buf, size); + unsigned size = min(audio.voice_r_status(), 256u); + audio.record_voice(buf, size); } } //Read the input buffer. void voicesub_state::read_input(float* buf, size_t& use, size_t maxuse) { - size_t rleft = audioapi_voice_r_status(); + size_t rleft = audio.voice_r_status(); unsigned toread = min(rleft, max(maxuse, use) - use); if(toread > 0) { - audioapi_record_voice(buf + use, toread); + audio.record_voice(buf + use, toread); use += toread; } } @@ -1578,8 +1579,8 @@ out: class inthread_th : public workthread::worker { public: - inthread_th(voicesub_state* _internal) - : internal(*_internal) + inthread_th(voicesub_state* _internal, audioapi_instance& _audio) + : internal(*_internal), audio(_audio) { quit = false; quit_ack = false; @@ -1628,8 +1629,8 @@ out: opus::encoder oenc(opus::samplerate::r48k, false, opus::application::voice); oenc.ctl(opus::bitrate(SET_opus_bitrate(internal.settings))); - audioapi_resampler rin; - audioapi_resampler rout; + audioapi_instance::resampler rin; + audioapi_instance::resampler rout; const unsigned buf_max = 6144; //These buffers better be large. size_t buf_in_use = 0; size_t buf_inr_use = 0; @@ -1663,8 +1664,8 @@ out: break; //Read input, up to 25ms. - unsigned rate_in = audioapi_voice_rate().first; - unsigned rate_out = audioapi_voice_rate().second; + unsigned rate_in = audio.voice_rate().first; + unsigned rate_out = audio.voice_rate().second; size_t dbuf_max = min(buf_max, rate_in / REC_THRESHOLD_DIV); internal.read_input(buf_in, buf_in_use, dbuf_max); @@ -1689,8 +1690,8 @@ out: 1.0 * rate_out / OPUS_SAMPLERATE); //Output stuff. - if(buf_out_use > 0 && audioapi_voice_p_status2() < rate_out / PLAY_THRESHOLD_DIV) { - audioapi_play_voice(buf_out, buf_out_use); + if(buf_out_use > 0 && audio.voice_p_status2() < rate_out / PLAY_THRESHOLD_DIV) { + audio.play_voice(buf_out, buf_out_use); buf_out_use = 0; } @@ -1711,6 +1712,7 @@ out: threads::lock lmut; threads::cv lcond; voicesub_state& internal; + audioapi_instance& audio; }; //The tangent function. @@ -1727,8 +1729,9 @@ out: keyboard::invbind_info IBIND_itangent(lsnes_invbinds, "+tangent", "Movie‣Voice tangent"); } -voice_commentary::voice_commentary(settingvar::group& _settings, emulator_dispatch& _dispatch) - : settings(_settings), edispatch(_dispatch) +voice_commentary::voice_commentary(settingvar::group& _settings, emulator_dispatch& _dispatch, + audioapi_instance& _audio) + : settings(_settings), edispatch(_dispatch), audio(_audio) { internal = NULL; } @@ -1757,10 +1760,10 @@ void voice_commentary::frame_number(uint64_t newframe, double rate) void voice_commentary::init() { - internal = new voicesub_state(settings, edispatch); + internal = new voicesub_state(settings, edispatch, audio); auto _internal = get_state(internal); try { - _internal->int_task = new inthread_th(_internal); + _internal->int_task = new inthread_th(_internal, audio); } catch(...) { delete _internal; throw; diff --git a/src/core/window.cpp b/src/core/window.cpp index 0038d8e8..6993ddef 100644 --- a/src/core/window.cpp +++ b/src/core/window.cpp @@ -173,7 +173,7 @@ void platform::init() system_log << "-----------------------------------------------------------------------" << std::endl; do_init_font(); graphics_driver_init(); - audioapi_init(); + lsnes_instance.audio->init(); audioapi_driver_init(); joystick_driver_init(); } @@ -182,7 +182,7 @@ void platform::quit() { joystick_driver_quit(); audioapi_driver_quit(); - audioapi_quit(); + lsnes_instance.audio->quit(); graphics_driver_quit(); msgbuf.unregister_handler(msg_callback_obj); time_t curtime = time(NULL); diff --git a/src/emulation/bsnes-legacy/core.cpp b/src/emulation/bsnes-legacy/core.cpp index 8255fc64..d37a4926 100644 --- a/src/emulation/bsnes-legacy/core.cpp +++ b/src/emulation/bsnes-legacy/core.cpp @@ -1754,7 +1754,7 @@ again2: ecore_callbacks->output_frame(ls, fps_n, fps_d); if(soundbuf_fill > 0) { auto freq = SNES::system.apu_frequency(); - audioapi_submit_buffer(soundbuf, soundbuf_fill / 2, true, freq / 768.0); + CORE().audio->submit_buffer(soundbuf, soundbuf_fill / 2, true, freq / 768.0); soundbuf_fill = 0; } } diff --git a/src/emulation/gambatte/core.cpp b/src/emulation/gambatte/core.cpp index 076fc172..38b6045d 100644 --- a/src/emulation/gambatte/core.cpp +++ b/src/emulation/gambatte/core.cpp @@ -700,7 +700,7 @@ namespace framebuffer::raw ls(inf); ecore_callbacks->output_frame(ls, 262144, 4389); - audioapi_submit_buffer(soundbuf, emitted / 2, true, native_rate ? 2097152 : 32768); + CORE().audio->submit_buffer(soundbuf, emitted / 2, true, native_rate ? 2097152 : 32768); } void c_runtosave() {} bool c_get_pflag() { return pflag; } diff --git a/src/emulation/sky/sky.cpp b/src/emulation/sky/sky.cpp index 9343ebff..32d98f90 100644 --- a/src/emulation/sky/sky.cpp +++ b/src/emulation/sky/sky.cpp @@ -6,6 +6,7 @@ #include "demo.hpp" #include "core/dispatch.hpp" #include "core/audioapi.hpp" +#include "core/instance.hpp" #include "core/messages.hpp" #include "interface/romtype.hpp" #include "interface/callbacks.hpp" @@ -326,7 +327,7 @@ namespace sky samples += corei.extrasamples(); int16_t sbuf[2668]; fetch_sfx(corei, sbuf, samples); - audioapi_submit_buffer(sbuf, samples, true, 48000); + CORE().audio->submit_buffer(sbuf, samples, true, 48000); } void c_runtosave() {} bool c_get_pflag() { return pflag; } diff --git a/src/emulation/test/test.cpp b/src/emulation/test/test.cpp index 2c83d883..e78d2d81 100644 --- a/src/emulation/test/test.cpp +++ b/src/emulation/test/test.cpp @@ -27,6 +27,7 @@ #include "core/controllerframe.hpp" #include "core/dispatch.hpp" #include "core/framebuffer.hpp" +#include "core/instance.hpp" #include "core/messages.hpp" #include "interface/callbacks.hpp" #include "interface/cover.hpp" @@ -163,7 +164,7 @@ namespace inf.offset_y = 0; framebuffer::raw ls(inf); ecore_callbacks->output_frame(ls, 60,1); - audioapi_submit_buffer(audio, 800, false, 48000); + CORE().audio->submit_buffer(audio, 800, false, 48000); } void c_runtosave() {} bool c_get_pflag() { return pflag; } diff --git a/src/interface/c-interface.cpp b/src/interface/c-interface.cpp index 87b09354..bb8eb441 100644 --- a/src/interface/c-interface.cpp +++ b/src/interface/c-interface.cpp @@ -12,6 +12,7 @@ #include "library/framebuffer-pixfmt-rgb32.hpp" #include "library/framebuffer-pixfmt-lrgb.hpp" #include "core/audioapi.hpp" +#include "core/instance.hpp" #include "core/messages.hpp" template<> int ccore_call_param_map::id = LSNES_CORE_ENUMERATE_CORES; @@ -855,7 +856,7 @@ failed: void callback_submit_sound(const int16_t* samples, size_t count, int stereo, double rate) { - audioapi_submit_buffer((int16_t*)samples, count, stereo, rate); + CORE().audio->submit_buffer((int16_t*)samples, count, stereo, rate); } void callback_notify_latch(const char** params) diff --git a/src/platform/libao/sound.cpp b/src/platform/libao/sound.cpp index a7ce93be..9d473068 100644 --- a/src/platform/libao/sound.cpp +++ b/src/platform/libao/sound.cpp @@ -21,6 +21,7 @@ #include #include #include "core/audioapi.hpp" +#include "core/instance.hpp" #include "library/minmax.hpp" #include "library/workthread.hpp" #include @@ -45,7 +46,7 @@ namespace { int16_t buffer[1024]; while(true) { - audioapi_get_mixed(buffer, 512, true); + lsnes_instance.audio->get_mixed(buffer, 512, true); if(!was_enabled) memset(buffer, 0, sizeof(buffer)); ao_device* d = cdev; @@ -67,7 +68,7 @@ namespace usleep(50000); ao_close(d); current_device = ""; - audioapi_voice_rate(0, 0); + lsnes_instance.audio->voice_rate(0, 0); } //Open new audio. if(newdevice != -1) { @@ -101,7 +102,7 @@ namespace (stringfmt() << "Error code " << err).throwex(); } } - audioapi_voice_rate(0, 48000); + lsnes_instance.audio->voice_rate(0, 48000); } if(cdev) { current_device = name; diff --git a/src/platform/portaudio/sound.cpp b/src/platform/portaudio/sound.cpp index 2a3275a1..5ea54d08 100644 --- a/src/platform/portaudio/sound.cpp +++ b/src/platform/portaudio/sound.cpp @@ -3,6 +3,7 @@ #include "core/command.hpp" #include "core/dispatch.hpp" #include "core/framerate.hpp" +#include "core/instance.hpp" #include "core/messages.hpp" #include "core/framerate.hpp" #include "core/keymapper.hpp" @@ -53,7 +54,7 @@ namespace size_t ptr = 0; while(pframe_count > 0) { unsigned bsize = min(voice_blocksize / 2, static_cast(pframe_count)); - audioapi_get_mixed(voicebuf, bsize, flag_pstereo); + lsnes_instance.audio->get_mixed(voicebuf, bsize, flag_pstereo); unsigned limit = bsize * (flag_pstereo ? 2 : 1); if(was_enabled) for(size_t i = 0; i < limit; i++) @@ -80,7 +81,7 @@ namespace else for(size_t i = 0; i < bsize; i++) voicebuf2[i] = _input[iptr++]; - audioapi_put_voice(voicebuf2, bsize); + lsnes_instance.audio->put_voice(voicebuf2, bsize); rframe_count -= bsize; } } @@ -175,7 +176,7 @@ namespace stream_p = NULL; current_pdev = paNoDevice; current_pfreq = 0; - audioapi_voice_rate(current_rfreq, current_pfreq); + lsnes_instance.audio->voice_rate(current_rfreq, current_pfreq); } void close_input() @@ -184,7 +185,7 @@ namespace stream_r = NULL; current_rdev = paNoDevice; current_rfreq = 0; - audioapi_voice_rate(current_rfreq, current_pfreq); + lsnes_instance.audio->voice_rate(current_rfreq, current_pfreq); } void close_all() @@ -228,20 +229,20 @@ namespace PaError err = Pa_OpenStream(&stream_p, NULL, output, inf->defaultSampleRate, 0, 0, audiocb, NULL); if(err != paNoError) { messages << "Portaudio: error (open): " << Pa_GetErrorText(err) << std::endl; - audioapi_voice_rate(current_rfreq, current_pfreq); + lsnes_instance.audio->voice_rate(current_rfreq, current_pfreq); return 1; } flag_pstereo = (output && output->channelCount == 2); err = Pa_StartStream(stream_p); if(err != paNoError) { messages << "Portaudio error (start): " << Pa_GetErrorText(err) << std::endl; - audioapi_voice_rate(current_rfreq, current_pfreq); + lsnes_instance.audio->voice_rate(current_rfreq, current_pfreq); return 1; } const PaStreamInfo* si = Pa_GetStreamInfo(stream_p); current_pfreq = output ? si->sampleRate : 0; current_pdev = dev; - audioapi_voice_rate(current_rfreq, current_pfreq); + lsnes_instance.audio->voice_rate(current_rfreq, current_pfreq); print_status(2); return 3; } @@ -261,20 +262,20 @@ namespace PaError err = Pa_OpenStream(&stream_r, input, NULL, inf->defaultSampleRate, 0, 0, audiocb, NULL); if(err != paNoError) { messages << "Portaudio: error (open): " << Pa_GetErrorText(err) << std::endl; - audioapi_voice_rate(current_rfreq, current_pfreq); + lsnes_instance.audio->voice_rate(current_rfreq, current_pfreq); return 2; } flag_rstereo = (input && input->channelCount == 2); err = Pa_StartStream(stream_r); if(err != paNoError) { messages << "Portaudio error (start): " << Pa_GetErrorText(err) << std::endl; - audioapi_voice_rate(current_rfreq, current_pfreq); + lsnes_instance.audio->voice_rate(current_rfreq, current_pfreq); return 2; } const PaStreamInfo* si = Pa_GetStreamInfo(stream_r); current_rfreq = input ? si->sampleRate : 0; current_rdev = dev; - audioapi_voice_rate(current_rfreq, current_pfreq); + lsnes_instance.audio->voice_rate(current_rfreq, current_pfreq); print_status(1); return 3; } diff --git a/src/platform/wxwidgets/vumeter.cpp b/src/platform/wxwidgets/vumeter.cpp index 4d3f6e3a..d74fc443 100644 --- a/src/platform/wxwidgets/vumeter.cpp +++ b/src/platform/wxwidgets/vumeter.cpp @@ -105,8 +105,8 @@ public: private: struct _vupanel : public wxPanel { - _vupanel(wxwin_vumeter* v) - : wxPanel(v, wxID_ANY, wxDefaultPosition, wxSize(320, 64)) + _vupanel(wxwin_vumeter* v, audioapi_instance& _audio) + : wxPanel(v, wxID_ANY, wxDefaultPosition, wxSize(320, 64)), audio(_audio) { obj = v; buffer.resize(61440); @@ -127,10 +127,10 @@ private: void signal_repaint() { - mleft = vu_to_pixels(audioapi_vu_mleft); - mright = vu_to_pixels(audioapi_vu_mright); - vout = vu_to_pixels(audioapi_vu_vout); - vin = vu_to_pixels(audioapi_vu_vin); + mleft = vu_to_pixels(audio.vu_mleft); + mright = vu_to_pixels(audio.vu_mright); + vout = vu_to_pixels(audio.vu_vout); + vin = vu_to_pixels(audio.vu_vin); Refresh(); obj->update_sent = false; } @@ -162,6 +162,7 @@ private: std::vector buffer; unsigned char colorstrip[960]; size_t bufferstride; + audioapi_instance& audio; void draw_text(unsigned x, unsigned y, unsigned w, unsigned h, const uint32_t* buf) { unsigned spos = 0; @@ -229,20 +230,20 @@ wxwin_vumeter::wxwin_vumeter(wxWindow* parent, emulator_instance& _inst) wxFlexGridSizer* top_s = new wxFlexGridSizer(5, 1, 0, 0); SetSizer(top_s); - top_s->Add(vupanel = new _vupanel(this)); + top_s->Add(vupanel = new _vupanel(this, *inst.audio)); top_s->Add(rate = new wxStaticText(this, wxID_ANY, wxT("")), 0, wxGROW); wxFlexGridSizer* slier_s = new wxFlexGridSizer(3, 3, 0, 0); slier_s->Add(new wxStaticText(this, wxID_ANY, wxT("Game:")), 0, wxGROW); - slier_s->Add(gamevol = new wxSlider(this, wxID_ANY, to_db(audioapi_music_volume()), -100, 50, + slier_s->Add(gamevol = new wxSlider(this, wxID_ANY, to_db(inst.audio->music_volume()), -100, 50, wxDefaultPosition, wxSize(320, -1)), 1, wxGROW); slier_s->Add(dgamevol = new wxButton(this, wxID_ANY, wxT("Reset"))); slier_s->Add(new wxStaticText(this, wxID_ANY, wxT("Voice out:")), 1, wxGROW); - slier_s->Add(voutvol = new wxSlider(this, wxID_ANY, to_db(audioapi_voicep_volume()), -100, 50, + slier_s->Add(voutvol = new wxSlider(this, wxID_ANY, to_db(inst.audio->voicep_volume()), -100, 50, wxDefaultPosition, wxSize(320, -1)), 1, wxGROW); slier_s->Add(dvoutvol = new wxButton(this, wxID_ANY, wxT("Reset"))); slier_s->Add(new wxStaticText(this, wxID_ANY, wxT("Voice in:")), 1, wxGROW); - slier_s->Add(vinvol = new wxSlider(this, wxID_ANY, to_db(audioapi_voicer_volume()), -100, 50, + slier_s->Add(vinvol = new wxSlider(this, wxID_ANY, to_db(inst.audio->voicer_volume()), -100, 50, wxDefaultPosition, wxSize(320, -1)), 1, wxGROW); slier_s->Add(dvinvol = new wxButton(this, wxID_ANY, wxT("Reset"))); top_s->Add(slier_s, 1, wxGROW); @@ -347,34 +348,34 @@ void wxwin_vumeter::on_devsel(wxCommandEvent& e) void wxwin_vumeter::on_game_change(wxScrollEvent& e) { - audioapi_music_volume(pow(10, gamevol->GetValue() / 20.0)); + inst.audio->music_volume(pow(10, gamevol->GetValue() / 20.0)); } void wxwin_vumeter::on_vout_change(wxScrollEvent& e) { - audioapi_voicep_volume(pow(10, voutvol->GetValue() / 20.0)); + inst.audio->voicep_volume(pow(10, voutvol->GetValue() / 20.0)); } void wxwin_vumeter::on_vin_change(wxScrollEvent& e) { - audioapi_voicer_volume(pow(10, vinvol->GetValue() / 20.0)); + inst.audio->voicer_volume(pow(10, vinvol->GetValue() / 20.0)); } void wxwin_vumeter::on_game_reset(wxCommandEvent& e) { - audioapi_music_volume(1); + inst.audio->music_volume(1); gamevol->SetValue(0); } void wxwin_vumeter::on_vout_reset(wxCommandEvent& e) { - audioapi_voicep_volume(1); + inst.audio->voicep_volume(1); voutvol->SetValue(0); } void wxwin_vumeter::on_vin_reset(wxCommandEvent& e) { - audioapi_voicer_volume(1); + inst.audio->voicer_volume(1); vinvol->SetValue(0); } @@ -385,8 +386,8 @@ void wxwin_vumeter::on_mute(wxCommandEvent& e) void wxwin_vumeter::refresh() { - auto rate_cur = audioapi_voice_rate(); - unsigned rate_nom = audioapi_orig_voice_rate(); + auto rate_cur = inst.audio->voice_rate(); + unsigned rate_nom = inst.audio->orig_voice_rate(); rate->SetLabel(towxstring((stringfmt() << "Current: " << rate_cur.second << "Hz (nominal " << rate_nom << "Hz), record: " << rate_cur.first << "Hz").str())); vupanel->signal_repaint(); -- 2.11.4.GIT