Skip to content
Permalink
Browse files
Remove the need for a separate channel-mapping loop
The channel mapping is now handled inline by the mixer in
a generic and minimal way (without adding new logic or
loops).  This eliminates the need for a separate loop in
the CD handling code, as well as eliminating the same
volume and channel mapping loop in the Windows CDROM code.
There's also no longer a need for the image player class
to carry around a TCtrl object and the associated ctrlUsed
boolean.
  • Loading branch information
krcroft committed Nov 11, 2019
1 parent 61a62fd commit a381c8be900edb699e796a21c63ba044861893f3
Showing with 172 additions and 115 deletions.
  1. +23 −20 include/mixer.h
  2. +2 −4 src/dos/cdrom.h
  3. +21 −29 src/dos/cdrom_image.cpp
  4. +8 −12 src/dos/cdrom_ioctl_win32.cpp
  5. +118 −50 src/hardware/mixer.cpp
@@ -46,9 +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 _left, float _right_);
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);
@@ -78,24 +80,25 @@ class MixerChannel {

void FillUp(void);
void Enable(bool _yesno);
MIXER_Handler handler;
float volmain[2];
float scale[2];
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);
@@ -51,8 +51,8 @@ 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
@@ -238,7 +238,6 @@ static void CDAudioCallBack(Bitu desired_frames);

static struct imagePlayer {
Bit16s buffer[MIXER_BUFSIZE * 2]; // 2 channels (max)
TCtrl ctrlData;
TrackFile *trackFile;
MixerChannel *channel;
CDROM_Interface_Image *cd;
@@ -249,7 +248,6 @@ static struct imagePlayer {
Bit32u totalTrackFrames;
bool isPlaying;
bool isPaused;
bool ctrlUsed;
} player;

void ClearTracks();
@@ -27,21 +27,21 @@
#include <fstream>
#include <iostream>
#include <limits>
#include <limits.h> //GCC 2.95
#include <sstream>
#include <vector>
#include <sys/stat.h>
#include "cdrom.h"
#include "drives.h"
#include "support.h"
#include "setup.h"

#if !defined(WIN32)
#include <libgen.h>
#else
#include <string.h>
#endif

#include "cdrom.h"
#include "drives.h"
#include "support.h"
#include "setup.h"

using namespace std;

#define MAX_LINE_LENGTH 512
@@ -208,7 +208,6 @@ int CDROM_Interface_Image::refCount = 0;
CDROM_Interface_Image* CDROM_Interface_Image::images[26] = {};
CDROM_Interface_Image::imagePlayer CDROM_Interface_Image::player = {
{0}, // buffer[]
{{0}, {0}}, // TCtrl struct
nullptr, // TrackFile*
nullptr, // MixerChannel*
nullptr, // CDROM_Interface_Image*
@@ -218,8 +217,7 @@ CDROM_Interface_Image::imagePlayer CDROM_Interface_Image::player = {
0, // playedTrackFrames
0, // totalTrackFrames
false, // isPlaying
false, // isPaused
false // ctrlUsed
false // isPaused
};

CDROM_Interface_Image::CDROM_Interface_Image(Bit8u subUnit)
@@ -432,7 +430,7 @@ bool CDROM_Interface_Image::PlayAudioSector(unsigned long start, unsigned long l

// We can't play audio from a data track (as it would result in garbage/static)
else if (track >= 0 && tracks[track].attr == 0x40)
LOG(LOG_MISC,LOG_WARN)("Game tries to play the data track. Not doing this");
LOG(LOG_MISC,LOG_WARN)("Game tried to play the data track. Not doing this");

// Checks passed, setup the audio stream
else {
@@ -469,19 +467,15 @@ bool CDROM_Interface_Image::PlayAudioSector(unsigned long start, unsigned long l
player.playedTrackFrames = 0;

#ifdef DEBUG
LOG_MSG("%s CDROM: Playing track %d at %d Hz "
"%d-channel at start sector %lu (%.1f minute-mark), seek %u ms from track start, "
"(skip=%d,dstart=%d,secsize=%d), for %u Redbook frames (%.1f seconds)",
LOG_MSG("%s CDROM: Playing track %d (%d Hz "
"%d-channel) at starting sector %lu (%.1f minute-mark) "
"for %u Redbook frames (%.1f seconds)",
get_time(),
track,
track_rate,
track_channels,
start,
static_cast<float>(start) / (REDBOOK_FRAMES_PER_SECOND * 60),
offset,
tracks[track].skip,
tracks[track].start,
tracks[track].sectorSize,
player.totalRedbookFrames,
static_cast<float>(player.totalRedbookFrames) / REDBOOK_FRAMES_PER_SECOND);
#endif
@@ -529,19 +523,14 @@ bool CDROM_Interface_Image::StopAudio(void)

void CDROM_Interface_Image::ChannelControl(TCtrl ctrl)
{
player.ctrlUsed = (ctrl.out[0]!=0 || ctrl.out[1]!=1 || ctrl.vol[0]<0xfe || ctrl.vol[1]<0xfe);
player.ctrlData = ctrl;

// Apply the volume to our Mixer Channel
if (player.ctrlUsed && player.channel != NULL) {
const float leftVolumePercent = static_cast<float>(player.ctrlData.vol[0] / 255.0);
const float rightVolumePercent = static_cast<float>(player.ctrlData.vol[1] / 255.0);
player.channel->SetScale(leftVolumePercent, rightVolumePercent);
#ifdef DEBUG
LOG_MSG("%s CDROM: Game set the left and right volume to %3.0f%% and %3.0f%%, respectively",
get_time(), leftVolumePercent * 100, rightVolumePercent * 100);
#endif
}
if (player.channel == NULL) return;

// Scale our mixer channel's volume as defined by the application
player.channel->SetScale(static_cast<float>(ctrl.vol[0]/255.0),
static_cast<float>(ctrl.vol[1]/255.0));

// Map our mixer channel's as defined by the application
player.channel->MapChannels(ctrl.out[0], ctrl.out[1]);
}

bool CDROM_Interface_Image::ReadSectors(PhysPt buffer, bool raw, unsigned long sector, unsigned long num)
@@ -597,6 +586,7 @@ bool CDROM_Interface_Image::ReadSector(Bit8u *buffer, bool raw, unsigned long se
if (tracks[track].sectorSize == RAW_SECTOR_SIZE && !tracks[track].mode2 && !raw) seek += 16;
if (tracks[track].mode2 && !raw) seek += 24;

#if 0 // Excessively verbose.. only enable if needed
#ifdef DEBUG
LOG_MSG("%s CDROM: ReadSector track=%d, desired raw=%s, sector=%ld, length=%d",
get_time(),
@@ -605,6 +595,8 @@ bool CDROM_Interface_Image::ReadSector(Bit8u *buffer, bool raw, unsigned long se
sector,
length);
#endif
#endif

return tracks[track].file->read(buffer, seek, length);
}

@@ -470,8 +470,14 @@ bool CDROM_Interface_Ioctl::StopAudio(void) {

void CDROM_Interface_Ioctl::ChannelControl(TCtrl ctrl)
{
player.ctrlUsed = (ctrl.out[0]!=0 || ctrl.out[1]!=1 || ctrl.vol[0]<0xfe || ctrl.vol[1]<0xfe);
player.ctrlData = ctrl;
if (player.channel == NULL) return;

// Scale our mixer channel's volume as defined by the application
player.channel->SetScale(static_cast<float>(ctrl.vol[0]/255.0),
static_cast<float>(ctrl.vol[1]/255.0));

// Map our mixer channel's as defined by the application
player.channel->MapChannels(ctrl.out[0], ctrl.out[1]);
}

bool CDROM_Interface_Ioctl::LoadUnloadMedia(bool unload) {
@@ -565,16 +571,6 @@ void CDROM_Interface_Ioctl::dx_CDAudioCallBack(Bitu len) {
}
}
SDL_mutexV(player.mutex);
if (player.ctrlUsed) {
Bit16s sample0,sample1;
Bit16s * samples=(Bit16s *)&player.buffer;
for (Bitu pos=0;pos<len/4;pos++) {
sample0=samples[pos*2+player.ctrlData.out[0]];
sample1=samples[pos*2+player.ctrlData.out[1]];
samples[pos*2+0]=(Bit16s)(sample0*player.ctrlData.vol[0]/255.0);
samples[pos*2+1]=(Bit16s)(sample1*player.ctrlData.vol[1]/255.0);
}
}
player.channel->AddSamples_s16(len/4,(Bit16s *)player.buffer);
memmove(player.buffer, &player.buffer[len], player.bufLen - len);
player.bufLen -= len;

0 comments on commit a381c8b

Please sign in to comment.