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

📄 output.cpp

📁 pxa270平台 windows mobile 5.2 wm9713 触摸屏+音频驱动
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//-----------------------------------------------------------------------------
// Copyright (c) Wolfson Microelectronics plc.  All rights reserved.
//
// This software as well as any related documentation is furnished under 
// license and may only be used or copied in accordance with the terms of the 
// license. The information in this file is furnished for informational use 
// only, is subject to change without notice, and should not be construed as 
// a commitment by Wolfson Microelectronics plc. Wolfson Microelectronics plc
// assumes no responsibility or liability for any errors or inaccuracies that
// may appear in this document or any software that may be provided in
// association with this document. 
//
// Except as permitted by such license, no part of this document may be 
// reproduced, stored in a retrieval system, or transmitted in any form or by 
// any means without the express written consent of Wolfson Microelectronics plc. 
//
// $Id: output.cpp 3178 2006-05-02 10:24:00Z ian $
//
// This file contains the code specific to output streams for the WaveDev2
// driver for Wolfson codecs.
//
// Warning:
//  This driver is specifically written for Wolfson Audio Codecs.  It is
//  not a general audio CODEC device driver.
//-----------------------------------------------------------------------------

//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
// -----------------------------------------------------------------------------
//
//      THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
//      ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
//      THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//      PARTICULAR PURPOSE.
//
// -----------------------------------------------------------------------------
#include "wavemain.h"

//-----------------------------------------------------------------------------
// Member function:    Open
//
// Opens an output stream context.
//
// Parameters:
//		pDeviceContext  The device context to use.
//      lpWOD           The WaveOpen descriptor passed to the driver.
//      dwFlags         The flags passed to the driver.
//
// Returns:     HRESULT
//		Status returned from WaveStreamContext::Open
//-----------------------------------------------------------------------------
HRESULT OutputStreamContext::Open(DeviceContext *pDeviceContext, LPWAVEOPENDESC lpWOD, DWORD dwFlags)
{
    HRESULT Result;

    Result = WaveStreamContext::Open(pDeviceContext, lpWOD, dwFlags);

    if (Result==MMSYSERR_NOERROR)
    {
        // Note: Output streams should be initialized in the run state.
        Run();
    }

    return Result;
}

//-----------------------------------------------------------------------------
// Member function:    Reset
//
// Reset the stream to a known state.
//
// Parameters:
//		none
//
// Returns:     DWORD
//		Status returned from WaveStreamContext::Reset.
//-----------------------------------------------------------------------------
DWORD OutputStreamContext::Reset()
{
    HRESULT Result;

    Result = WaveStreamContext::Reset();

    if (Result==MMSYSERR_NOERROR)
    {
        // Note: Output streams should be reset to the run state.
        Run();
    }

    return Result;
};

//-----------------------------------------------------------------------------
// Member function:    SetRate
//
// Init m_DeltaT with (SampleRate/HWSampleRate) calculated in the appropriate fixed point form.
// Note that we need to hold the result in a 64-bit value until we're done shifting,
// since the result of the multiply will overflow 32 bits for sample rates greater than
// or equal to the hardware's sample rate.
//
// Parameters:
//       dwMultiplier    Multiplier in 16.16 format (i.e. 0x1000 => x 1.000)
//
// Returns:     DWORD
//      Always MMSYSERR_NOERROR
//-----------------------------------------------------------------------------
DWORD OutputStreamContext::SetRate(DWORD dwMultiplier)
{
    UINT64 Delta;

    m_dwMultiplier = dwMultiplier;

    // The following code makes a bunch of assumptions on why we don't overflow a 64-bit value:
    // nSamplesPerSec is < 20 bits (e.g. no input data rates greater than ~1 MHz!)
    // m_dwMultiplier is < 24 bits (e.g. no speedup beyond 256x)
    // INVSAMPLERATE is < 20 bits (e.g. no playback rates less than 4kHz)

    Delta = (m_WaveFormat.nSamplesPerSec * m_dwMultiplier);
    Delta = (Delta * InverseSampleRate());    // < Note: These two lines are out of order to preserve accuracy
    Delta >>= 16;                             // <
    Delta >>= DELTAINT;  // Convert to x.x format (e.g. 17.15)

    m_DeltaT = (DWORD)Delta;

    return MMSYSERR_NOERROR;
}

//-----------------------------------------------------------------------------
// Member function:    OutputStreamContext::Render
//
// This function renders the next buffer-full of data to the given buffer.
// This is a parent function - each different type of stream context has its
// own Render2 function which handles the differences.  This function handles
// the stuff common to all output streams.
//
// Originally, this code used to be in each renderer, and each one would call
// GetNextBuffer as needed.  Pulling this code out of each low level renderer
// allows the inner loop to be in a leaf routine (ie no subroutine calls out
// of that routine), which helps the compiler optimize the inner loop.
//
// Parameters:
//      pBuffer     the start of the output buffer.
//      pBufferEnd  the end of the output buffer.
//      pBufferLast the current high-water mark in the buffer.  This is the
//                  furthest point in the buffer which has had data rendered
//                  into it.
//
// Returns:     PBYTE
//      The end point rendered to by this stream.  This is used to update
//      pBufferLast when rendering several streams to the same buffer.
//-----------------------------------------------------------------------------
PBYTE WaveStreamContext::Render(PBYTE pBuffer, PBYTE pBufferEnd, PBYTE pBufferLast)
{
    if (!m_bRunning || !m_lpCurrData)
    {
        return pBuffer;
    }

    while (pBuffer < pBufferEnd)
    {
        while (m_lpCurrData>=m_lpCurrDataEnd)
        {
            if (!GetNextBuffer())
            {
                return pBuffer;
            }
        }

        _try
        {
            pBuffer = Render2(pBuffer,pBufferEnd,pBufferLast);
        }
        _except (GetExceptionCode() == STATUS_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
        {
            RETAILMSG(ZONE_ALWAYS, (TEXT("EXCEPTION IN IST for stream 0x%X, buffer 0x%X!!!!\r\n"), this, m_lpCurrData));
            m_lpCurrData=m_lpCurrDataEnd; // Pretend we finished reading the application buffer
        }
    }

    return pBuffer;
}

//-----------------------------------------------------------------------------
// Member function:    OutputStreamContextM8S::Render2
//
// This function renders the next buffer-full of data to the given buffer.
// This class renders from mono 8-bit to stereo.
//
// Parameters:
//      pBuffer     the start of the output buffer.
//      pBufferEnd  the end of the output buffer.
//      pBufferLast the current high-water mark in the buffer.  This is the
//                  furthest point in the buffer which has had data rendered
//                  into it.
//
// Returns:     PBYTE
//      The end point rendered to by this stream.  This is used to update
//      pBufferLast when rendering several streams to the same buffer.
//-----------------------------------------------------------------------------
PBYTE OutputStreamContextM8S::Render2(PBYTE pBuffer, PBYTE pBufferEnd, PBYTE pBufferLast)
{
    LONG CurrT = m_CurrT;
    LONG DeltaT = m_DeltaT;
    LONG CurrSamp0 = m_CurrSamp[0];
    LONG PrevSamp0 = m_PrevSamp[0];
    PBYTE pCurrData = m_lpCurrData;
    PBYTE pCurrDataEnd = m_lpCurrDataEnd;
    LONG fxpGain[2];
    fxpGain[0] = m_fxpGain[0];
    fxpGain[1] = m_fxpGain[1];
    LONG OutSamp0;
    LONG OutSamp1;

    while (pBuffer < pBufferEnd)
    {
        while (CurrT >= DELTA_OVERFLOW)
        {
            if (pCurrData>=pCurrDataEnd)
            {
                goto Exit;
            }

            CurrT -= DELTA_OVERFLOW;

            PrevSamp0 = CurrSamp0;

            PPCM_SAMPLE pSampleSrc = (PPCM_SAMPLE)pCurrData;
            CurrSamp0 = (LONG)pSampleSrc->m8.sample;
            CurrSamp0 = (CurrSamp0 - 128) << 8;
            pCurrData+=1;
        }

        OutSamp0 = PrevSamp0 + (((CurrSamp0 - PrevSamp0) * CurrT) >> DELTAFRAC);
        CurrT += DeltaT;
		// Commented out for (possible) debug build optimisation
        // DEBUGMSG(ZONE_VERBOSE, (TEXT("PrevSamp0=0x%X, CurrSamp0=0x%X, CurrT=0x%X, OutSamp0=0x%X\r\n"), PrevSamp0,CurrSamp0,CurrT,OutSamp0));

        OutSamp1=OutSamp0;
        OutSamp0 = (OutSamp0 * fxpGain[0]) >> VOLSHIFT;
        OutSamp1 = (OutSamp1 * fxpGain[1]) >> VOLSHIFT;
        if (pBuffer < pBufferLast)
        {
            OutSamp0 += ((HWSAMPLE *)pBuffer)[0];
            OutSamp1 += ((HWSAMPLE *)pBuffer)[1];
#if USE_MIX_SATURATE
            // Handle saturation
            if (OutSamp0>AUDIO_SAMPLE_MAX)
            {
                OutSamp0=AUDIO_SAMPLE_MAX;
            }
            else if (OutSamp0<AUDIO_SAMPLE_MIN)
            {
                OutSamp0=AUDIO_SAMPLE_MIN;
            }
            if (OutSamp1>AUDIO_SAMPLE_MAX)
            {
                OutSamp1=AUDIO_SAMPLE_MAX;
            }
            else if (OutSamp1<AUDIO_SAMPLE_MIN)
            {
                OutSamp1=AUDIO_SAMPLE_MIN;
            }
#endif
        }
        ((HWSAMPLE *)pBuffer)[0] = (HWSAMPLE)OutSamp0;
        ((HWSAMPLE *)pBuffer)[1] = (HWSAMPLE)OutSamp1;
        pBuffer += 2*sizeof(HWSAMPLE);
    }

Exit:

    m_dwByteCount += (pCurrData - m_lpCurrData);
    m_lpCurrData = pCurrData;
    m_CurrT = CurrT;
    m_PrevSamp[0] = PrevSamp0;
    m_CurrSamp[0] = CurrSamp0;
    return pBuffer;
}

//-----------------------------------------------------------------------------
// Member function:    OutputStreamContextM16S::Render2
//
// This function renders the next buffer-full of data to the given buffer.
// This class renders from mono 16-bit to stereo.
//
// Parameters:
//      pBuffer     the start of the output buffer.
//      pBufferEnd  the end of the output buffer.
//      pBufferLast the current high-water mark in the buffer.  This is the
//                  furthest point in the buffer which has had data rendered
//                  into it.
//
// Returns:     PBYTE
//      The end point rendered to by this stream.  This is used to update
//      pBufferLast when rendering several streams to the same buffer.
//-----------------------------------------------------------------------------
PBYTE OutputStreamContextM16S::Render2(PBYTE pBuffer, PBYTE pBufferEnd, PBYTE pBufferLast)
{
    LONG CurrT = m_CurrT;
    LONG DeltaT = m_DeltaT;
    LONG CurrSamp0 = m_CurrSamp[0];
    LONG PrevSamp0 = m_PrevSamp[0];
    PBYTE pCurrData = m_lpCurrData;
    PBYTE pCurrDataEnd = m_lpCurrDataEnd;
    LONG fxpGain[2];
    fxpGain[0] = m_fxpGain[0];
    fxpGain[1] = m_fxpGain[1];
    LONG OutSamp0;
    LONG OutSamp1;

    while (pBuffer < pBufferEnd)
    {
        while (CurrT >= DELTA_OVERFLOW)
        {
            if (pCurrData>=pCurrDataEnd)
            {
                goto Exit;
            }

            CurrT -= DELTA_OVERFLOW;

            PrevSamp0 = CurrSamp0;

            PPCM_SAMPLE pSampleSrc = (PPCM_SAMPLE)pCurrData;
            CurrSamp0 = (LONG)pSampleSrc->m16.sample;
            pCurrData+=2;
        }

        OutSamp0 = PrevSamp0 + (((CurrSamp0 - PrevSamp0) * CurrT) >> DELTAFRAC);
        CurrT += DeltaT;
        // Commented out for (possible) debug build optimisation
		// DEBUGMSG(ZONE_VERBOSE, (TEXT("PrevSamp0=0x%X, CurrSamp0=0x%X, CurrT=0x%X, OutSamp0=0x%X\r\n"), PrevSamp0,CurrSamp0,CurrT,OutSamp0));

        OutSamp1=OutSamp0;
        OutSamp0 = (OutSamp0 * fxpGain[0]) >> VOLSHIFT;
        OutSamp1 = (OutSamp1 * fxpGain[1]) >> VOLSHIFT;
        if (pBuffer < pBufferLast)
        {
            OutSamp0 += ((HWSAMPLE *)pBuffer)[0];
            OutSamp1 += ((HWSAMPLE *)pBuffer)[1];
#if USE_MIX_SATURATE
            // Handle saturation
            if (OutSamp0>AUDIO_SAMPLE_MAX)
            {
                OutSamp0=AUDIO_SAMPLE_MAX;
            }
            else if (OutSamp0<AUDIO_SAMPLE_MIN)
            {
                OutSamp0=AUDIO_SAMPLE_MIN;
            }
            if (OutSamp1>AUDIO_SAMPLE_MAX)
            {
                OutSamp1=AUDIO_SAMPLE_MAX;
            }
            else if (OutSamp1<AUDIO_SAMPLE_MIN)
            {
                OutSamp1=AUDIO_SAMPLE_MIN;
            }
#endif
        }
        ((HWSAMPLE *)pBuffer)[0] = (HWSAMPLE)OutSamp0;
        ((HWSAMPLE *)pBuffer)[1] = (HWSAMPLE)OutSamp1;
        pBuffer += 2*sizeof(HWSAMPLE);
    }

Exit:

    m_dwByteCount += (pCurrData - m_lpCurrData);
    m_lpCurrData = pCurrData;
    m_CurrT = CurrT;
    m_PrevSamp[0] = PrevSamp0;
    m_CurrSamp[0] = CurrSamp0;
    return pBuffer;
}

//-----------------------------------------------------------------------------
// Member function:    OutputStreamContextM8M::Render2
//
// This function renders the next buffer-full of data to the given buffer.
// This class renders from mono 8-bit to mono.
//
// Parameters:
//      pBuffer     the start of the output buffer.
//      pBufferEnd  the end of the output buffer.
//      pBufferLast the current high-water mark in the buffer.  This is the
//                  furthest point in the buffer which has had data rendered
//                  into it.
//
// Returns:     PBYTE
//      The end point rendered to by this stream.  This is used to update
//      pBufferLast when rendering several streams to the same buffer.
//-----------------------------------------------------------------------------
PBYTE OutputStreamContextM8M::Render2(PBYTE pBuffer, PBYTE pBufferEnd, PBYTE pBufferLast)
{
    LONG CurrT = m_CurrT;
    LONG DeltaT = m_DeltaT;
    LONG CurrSamp0 = m_CurrSamp[0];
    LONG PrevSamp0 = m_PrevSamp[0];
    PBYTE pCurrData = m_lpCurrData;
    PBYTE pCurrDataEnd = m_lpCurrDataEnd;
    LONG fxpGain = m_fxpGain[0];
    LONG OutSamp0;

    while (pBuffer < pBufferEnd)
    {
        while (CurrT >= DELTA_OVERFLOW)
        {
            if (pCurrData>=pCurrDataEnd)
            {
                goto Exit;

⌨️ 快捷键说明

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