Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CD audio optimizations and buffer zero-copy #36

Closed
wants to merge 7 commits into from
Closed
Changes from all commits
Commits
File filter
Filter file types
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.

Always

Just for now

@@ -98,7 +98,7 @@ jobs:
- name: Install packages
shell: pwsh
run: |
vcpkg install libpng sdl1 sdl1-net opusfile speexdsp
vcpkg install libpng sdl1 sdl1-net opusfile
vcpkg integrate install
- name: Build
shell: pwsh
@@ -120,7 +120,7 @@ jobs:
- name: Install packages
shell: pwsh
run: |
vcpkg install libpng sdl1 sdl1-net opusfile speexdsp
vcpkg install libpng sdl1 sdl1-net opusfile
vcpkg integrate install
- name: Build
shell: pwsh
@@ -466,15 +466,11 @@ else
AC_MSG_WARN([Can't find SDL_net, internal modem and ipx disabled])
fi

# Check for required Opus decoding libraries
# Check for the Opus file-handling library
PKG_CHECK_MODULES([OPUSFILE], [opusfile],
[ LIBS="$LIBS ${OPUSFILE_LIBS}"
CPPFLAGS="$CPPFLAGS ${OPUSFILE_CFLAGS}" ], [])

PKG_CHECK_MODULES([SPEEXDSP], [speexdsp],
[ LIBS="$LIBS ${SPEEXDSP_LIBS}"
CPPFLAGS="$CPPFLAGS ${SPEEXDSP_CFLAGS}" ], [])

AH_TEMPLATE(C_X11_XKB,[define to 1 if you have XKBlib.h and X11 lib])
AC_CHECK_LIB(X11, main, have_x11_lib=yes, have_x11_lib=no, )
AC_CHECK_HEADER(X11/XKBlib.h, have_x11_h=yes, have_x11_h=no, )
@@ -46,8 +46,11 @@ extern Bit8u MixTemp[MIXER_BUFSIZE];

class MixerChannel {
public:
MixerChannel(MIXER_Handler _handler, Bitu _freq, const char * _name);
void SetVolume(float _left,float _right);
void SetScale( float f );
void SetScale(float f);
void SetScale(float _left, float _right);
void MapChannels(Bit8u _left, Bit8u _right);
void UpdateVolume(void);
void SetFreq(Bitu _freq);
void Mix(Bitu _needed);
@@ -77,24 +80,25 @@ class MixerChannel {

void FillUp(void);
void Enable(bool _yesno);
MIXER_Handler handler;
float volmain[2];
float scale;
Bit32s volmul[2];

//This gets added the frequency counter each mixer step
Bitu freq_add;
//When this flows over a new sample needs to be read from the device
Bitu freq_counter;
//Timing on how many samples have been done and were needed by th emixer
Bitu done, needed;
//Previous and next samples
Bits prevSample[2];
Bits nextSample[2];
const char * name;
bool interpolate;
bool enabled;
MixerChannel * next;

float volmain[2];
MixerChannel* next;
const char* name;
Bitu done; //Timing on how many samples have been done by the mixer
bool enabled;

private:
MixerChannel();
MIXER_Handler handler;
Bitu freq_add; //This gets added the frequency counter each mixer step
Bitu freq_counter; //When this flows over a new sample needs to be read from the device
Bitu needed; //Timing on how many samples were needed by the mixer
Bits prev_sample[2]; //Previous and next samples
Bits next_sample[2];
Bit32s volmul[2];
float scale[2];
Bit8u channel_map[2]; //Output channel mapping
bool interpolate;
};

MixerChannel * MIXER_AddChannel(MIXER_Handler handler,Bitu freq,const char * name);
@@ -105,31 +105,31 @@ function list_packages() {
if [[ "${COMPILER}" == "gcc" ]]; then
COMPILER="g++"
fi
PACKAGES=(libtool build-essential autoconf-archive libsdl1.2-dev libsdl-net1.2-dev libopusfile-dev libspeexdsp-dev)
PACKAGES=(libtool build-essential autoconf-archive libsdl1.2-dev libsdl-net1.2-dev libopusfile-dev)
;;

dnf)
VERSION_DELIM="-"
PACKAGES=(libtool autoconf-archive SDL SDL_net-devel opusfile-devel speexdsp-devel)
PACKAGES=(libtool autoconf-archive SDL SDL_net-devel opusfile-devel)
;;

pacman)
# Arch offers 32-bit versions of SDL and speexDSP (but not others)
# Arch offers 32-bit versions of SDL (but not others)
PACKAGES=(libtool autoconf-archive sdl_net opusfile)
if [[ "${BITS}" == 32 ]]; then
PACKAGES+=(lib32-sdl lib32-speexdsp)
PACKAGES+=(lib32-sdl)
else
PACKAGES+=(sdl speexdsp)
PACKAGES+=(sdl)
fi
;;

zypper)
# OpenSUSE offers 32-bit versions of SDL, SDL_net, and speexDSP (but not others)
# OpenSUSE offers 32-bit versions of SDL and SDL_net (but not others)
PACKAGES=(devel_basis libtool autoconf-archive opusfile)
if [[ "${BITS}" == 32 ]]; then
PACKAGES+=(libSDL-devel-32bit libSDL_net-devel-32bit libspeexdsp1-32bit)
PACKAGES+=(libSDL-devel-32bit libSDL_net-devel-32bit)
else
PACKAGES+=(SDL SDL_net speexdsp)
PACKAGES+=(SDL SDL_net)
fi
;;

@@ -142,7 +142,7 @@ function list_packages() {
echo " sudo xcodebuild -license # to accept Apple's license agreement"
echo ""
echo "Now download, build, and install the following manually to avoid using Homebrew or MacPorts:"
echo " - coreutils autogen autoconf automake pkg-config libpng sdl sdl_net opusfile speexdsp"
echo " - coreutils autogen autoconf automake pkg-config libpng sdl sdl_net opusfile"
;;

brew)
@@ -151,11 +151,11 @@ function list_packages() {
if [[ "${COMPILER}" == "clang" ]]; then
COMPILER=""
fi
PACKAGES=(coreutils autogen autoconf autoconf-archive automake pkg-config libpng sdl sdl_net opusfile speexdsp)
PACKAGES=(coreutils autogen autoconf autoconf-archive automake pkg-config libpng sdl sdl_net opusfile)
;;

macports)
PACKAGES=(coreutils autogen automake autoconf autoconf-archive pkgconfig libpng libsdl libsdl_net opusfile speexDSP)
PACKAGES=(coreutils autogen automake autoconf autoconf-archive pkgconfig libpng libsdl libsdl_net opusfile)
;;

msys2)
@@ -167,7 +167,7 @@ function list_packages() {
pkg_type="i686"
fi
PACKAGES=(autogen autoconf autoconf-archive base-devel automake-wrapper)
for pkg in pkg-config libtool libpng zlib SDL SDL_net opusfile speexdsp; do
for pkg in pkg-config libtool libpng zlib SDL SDL_net opusfile; do
PACKAGES+=("mingw-w64-${pkg_type}-${pkg}")
done
COMPILER="mingw-w64-${pkg_type}-${COMPILER}"
@@ -176,7 +176,7 @@ function list_packages() {
vcpkg)
# VCPKG doesn't provide Clang or GCC, so we knock out the compiler and just give packages
COMPILER=""
PACKAGES=(libpng sdl1 sdl1-net opusfile speexdsp)
PACKAGES=(libpng sdl1 sdl1-net opusfile)
;;
*)
usage "Unknown package manager ${1}"
@@ -36,13 +36,11 @@
#include "mixer.h"
#include "../libs/decoders/SDL_sound.h"

#define RAW_SECTOR_SIZE 2352
#define COOKED_SECTOR_SIZE 2048
#define AUDIO_DECODE_BUFFER_SIZE 16512
// 16512 is 16384 + 128, which enough for four 4KB decode audio chunks plus 128 bytes extra,
// which accomodate the leftovers from typically callbacks, which also helps minimize
// most of the time. This size is also an even multiple of 8-bytes, allowing the compiler to
// use "large-D" SIMD instructions on it.
// CDROM data and audio format constants
#define RAW_SECTOR_SIZE 2352
#define COOKED_SECTOR_SIZE 2048
#define BYTES_PER_TRACK_FRAME 4
#define REDBOOK_FRAMES_PER_SECOND 75

enum { CDROM_USE_SDL, CDROM_USE_ASPI, CDROM_USE_IOCTL_DIO, CDROM_USE_IOCTL_DX, CDROM_USE_IOCTL_MCI };

@@ -53,17 +51,16 @@ typedef struct SMSF {
} TMSF;

typedef struct SCtrl {
Bit8u out[4]; // output channel
Bit8u vol[4]; // channel volume
Bit8u out[4]; // output channel mapping
Bit8u vol[4]; // channel volume (0 to 255)
} TCtrl;

// Conversion function from frames to Minutes/Second/Frames
//
template<typename T>
inline void frames_to_msf(int frames, T *m, T *s, T *f) {
const int cd_fps = 75;
*f = frames % cd_fps;
frames /= cd_fps;
*f = frames % REDBOOK_FRAMES_PER_SECOND;
frames /= REDBOOK_FRAMES_PER_SECOND;
*s = frames % 60;
frames /= 60;
*m = frames;
@@ -72,8 +69,7 @@ inline void frames_to_msf(int frames, T *m, T *s, T *f) {
// Conversion function from Minutes/Second/Frames to frames
//
inline int msf_to_frames(int m, int s, int f) {
const int cd_fps = 75;
return m * 60 * cd_fps + s * cd_fps + f;
return m * 60 * REDBOOK_FRAMES_PER_SECOND + s * REDBOOK_FRAMES_PER_SECOND + f;
}

extern int CDROM_GetMountType(char* path, int force);
@@ -161,7 +157,7 @@ class CDROM_Interface_Image : public CDROM_Interface
public:
virtual bool read(Bit8u *buffer, int seek, int count) = 0;
virtual bool seek(Bit32u offset) = 0;
virtual Bit16u decode(Bit8u *buffer) = 0;
virtual Bit32u decode(Bit16s *buffer, Bit32u desired_track_frames) = 0;
virtual Bit16u getEndian() = 0;
virtual Bit32u getRate() = 0;
virtual Bit8u getChannels() = 0;
@@ -175,7 +171,7 @@ class CDROM_Interface_Image : public CDROM_Interface
BinaryFile (const char *filename, bool &error);
bool read(Bit8u *buffer, int seek, int count);
bool seek(Bit32u offset);
Bit16u decode(Bit8u *buffer);
Bit32u decode(Bit16s *buffer, Bit32u desired_track_frames);
Bit16u getEndian();
Bit32u getRate() { return 44100; }
Bit8u getChannels() { return 2; }
@@ -191,7 +187,7 @@ class CDROM_Interface_Image : public CDROM_Interface
AudioFile (const char *filename, bool &error);
bool read(Bit8u *buffer, int seek, int count) { return false; }
bool seek(Bit32u offset);
Bit16u decode(Bit8u *buffer);
Bit32u decode(Bit16s *buffer, Bit32u desired_track_frames);
Bit16u getEndian();
Bit32u getRate();
Bit8u getChannels();
@@ -237,26 +233,21 @@ static CDROM_Interface_Image* images[26];

private:
// player
static void CDAudioCallBack(Bitu len);
static void CDAudioCallBack(Bitu desired_frames);
int GetTrack(int sector);

static struct imagePlayer {
Bit8u buffer[AUDIO_DECODE_BUFFER_SIZE];
TCtrl ctrlData;
Bit16s buffer[MIXER_BUFSIZE * 2]; // 2 channels (max)
TrackFile *trackFile;
MixerChannel *channel;
CDROM_Interface_Image *cd;
void (MixerChannel::*addSamples) (Bitu, const Bit16s*);
Bit32u startFrame;
Bit32u currFrame;
Bit32u numFrames;
Bit32u playbackTotal;
Bit32s playbackRemaining;
Bit16u bufferPos;
Bit16u bufferConsumed;
void (MixerChannel::*addFrames) (Bitu, const Bit16s*);
Bit32u startRedbookFrame;
Bit32u totalRedbookFrames;
Bit32u playedTrackFrames;
Bit32u totalTrackFrames;
bool isPlaying;
bool isPaused;
bool ctrlUsed;
} player;

void ClearTracks();
@@ -407,7 +398,7 @@ class CDROM_Interface_Ioctl : public CDROM_Interface
SDL_mutex *mutex;
Bit8u buffer[8192];
int bufLen;
int currFrame;
int currFrame;
int targetFrame;
bool isPlaying;
bool isPaused;
ProTip! Use n and p to navigate between commits in a pull request.