Instancefy audioapi core (but not driver) stuff
This commit is contained in:
parent
a2fed56d69
commit
8f54db2902
16 changed files with 290 additions and 258 deletions
|
@ -1,50 +1,55 @@
|
|||
#ifndef _audioapi__hpp__included__
|
||||
#define _audioapi__hpp__included__
|
||||
|
||||
#include "library/threads.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
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<unsigned,unsigned> audioapi_voice_rate();
|
||||
|
||||
std::pair<unsigned,unsigned> 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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -12,65 +12,37 @@
|
|||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
//3 music buffers is not enough due to huge blocksizes used by SDL.
|
||||
#define MUSIC_BUFFERS 8
|
||||
#define MAX_VOICE_ADJUST 200
|
||||
|
||||
audioapi_instance::dummy_cb_proc::dummy_cb_proc(audioapi_instance& _parent)
|
||||
: parent(_parent)
|
||||
{
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
|
||||
// | -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;
|
||||
}
|
||||
|
||||
std::pair<unsigned, unsigned> audioapi_voice_rate()
|
||||
audioapi_instance::~audioapi_instance()
|
||||
{
|
||||
quit();
|
||||
}
|
||||
|
||||
std::pair<unsigned, unsigned> 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;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "core/audioapi.hpp"
|
||||
#include "core/instance.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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<lsnes_core_enumerate_cores>::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)
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <fstream>
|
||||
#include <cassert>
|
||||
#include "core/audioapi.hpp"
|
||||
#include "core/instance.hpp"
|
||||
#include "library/minmax.hpp"
|
||||
#include "library/workthread.hpp"
|
||||
#include <string>
|
||||
|
@ -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;
|
||||
|
|
|
@ -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<unsigned>(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;
|
||||
}
|
||||
|
|
|
@ -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<unsigned char> 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();
|
||||
|
|
Loading…
Add table
Reference in a new issue