mirror of https://github.com/snes9xgit/snes9x.git
unix: Fix sound.
This commit is contained in:
parent
0306b68d2a
commit
f5c5c8c2b3
|
@ -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"))
|
||||
{
|
||||
|
|
|
@ -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\\"
|
||||
|
||||
|
|
185
unix/unix.cpp
185
unix/unix.cpp
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue