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:
parent
0438430b24
commit
8c29440d39
4 changed files with 91 additions and 4 deletions
|
@ -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;
|
||||
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue