⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aspilib.c

📁 读取音乐光盘磁道为磁盘文件的DLL源码
💻 C
📖 第 1 页 / 共 3 页
字号:
      if ( cdHandles[idx].sm.ccsmAvail )
	{
	  retVal = TRUE;
	  *pNum = ((DWORD)cdHandles[idx].sm.ccsm[10] << 8) + (DWORD)cdHandles[idx].sm.ccsm[11];
	}
      break;

    case CDP_BUFSIZE:
      if ( cdHandles[idx].sm.ccsmAvail )
	{
	  retVal = TRUE;
	  *pNum = ((DWORD)cdHandles[idx].sm.ccsm[12] << 8) + (DWORD)cdHandles[idx].sm.ccsm[13];
	}
      break;

    case CDP_CURRSPEED:
      if ( cdHandles[idx].sm.ccsmAvail )
	{
	  retVal = TRUE;
	  *pNum = ((DWORD)cdHandles[idx].sm.ccsm[14] << 8) + (DWORD)cdHandles[idx].sm.ccsm[15];
	}
      break;

    case CDP_SPM:
      if ( cdHandles[idx].sm.cpmAvail )
	{
	  retVal = TRUE;
	  *pNum = ((DWORD)cdHandles[idx].sm.cpm[4] << 8) + (DWORD)cdHandles[idx].sm.cpm[5];
	}
      break;

    case CDP_FPS:
      if ( cdHandles[idx].sm.cpmAvail )
	{
	  retVal = TRUE;
	  *pNum = ((DWORD)cdHandles[idx].sm.cpm[6] << 8) + (DWORD)cdHandles[idx].sm.cpm[7];
	}
      break;

    case CDP_INACTMULT:
      if ( cdHandles[idx].sm.cpmAvail )
	{
	  retVal = TRUE;
	  *pNum = (DWORD)(cdHandles[idx].sm.cpm[3] & 0x0F);
	}
      break;

    case CDP_MSF:
      retVal = cdHandles[idx].bMSF;
      break;

    case CDP_JITTER:
      retVal = TRUE;
      *pNum = (DWORD)(cdHandles[idx].numCheck);
      break;

    case CDP_OVERLAP:
      retVal = TRUE;
      *pNum = (DWORD)(cdHandles[idx].numOverlap);
      break;

    case CDP_READMODE:
      retVal = TRUE;
      *pNum = (DWORD)(cdHandles[idx].readMode);
      break;

    default:
      break;
    }

  ReleaseMutex( cdMutexes[idx] );
  return retVal;
}


/*
 * Complement to queryCDParms -- used to set values in the various control
 * pages on the CD drive.
 */
BOOL ModifyCDParms( HCDROM hCD, int which, DWORD val )
{
  //SENSEMASK smask;
  //BOOL smRead = FALSE;
  BOOL retVal = FALSE;
  int idx = (int)hCD - 1;

  if ( (idx<0) || (idx>=MAXCDHAND) || !cdHandles[idx].used )
    {
      alErrCode = ALERR_INVHANDLE;
      return FALSE;
    }

  if ( WaitForSingleObject( cdMutexes[idx], TIMEOUT ) != WAIT_OBJECT_0 )
    {
      alErrCode = ALERR_LOCK;
      return SS_ERR;
    }

#if 0
  if ( readCDParameters( hCD, TRUE ) != SS_COMP )
    {
      ReleaseMutex( cdMutexes[idx] );
      return FALSE;
    }
#endif

  switch( which )
    {
    case CDP_CURRSPEED:
      if ( setCDSpeed( hCD, val ) == SS_COMP )
	retVal = TRUE;
      break;

    case CDP_MSF:
      cdHandles[idx].bMSF = (BOOL)val;
      retVal = TRUE;
      break;

    case CDP_JITTER:
      cdHandles[idx].numCheck = (int)val;
      retVal = TRUE;
      break;

    case CDP_OVERLAP:
      cdHandles[idx].numOverlap = (int)val;
      retVal = TRUE;
      break;

    case CDP_READMODE:
      cdHandles[idx].readMode = (int)val;
      retVal = TRUE;
      break;
    }

  ReleaseMutex( cdMutexes[idx] );
  return retVal;
}


/*
 * Speed is specified in KB/sec: 1x == 176, 2x == 353, 4x == 706
 *
 * To set to the maximum allowed speed, specify 0xFFFF.  Attempting to set
 * a speed higher than the allowed maximum speed should not cause an error,
 * but should set the speed at the highest allowed value.
 */
DWORD setCDSpeed( HCDROM hCD, DWORD speed )
{
  DWORD dwStatus;
  HANDLE heventSRB;
  SRB_ExecSCSICmd s;
  int idx = (int)hCD - 1;

  if ( (idx<0) || (idx>=MAXCDHAND) || !cdHandles[idx].used )
    {
      alErrCode = ALERR_INVHANDLE;
      return SS_ERR;
    }

  heventSRB = CreateEvent( NULL, TRUE, FALSE, NULL );

  memset( &s, 0, sizeof( s ) );

  s.SRB_Cmd      = SC_EXEC_SCSI_CMD;
  s.SRB_HaID     = cdHandles[idx].ha;
  s.SRB_Target   = cdHandles[idx].tgt;
  s.SRB_Lun      = cdHandles[idx].lun;
  s.SRB_Flags    = SRB_DIR_OUT | SRB_EVENT_NOTIFY;
  s.SRB_SenseLen = SENSE_LEN;
  s.SRB_CDBLen   = 12;
  s.SRB_PostProc = (LPVOID)heventSRB;
  s.CDBByte[0]   = 0xBB;
  s.CDBByte[2]   = (BYTE)(speed >> 8);
  s.CDBByte[3]   = (BYTE)speed;

  ResetEvent( heventSRB );
  dwStatus = pfnSendASPI32Command( (LPSRB)&s );
  if ( dwStatus == SS_PENDING )
    {
      WaitForSingleObject( heventSRB, DEFWAITLEN );
    }
  CloseHandle( heventSRB );

  if ( s.SRB_Status != SS_COMP )
    {
      alErrCode = ALERR_ASPI;
      alAspiErr = s.SRB_Status;
      CloseHandle( cdMutexes[idx] );
      return SS_ERR;
    }

  return s.SRB_Status;
}


DWORD pauseResumeCD( HCDROM hCD, BOOL bPause )
{
  DWORD dwStatus;
  HANDLE heventSRB;
  SRB_ExecSCSICmd s;
  int idx = (int)hCD - 1;

  if ( (idx<0) || (idx>=MAXCDHAND) || !cdHandles[idx].used )
    {
      alErrCode = ALERR_INVHANDLE;
      return SS_ERR;
    }

  if ( WaitForSingleObject( cdMutexes[idx], TIMEOUT ) != WAIT_OBJECT_0 )
    {
      alErrCode = ALERR_LOCK;
      return SS_ERR;
    }

  heventSRB = CreateEvent( NULL, TRUE, FALSE, NULL );

  memset( &s, 0, sizeof( s ) );

  s.SRB_Cmd      = SC_EXEC_SCSI_CMD;
  s.SRB_HaID     = cdHandles[idx].ha;
  s.SRB_Target   = cdHandles[idx].tgt;
  s.SRB_Lun      = cdHandles[idx].lun;
  s.SRB_Flags    = SRB_EVENT_NOTIFY;
  s.SRB_SenseLen = SENSE_LEN;
  s.SRB_CDBLen   = 10;
  s.SRB_PostProc = (LPVOID)heventSRB;
  s.CDBByte[0]   = 0x4B;
  s.CDBByte[8]   = bPause?0:1;

  ResetEvent( heventSRB );
  dwStatus = pfnSendASPI32Command( (LPSRB)&s );
  if ( dwStatus == SS_PENDING )
    {
      WaitForSingleObject( heventSRB, DEFWAITLEN );
    }
  CloseHandle( heventSRB );

  if ( s.SRB_Status != SS_COMP )
    {
      alErrCode = ALERR_ASPI;
      alAspiErr = s.SRB_Status;
      ReleaseMutex( cdMutexes[idx] );
      return SS_ERR;
    }

  ReleaseMutex( cdMutexes[idx] );
  return s.SRB_Status;
}


DWORD startStopUnit( HCDROM hCD, BOOL bLoEj, BOOL bStart )
{
  DWORD dwStatus;
  HANDLE heventSRB;
  SRB_ExecSCSICmd s;
  int idx = (int)hCD - 1;

  if ( (idx<0) || (idx>=MAXCDHAND) || !cdHandles[idx].used )
    {
      alErrCode = ALERR_INVHANDLE;
      return SS_ERR;
    }
 
  if ( WaitForSingleObject( cdMutexes[idx], TIMEOUT ) != WAIT_OBJECT_0 )
    {
      alErrCode = ALERR_LOCK;
      return SS_ERR;
    }

  heventSRB = CreateEvent( NULL, TRUE, FALSE, NULL );

  memset( &s, 0, sizeof( s ) );

  s.SRB_Cmd      = SC_EXEC_SCSI_CMD;
  s.SRB_HaID     = cdHandles[idx].ha;
  s.SRB_Target   = cdHandles[idx].tgt;
  s.SRB_Lun      = cdHandles[idx].lun;
  s.SRB_Flags    = SRB_EVENT_NOTIFY;
  s.SRB_SenseLen = SENSE_LEN;
  s.SRB_CDBLen   = 6;
  s.SRB_PostProc = (LPVOID)heventSRB;
  s.CDBByte[0]   = 0x1B;
  s.CDBByte[4]  |= bLoEj?0x02:0x00;
  s.CDBByte[4]  |= bStart?0x01:0x00;

  ResetEvent( heventSRB );
  dwStatus = pfnSendASPI32Command( (LPSRB)&s );
  if ( dwStatus == SS_PENDING )
    {
      WaitForSingleObject( heventSRB, DEFWAITLEN );
    }
  CloseHandle( heventSRB );

  if ( s.SRB_Status != SS_COMP )
    {
      alErrCode = ALERR_ASPI;
      alAspiErr = s.SRB_Status;
      ReleaseMutex( cdMutexes[idx] );
      return SS_ERR;
    }

  ReleaseMutex( cdMutexes[idx] );
  return s.SRB_Status;
}


/****************************************************************
 * GetAspiLibError
 *
 * Used after functions return SS_ERR to get more specific error
 * information.  If it returns AL_ERRASPI, call getAspiLibAspiError
 * to get the actual status code returned by the calls to the ASPI
 * manager.  After reading, the error code is cleared.
 *
 ****************************************************************/
int GetAspiLibError( void )
{
  int retVal;

  retVal = alErrCode;
  alErrCode = ALERR_NOERROR;

  return retVal;
}


/****************************************************************
 * GetAspiLibAspiError
 *
 * Returns the last error completion code from the ASPI manager.
 * After reading, the error code is cleared.
 *
 ****************************************************************/
BYTE GetAspiLibAspiError( void )
{
  BYTE retVal;

  retVal = alAspiErr;
  alAspiErr = SS_COMP;

  return retVal;
}


/****************************************************************
 * GetCDId
 *
 * Generates an identifier string for the CD drive identified by
 * hCD
 *
 ****************************************************************/
DWORD  GetCDId( HCDROM hCD, char *buf, int maxBuf )
{
  int idx = (int)hCD - 1;
  CDREC cd;

  if ( (idx<0) || (idx>=MAXCDHAND) || !cdHandles[idx].used )
    {
      alErrCode = ALERR_INVHANDLE;
      return SS_ERR;
    }

  if ( !buf )
    {
      alErrCode = ALERR_BUFPTR;
      return SS_ERR;
    }

  if ( WaitForSingleObject( cdMutexes[idx], TIMEOUT ) != WAIT_OBJECT_0 )
    {
      alErrCode = ALERR_LOCK;
      return SS_ERR;
    }

  memset( &cd, 0, sizeof(cd) );
  GetDriveInfo( cdHandles[idx].ha, cdHandles[idx].tgt, cdHandles[idx].lun,
		&cd );
  if ( strlen( cd.id ) > maxBuf-1 )
    {
      alErrCode = ALERR_BUFTOOSMALL;
      strncpy( buf, cd.id, maxBuf );
      buf[maxBuf-1] = '\0';
      ReleaseMutex( cdMutexes[idx] );
      return SS_ERR;
    }
  else
    strcpy( buf, cd.id );

  ReleaseMutex( cdMutexes[idx] );
  return SS_COMP;
}


/*
 * Returns TRUE if the overlap buffer is located in the track buffer.  The
 * track buffer startOffset is adjusted to reflect where in the buffer the
 * aligned data begins.  numFrames and len are also adjusted to reflect the
 * number of complete frames are contained in the buffer.
 */
int jitterAdjust( LPTRACKBUF tbuf, LPTRACKBUF tover, int checkFrames )
{
  int i;
  int max;
  int bFound = 0;
  BYTE *p;
  int checkLen = checkFrames * 2352;

  max = tbuf->len - checkLen;

  if ( tover->len == 0 )
    return 1;

  p = &tover->buf[tover->startOffset];

  bFound = 0;
  for( i = 0; i < max; i++ )
    {
      if ( compBuf( p, &(tbuf->buf[i]), checkLen ) )
	{
	  tbuf->startOffset = i + checkLen;
	  tbuf->len -= (i + checkLen);
	  tbuf->startFrame = tover->startFrame + checkFrames;
	  i = max + 1;
	  bFound = -1;
	}
    }

  /* adjust frame count and crop length */
  tbuf->numFrames = tbuf->len / 2352;
  tbuf->len = 2352 * tbuf->numFrames;

  //  return (tbuf->startOffset == 0);
  return bFound;
}


/*
 * Reads CD-DA audio, implementing jitter correction.  tOver is used to align
 * the current read, if possible.  After a successful read, numOverlap frames
 * are copied to tOver.
 */
DWORD ReadCDAudioLBAEx( HCDROM hCD, LPTRACKBUF t, LPTRACKBUF tOver )
{
  DWORD retVal;
  int idx = (int)hCD - 1;
  int j, o;
  unsigned char *pOverAddr;
  BOOL bJitterCorr;

  if ( (idx<0) || (idx>=MAXCDHAND) )
    {
      alErrCode = ALERR_INVHANDLE;
      return SS_ERR;
    }

  retVal = WaitForSingleObject( cdMutexes[idx], TIMEOUT );
  if ( retVal != WAIT_OBJECT_0 )
    {
      alErrCode = ALERR_LOCK;
      return SS_ERR;
    }

  if ( !cdHandles[idx].used )
    {
      alErrCode = ALERR_INVHANDLE;
      ReleaseMutex( cdMutexes[idx] );
      return SS_ERR;
    }

  j = cdHandles[idx].numCheck;
  o = cdHandles[idx].numOverlap;

  // check that the overlap buffer is large enough -- if not, disable
  // jitter correction.  We may want to eventually throw an error
  bJitterCorr = ((tOver->maxLen / 2352) >= o);

#ifdef _DEBUG
  dbprintf( "akrip32: ReadCDAudioLBAEx( t->startFrame == %08X, tOver->startFrame == %08X, j == %d )", t->startFrame, tOver->startFrame, j );
  dbprintf( "       : t: %08X %d %d", t->startFrame, t->numFrames, t->len );
  dbprintf( "       : tOver: %08X %d %d", tOver->startFrame, tOver->numFrames, tOver->len );
#endif

  // adjust the starting address of the read if necessary
  if ( bJitterCorr && tOver->startFrame && tOver->numFrames && tOver->len )
    {
      // is this tOver from the last sequential read?
      if ( tOver->startFrame == (t->startFrame - j) )
	{
#ifdef _DEBUG
	  dbprintf( "Rolling back the read..." );
#endif
	  t->startFrame -= o;
	}
      else
	{
#ifdef _DEBUG
	  dbprintf( "Zeroing out the overlap!" );
#endif
	  tOver->len = tOver->startFrame = tOver->numFrames = 0;
	}
    }

  retVal = cdHandles[idx].pfnRead( hCD, t );

  if ( (retVal == SS_COMP) && bJitterCorr )
    {
#ifdef _DEBUG
      dbprintf( "akrip32: ReadCDAudioLBAEx: read itself OK" );
#endif
      j = cdHandles[idx].numCheck;
      if ( !jitterAdjust( t, tOver, j ) )
	{
#ifdef _DEBUG
	  dbprintf( "akrip32: ... jitterAdjust failed!" );
#endif
	  alErrCode = ALERR_JITTER;
	  ReleaseMutex( cdMutexes[idx] );
	  return SS_ERR;
	}
#ifdef _DEBUG
      dbprintf( "akrip32: ... after successful jitter adjust" );
#endif
      pOverAddr = &(t->buf[2352*(t->numFrames-j)+t->startOffset]);
      memcpy( tOver->buf, pOverAddr, 2352*j );

      tOver->startFrame = t->startFrame + t->numFrames - j;
      tOver->numFrames = j;
      tOver->len = 2352 * j;
      tOver->startOffset = 0;
    }
#ifdef _DEBUG
  else
    dbprintf( "akrip32: ReadCDAudioLBAEx: read failed" );
#endif

  ReleaseMutex( cdMutexes[idx] );

#ifdef _DEBUG
  dbprintf( "akrip32: readCDAudioLBAEx: returning %04X", retVal );
#endif

  return retVal;
}


/********************************************************************
 * compBuf
 *
 * Compares two buffers up to n bytes, returning 1 if they contain the
 * same data, or zero if they are different.
 *
 ********************************************************************/
int compBuf( BYTE *b1, BYTE *b2, int n )
{
#if 0
  int i;

  for( i = 0; i < n; i++ )
    if ( b1[i] != b2[i] )
      {
	return 0;
      }

  return 1;
#else
  return !memcmp( b1, b2, n );
#endif
}



DWORD GetAKRipDllVersion( void )
{
  DWORD retVal;

  retVal = (DWORD)( (((WORD)MAJVER)<<16) | (WORD)MINVER );
  return retVal;
}


void dbprintf( char *fmt, ... )
{
  char buf[512];
  va_list arg;

  va_start( arg, fmt );

  vsprintf( buf, fmt, arg );
  OutputDebugString( buf );

  va_end( arg );
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -