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

📄 waveout.cpp

📁 EP931X系列的WinCE声卡驱动源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
    // the DSP task.
    //
    if((dwStartPos == 0) && (dwEndPos == m_ulDmaBufferSize))
    {
        bIsFirstFill = TRUE;
    }

    //
    // Check to see if there are no more wave headers.  If so, then we fill
    // the next half of the DMA buffer with silence and set a flag to stop
    // the DSP task when we receive the next interrupt.  We have to fill the
    // DMA buffer with silence since the DSP task will play part of that half
    // of the DMA buffer before we are able to stop it...filling with silence
    // insures that it will play silence.  This code will only be executed
    // when we are called by the stream callback...there will be wave headers
    // on the list when we are called as a result of WODM_WRITE.
    //
    if(!m_pWaveNext)
    {
        //
        // Fill the remainder of the DMA buffer with silence.  
        // Silence 0x0000 for 16 bit PCM streams.
        //
        memset((char *)((ULONG)m_pBuffer + dwStartPos), (char)0x00,
               m_ulDmaBufferSize>> 1);

        //
        // Set a flag to cause playback to cease at the next interrupt.
        //
        m_bStopAtNextInterrupt = TRUE;

        //
        // Save off the previous start and length position.
        //
        m_dwPreviousStart        = dwStartPos;
        m_dwPreviousEnd          = dwEndPos;

        //
        // We're done.
        //
        return;
    }

    //
    // We have more DMA buffers so don't stop at the next interrupt.
    //
    m_bStopAtNextInterrupt = FALSE;
    
    //
    // While the DMA buffer is not full, try to fill it with wave data from
    // the wave headers on our input queue.
    //
    while(!bIsFull)
    {
        //
        // If there are no more wave headers on the input queue, then fill the
        // remainder of the DMA buffer with silence.
        //
        if(!m_pWaveNext)
        {
            //
            // Fill the DMA buffer with silence.  
            // Silence is 0x0000 for 16 bit PCM streams.
            //
            memset((char *)m_pBuffer + dwStartPos, (char)0x00,
                   dwEndPos - dwStartPos);
 
            //
            // We're done filling the DMA buffer.
            //
            break;
        }

        //
        // See if the number of remaining bytes in the current wave header is
        // less than the number of unused bytes in the DMA buffer.
        //
        if(((m_pWaveNext->dwBufferLength - m_pWaveNext->dwBytesRecorded)<<m_ulBufferShift) <
           (dwEndPos - dwStartPos))
        {
            //
            // Copy the remainder of the wave data in this wave header to the
            // DMA buffer.
            //
            m_pfnConversion
            (
                (PVOID)((PUCHAR)m_pBuffer + dwStartPos),
                (UCHAR *)(m_pWaveNext->lpData + m_pWaveNext->dwBytesRecorded),
                m_pWaveNext->dwBufferLength - m_pWaveNext->dwBytesRecorded
            );

            //
            // Increment the start point in the DMA buffer by the number of
            // bytes copied into it.
            //
            dwStartPos += (m_pWaveNext->dwBufferLength - m_pWaveNext->dwBytesRecorded)<<m_ulBufferShift;

            //
            // Mark all the bytes in this wave header as being used.
            //
            m_pWaveNext->dwBytesRecorded = m_pWaveNext->dwBufferLength;

        }
        else
        {
            //
            // Fill the remainder of the DMA buffer with wave data from this
            // wave header.
            //
            m_pfnConversion
            (
                (PULONG)((PUCHAR)m_pBuffer + dwStartPos),
                (PUCHAR)m_pWaveNext->lpData + m_pWaveNext->dwBytesRecorded,
                (dwEndPos - dwStartPos)>>m_ulBufferShift
            );

            //
            // Mark the bytes that were copied from this wave header as being
            // consumed so that they will not be copied into the DMA buffer
            // again.
            //
            m_pWaveNext->dwBytesRecorded += (dwEndPos - dwStartPos)>>m_ulBufferShift;

            //
            // Bump the start position up to the ending position.
            //
            dwStartPos = dwEndPos;

            //
            // Indicate that the DMA buffer is now full.
            //
            bIsFull = TRUE;
        }

        //
        // If the wave data in the current wave header has been completely
        // consumed, then we must move on to the next wave header.
        //
        if(m_pWaveNext->dwBytesRecorded == m_pWaveNext->dwBufferLength)
        {
            //
            // See if we are in the middle of a loop, in which case we do not
            // return this wave header since it will be needed again.
            //
            if(m_dwLoopCount)
            {
                //
                // If this wave header is the last in the loop, then go back to
                // the beginning of the loop.
                //
                if(m_pWaveNext->dwFlags & WHDR_ENDLOOP)
                {
                    //
                    // Go back to the beginning of the loop.
                    //
                    m_pWaveNext = m_pWaveHead;

                    //
                    // We've completed a loop, so decrement the number of
                    // loops.
                    //
                    m_dwLoopCount--;
                }
                else
                {
                    //
                    // This isn't the last wave header in the loop, so go on to
                    // the next one.
                    //
                    m_pWaveNext = m_pWaveNext->lpNext;
                }
            }
            else
            {
                m_pWaveNext->dwFlags |= WHDR_DONE;   
                m_pWaveNext         = m_pWaveNext->lpNext;

                //
                // If the next wave header is the beginning of a loop, then
                // setup the loop count.
                //
                if(m_pWaveNext && (m_pWaveNext->dwFlags & WHDR_BEGINLOOP))
                {
                    m_dwLoopCount = m_pWaveNext->dwLoops - 1;
                }
            }

            //
            // If there is another wave header on the list, then set its
            // reserved field to zero, so that we will use all the wave data in
            // the wave header.  We do this here, in addition to in
            // WaveOut::Write, since the reserved field will get incremented
            // to the size of the wave header's buffer in the processing of
            // consuming it's data, and we will want to reconsume all the wave
            // data when we re-encounter a wave header in a loop.
            //
            if(m_pWaveNext)
            {
                m_pWaveNext->dwBytesRecorded = 0;
            }
        }
    }

    //
    // Save off the previous start and length position.
    //
    m_dwPreviousStart        = dwStartPos;
    m_dwPreviousEnd          = dwEndPos;

    //
    // Now that we've filled the DMA buffer, we need to try and start the DSP
    // task, if the wave device is not currently paused and is not currently
    // playing.
    //
    if(!m_bIsPaused && !m_bIsPlaying && !m_bStopAtNextInterrupt)
    { 
        FUNC_WAVEOUT((L"WaveOut::FillDMABuffer Start\r\n"));
        m_pCodec->StartPlayback(0);
        Sleep(1);
        m_Dma.Start();
        
        //
        // Indicate that we are currently playing.
        //
        m_bIsPlaying = TRUE;
    }
}

//****************************************************************************
// WaveOut::InterruptHandler
//****************************************************************************
// Interrupt handler for Wave interface.
// 
//
void WaveOut::InterruptHandler(void *Handle, BOOL bLastHalf)
{
    WaveOut *pWaveOut = (WaveOut *)Handle;
    DWORD   dwAccessKey;
    DWORD   dwStartPos, dwEndPos;
    
    EnterCriticalSection( &pWaveOut->m_CriticalSection);
    dwAccessKey=GetCurrentPermissions();
    SetProcPermissions((ULONG) -1); //  access everybody

    
    //
    // Remove the completed buffers.
    //
    pWaveOut->RemoveCompleteBlocks();
    
    if(pWaveOut->m_bStopAtNextInterrupt && !pWaveOut->m_pWaveNext)
    {
        pWaveOut->m_Dma.Stop();
        Sleep(1);
        pWaveOut->m_pCodec->StopPlayback(0);
        pWaveOut->m_bIsPlaying    = FALSE;
        FUNC_WAVEOUT((L"WaveOut::IntHander Stop\r\n"));

    }
    else 
    {
        //
        // Find out which half of the DMA buffer we are playing.
        //
        if(bLastHalf)
        {
            dwStartPos  = pWaveOut->m_ulDmaBufferSize/2;
            dwEndPos    = pWaveOut->m_ulDmaBufferSize;
        }
        else        
        {
            dwStartPos  = 0;
            dwEndPos    = pWaveOut->m_ulDmaBufferSize/2;
        }        
    
        //
        // Copy the data into the buffer.
        //
        pWaveOut->FillDMABuffer(dwStartPos, dwEndPos);
    }        
    
    //
    //  change permission back
    //
    SetProcPermissions(dwAccessKey);
    
    LeaveCriticalSection( &pWaveOut->m_CriticalSection);

    return;    
}




//****************************************************************************
// WaveOut::RemoveCompleteBlocks
//****************************************************************************
// Removes any blocks that have been completed.
// 
//
void WaveOut::RemoveCompleteBlocks()
{
    PWAVEHDR pWave;

    while (m_pWaveHead != NULL) 
    {
        if (IS_BUFFER_DONE(m_pWaveHead))  
        {
            pWave = m_pWaveHead;
            //
            // Only remove a block if it's not in a loop.
            //
            //WODM_MSG((L"MM_WOM_DONE: pWave = 0x%08x\n",(DWORD)pWave));
            m_dwBytePosition += m_pWaveHead->dwBytesRecorded;
            m_pWaveHead = m_pWaveHead->lpNext;
            MARK_BUFFER_DEQUEUED(pWave);

            //
            // Check to see if the next buffer is at the front.
            // If so set it to the next one in the list.
            //
            if(pWave == m_pWaveNext)
            {
                m_pWaveNext = m_pWaveHead;
            }
            
            //
            // Make the callback function call to the Wave API Manager
            //
            m_pfnCallback(m_hCallback, MM_WOM_DONE, m_dwInstance, (DWORD) pWave, 0);
        }
        else 
        {
            //
            // Only remove from the front of the list, but as many as are done.
            //
            break;  // If the first one's not DONE, then break the loop.
        }
    }   
}


//****************************************************************************
// WaveOut::AddBuffer
//****************************************************************************
// Adds a buffer to the end of the buffer list.
// 
//
MMRESULT WaveOut::AddBuffer(WAVEHDR *pWave)
{

    //FUNC_WAVEOUT((L"WaveOut::AddBuffer pWave = 0x%08x, playing = 0x%08x ,Pause = 0x%08x\n",(ULONG)pWave, (ULONG)m_bIsPlaying, (ULONG)m_bIsPaused));
    PWAVEHDR    p;   

    //
    //  set some default value assume it is only one node
    //
    pWave->lpNext = NULL;
    pWave->dwFlags &= ~WHDR_DONE;
    pWave->dwBytesRecorded=0;
    pWave->reserved = (DWORD) FALSE;  // mark as not a looped buffer by default.
    
    //
    //  Add it to the end if the WaveHead is null.
    //
    if(!m_pWaveHead) 
    {
        m_pWaveHead = m_pWaveNext = pWave;

        //
        // Set up the loop if this is the start of a loop.
        //
        if(m_pWaveNext->dwFlags & WHDR_BEGINLOOP)
        {
            m_dwLoopCount = m_pWaveNext->dwLoops - 1;
        }
    } 
    else 
    {
        //
        //  add the buffer to the tail
        //
        p = m_pWaveHead;
        while(p->lpNext)
            p = p->lpNext;
        p->lpNext = pWave;

        //
        // If the next wave header is NULL, then we've consumed all the wave
        // data received so far in the loop, so set the next wave header to be
        // the just written wave header (so we'll continue the loop with this
        // wave header).
        //
        if(!m_pWaveNext)
        {
            m_pWaveNext = pWave;
        }

    }

    MARK_BUFFER_QUEUED(pWave);
    

    //FUNC_WAVEOUT((L"-WaveOut::AddBuffer\n"));
    return(MMSYSERR_NOERROR);
}    


⌨️ 快捷键说明

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