Merge pull request #642 from Holzhaus/audio-system-cleanup
Audio backends cleanup
This commit is contained in:
commit
28a6d1d9b6
|
@ -110,9 +110,6 @@ void emit_WriteCodeCache();
|
|||
|
||||
static int JoyFD = -1; // Joystick file descriptor
|
||||
static int kbfd = -1;
|
||||
#ifdef TARGET_PANDORA
|
||||
static int audio_fd = -1;
|
||||
#endif
|
||||
|
||||
|
||||
#define MAP_SIZE 32
|
||||
|
@ -755,7 +752,6 @@ void clean_exit(int sig_num) {
|
|||
// close files
|
||||
if (JoyFD>=0) close(JoyFD);
|
||||
if (kbfd>=0) close(kbfd);
|
||||
if(audio_fd>=0) close(audio_fd);
|
||||
|
||||
// Close EGL context ???
|
||||
if (sig_num!=0)
|
||||
|
@ -781,26 +777,6 @@ void clean_exit(int sig_num) {
|
|||
}
|
||||
}
|
||||
|
||||
void init_sound()
|
||||
{
|
||||
if((audio_fd=open("/dev/dsp",O_WRONLY))<0) {
|
||||
printf("Couldn't open /dev/dsp.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("sound enabled, dsp openned for write\n");
|
||||
int tmp=44100;
|
||||
int err_ret;
|
||||
err_ret=ioctl(audio_fd,SNDCTL_DSP_SPEED,&tmp);
|
||||
printf("set Frequency to %i, return %i (rate=%i)\n", 44100, err_ret, tmp);
|
||||
int channels=2;
|
||||
err_ret=ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &channels);
|
||||
printf("set dsp to stereo (%i => %i)\n", channels, err_ret);
|
||||
int format=AFMT_S16_LE;
|
||||
err_ret=ioctl(audio_fd, SNDCTL_DSP_SETFMT, &format);
|
||||
printf("set dsp to %s audio (%i/%i => %i)\n", "16bits signed" ,AFMT_S16_LE, format, err_ret);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, wchar* argv[])
|
||||
|
@ -812,11 +788,6 @@ int main(int argc, wchar* argv[])
|
|||
#ifdef TARGET_PANDORA
|
||||
signal(SIGSEGV, clean_exit);
|
||||
signal(SIGKILL, clean_exit);
|
||||
|
||||
init_sound();
|
||||
#else
|
||||
void os_InitAudio();
|
||||
os_InitAudio();
|
||||
#endif
|
||||
|
||||
#if defined(USES_HOMEDIR) && HOST_OS != OS_DARWIN
|
||||
|
@ -873,21 +844,6 @@ int main(int argc, wchar* argv[])
|
|||
return 0;
|
||||
}
|
||||
|
||||
u32 alsa_Push(void* frame, u32 samples, bool wait);
|
||||
u32 os_Push(void* frame, u32 samples, bool wait)
|
||||
{
|
||||
#ifndef TARGET_PANDORA
|
||||
int audio_fd = -1;
|
||||
#endif
|
||||
|
||||
if (audio_fd > 0) {
|
||||
write(audio_fd, frame, samples*4);
|
||||
} else {
|
||||
return alsa_Push(frame, samples, wait);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int get_mic_data(u8* buffer) { return 0; }
|
||||
|
|
|
@ -1,81 +1,12 @@
|
|||
|
||||
#include "audiostream_rif.h"
|
||||
#include "oslib/oslib.h"
|
||||
|
||||
#include "cfg/cfg.h"
|
||||
|
||||
#if HOST_OS==OS_LINUX && !defined(TARGET_NACL32) && !defined(ANDROID)
|
||||
|
||||
#if 1
|
||||
#include "oslib/audiobackend_alsa.h"
|
||||
#if USE_ALSA
|
||||
#include <alsa/asoundlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
snd_pcm_t *handle;
|
||||
|
||||
u32 alsa_Push(void* frame, u32 samples, bool wait) {
|
||||
|
||||
snd_pcm_nonblock(handle, wait ? 0 : 1);
|
||||
|
||||
int rc = snd_pcm_writei(handle, frame, samples);
|
||||
if (rc == -EPIPE)
|
||||
// We're making these functions static - there's no need to pollute the global namespace
|
||||
static void alsa_init()
|
||||
{
|
||||
/* EPIPE means underrun */
|
||||
fprintf(stderr, "ALSA: underrun occurred\n");
|
||||
snd_pcm_prepare(handle);
|
||||
alsa_Push(frame, samples * 8, wait);
|
||||
}
|
||||
else if (rc < 0)
|
||||
{
|
||||
fprintf(stderr, "ALSA: error from writei: %s\n", snd_strerror(rc));
|
||||
}
|
||||
else if (rc != samples)
|
||||
{
|
||||
fprintf(stderr, "ALSA: short write, wrote %d frames of %d\n", rc, samples);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#if 0
|
||||
u8 Tempbuffer[8192*4];
|
||||
void* AudioThread(void*)
|
||||
{
|
||||
sched_param sched;
|
||||
int policy;
|
||||
|
||||
pthread_getschedparam(pthread_self(),&policy,&sched);
|
||||
sched.sched_priority++;//policy=SCHED_RR;
|
||||
pthread_setschedparam(pthread_self(),policy,&sched);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
UpdateBuff(Tempbuffer);
|
||||
int rc = snd_pcm_writei(handle, Tempbuffer, settings.aica.BufferSize);
|
||||
if (rc == -EPIPE)
|
||||
{
|
||||
/* EPIPE means underrun */
|
||||
fprintf(stderr, "underrun occurred\n");
|
||||
snd_pcm_prepare(handle);
|
||||
}
|
||||
else if (rc < 0)
|
||||
{
|
||||
fprintf(stderr, "error from writei: %s\n", snd_strerror(rc));
|
||||
}
|
||||
else if (rc != (int)settings.aica.BufferSize)
|
||||
{
|
||||
fprintf(stderr, "short write, write %d frames\n", rc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cThread aud_thread(AudioThread,0);
|
||||
#endif
|
||||
|
||||
void os_InitAudio()
|
||||
{
|
||||
|
||||
if (cfgLoadInt("audio","disable",0))
|
||||
return;
|
||||
|
||||
cfgSaveInt("audio","disable",0);
|
||||
|
||||
long loops;
|
||||
int size;
|
||||
|
@ -171,12 +102,40 @@ void os_InitAudio()
|
|||
}
|
||||
}
|
||||
|
||||
void os_TermAudio()
|
||||
static u32 alsa_push(void* frame, u32 samples, bool wait)
|
||||
{
|
||||
snd_pcm_nonblock(handle, wait ? 0 : 1);
|
||||
|
||||
int rc = snd_pcm_writei(handle, frame, samples);
|
||||
if (rc == -EPIPE)
|
||||
{
|
||||
/* EPIPE means underrun */
|
||||
fprintf(stderr, "ALSA: underrun occurred\n");
|
||||
snd_pcm_prepare(handle);
|
||||
alsa_push(frame, samples * 8, wait);
|
||||
}
|
||||
else if (rc < 0)
|
||||
{
|
||||
fprintf(stderr, "ALSA: error from writei: %s\n", snd_strerror(rc));
|
||||
}
|
||||
else if (rc != samples)
|
||||
{
|
||||
fprintf(stderr, "ALSA: short write, wrote %d frames of %d\n", rc, samples);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void alsa_term()
|
||||
{
|
||||
snd_pcm_drain(handle);
|
||||
snd_pcm_close(handle);
|
||||
}
|
||||
#else
|
||||
|
||||
#endif
|
||||
audiobackend_t audiobackend_alsa = {
|
||||
"alsa", // Slug
|
||||
"Advanced Linux Sound Architecture", // Name
|
||||
&alsa_init,
|
||||
&alsa_push,
|
||||
&alsa_term
|
||||
};
|
||||
#endif
|
|
@ -0,0 +1,4 @@
|
|||
#pragma once
|
||||
#include "oslib/audiostream.h"
|
||||
|
||||
extern audiobackend_t audiobackend_alsa;
|
|
@ -0,0 +1,4 @@
|
|||
#pragma once
|
||||
#include "oslib/audiostream.h"
|
||||
|
||||
extern audiobackend_t audiobackend_android;
|
|
@ -1,10 +1,8 @@
|
|||
#include "types.h"
|
||||
|
||||
#include "oslib/audiobackend_directsound.h"
|
||||
#if HOST_OS==OS_WINDOWS
|
||||
#include "oslib.h"
|
||||
#include <initguid.h>
|
||||
#include <dsound.h>
|
||||
#include "audiostream_rif.h"
|
||||
#include "oslib.h"
|
||||
|
||||
void* SoundThread(void* param);
|
||||
#define V2_BUFFERSZ (16*1024)
|
||||
|
@ -14,7 +12,7 @@ IDirectSoundBuffer8* buffer;
|
|||
|
||||
u32 ds_ring_size;
|
||||
|
||||
void os_InitAudio()
|
||||
static void directsound_init()
|
||||
{
|
||||
verifyc(DirectSoundCreate8(NULL,&dsound,NULL));
|
||||
|
||||
|
@ -80,7 +78,7 @@ void os_InitAudio()
|
|||
DWORD wc=0;
|
||||
|
||||
|
||||
int os_getfreesz()
|
||||
static int directsound_getfreesz()
|
||||
{
|
||||
DWORD pc,wch;
|
||||
|
||||
|
@ -96,25 +94,12 @@ int os_getfreesz()
|
|||
return fsz;
|
||||
}
|
||||
|
||||
int os_getusedSamples()
|
||||
static int directsound_getusedSamples()
|
||||
{
|
||||
return (ds_ring_size-os_getfreesz())/4;
|
||||
return (ds_ring_size-directsound_getfreesz())/4;
|
||||
}
|
||||
|
||||
|
||||
bool os_IsAudioBuffered()
|
||||
{
|
||||
return os_getusedSamples()>=3000;
|
||||
}
|
||||
|
||||
|
||||
bool os_IsAudioBufferedLots()
|
||||
{
|
||||
u32 xxx=os_getusedSamples();
|
||||
return xxx>=4096;
|
||||
}
|
||||
|
||||
u32 os_Push_nw(void* frame, u32 samplesb)
|
||||
static u32 directsound_push_nw(void* frame, u32 samplesb)
|
||||
{
|
||||
DWORD pc,wch;
|
||||
|
||||
|
@ -155,7 +140,7 @@ u32 os_Push_nw(void* frame, u32 samplesb)
|
|||
//ds_ring_size
|
||||
}
|
||||
|
||||
u32 os_Push(void* frame, u32 samples, bool wait)
|
||||
static u32 directsound_push(void* frame, u32 samples, bool wait)
|
||||
{
|
||||
|
||||
u16* f=(u16*)frame;
|
||||
|
@ -175,16 +160,17 @@ u32 os_Push(void* frame, u32 samples, bool wait)
|
|||
|
||||
int ffs=1;
|
||||
|
||||
while (os_IsAudioBufferedLots() && wait)
|
||||
while (directsound_IsAudioBufferedLots() && wait)
|
||||
if (ffs == 0)
|
||||
ffs = printf("AUD WAIT %d\n",os_getusedSamples());
|
||||
ffs = printf("AUD WAIT %d\n", directsound_getusedSamples());
|
||||
|
||||
while(!os_Push_nw(frame,samples) && wait)
|
||||
printf("FAILED waiting on audio FAILED %d\n",os_getusedSamples());
|
||||
while(!directsound_Push_nw(frame,samples) && wait)
|
||||
printf("FAILED waiting on audio FAILED %d\n", directsound_getusedSamples());
|
||||
|
||||
return 1;
|
||||
}
|
||||
void os_TermAudio()
|
||||
|
||||
static void directsound_term()
|
||||
{
|
||||
buffer->Stop();
|
||||
|
||||
|
@ -192,4 +178,11 @@ void os_TermAudio()
|
|||
dsound->Release();
|
||||
}
|
||||
|
||||
audiobackend_t audiobackend_directsound = {
|
||||
"directsound", // Slug
|
||||
"Microsoft DirectSound", // Name
|
||||
&directsound_init,
|
||||
&directsound_push,
|
||||
&directsound_term
|
||||
};
|
||||
#endif
|
|
@ -0,0 +1,4 @@
|
|||
#pragma once
|
||||
#include "oslib/audiostream.h"
|
||||
|
||||
extern audiobackend_t audiobackend_directsound;
|
|
@ -0,0 +1,54 @@
|
|||
#include "oslib/audiobackend_oss.h"
|
||||
#ifdef USE_OSS
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/unistd.h>
|
||||
#include <sys/soundcard.h>
|
||||
|
||||
static int oss_audio_fd = -1;
|
||||
|
||||
static void oss_init()
|
||||
{
|
||||
oss_audio_fd = open("/dev/dsp", O_WRONLY);
|
||||
if (oss_audio_fd < 0)
|
||||
{
|
||||
printf("Couldn't open /dev/dsp.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("sound enabled, dsp openned for write\n");
|
||||
int tmp=44100;
|
||||
int err_ret;
|
||||
err_ret=ioctl(oss_audio_fd,SNDCTL_DSP_SPEED,&tmp);
|
||||
printf("set Frequency to %i, return %i (rate=%i)\n", 44100, err_ret, tmp);
|
||||
int channels=2;
|
||||
err_ret=ioctl(oss_audio_fd, SNDCTL_DSP_CHANNELS, &channels);
|
||||
printf("set dsp to stereo (%i => %i)\n", channels, err_ret);
|
||||
int format=AFMT_S16_LE;
|
||||
err_ret=ioctl(oss_audio_fd, SNDCTL_DSP_SETFMT, &format);
|
||||
printf("set dsp to %s audio (%i/%i => %i)\n", "16bits signed", AFMT_S16_LE, format, err_ret);
|
||||
}
|
||||
}
|
||||
|
||||
static u32 oss_push(void* frame, u32 samples, bool wait)
|
||||
{
|
||||
write(oss_audio_fd, frame, samples*4);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void oss_term() {
|
||||
if(oss_audio_fd >= 0)
|
||||
{
|
||||
close(oss_audio_fd);
|
||||
}
|
||||
}
|
||||
|
||||
audiobackend_t audiobackend_oss = {
|
||||
"oss", // Slug
|
||||
"Open Sound System", // Name
|
||||
&oss_init,
|
||||
&oss_push,
|
||||
&oss_term
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,4 @@
|
|||
#pragma once
|
||||
#include "oslib/audiostream.h"
|
||||
|
||||
extern audiobackend_t audiobackend_oss;
|
|
@ -0,0 +1,48 @@
|
|||
#include "oslib/audiobackend_pulseaudio.h"
|
||||
#ifdef USE_PULSEAUDIO
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/unistd.h>
|
||||
#include <pulse/simple.h>
|
||||
|
||||
static pa_simple *pulse_stream;
|
||||
|
||||
static void pulseaudio_init()
|
||||
{
|
||||
pa_sample_spec ss;
|
||||
ss.format = PA_SAMPLE_S16LE;
|
||||
ss.channels = 2;
|
||||
ss.rate = 44100;
|
||||
/* Create a new playback stream */
|
||||
pulse_stream = pa_simple_new(NULL, "reicast", PA_STREAM_PLAYBACK, NULL, "reicast", &ss, NULL, NULL, NULL);
|
||||
if (!pulse_stream) {
|
||||
fprintf(stderr, "PulseAudio: pa_simple_new() failed!\n");
|
||||
}
|
||||
}
|
||||
|
||||
static u32 pulseaudio_push(void* frame, u32 samples, bool wait)
|
||||
{
|
||||
if (pa_simple_write(pulse_stream, frame, (size_t) samples*4, NULL) < 0) {
|
||||
fprintf(stderr, "PulseAudio: pa_simple_write() failed!\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void pulseaudio_term() {
|
||||
if(pulse_stream != NULL)
|
||||
{
|
||||
// Make sure that every single sample was played
|
||||
if (pa_simple_drain(pulse_stream, NULL) < 0) {
|
||||
fprintf(stderr, "PulseAudio: pa_simple_drain() failed!\n");
|
||||
}
|
||||
pa_simple_free(pulse_stream);
|
||||
}
|
||||
}
|
||||
|
||||
audiobackend_t audiobackend_pulseaudio = {
|
||||
"pulse", // Slug
|
||||
"PulseAudio", // Name
|
||||
&pulseaudio_init,
|
||||
&pulseaudio_push,
|
||||
&pulseaudio_term
|
||||
};
|
||||
#endif
|
|
@ -0,0 +1,4 @@
|
|||
#pragma once
|
||||
#include "oslib/audiostream.h"
|
||||
|
||||
extern audiobackend_t audiobackend_pulseaudio;
|
|
@ -1,8 +1,12 @@
|
|||
#include "audiostream_rif.h"
|
||||
#include "stdclass.h"
|
||||
#include <limits.h>
|
||||
#include "cfg/cfg.h"
|
||||
#include "oslib/oslib.h"
|
||||
|
||||
//cResetEvent speed_limit(true,true);
|
||||
#include "audiostream.h"
|
||||
#include "oslib/audiobackend_directsound.h"
|
||||
#include "oslib/audiobackend_android.h"
|
||||
#include "oslib/audiobackend_alsa.h"
|
||||
#include "oslib/audiobackend_oss.h"
|
||||
#include "oslib/audiobackend_pulseaudio.h"
|
||||
|
||||
struct SoundFrame { s16 l;s16 r; };
|
||||
#define SAMPLE_COUNT 512
|
||||
|
@ -16,14 +20,117 @@ volatile u32 ReadPtr; //next sample to read
|
|||
|
||||
u32 gen_samples=0;
|
||||
|
||||
double time_diff, time_last;
|
||||
double time_diff = 128/44100.0;
|
||||
double time_last;
|
||||
#ifdef LOG_SOUND
|
||||
WaveWriter rawout("d:\\aica_out.wav");
|
||||
#endif
|
||||
|
||||
static bool audiobackends_registered = false;
|
||||
static unsigned int audiobackends_num_max = 1;
|
||||
static unsigned int audiobackends_num_registered = 0;
|
||||
static audiobackend_t **audiobackends = static_cast<audiobackend_t**>(calloc(audiobackends_num_max, sizeof(audiobackend_t*)));
|
||||
static audiobackend_t *audiobackend_current = NULL;
|
||||
|
||||
u32 os_Push(void* frame, u32 amt, bool wait);
|
||||
//void os_Pull(u32 level)
|
||||
bool RegisterAudioBackend(audiobackend_t *backend)
|
||||
{
|
||||
/* This function announces the availability of an audio backend to reicast. */
|
||||
// Check if backend is valid
|
||||
if (backend == NULL)
|
||||
{
|
||||
printf("ERROR: Tried to register invalid audio backend (NULL pointer).\n");
|
||||
return false;
|
||||
}
|
||||
if (backend->slug == "auto" || backend->slug == "none") {
|
||||
printf("ERROR: Tried to register invalid audio backend (slug \"%s\" is a reserved keyword).\n", backend->slug.c_str());
|
||||
return false;
|
||||
}
|
||||
// Check if we need to allocate addition memory for storing the pointers and allocate if neccessary
|
||||
if (audiobackends_num_registered == audiobackends_num_max)
|
||||
{
|
||||
// Check for integer overflows
|
||||
if (audiobackends_num_max == UINT_MAX)
|
||||
{
|
||||
printf("ERROR: Registering audio backend \"%s\" (%s) failed. Cannot register more than %u backends\n", backend->slug.c_str(), backend->name.c_str(), audiobackends_num_max);
|
||||
return false;
|
||||
}
|
||||
audiobackends_num_max++;
|
||||
audiobackend_t **new_ptr = static_cast<audiobackend_t**>(realloc(audiobackends, audiobackends_num_max*sizeof(audiobackend_t*)));
|
||||
// Make sure that allocation worked
|
||||
if (new_ptr == NULL)
|
||||
{
|
||||
printf("ERROR: Registering audio backend \"%s\" (%s) failed. Cannot allocate additional memory.\n", backend->slug.c_str(), backend->name.c_str());
|
||||
return false;
|
||||
}
|
||||
audiobackends = new_ptr;
|
||||
}
|
||||
audiobackends[audiobackends_num_registered] = backend;
|
||||
audiobackends_num_registered++;
|
||||
return true;
|
||||
}
|
||||
|
||||
void RegisterAllAudioBackends() {
|
||||
#if HOST_OS==OS_WINDOWS
|
||||
RegisterAudioBackend(&audiobackend_directsound);
|
||||
#endif
|
||||
#if ANDROID
|
||||
RegisterAudioBackend(&audiobackend_android);
|
||||
#endif
|
||||
#if USE_ALSA
|
||||
RegisterAudioBackend(&audiobackend_alsa);
|
||||
#endif
|
||||
#if USE_OSS
|
||||
RegisterAudioBackend(&audiobackend_oss);
|
||||
#endif
|
||||
#if USE_PULSEAUDIO
|
||||
RegisterAudioBackend(&audiobackend_pulseaudio);
|
||||
#endif
|
||||
audiobackends_registered = true;
|
||||
}
|
||||
|
||||
static audiobackend_t* GetAudioBackend(std::string slug)
|
||||
{
|
||||
if (slug == "none")
|
||||
{
|
||||
printf("WARNING: Audio backend set to \"none\"!\n");
|
||||
}
|
||||
else if(audiobackends_num_registered > 0)
|
||||
{
|
||||
if (slug == "auto")
|
||||
{
|
||||
/* FIXME: At some point, one might want to insert some intelligent
|
||||
algorithm for autoselecting the approriate audio backend here.
|
||||
I'm too lazy right now. */
|
||||
printf("Auto-selected audio backend \"%s\" (%s).\n", audiobackends[0]->slug.c_str(), audiobackends[0]->name.c_str());
|
||||
return audiobackends[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
for(unsigned int i = 0; i < audiobackends_num_registered; i++)
|
||||
{
|
||||
if(audiobackends[i]->slug == slug)
|
||||
{
|
||||
return audiobackends[i];
|
||||
}
|
||||
}
|
||||
printf("WARNING: Audio backend \"%s\" not found!\n", slug.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("WARNING: No audio backends available!\n");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
u32 PushAudio(void* frame, u32 amt, bool wait) {
|
||||
if (audiobackend_current != NULL) {
|
||||
return audiobackend_current->push(frame, amt, wait);
|
||||
} else {
|
||||
printf("AUDIO: Backend is NULL!\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 asRingUsedCount()
|
||||
{
|
||||
|
@ -41,49 +148,6 @@ u32 asRingFreeCount()
|
|||
|
||||
void WriteSample(s16 r, s16 l)
|
||||
{
|
||||
|
||||
#if 0
|
||||
#if HOST_OS==OS_WINDOWS
|
||||
#ifdef LOG_SOUND
|
||||
rawout.Write(l,r);
|
||||
#endif
|
||||
|
||||
if (!asRingFreeCount())
|
||||
{
|
||||
//printf("Buffer overrun\n");
|
||||
if (settings.aica.LimitFPS)
|
||||
{
|
||||
//speed_limit.Wait();
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
gen_samples++;
|
||||
//while limit on, 128 samples done, there is a buffer ready to be service AND speed is too fast then wait
|
||||
if (settings.aica.LimitFPS==1 && gen_samples>128)
|
||||
{
|
||||
for(;asRingUsedCount()>BufferSampleCount && (os_GetSeconds()-time_last)<=time_diff;)
|
||||
;
|
||||
gen_samples=0;
|
||||
time_last=os_GetSeconds();
|
||||
}
|
||||
#else
|
||||
if (!asRingFreeCount())
|
||||
{
|
||||
if (settings.aica.LimitFPS)
|
||||
{
|
||||
while(!asRingFreeCount()) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
const u32 ptr=(WritePtr+1)%RingBufferSampleCount;
|
||||
RingBuffer[ptr].r=r;
|
||||
RingBuffer[ptr].l=l;
|
||||
|
@ -91,16 +155,44 @@ void WriteSample(s16 r, s16 l)
|
|||
|
||||
if (WritePtr==(SAMPLE_COUNT-1))
|
||||
{
|
||||
os_Push(RingBuffer,SAMPLE_COUNT,settings.aica.LimitFPS);
|
||||
PushAudio(RingBuffer,SAMPLE_COUNT,settings.aica.LimitFPS);
|
||||
}
|
||||
}
|
||||
|
||||
void InitAudio()
|
||||
{
|
||||
time_diff=128/44100.0;
|
||||
if (cfgLoadInt("audio", "disable", 0)) {
|
||||
printf("WARNING: Audio disabled in config!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
cfgSaveInt("audio","disable",0);
|
||||
|
||||
if (!audiobackends_registered) {
|
||||
//FIXME: There might some nicer way to do this.
|
||||
RegisterAllAudioBackends();
|
||||
}
|
||||
|
||||
if (audiobackend_current != NULL) {
|
||||
printf("ERROR: The audio backend \"%s\" (%s) has already been initialized, you need to terminate it before you can call audio_init() again!\n", audiobackend_current->slug.c_str(), audiobackend_current->name.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
string audiobackend_slug = cfgLoadStr("audio", "backend", "auto"); // FIXME: This could be made a parameter
|
||||
audiobackend_current = GetAudioBackend(audiobackend_slug);
|
||||
if (audiobackend_current == NULL) {
|
||||
printf("WARNING: Running without audio!\n");
|
||||
return;
|
||||
}
|
||||
printf("Initializing audio backend \"%s\" (%s)...\n", audiobackend_current->slug.c_str(), audiobackend_current->name.c_str());
|
||||
audiobackend_current->init();
|
||||
}
|
||||
|
||||
void TermAudio()
|
||||
{
|
||||
|
||||
if (audiobackend_current != NULL) {
|
||||
audiobackend_current->term();
|
||||
printf("Terminating audio backend \"%s\" (%s)...\n", audiobackend_current->slug.c_str(), audiobackend_current->name.c_str());
|
||||
audiobackend_current = NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
#pragma once
|
||||
#include "types.h"
|
||||
|
||||
//Get used size in the ring buffer
|
||||
u32 asRingUsedCount();
|
||||
//Get free size in the ring buffer
|
||||
u32 asRingFreeCount();
|
||||
//Read 'Count' samples from the ring buffer.Returns true if successful.
|
||||
//If sz==0 then a whole buffer is read
|
||||
bool asRingRead(u8* dst,u32 count=0);
|
||||
void UpdateBuff(u8* pos);
|
||||
|
||||
typedef void (*audio_backend_init_func_t)();
|
||||
typedef u32 (*audio_backend_push_func_t)(void*, u32, bool);
|
||||
typedef void (*audio_backend_term_func_t)();
|
||||
typedef struct {
|
||||
string slug;
|
||||
string name;
|
||||
audio_backend_init_func_t init;
|
||||
audio_backend_push_func_t push;
|
||||
audio_backend_term_func_t term;
|
||||
} audiobackend_t;
|
||||
extern bool RegisterAudioBackend(audiobackend_t* backend);
|
||||
extern void InitAudio();
|
||||
extern u32 PushAudio(void* frame, u32 amt, bool wait);
|
||||
extern void TermAudio();
|
|
@ -1,14 +0,0 @@
|
|||
#pragma once
|
||||
#include "types.h"
|
||||
|
||||
//Get used size in the ring buffer
|
||||
u32 asRingUsedCount();
|
||||
//Get free size in the ring buffer
|
||||
u32 asRingFreeCount();
|
||||
//Read 'Count' samples from the ring buffer.Returns true if successful.
|
||||
//If sz==0 then a whole buffer is read
|
||||
bool asRingRead(u8* dst,u32 count=0);
|
||||
void UpdateBuff(u8* pos);
|
||||
|
||||
void os_InitAudio();
|
||||
void os_TermAudio();
|
|
@ -7,9 +7,6 @@ double os_GetSeconds();
|
|||
|
||||
void os_DoEvents();
|
||||
void os_CreateWindow();
|
||||
bool os_IsAudioBuffered();
|
||||
int os_getusedSamples();
|
||||
bool os_IsAudioBufferedLots();
|
||||
void WriteSample(s16 right, s16 left);
|
||||
|
||||
#if BUILD_COMPILER==COMPILER_VC
|
||||
|
|
|
@ -17,11 +17,6 @@
|
|||
#include <SDL/SDL.h>
|
||||
#include <EGL/egl.h>
|
||||
|
||||
#ifdef USE_OSS
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/soundcard.h>
|
||||
#endif
|
||||
|
||||
#include <signal.h>
|
||||
#include <execinfo.h>
|
||||
|
||||
|
@ -103,11 +98,6 @@ static SDL_Joystick *JoySDL = 0;
|
|||
|
||||
extern bool FrameSkipping;
|
||||
|
||||
#ifdef USE_OSS
|
||||
static int audio_fd = -1;
|
||||
#endif
|
||||
|
||||
|
||||
#define MAP_SIZE 32
|
||||
|
||||
const u32 JMapBtn_USB[MAP_SIZE] =
|
||||
|
@ -426,9 +416,6 @@ void clean_exit(int sig_num) {
|
|||
|
||||
// close files
|
||||
if (JoySDL) SDL_JoystickClose(JoySDL);
|
||||
#ifdef USE_OSS
|
||||
if (audio_fd>=0) close(audio_fd);
|
||||
#endif
|
||||
|
||||
// Close EGL context ???
|
||||
if (sig_num!=0)
|
||||
|
@ -437,37 +424,6 @@ void clean_exit(int sig_num) {
|
|||
SDL_Quit();
|
||||
}
|
||||
|
||||
#ifdef USE_OSS
|
||||
void init_sound()
|
||||
{
|
||||
if((audio_fd=open("/dev/dsp",O_WRONLY))<0)
|
||||
printf("Couldn't open /dev/dsp.\n");
|
||||
else
|
||||
{
|
||||
printf("sound enabled, dsp openned for write\n");
|
||||
int tmp=44100;
|
||||
int err_ret;
|
||||
err_ret=ioctl(audio_fd,SNDCTL_DSP_SPEED,&tmp);
|
||||
printf("set Frequency to %i, return %i (rate=%i)\n", 44100, err_ret, tmp);
|
||||
int channels=2;
|
||||
err_ret=ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &channels);
|
||||
printf("set dsp to stereo (%i => %i)\n", channels, err_ret);
|
||||
int format=AFMT_S16_LE;
|
||||
err_ret=ioctl(audio_fd, SNDCTL_DSP_SETFMT, &format);
|
||||
printf("set dsp to %s audio (%i/%i => %i)\n", "16bits signed" ,AFMT_S16_LE, format, err_ret);
|
||||
int frag=(4<<16)|11;
|
||||
int f=frag;
|
||||
err_ret=ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag);
|
||||
printf("set dsp fragment to %i of %i bytes (0x%x => %i)\n", "16bits signed" ,(f>>16), 1<<(f&0xff), frag, err_ret);
|
||||
/*
|
||||
// this doesn't help stutering, and the emu goes too fast after that
|
||||
err_ret=ioctl(audio_fd, SNDCTL_DSP_NONBLOCK, NULL);
|
||||
printf("set dsp to non-blocking ( => %i)\n", err_ret);
|
||||
*/
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, wchar* argv[])
|
||||
{
|
||||
//if (argc==2)
|
||||
|
@ -502,10 +458,6 @@ int main(int argc, wchar* argv[])
|
|||
|
||||
SetupInput();
|
||||
|
||||
#ifdef USE_OSS
|
||||
init_sound();
|
||||
#endif
|
||||
|
||||
FrameSkipping=false;
|
||||
|
||||
dc_run();
|
||||
|
@ -514,16 +466,3 @@ int main(int argc, wchar* argv[])
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 os_Push(void* frame, u32 samples, bool wait)
|
||||
{
|
||||
#ifdef USE_OSS
|
||||
static bool blocking = true;
|
||||
if (wait!=blocking) {
|
||||
fcntl(audio_fd, F_SETFD, O_WRONLY | wait?0:O_NONBLOCK);
|
||||
blocking=wait;
|
||||
}
|
||||
write(audio_fd, frame, samples*4);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include "oslib\oslib.h"
|
||||
#include "oslib\audiostream_rif.h"
|
||||
#include "oslib\audiostream.h"
|
||||
#include "imgread\common.h"
|
||||
|
||||
#define _WIN32_WINNT 0x0500
|
||||
|
@ -365,48 +365,6 @@ cResetEvent evt_hld(false,true);
|
|||
double speed_load_mspdf;
|
||||
extern double full_rps;
|
||||
|
||||
void os_wait_cycl(u32 cycl)
|
||||
{
|
||||
if (cycl>8*1000*1000)
|
||||
cycl=8*1000*1000;
|
||||
|
||||
|
||||
static double trolol=os_GetSeconds();
|
||||
|
||||
double newt=os_GetSeconds();
|
||||
double ets=(newt-trolol)*200*1000*1000;
|
||||
|
||||
bool fast_enough=ets < cycl;
|
||||
|
||||
bool wait = full_rps >5 && (fast_enough || os_IsAudioBufferedLots());
|
||||
|
||||
speed_load_mspdf=(speed_load_mspdf*0.96235 + ets/cycl*10)/1.96235;
|
||||
|
||||
if (wait && os_IsAudioBuffered())
|
||||
{
|
||||
while (cycl_glob<cycl && os_IsAudioBuffered())
|
||||
evt_hld.Wait(8);
|
||||
|
||||
if (cycl_glob>cycl)
|
||||
InterlockedExchangeSubtract(&cycl_glob,cycl);
|
||||
}
|
||||
else //if (os_IsAudioBufferedLots())
|
||||
{
|
||||
//cycl_glob=0;
|
||||
}
|
||||
|
||||
|
||||
static int last_fe=fast_enough;
|
||||
if (!fast_enough || !last_fe)
|
||||
printf("Speed %.2f (%.2f%%) (%d)\n",ets/cycl*10,cycl/ets*100,os_getusedSamples());
|
||||
|
||||
last_fe=fast_enough;
|
||||
|
||||
|
||||
|
||||
trolol=os_GetSeconds();
|
||||
}
|
||||
|
||||
|
||||
void os_consume(double t)
|
||||
{
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "rend/TexCache.h"
|
||||
#include "hw/maple/maple_devs.h"
|
||||
#include "hw/maple/maple_if.h"
|
||||
#include "oslib/audiobackend_android.h"
|
||||
|
||||
#include "util.h"
|
||||
|
||||
|
@ -485,7 +486,8 @@ JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_initControllers(JNIEn
|
|||
env->ReleaseBooleanArrayElements(controllers, controllers_body, 0);
|
||||
}
|
||||
|
||||
u32 os_Push(void* frame, u32 amt, bool wait)
|
||||
// Audio Stuff
|
||||
u32 androidaudio_push(void* frame, u32 amt, bool wait)
|
||||
{
|
||||
verify(amt==SAMPLE_COUNT);
|
||||
//yeah, do some audio piping magic here !
|
||||
|
@ -493,11 +495,29 @@ u32 os_Push(void* frame, u32 amt, bool wait)
|
|||
return jenv->CallIntMethod(emu,writemid,jsamples,wait);
|
||||
}
|
||||
|
||||
void androidaudio_init()
|
||||
{
|
||||
// Nothing to do here...
|
||||
}
|
||||
|
||||
void androidaudio_term()
|
||||
{
|
||||
// Move along, there is nothing to see here!
|
||||
}
|
||||
|
||||
bool os_IsAudioBuffered()
|
||||
{
|
||||
return jenv->CallIntMethod(emu,writemid,jsamples,-1)==0;
|
||||
}
|
||||
|
||||
audiobackend_t audiobackend_android = {
|
||||
"android", // Slug
|
||||
"Android Audio", // Name
|
||||
&androidaudio_init,
|
||||
&androidaudio_push,
|
||||
&androidaudio_term
|
||||
};
|
||||
|
||||
int get_mic_data(u8* buffer)
|
||||
{
|
||||
jbyteArray jdata = (jbyteArray)jenv->CallObjectMethod(sipemu,getmicdata);
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
FOR_LINUX :=1
|
||||
USE_ALSA := 1
|
||||
USE_OSS := 1
|
||||
#USE_PULSEAUDIO := 1
|
||||
|
||||
RZDCY_SRC_DIR = ../../newdc
|
||||
|
||||
|
@ -55,7 +58,21 @@ INCS := -I$(RZDCY_SRC_DIR) -I$(RZDCY_SRC_DIR)/deps -I$(RZDCY_SRC_DIR)/khronos -I
|
|||
|
||||
LIBS := -L../linux-deps/lib
|
||||
LIBS += -lm -lrt -lEGL -lGLESv2 #-lglslcompiler -lIMGegl -lpvr2d -lsrv_um
|
||||
LIBS += -lpthread -lasound -lX11 -lXdmcp -lXau
|
||||
LIBS += -lpthread -lX11 -lXdmcp -lXau
|
||||
|
||||
ifdef USE_ALSA
|
||||
CXXFLAGS += -D USE_ALSA
|
||||
LIBS += -lasound
|
||||
endif
|
||||
|
||||
ifdef USE_OSS
|
||||
CXXFLAGS += -D USE_OSS
|
||||
endif
|
||||
|
||||
ifdef USE_PULSEAUDIO
|
||||
CXXFLAGS += -D USE_PULSEAUDIO
|
||||
LIBS += -lpulse-simple
|
||||
endif
|
||||
|
||||
|
||||
OBJECTS=$(RZDCY_FILES:.cpp=.build_obj)
|
||||
|
|
|
@ -4,6 +4,9 @@ FOR_LINUX :=1
|
|||
NOT_ARM := 1
|
||||
NO_REC := 1
|
||||
#NO_REND := 1
|
||||
USE_ALSA := 1
|
||||
#USE_OSS := 1
|
||||
#USE_PULSEAUDIO := 1
|
||||
|
||||
RZDCY_SRC_DIR = ../../core
|
||||
|
||||
|
@ -62,7 +65,21 @@ INCS := -I$(RZDCY_SRC_DIR) -I$(RZDCY_SRC_DIR)/deps -I$(RZDCY_SRC_DIR)/khronos -I
|
|||
LIBS := -L../linux-deps/lib -L./enta_viv
|
||||
LIBS += -lglapi
|
||||
LIBS += -lm -lrt -lEGL -lGLESv2 #-lglslcompiler -lIMGegl -lpvr2d -lsrv_um
|
||||
LIBS += -lpthread -lasound #-lX11 -lXdmcp -lXau
|
||||
LIBS += -lpthread #-lX11 -lXdmcp -lXau
|
||||
|
||||
ifdef USE_ALSA
|
||||
CXXFLAGS += -D USE_ALSA
|
||||
LIBS += -lasound
|
||||
endif
|
||||
|
||||
ifdef USE_OSS
|
||||
CXXFLAGS += -D USE_OSS
|
||||
endif
|
||||
|
||||
ifdef USE_PULSEAUDIO
|
||||
CXXFLAGS += -D USE_PULSEAUDIO
|
||||
LIBS += -lpulse-simple
|
||||
endif
|
||||
|
||||
|
||||
OBJECTS=$(RZDCY_FILES:.cpp=.build_obj)
|
||||
|
|
|
@ -550,6 +550,11 @@
|
|||
9C7A3A7118C806E00070BB5F /* gl3platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gl3platform.h; sourceTree = "<group>"; };
|
||||
9C7A3A7318C806E00070BB5F /* khrplatform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = khrplatform.h; sourceTree = "<group>"; };
|
||||
9C7A3A7C18C806E00070BB5F /* nullDC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = nullDC.cpp; sourceTree = "<group>"; };
|
||||
9C7A3A7E18C806E00070BB5F /* alsa_audiostream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = alsa_audiostream.cpp; sourceTree = "<group>"; };
|
||||
9C7A3A7F18C806E00070BB5F /* audiostream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = audiostream.cpp; sourceTree = "<group>"; };
|
||||
9C7A3A8018C806E00070BB5F /* audiostream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = audiostream.h; sourceTree = "<group>"; };
|
||||
9C7A3A8118C806E00070BB5F /* ds_audiostream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ds_audiostream.cpp; sourceTree = "<group>"; };
|
||||
9C7A3A8218C806E00070BB5F /* oslib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = oslib.h; sourceTree = "<group>"; };
|
||||
9C7A3A8418C806E00070BB5F /* profiler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = profiler.cpp; sourceTree = "<group>"; };
|
||||
9C7A3A8518C806E00070BB5F /* profiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = profiler.h; sourceTree = "<group>"; };
|
||||
9C7A3A8618C806E00070BB5F /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README.md; sourceTree = "<group>"; };
|
||||
|
|
|
@ -6,6 +6,9 @@ X86_REC := 1
|
|||
#NO_REC := 1
|
||||
#NO_REND := 1
|
||||
WEBUI :=1
|
||||
USE_ALSA := 1
|
||||
USE_OSS := 1
|
||||
#USE_PULSEAUDIO := 1
|
||||
|
||||
RZDCY_SRC_DIR = ../../core
|
||||
|
||||
|
@ -71,7 +74,21 @@ LIBS += -lm -lrt
|
|||
LIBS += -ldl -lGL #for desktop gl
|
||||
#use this for GLES
|
||||
#LIBS += -lEGL -lGLESv2 #-lglslcompiler -lIMGegl -lpvr2d -lsrv_um
|
||||
LIBS += -lpthread -lasound -lX11
|
||||
LIBS += -lpthread -lX11
|
||||
|
||||
ifdef USE_ALSA
|
||||
CXXFLAGS += -D USE_ALSA
|
||||
LIBS += -lasound
|
||||
endif
|
||||
|
||||
ifdef USE_OSS
|
||||
CXXFLAGS += -D USE_OSS
|
||||
endif
|
||||
|
||||
ifdef USE_PULSEAUDIO
|
||||
CXXFLAGS += -D USE_PULSEAUDIO
|
||||
LIBS += -lpulse-simple
|
||||
endif
|
||||
|
||||
|
||||
OBJECTS=$(RZDCY_FILES:.cpp=.build_obj)
|
||||
|
|
|
@ -4,7 +4,9 @@ FOR_LINUX :=1
|
|||
FOR_ARM :=1
|
||||
FOR_PANDORA :=1
|
||||
USE_SDL :=1
|
||||
#USE_ALSA :=1
|
||||
USE_OSS :=1
|
||||
#USE_PULSEAUDIO :=1
|
||||
#PGO_MAKE :=1
|
||||
#PGO_USE :=1
|
||||
#USE_CCACHE :=1
|
||||
|
@ -79,10 +81,18 @@ LIBS += -lm -lrt -lEGL -lGLESv2
|
|||
#-lglslcompiler -lIMGegl -lpvr2d -lsrv_um
|
||||
LIBS += -lpthread
|
||||
|
||||
ifdef USE_ALSA
|
||||
CXXFLAGS += -D USE_ALSA
|
||||
LIBS += -lasound
|
||||
endif
|
||||
|
||||
ifdef USE_OSS
|
||||
CXXFLAGS += -D USE_OSS
|
||||
else
|
||||
LIBS += -lasound
|
||||
endif
|
||||
|
||||
ifdef USE_PULSEAUDIO
|
||||
CXXFLAGS += -D USE_PULSEAUDIO
|
||||
LIBS += -lpulse-simple
|
||||
endif
|
||||
|
||||
ifdef USE_SDL
|
||||
|
|
|
@ -317,7 +317,7 @@
|
|||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Fast|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Fast|x64'">true</ExcludedFromBuild>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\core\oslib\audiostream_rif.h" />
|
||||
<ClInclude Include="..\core\oslib\audiostream.h" />
|
||||
<ClInclude Include="..\core\oslib\oslib.h" />
|
||||
<ClInclude Include="..\core\profiler\profiler.h" />
|
||||
<ClInclude Include="..\core\rec-x86\win86_ngen.h">
|
||||
|
|
|
@ -751,7 +751,7 @@
|
|||
<ClInclude Include="..\core\hw\sh4\sh4_mem.h">
|
||||
<Filter>hw\sh4</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\core\oslib\audiostream_rif.h">
|
||||
<ClInclude Include="..\core\oslib\audiostream.h">
|
||||
<Filter>oslib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\core\hw\sh4\modules\ccn.h">
|
||||
|
|
Loading…
Reference in New Issue