1
0
Fork 0

Add audio volume control for mscdex. Implemented it in images and win32ioctl. Others are still open. Thanks ripsaw.

Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@3631
This commit is contained in:
Peter Veenstra 2010-08-07 18:32:39 +00:00
parent 0438430b24
commit 8c29440d39
4 changed files with 91 additions and 4 deletions

View file

@ -31,6 +31,11 @@ typedef struct SMSF {
unsigned char fr;
} TMSF;
typedef struct SCtrl {
Bit8u out[4]; // output channel
Bit8u vol[4]; // channel volume
} TCtrl;
extern int CDROM_GetMountType(char* path, int force);
class CDROM_Interface
@ -52,6 +57,7 @@ public:
virtual bool PlayAudioSector (unsigned long start,unsigned long len) = 0;
virtual bool PauseAudio (bool resume) = 0;
virtual bool StopAudio (void) = 0;
virtual void ChannelControl (TCtrl ctrl) = 0;
virtual bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num) = 0;
@ -76,6 +82,7 @@ public:
virtual bool PlayAudioSector (unsigned long start,unsigned long len);
virtual bool PauseAudio (bool resume);
virtual bool StopAudio (void);
virtual void ChannelControl (TCtrl ctrl) { return; };
virtual bool ReadSectors (PhysPt /*buffer*/, bool /*raw*/, unsigned long /*sector*/, unsigned long /*num*/) { return false; };
virtual bool LoadUnloadMedia (bool unload);
@ -101,6 +108,7 @@ public:
bool PlayAudioSector (unsigned long /*start*/,unsigned long /*len*/) { return true; };
bool PauseAudio (bool /*resume*/) { return true; };
bool StopAudio (void) { return true; };
void ChannelControl (TCtrl ctrl) { return; };
bool ReadSectors (PhysPt /*buffer*/, bool /*raw*/, unsigned long /*sector*/, unsigned long /*num*/) { return true; };
bool LoadUnloadMedia (bool /*unload*/) { return true; };
};
@ -166,6 +174,7 @@ public:
bool PlayAudioSector (unsigned long start,unsigned long len);
bool PauseAudio (bool resume);
bool StopAudio (void);
void ChannelControl (TCtrl ctrl);
bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num);
bool LoadUnloadMedia (bool unload);
bool ReadSector (Bit8u *buffer, bool raw, unsigned long sector);
@ -188,6 +197,8 @@ static struct imagePlayer {
int targetFrame;
bool isPlaying;
bool isPaused;
bool ctrlUsed;
TCtrl ctrlData;
} player;
void ClearTracks();
@ -234,6 +245,7 @@ public:
bool PlayAudioSector (unsigned long start,unsigned long len);
bool PauseAudio (bool resume);
bool StopAudio (void);
void ChannelControl (TCtrl ctrl) { return; };
bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num);
@ -284,6 +296,7 @@ public:
bool PlayAudioSector (unsigned long start,unsigned long len);
bool PauseAudio (bool resume);
bool StopAudio (void);
void ChannelControl (TCtrl ctrl);
bool ReadSector (Bit8u *buffer, bool raw, unsigned long sector);
bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num);
@ -338,6 +351,8 @@ private:
int targetFrame;
bool isPlaying;
bool isPaused;
bool ctrlUsed;
TCtrl ctrlData;
} player;
};

View file

@ -131,7 +131,7 @@ int CDROM_Interface_Image::AudioFile::getLength()
int CDROM_Interface_Image::refCount = 0;
CDROM_Interface_Image* CDROM_Interface_Image::images[26];
CDROM_Interface_Image::imagePlayer CDROM_Interface_Image::player = {
NULL, NULL, NULL, {0}, 0, 0, 0, false, false };
NULL, NULL, NULL, {0}, 0, 0, 0, false, false, false, {0} };
CDROM_Interface_Image::CDROM_Interface_Image(Bit8u subUnit)
@ -259,6 +259,12 @@ bool CDROM_Interface_Image::StopAudio(void)
return true;
}
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;
}
bool CDROM_Interface_Image::ReadSectors(PhysPt buffer, bool raw, unsigned long sector, unsigned long num)
{
int sectorSize = raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE;
@ -336,6 +342,16 @@ void CDROM_Interface_Image::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);
}
}
#if defined(WORDS_BIGENDIAN)
player.channel->AddSamples_s16_nonnative(len/4,(Bit16s *)player.buffer);
#else

View file

@ -175,7 +175,7 @@ bool CDROM_Interface_Ioctl::mci_CDPosition(int *position) {
CDROM_Interface_Ioctl::dxPlayer CDROM_Interface_Ioctl::player = {
NULL, NULL, NULL, 0, 0, 0, 0, 0, false, false };
NULL, NULL, NULL, {0}, 0, 0, 0, false, false, false, {0} };
CDROM_Interface_Ioctl::CDROM_Interface_Ioctl(cdioctl_cdatype ioctl_cda) {
pathname[0] = 0;
@ -462,6 +462,12 @@ bool CDROM_Interface_Ioctl::StopAudio(void) {
return bStat>0;
}
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;
}
bool CDROM_Interface_Ioctl::LoadUnloadMedia(bool unload) {
BOOL bStat;
DWORD byteCount;
@ -553,6 +559,16 @@ 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;

View file

@ -152,6 +152,7 @@ private:
bool locked; // drive locked ?
bool lastResult; // last operation success ?
Bit32u volumeSize; // for media change
TCtrl audioCtrl; // audio channel control
} TDriveInfo;
Bit16u defaultBufSeg;
@ -160,6 +161,9 @@ private:
public:
Bit16u rootDriverHeaderSeg;
bool ChannelControl (Bit8u subUnit, TCtrl ctrl);
bool GetChannelControl (Bit8u subUnit, TCtrl& ctrl);
};
CMscdex::CMscdex(void) {
@ -391,6 +395,11 @@ int CMscdex::AddDrive(Bit16u _drive, char* physicalPath, Bit8u& subUnit)
subUnit = (Bit8u)numDrives;
}
numDrives++;
// init channel control
for (Bit8u chan=0;chan<4;chan++) {
dinfo[subUnit].audioCtrl.out[chan]=chan;
dinfo[subUnit].audioCtrl.vol[chan]=0xff;
}
// stop audio
StopAudio(subUnit);
return result;
@ -463,7 +472,7 @@ bool CMscdex::PlayAudioSector(Bit8u subUnit, Bit32u sector, Bit32u length)
if (subUnit>=numDrives) return false;
// If value from last stop is used, this is meant as a resume
// better start using resume command
if (dinfo[subUnit].audioPaused && (sector==dinfo[subUnit].audioStart)) {
if (dinfo[subUnit].audioPaused && (sector==dinfo[subUnit].audioStart) && (dinfo[subUnit].audioEnd!=0)) {
dinfo[subUnit].lastResult = cdrom[subUnit]->PauseAudio(true);
} else
dinfo[subUnit].lastResult = cdrom[subUnit]->PlayAudioSector(sector,length);
@ -800,6 +809,7 @@ Bit32u CMscdex::GetDeviceStatus(Bit8u subUnit)
(dinfo[subUnit].locked << 1) | // Drive is locked ?
(1<<2) | // raw + cooked sectors
(1<<4) | // Can read sudio
(1<<8) | // Can control audio
(1<<9) | // Red book & HSG
((!media) << 11); // Drive is empty ?
return status;
@ -864,6 +874,22 @@ void CMscdex::InitNewMedia(Bit8u subUnit) {
}
}
bool CMscdex::ChannelControl(Bit8u subUnit, TCtrl ctrl) {
if (subUnit>=numDrives) return false;
// adjust strange channel mapping
if (ctrl.out[0]>1) ctrl.out[0]=0;
if (ctrl.out[1]>1) ctrl.out[1]=1;
dinfo[subUnit].audioCtrl=ctrl;
cdrom[subUnit]->ChannelControl(ctrl);
return true;
}
bool CMscdex::GetChannelControl(Bit8u subUnit, TCtrl& ctrl) {
if (subUnit>=numDrives) return false;
ctrl=dinfo[subUnit].audioCtrl;
return true;
}
static CMscdex* mscdex = 0;
static PhysPt curReqheaderPtr = 0;
@ -893,6 +919,14 @@ static Bit16u MSCDEX_IOCTL_Input(PhysPt buffer,Bit8u drive_unit) {
return 0x03; // invalid function
}
}break;
case 0x04 : /* Audio Channel control */
TCtrl ctrl;
if (!mscdex->GetChannelControl(drive_unit,ctrl)) return 0x01;
for (Bit8u chan=0;chan<4;chan++) {
mem_writeb(buffer+chan*2+1,ctrl.out[chan]);
mem_writeb(buffer+chan*2+2,ctrl.vol[chan]);
}
break;
case 0x06 : /* Get Device status */
mem_writed(buffer+1,mscdex->GetDeviceStatus(drive_unit));
break;
@ -984,7 +1018,13 @@ static Bit16u MSCDEX_IOCTL_Optput(PhysPt buffer,Bit8u drive_unit) {
if (!mscdex->LoadUnloadMedia(drive_unit,true)) return 0x02;
break;
case 0x03: //Audio Channel control
MSCDEX_LOG("MSCDEX: Audio Channel Control used. Not handled. Faking succes!");
TCtrl ctrl;
for (Bit8u chan=0;chan<4;chan++) {
ctrl.out[chan]=mem_readb(buffer+chan*2+1);
ctrl.vol[chan]=mem_readb(buffer+chan*2+2);
}
if (!mscdex->ChannelControl(drive_unit,ctrl)) return 0x01;
break;
case 0x01 : // (un)Lock door
// do nothing -> report as success
break;