unix: Fix sound.

This commit is contained in:
Brandon Wright 2019-03-18 14:28:38 -05:00
parent 0306b68d2a
commit f5c5c8c2b3
3 changed files with 88 additions and 128 deletions

View File

@ -491,6 +491,11 @@ char * S9xParseArgs (char **argv, int argc)
if (!strcasecmp(argv[i], "-soundsync"))
Settings.SoundSync = TRUE;
else if (!strcasecmp(argv[i], "-dynamicratecontrol"))
{
Settings.DynamicRateControl = TRUE;
Settings.DynamicRateLimit = 5;
}
else
if (!strcasecmp(argv[i], "-playbackrate"))
{

20
unix/configure vendored
View File

@ -1,7 +1,7 @@
#! /bin/sh
# From configure.ac Revision: 1.59.2 .
# From configure.ac Revision: 1.60 .
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for Snes9x 1.59.2.
# Generated by GNU Autoconf 2.69 for Snes9x 1.60.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@ -578,8 +578,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='Snes9x'
PACKAGE_TARNAME='snes9x'
PACKAGE_VERSION='1.59.2'
PACKAGE_STRING='Snes9x 1.59.2'
PACKAGE_VERSION='1.60'
PACKAGE_STRING='Snes9x 1.60'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@ -1280,7 +1280,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures Snes9x 1.59.2 to adapt to many kinds of systems.
\`configure' configures Snes9x 1.60 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1350,7 +1350,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of Snes9x 1.59.2:";;
short | recursive ) echo "Configuration of Snes9x 1.60:";;
esac
cat <<\_ACEOF
@ -1468,7 +1468,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
Snes9x configure 1.59.2
Snes9x configure 1.60
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@ -1871,7 +1871,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by Snes9x $as_me 1.59.2, which was
It was created by Snes9x $as_me 1.60, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@ -6915,7 +6915,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by Snes9x $as_me 1.59.2, which was
This file was extended by Snes9x $as_me 1.60, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@ -6968,7 +6968,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
Snes9x config.status 1.59.2
Snes9x config.status 1.60
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"

View File

@ -753,8 +753,7 @@ void S9xSyncSpeed (void)
#ifndef NOSOUND
if (Settings.SoundSync)
{
while (!S9xSyncSound())
usleep(0);
return;
}
#endif
@ -1268,47 +1267,80 @@ static void ReadJoysticks (void)
#endif
static void SoundTrigger (void)
void S9xSamplesAvailable(void *data)
{
#ifndef NOSOUND
S9xProcessSound(NULL);
#endif
}
static void InitTimer (void)
{
#ifndef NOSOUND
struct itimerval timeout;
#endif
struct sigaction sa;
audio_buf_info info;
int samples_to_write;
int bytes_to_write;
int bytes_written;
static uint8 *sound_buffer = NULL;
static int sound_buffer_size = 0;
#ifdef USE_THREADS
if (unixSettings.ThreadSound)
ioctl(so.sound_fd, SNDCTL_DSP_GETOSPACE, &info);
if (Settings.DynamicRateControl)
{
pthread_mutex_init(&mutex, NULL);
pthread_create(&thread, NULL, S9xProcessSound, NULL);
S9xUpdateDynamicRate(info.bytes, so.fragment_size * 4);
}
samples_to_write = S9xGetSampleCount();
if (Settings.DynamicRateControl && !Settings.SoundSync)
{
// Using rate control, we should always keep the emulator's sound buffers empty to
// maintain an accurate measurement.
if (samples_to_write > (info.bytes >> 1))
{
S9xClearSamples();
return;
}
#endif
}
sa.sa_handler = (SIG_PF) SoundTrigger;
if (Settings.SoundSync && !Settings.TurboMode && !Settings.Mute)
{
while (info.bytes >> 1 < samples_to_write)
{
int usec_to_sleep = ((samples_to_write >> 1) - (info.bytes >> 2)) * 10000 /
(Settings.SoundPlaybackRate / 100);
usleep(usec_to_sleep > 0 ? usec_to_sleep : 0);
ioctl(so.sound_fd, SNDCTL_DSP_GETOSPACE, &info);
}
}
else
{
samples_to_write = MIN(info.bytes >> 1, samples_to_write) & ~1;
}
#ifdef SA_RESTART
sa.sa_flags = SA_RESTART;
#else
sa.sa_flags = 0;
#endif
if (samples_to_write < 0)
return;
#ifndef NOSOUND // FIXME: Kludge to get calltree running. Remove later.
sigemptyset(&sa.sa_mask);
sigaction(SIGALRM, &sa, NULL);
if (sound_buffer_size < samples_to_write * 2)
{
sound_buffer = (uint8 *)realloc(sound_buffer, samples_to_write * 2);
sound_buffer_size = samples_to_write * 2;
}
timeout.it_interval.tv_sec = 0;
timeout.it_interval.tv_usec = 10000;
timeout.it_value.tv_sec = 0;
timeout.it_value.tv_usec = 10000;
if (setitimer(ITIMER_REAL, &timeout, NULL) < 0)
perror("setitimer");
S9xMixSamples(sound_buffer, samples_to_write);
bytes_written = 0;
bytes_to_write = samples_to_write * 2;
while (bytes_to_write > bytes_written)
{
int result;
result = write(so.sound_fd,
((char *)sound_buffer) + bytes_written,
bytes_to_write - bytes_written);
if (result < 0)
break;
bytes_written += result;
}
#endif
}
@ -1324,15 +1356,15 @@ bool8 S9xOpenSoundDevice (void)
return (FALSE);
}
J = log2(unixSettings.SoundFragmentSize) | (3 << 16);
J = log2(unixSettings.SoundFragmentSize) | (4 << 16);
if (ioctl(so.sound_fd, SNDCTL_DSP_SETFRAGMENT, &J) == -1)
return (FALSE);
J = K = Settings.SixteenBitSound ? AFMT_S16_NE : AFMT_U8;
J = K = AFMT_S16_NE;
if (ioctl(so.sound_fd, SNDCTL_DSP_SETFMT, &J) == -1 || J != K)
return (FALSE);
J = K = Settings.Stereo ? 1 : 0;
J = K = 1;
if (ioctl(so.sound_fd, SNDCTL_DSP_STEREO, &J) == -1 || J != K)
return (FALSE);
@ -1348,89 +1380,13 @@ bool8 S9xOpenSoundDevice (void)
printf("fragment size: %d\n", J);
#endif
S9xSetSamplesAvailableCallback(S9xSamplesAvailable, NULL);
return (TRUE);
}
#ifndef NOSOUND
static void * S9xProcessSound (void *)
{
// If threads in use, this is to loop indefinitely.
// If not, this will be called by timer.
audio_buf_info info;
if (!unixSettings.ThreadSound && (ioctl(so.sound_fd, SNDCTL_DSP_GETOSPACE, &info) == -1 || info.bytes < (int) so.fragment_size))
return (NULL);
#ifdef USE_THREADS
do
{
#endif
int sample_count = so.fragment_size;
if (Settings.SixteenBitSound)
sample_count >>= 1;
#ifdef USE_THREADS
if (unixSettings.ThreadSound)
pthread_mutex_lock(&mutex);
else
#endif
if (block_signal)
return (NULL);
block_generate_sound = TRUE;
if (so.samples_mixed_so_far < sample_count)
{
unsigned ofs = so.play_position + (Settings.SixteenBitSound ? (so.samples_mixed_so_far << 1) : so.samples_mixed_so_far);
S9xMixSamples(Buf + (ofs & SOUND_BUFFER_SIZE_MASK), sample_count - so.samples_mixed_so_far);
so.samples_mixed_so_far = sample_count;
}
unsigned bytes_to_write = sample_count;
if (Settings.SixteenBitSound)
bytes_to_write <<= 1;
unsigned byte_offset = so.play_position;
so.play_position += bytes_to_write;
so.play_position &= SOUND_BUFFER_SIZE_MASK;
#ifdef USE_THREADS
if (unixSettings.ThreadSound)
pthread_mutex_unlock(&mutex);
#endif
block_generate_sound = FALSE;
for (;;)
{
int I = bytes_to_write;
if (byte_offset + I > SOUND_BUFFER_SIZE)
I = SOUND_BUFFER_SIZE - byte_offset;
if (I == 0)
break;
I = write(so.sound_fd, (char *) Buf + byte_offset, I);
if (I > 0)
{
bytes_to_write -= I;
byte_offset += I;
byte_offset &= SOUND_BUFFER_SIZE_MASK;
}
else
if (I < 0 && errno != EINTR)
break;
}
so.samples_mixed_so_far -= sample_count;
#ifdef USE_THREADS
} while (unixSettings.ThreadSound);
#endif
return (NULL);
}
#endif
@ -1537,7 +1493,7 @@ int main (int argc, char **argv)
exit(1);
}
S9xInitSound(unixSettings.SoundBufferSize);
S9xInitSound(0);
S9xSetSoundMute(TRUE);
S9xReportControllers();
@ -1714,7 +1670,6 @@ int main (int argc, char **argv)
uint32 JoypadSkip = 0;
#endif
InitTimer();
S9xSetSoundMute(FALSE);
#ifdef NETPLAY_SUPPORT