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

📄 acm.c

📁 书中的主要程序文件。在打开例题的.dsw文件后,请读者在 tools菜单下的 Options 的 Directories 标签中选择 Executable files
💻 C
📖 第 1 页 / 共 5 页
字号:
            padft->cbFilterSize     = sizeof(ECHOWAVEFILTER);
            padft->fdwSupport       = ACMDRIVERDETAILS_SUPPORTF_FILTER;
            padft->cStandardFilters = ACM_DRIVER_MAX_ECHO_FILTERS;

            uIds = IDS_ACM_DRIVER_TAG_NAME_ECHO;
            break;

        default:
            return (ACMERR_NOTPOSSIBLE);
    }


    //
    //  return only the requested info
    //
    //  the ACM will guarantee that the ACMFILTERTAGDETAILS structure
    //  passed is at least large enough to hold the base structure
    //
    padft->cbStruct = min(padft->cbStruct, sizeof(*padft));

    LoadStringACM(pdi->hinst, uIds, padft->szFilterTag, SIZEOFACMSTR(padft->szFilterTag));


    //
    //
    //
    return (MMSYSERR_NOERROR);
} // acmdFilterTagDetails()


//--------------------------------------------------------------------------;
//  
//  UINT acmdFilterDetailsToString
//  
//  Description:
//      This function has a special UNICODE string implementation for common
//      binary ACMs between Chicago and Daytona.
//  
//  Arguments:
//      LPWAVEFILTER pwf:
//  
//      LPTSTR szFilter:
//  
//  Return (UINT):
//  
//  
//--------------------------------------------------------------------------;

#if defined(WIN32) && !defined(UNICODE)

UINT FNLOCAL acmdFilterDetailsToString
(
    PDRIVERINSTANCE         pdi,
    LPWAVEFILTER            pwf,
    LPWSTR                  szFilter
)
{
    UINT                u;
    CHAR                ach1[ACMFILTERDETAILS_FILTER_CHARS];
    CHAR                ach2[ACMFILTERDETAILS_FILTER_CHARS];
    LPVOLUMEWAVEFILTER  pwfVol;
    LPECHOWAVEFILTER    pwfEcho;


    if( !szFilter ) {
        return 0L;
    }
    
    *szFilter = L'\0';
    if (volumeIsValidFilter(pwf))
    {
        pwfVol = (LPVOLUMEWAVEFILTER)pwf;
        LoadStringA(pdi->hinst, IDS_ACM_DRIVER_FORMAT_VOLUME, ach1, SIZEOF(ach1));
        u = wsprintfA( ach2, ach1,
                 (WORD)(((pwfVol->dwVolume * 100) / 0x10000)) );
    	MultiByteToWideChar( GetACP(), 0, ach2, u+1, szFilter,
                                        ACMFILTERDETAILS_FILTER_CHARS );
        return( u );
    }
    else if (echoIsValidFilter(pwf))
    {
        pwfEcho = (LPECHOWAVEFILTER)pwf;
        LoadStringA(pdi->hinst, IDS_ACM_DRIVER_FORMAT_ECHO, ach1, SIZEOF(ach1));
        u = wsprintfA( ach2, ach1,
                 (WORD)(((pwfEcho->dwVolume * 100) / 0x10000)),
                     (WORD)pwfEcho->dwDelay );
    	MultiByteToWideChar( GetACP(), 0, ach2, u+1, szFilter,
                                        ACMFILTERDETAILS_FILTER_CHARS );
        return( u );
    }
    return ( 0 );
} // acmdFilterDetailsToString()

#else

UINT FNLOCAL acmdFilterDetailsToString
(
    PDRIVERINSTANCE         pdi,
    LPWAVEFILTER            pwf,
    LPTSTR                  szFilter
)
{
    UINT                u;
    TCHAR               ach[ACMFILTERDETAILS_FILTER_CHARS];
    LPVOLUMEWAVEFILTER  pwfVol;
    LPECHOWAVEFILTER    pwfEcho;


    if( !szFilter ) {
        return 0L;
    }
    
    *szFilter = TEXT('\0');
    if (volumeIsValidFilter(pwf))
    {
        pwfVol = (LPVOLUMEWAVEFILTER)pwf;
        LoadString(pdi->hinst, IDS_ACM_DRIVER_FORMAT_VOLUME, ach, SIZEOF(ach));
        u = wsprintf( szFilter, ach,
                 (WORD)(((pwfVol->dwVolume * 100) / 0x10000)) );
        return( u );
    }
    else if (echoIsValidFilter(pwf))
    {
        pwfEcho = (LPECHOWAVEFILTER)pwf;
        LoadString(pdi->hinst, IDS_ACM_DRIVER_FORMAT_ECHO, ach, SIZEOF(ach));
        u = wsprintf( szFilter, ach,
                 (WORD)(((pwfEcho->dwVolume * 100) / 0x10000)),
                     (WORD)pwfEcho->dwDelay );
        return( u );
    }
    return ( 0 );
} // acmdFilterDetailsToString()

#endif



//--------------------------------------------------------------------------;
//  
//  LRESULT acmdFilterDetails
//  
//  Description:
//  
//  
//  Arguments:
//      PDRIVERINSTANCE pdi: Pointer to private ACM driver instance structure.
//      This structure is [optionally] allocated during the DRV_OPEN message
//      which is handled by the acmdDriverOpen function.
//
//      LPACMFILTERDETAILS padf:
//
//      DWORD fdwDetails:
//  
//  Return (LRESULT):
//
//
//--------------------------------------------------------------------------;

LRESULT FNLOCAL acmdFilterDetails
(
    PDRIVERINSTANCE         pdi,
    LPACMFILTERDETAILS      padf,
    DWORD                   fdwDetails
)
{
    UINT                uFilterIndex;
    LPWAVEFILTER        pwf;
    LPVOLUMEWAVEFILTER  pwfVolume;
    LPECHOWAVEFILTER    pwfEcho;
    UINT                u;

    pwf = padf->pwfltr;

    //
    //
    //
    //
    //
    switch (ACM_FILTERDETAILSF_QUERYMASK & fdwDetails)
    {
        case ACM_FILTERDETAILSF_INDEX:
            //
            //  enumerate by index
            //
            //  for this converter, this is more code than necessary... just
            //  verify that the filter tag is something we know about
            //
            switch (padf->dwFilterTag)
            {
                case WAVE_FILTER_VOLUME:
                    if (ACM_DRIVER_MAX_VOLUME_FILTERS <= padf->dwFilterIndex)
                        return (ACMERR_NOTPOSSIBLE);

                    pwfVolume        = (LPVOLUMEWAVEFILTER)padf->pwfltr;
                    pwf->cbStruct    = sizeof(VOLUMEWAVEFILTER);
                    pwf->dwFilterTag = WAVE_FILTER_VOLUME;
                    pwf->fdwFilter   = 0;
                    pwfVolume->dwVolume = gdwFilterIndexToVolume[(UINT)padf->dwFilterIndex];
                    break;

                case WAVE_FILTER_ECHO:
                    if (ACM_DRIVER_MAX_ECHO_FILTERS <= padf->dwFilterIndex)
                        return (ACMERR_NOTPOSSIBLE);

                    pwfEcho             = (LPECHOWAVEFILTER)padf->pwfltr;
                    pwf->cbStruct       = sizeof(ECHOWAVEFILTER);
                    pwf->dwFilterTag    = WAVE_FILTER_ECHO;
                    pwf->fdwFilter      = 0;

                    uFilterIndex = (UINT)padf->dwFilterIndex;

                    u = uFilterIndex / ACM_DRIVER_NUM_DELAY;
                    pwfEcho->dwVolume = gdwFilterIndexToEchoVol[u]; 

                    u = uFilterIndex % ACM_DRIVER_NUM_DELAY;
                    pwfEcho->dwDelay = gdwFilterIndexToDelay[u]; 
                    break;

                default:
                    return (ACMERR_NOTPOSSIBLE);
            }

        case ACM_FILTERDETAILSF_FILTER:
            //
            //  must want to verify that the filter passed in is supported
            //  and return a string description...
            //
            switch (pwf->dwFilterTag)
            {
                case WAVE_FILTER_VOLUME:
                    if (!volumeIsValidFilter(pwf))
                        return (ACMERR_NOTPOSSIBLE);

                    break;

                case WAVE_FILTER_ECHO:
                    if (!echoIsValidFilter(pwf))
                        return (ACMERR_NOTPOSSIBLE);

                    break;

                default:
                    return (ACMERR_NOTPOSSIBLE);
            }
            break;


        default:
            //
            //  don't know how to do the query type passed--return 'not
            //  supported'.
            //
            return (MMSYSERR_NOTSUPPORTED);
    }
    

    //
    //  return only the requested info
    //
    //  the ACM will guarantee that the ACMFILTERDETAILS structure
    //  passed is at least large enough to hold everything in the base
    //  filter details structure...
    //
    //  get a nice friendly string for the filter we made
    //
    acmdFilterDetailsToString(pdi, pwf, padf->szFilter);


    //
    //  if they asked for more info than we know how to return, then
    //  set size of valid structure bytes to correct value.
    //
    padf->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_FILTER;
    padf->cbStruct   = min(padf->cbStruct, sizeof(*padf));

    //
    //
    //
    return (MMSYSERR_NOERROR);
} // acmdFilterDetails()



//==========================================================================;
//
//
//
//
//==========================================================================;

//--------------------------------------------------------------------------;
//
//  LRESULT acmdStreamOpen
//
//  Description:
//      This function handles the ACMDM_STREAM_OPEN message. This message
//      is sent to initiate a new conversion stream. This is usually caused
//      by an application calling acmStreamOpen. If this function is
//      successful, then one or more ACMDM_STREAM_CONVERT messages will be
//      sent to convert individual buffers (user calls acmStreamConvert).
//
//      Note that an ACM driver will not receive open requests for ASYNC
//      or FILTER operations unless the ACMDRIVERDETAILS_SUPPORTF_ASYNC
//      or ACMDRIVERDETAILS_SUPPORTF_FILTER flags are set in the 
//      ACMDRIVERDETAILS structure. There is no need for the driver to
//      check for these requests unless it sets those support bits.
//
//      If the ACM_STREAMOPENF_QUERY flag is set in the padsi->fdwOpen
//      member, then no resources should be allocated. Just verify that
//      the conversion request is possible by this driver and return the
//      appropriate error (either ACMERR_NOTPOSSIBLE or MMSYSERR_NOERROR).
//      The driver will NOT receive an ACMDM_STREAM_CLOSE for queries.
//
//      If the ACM_STREAMOPENF_NONREALTIME bit is NOT set, then conversion
//      must be done in 'real-time'. This is a tough one to describe
//      exactly. If the driver may have trouble doing the conversion without
//      breaking up the audio, then a Configururation dialog might be used
//      to allow the user to specify whether the real-time conversion 
//      request should be succeeded. DO NOT SUCCEED THE CALL UNLESS YOU
//      ACTUALLY CAN DO REAL-TIME CONVERSIONS! There may be another driver
//      installed that can--so if you succeed the call you are hindering
//      the performance of the user's system! Don't be foolish.
//
//  Arguments:
//      PDRIVERINSTANCE pdi: Pointer to private ACM driver instance structure.
//      This structure is [optionally] allocated during the DRV_OPEN message
//      which is handled by the acmdDriverOpen function.
//
//      LPACMDRVSTREAMINSTANCE padsi: Pointer to instance data for the
//      conversion stream. This structure was allocated by the ACM and
//      filled with the most common instance data needed for conversions.
//      This structure will be passed back to all future stream messages
//      if the open succeeds. The information in this structure will never
//      change during the lifetime of the stream--so it is not necessary
//      to re-verify the information referenced by this structure.
//
//  Return (LRESULT):
//      The return value is zero (MMSYSERR_NOERROR) if this function
//      succeeds with no errors. The return value is a non-zero error code
//      if the function fails.
//
//      A driver should return ACMERR_NOTPOSSIBLE if the conversion cannot
//      be performed due to incompatible source and destination formats.
//
//      A driver should return MMSYSERR_NOTSUPPORTED if the conversion
//      cannot be performed in real-time and the request does not specify
//      the ACM_STREAMOPENF_NONREALTIME flag.
//
//--------------------------------------------------------------------------;

LRESULT FNLOCAL acmdStreamOpen
(
    PDRIVERINSTANCE         pdi,
    LPACMDRVSTREAMINSTANCE  padsi
)
{
    PSTREAMINSTANCE     psi;
    LPWAVEFORMATEX      pwfxSrc;
    LPWAVEFORMATEX      pwfxDst;
    LPWAVEFILTER        pwfltr;
    BOOL                fRealTime;


    //
    //
    //
    pwfxSrc = padsi->pwfxSrc;
    pwfxDst = padsi->pwfxDst;
    pwfltr  = padsi->pwfltr;

    fRealTime = (0 == (padsi->fdwOpen & ACM_STREAMOPENF_NONREALTIME));

    if( fRealTime )
    {
    	//
        //  We only do non-realtime conversions.
    	//  Return failure if we are asked for realtime.
        //
        return (ACMERR_NOTPOSSIBLE);
    }

    
    //
    //  the most important condition to check before doing anything else
    //  is that this ACM driver can actually perform the conversion we are
    //  being opened for. this check should fail as quickly as possible
    //  if the conversion is not possible by this driver.
    //
    //  it is VERY important to fail quickly so the ACM can attempt to 
    //  find a driver that is suitable for the conversion. also note that
    //  the ACM may call this driver several times with slightl

⌨️ 快捷键说明

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