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")) if (!strcasecmp(argv[i], "-soundsync"))
Settings.SoundSync = TRUE; Settings.SoundSync = TRUE;
else if (!strcasecmp(argv[i], "-dynamicratecontrol"))
{
Settings.DynamicRateControl = TRUE;
Settings.DynamicRateLimit = 5;
}
else else
if (!strcasecmp(argv[i], "-playbackrate")) if (!strcasecmp(argv[i], "-playbackrate"))
{ {

20
unix/configure vendored
View File

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

View File

@ -753,8 +753,7 @@ void S9xSyncSpeed (void)
#ifndef NOSOUND #ifndef NOSOUND
if (Settings.SoundSync) if (Settings.SoundSync)
{ {
while (!S9xSyncSound()) return;
usleep(0);
} }
#endif #endif
@ -1268,47 +1267,80 @@ static void ReadJoysticks (void)
#endif #endif
static void SoundTrigger (void) void S9xSamplesAvailable(void *data)
{ {
#ifndef NOSOUND #ifndef NOSOUND
S9xProcessSound(NULL);
#endif
}
static void InitTimer (void) audio_buf_info info;
{ int samples_to_write;
#ifndef NOSOUND int bytes_to_write;
struct itimerval timeout; int bytes_written;
#endif static uint8 *sound_buffer = NULL;
struct sigaction sa; static int sound_buffer_size = 0;
#ifdef USE_THREADS
if (unixSettings.ThreadSound)
{
pthread_mutex_init(&mutex, NULL);
pthread_create(&thread, NULL, S9xProcessSound, NULL);
return;
}
#endif
sa.sa_handler = (SIG_PF) SoundTrigger; ioctl(so.sound_fd, SNDCTL_DSP_GETOSPACE, &info);
#ifdef SA_RESTART if (Settings.DynamicRateControl)
sa.sa_flags = SA_RESTART; {
#else S9xUpdateDynamicRate(info.bytes, so.fragment_size * 4);
sa.sa_flags = 0; }
#endif
#ifndef NOSOUND // FIXME: Kludge to get calltree running. Remove later. samples_to_write = S9xGetSampleCount();
sigemptyset(&sa.sa_mask);
sigaction(SIGALRM, &sa, NULL);
timeout.it_interval.tv_sec = 0; if (Settings.DynamicRateControl && !Settings.SoundSync)
timeout.it_interval.tv_usec = 10000; {
timeout.it_value.tv_sec = 0; // Using rate control, we should always keep the emulator's sound buffers empty to
timeout.it_value.tv_usec = 10000; // maintain an accurate measurement.
if (setitimer(ITIMER_REAL, &timeout, NULL) < 0) if (samples_to_write > (info.bytes >> 1))
perror("setitimer"); {
S9xClearSamples();
return;
}
}
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;
}
if (samples_to_write < 0)
return;
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;
}
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 #endif
} }
@ -1324,15 +1356,15 @@ bool8 S9xOpenSoundDevice (void)
return (FALSE); return (FALSE);
} }
J = log2(unixSettings.SoundFragmentSize) | (3 << 16); J = log2(unixSettings.SoundFragmentSize) | (4 << 16);
if (ioctl(so.sound_fd, SNDCTL_DSP_SETFRAGMENT, &J) == -1) if (ioctl(so.sound_fd, SNDCTL_DSP_SETFRAGMENT, &J) == -1)
return (FALSE); 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) if (ioctl(so.sound_fd, SNDCTL_DSP_SETFMT, &J) == -1 || J != K)
return (FALSE); return (FALSE);
J = K = Settings.Stereo ? 1 : 0; J = K = 1;
if (ioctl(so.sound_fd, SNDCTL_DSP_STEREO, &J) == -1 || J != K) if (ioctl(so.sound_fd, SNDCTL_DSP_STEREO, &J) == -1 || J != K)
return (FALSE); return (FALSE);
@ -1348,89 +1380,13 @@ bool8 S9xOpenSoundDevice (void)
printf("fragment size: %d\n", J); printf("fragment size: %d\n", J);
#endif #endif
S9xSetSamplesAvailableCallback(S9xSamplesAvailable, NULL);
return (TRUE); return (TRUE);
} }
#ifndef NOSOUND #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 #endif
@ -1537,7 +1493,7 @@ int main (int argc, char **argv)
exit(1); exit(1);
} }
S9xInitSound(unixSettings.SoundBufferSize); S9xInitSound(0);
S9xSetSoundMute(TRUE); S9xSetSoundMute(TRUE);
S9xReportControllers(); S9xReportControllers();
@ -1714,7 +1670,6 @@ int main (int argc, char **argv)
uint32 JoypadSkip = 0; uint32 JoypadSkip = 0;
#endif #endif
InitTimer();
S9xSetSoundMute(FALSE); S9xSetSoundMute(FALSE);
#ifdef NETPLAY_SUPPORT #ifdef NETPLAY_SUPPORT