1
0
Fork 0

Refactor CD-DA flow by removing intermediate buffers and loops

Thanks to @ripsaw8080 for insight into CD-DA channel mapping,
@hail-to-the-ryzen for testing and flagging a position-tracking bug,
and @dreamer_ for guidance and code review.

The CD-DA volume and channel mapping loops were moved to generic mixer
calls and no longer require a pre-processing loop:
 - Application-controlled CD-DA volume adjustment is now applied using
   an existing mixer volume scalar that was previously unused by the
   CD-DA code.
 - Mapping of CD-DA left and right channels is now applied at the tail
   end of the mixer's sample ingest sequence.

The following have been removed:
 - The CD-DA callback chunk-wise circular buffer
 - The decode buffers in the Opus and MP3 decoders
 - The decode buffer and conversion buffers in SDL_Sound
These removals and API changes allow the image player's buffer
to be passed-through ultimately to the audio codec, skipping multiple
intermediate buffers.
This commit is contained in:
krcroft 2019-11-11 13:36:31 -08:00 committed by Patryk Obara
parent 5a9dd2866b
commit d1a6f373cb
5 changed files with 310 additions and 336 deletions

View file

@ -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 @@ private:
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 @@ private:
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 @@ private:
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 @@ private:
SDL_mutex *mutex;
Bit8u buffer[8192];
int bufLen;
int currFrame;
int currFrame;
int targetFrame;
bool isPlaying;
bool isPaused;