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

📄 dlgdest.cpp

📁 C语言编程的不错工具
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
*	Copyright (c) Microsoft Corportation. All rights reserved.
*/

// DlgDest.cpp : implementation file
//

#include "stdafx.h"
#include "multichan.h"
#include "DlgDest.h"
#include "dlgsrc.h"
#include "childview.h"
#include <initguid.h>
#include <mmreg.h>
#include <msacm.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


/*
 *	CDlgDest	
 *	MFC stuff
 */

/////////////////////////////////////////////////////////////////////////////
// CDlgDest dialog
void 
CDlgDest::DoDataExchange
(
	CDataExchange* pDX
)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CDlgDest)
	DDX_Control(pDX, IDC_SPEAKERFLAGS, m_cChannelMask);
	DDX_Control(pDX, IDC_AVEBITS, m_cAveBitsPerSec);
	DDX_Control(pDX, IDC_REMIX, m_cRemix);
	DDX_Control(pDX, IDC_EDIT_VALIDBITS, m_cValidBits);
	DDX_Control(pDX, IDC_CHANNELS, m_cChannels);
	DDX_Control(pDX, IDC_OUTPUT, m_cOutput);
	DDX_Control(pDX, IDC_COMBO_BITDEPTH, m_comboBitDepth);
	DDX_Control(pDX, IDC_COMBO_SAMPLERATE, m_comboSampleRate);
	DDX_Control(pDX, IDC_COMBO_WAVEFORMAT, m_comboFormat);
	DDX_Control(pDX, IDC_PLAY, m_butPlay);
    DDX_Control(pDX, IDC_STOP, m_butStop);
	DDX_Text(pDX, IDC_EDIT_VALIDBITS, m_wValidBitsPerSample);
	DDV_MinMaxUInt(pDX, m_wValidBitsPerSample, 0, 65535);
	DDX_Text(pDX, IDC_SPEAKERFLAGS, m_strChannelMask);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CDlgDest, CDialog)
	//{{AFX_MSG_MAP(CDlgDest)
	ON_BN_CLICKED(IDC_REMIX, OnRemix)
	ON_BN_CLICKED(IDC_PLAY, OnPlay)
    ON_BN_CLICKED(IDC_STOP, OnStop)
	ON_CBN_SELENDOK(IDC_COMBO_SAMPLERATE, OnComboSamplerate)
	ON_CBN_SELENDOK(IDC_COMBO_WAVEFORMAT, OnComboWaveformat)
	ON_CBN_SELENDOK(IDC_COMBO_BITDEPTH, OnComboBitdepth)
	ON_EN_KILLFOCUS(IDC_EDIT_VALIDBITS, OnEditValidbits)
	ON_WM_CTLCOLOR()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_MOUSEMOVE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/*
 *	CDlgDest	
 *	construction
 */

// ----------------------------------------------------------------------------------
// constructor
// ----------------------------------------------------------------------------------
CDlgDest::CDlgDest
(
	CWnd* pParent /*=NULL*/
)
  : CDialog(CDlgDest::IDD, pParent),
    m_pwndParent(pParent),
    m_pbData(NULL),
    m_fPlayable(FALSE),
    m_fDragging(FALSE),
	m_cbData( 0 ),
    m_lpwhdr( 0 )
{
	//{{AFX_DATA_INIT(CDlgDest)
	m_wValidBitsPerSample = 0;
	m_strChannelMask = _T("0x00000000");
	//}}AFX_DATA_INIT

    m_wfExt.Format.wFormatTag = WAVE_FORMAT_PCM;
    m_wfExt.Format.cbSize = 0;
    m_wfExt.Format.wBitsPerSample = 16;
    m_wfExt.Format.nChannels = 0;
    m_wfExt.Format.nBlockAlign = 4;
    m_wfExt.Format.nSamplesPerSec = 44100;
    m_wfExt.Format.nAvgBytesPerSec = m_wfExt.Format.nBlockAlign * m_wfExt.Format.nSamplesPerSec;
    m_wfExt.Samples.wValidBitsPerSample = 16;
    m_wfExt.dwChannelMask = 0;
    m_wfExt.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
    m_wValidBitsPerSample = m_wfExt.Samples.wValidBitsPerSample;
}

// ----------------------------------------------------------------------------------
// destructor
// ----------------------------------------------------------------------------------
CDlgDest::~CDlgDest
()
{
	SafeLocalFree( m_pbData );
    SafeLocalFree( m_lpwhdr );
}

// ----------------------------------------------------------------------------------
// Create
// ----------------------------------------------------------------------------------
void 
CDlgDest::Create
(
    void
)  
{
    CDialog::Create(CDlgDest::IDD, m_pwndParent);
}

// ----------------------------------------------------------------------------------
// OnInitDialog
// ----------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------
CONST_GUID_REP cgrFormats[] =
{
    &GUID_NULL,                 "GUID_NULL",
    &KSDATAFORMAT_SUBTYPE_PCM,  "KSDATAFORMAT_SUBTYPE_PCM"
};

UINT    rgnSampleRate[]	= { 8000, 11025, 16000, 22050, 32000, 44100, 48000, 96000 };
UINT    rgnBitDepth[]	= { 8, 16, 24, 32 };

BOOL 
CDlgDest::OnInitDialog
() 
{
	CDialog::OnInitDialog();

    int c,i;

    i = m_comboFormat.AddString("WAVE_FORMAT_PCM");
    m_comboFormat.SetItemData(i, WAVE_FORMAT_PCM);
    i = m_comboFormat.AddString("WAVE_FORMAT_EXTENSIBLE");
    m_comboFormat.SetItemData(i, WAVE_FORMAT_EXTENSIBLE);

    char sz[10];
    for(c = 0; c < ARRAY_ELEMENTS(rgnSampleRate); c++)
    {
        _snprintf(sz, 10, "%d", rgnSampleRate[c]);
        i = m_comboSampleRate.AddString(sz);
        m_comboSampleRate.SetItemData(i, rgnSampleRate[c]);
    }

    for(c = 0; c < ARRAY_ELEMENTS(rgnBitDepth); c++)
    {
        _snprintf(sz, 10, "%d", rgnBitDepth[c]);
        i = m_comboBitDepth.AddString(sz);
        m_comboBitDepth.SetItemData(i, rgnBitDepth[c]);
    }

    m_comboSampleRate.SelectString(0, "44100");
    m_comboBitDepth.SelectString(0, "16");
    m_comboFormat.SelectString(0, "WAVE_FORMAT_PCM");

	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

/*
 *	CDlgDest	
 *	operations
 */

// ----------------------------------------------------------------------------------
// OnRemix
//	traverses the list of source channels and mixes them according to the user settings
// ----------------------------------------------------------------------------------
void 
CDlgDest::OnRemix
() 
{
    CDlgSrc *	pdlgSrc		= 0;
    ULONG       cMaxSamples = 0;
    UINT        nSample;
    ULONG       cbSample;

    // move over, bacon
    SafeLocalFree(m_pbData);

    //
    // update UI
    //
    Update();

    //
    // determine the max number of samples
    //
    ULONG   cSamplesSrcThisFormat = 0;
	for
	(
		POSITION	pos = g_listSources.GetHeadPosition();
		pos;
	)
    {
        pdlgSrc = g_listSources.GetNext(pos);

        cSamplesSrcThisFormat = MulDiv(
											m_wfExt.Format.nSamplesPerSec, 
											pdlgSrc->m_cSamples, 
											pdlgSrc->m_wfx.nSamplesPerSec
									);
        cMaxSamples = max(cMaxSamples, cSamplesSrcThisFormat);
    }

    //
	//	determine the length of the buffer required 
	//
    cbSample = m_wfExt.Format.nChannels * m_wfExt.Format.wBitsPerSample / 8;
    m_cbData = cbSample * cMaxSamples;
    m_pbData = (PBYTE)LocalAlloc(LPTR, m_cbData);
    if( 0 == m_pbData)
	{
		MessageBox( "Insufficient memory to complete the task.", "MultiChan : Error", MB_OK | MB_ICONSTOP );
		return;
	}

    //
    // copy data from each src to the dst
    //
	
    MMRESULT        mmRes;
    HACMSTREAM      has;
    ULONG           cbConversion;
    PVOID           pvConversion;
    ACMSTREAMHEADER ash;
    ULONG           cSamplesOut;
    BOOL            fRes = FALSE;
    WAVEFORMATEX    wfxConversion;

	wfxConversion.wFormatTag		= WAVE_FORMAT_PCM;
	wfxConversion.cbSize			= 0;
	wfxConversion.nChannels			= 1;
	wfxConversion.nSamplesPerSec	= m_wfExt.Format.nSamplesPerSec;
	wfxConversion.wBitsPerSample	= m_wfExt.Format.wBitsPerSample;
	wfxConversion.nBlockAlign		= wfxConversion.wBitsPerSample / 8;
	wfxConversion.nAvgBytesPerSec	= wfxConversion.nBlockAlign * wfxConversion.nSamplesPerSec;

	//
	// for each SRC (src dialog), convert it's buffer into 1 channel of the Dst format
	//
	for
	(
	    pos = g_listSources.GetHeadPosition();
		pos;
	)
    {
        pdlgSrc = g_listSources.GetNext(pos);

        // 
        // first, convert dlg format to dest format using ACM
        //
		
        // open an appropriate ACM driver
        mmRes = 
            acmStreamOpen
            (
                &has,
                NULL,
                &pdlgSrc->m_wfx,
                &wfxConversion,
                NULL,   //wFilter,
                NULL,
                0,
                ACM_STREAMOPENF_NONREALTIME 
            );

        if(!TrapMMError(mmRes, "acmStreamOpen"))
            break;
		
		//
        //	how big a buffer do we need to convert this one channel?
		//	in any case, acm overestimates the size of the buffer needed 
		//	if the acm size is used when copying we will exceed the boundaries of our allocated m_pbData
		//	
        mmRes = 
            acmStreamSize
            (
                has,
                pdlgSrc->m_cbData,
                &cbConversion,
                ACM_STREAMSIZEF_SOURCE
            );

        if(!TrapMMError(mmRes, "acmStreamSize"))
            break;

        // alloc
        pvConversion = LocalAlloc(LPTR, cbConversion);
        if(!(fRes = (pvConversion != NULL)))
        {
            MessageBox("Not enough memory for ACM operation", "MultiChan : Error!", MB_ICONEXCLAMATION | MB_OK);
            break;
        }

        // be prepared!
		ZeroMemory(&ash, sizeof(ACMSTREAMHEADER));
		ash.cbStruct	= sizeof(ACMSTREAMHEADER);
		ash.pbSrc		= (PBYTE)pdlgSrc->m_pvData;
		ash.cbSrcLength = pdlgSrc->m_cbData;      
		ash.pbDst		= (PBYTE)pvConversion;
		ash.cbDstLength = cbConversion;

        mmRes = acmStreamPrepareHeader(has, &ash, 0);
        if(!TrapMMError(mmRes, "acmStreamPrepareHeader"))
            break;

        // do it
        mmRes = acmStreamConvert(has, &ash, 0);
        if(!TrapMMError(mmRes, "acmStreamConvert"))
            break;

        // clean up
        mmRes = acmStreamUnprepareHeader(has, &ash, 0) |
                acmStreamClose(has, 0);
        if(!TrapMMError(mmRes, "acmStreamUnprepareHeader"))
            break;

        //
        // now copy the data from conversion buffer to final output buffer
        //
        cSamplesOut =	( cbConversion > m_cbData ) ? 
						( m_cbData / wfxConversion.nBlockAlign ) : 
						( cbConversion / wfxConversion.nBlockAlign );

        switch(wfxConversion.nBlockAlign)
        {
            case 1:     // 8-bit
            {
                // stagger dest
                PBYTE   pbDst = m_pbData + pdlgSrc->m_nChannel;
                PBYTE   pbSrc = (PBYTE)pvConversion;

                for(nSample = 0; nSample < cSamplesOut; nSample++)
                {
                    *pbDst = *pbSrc++;
                    pbDst += m_wfExt.Format.nChannels;
                }

                break;
            }

            case 2:     // 16-bit
            {
                // stagger dest
                PUSHORT pusDst = ((PUSHORT)m_pbData) + pdlgSrc->m_nChannel;
                PUSHORT pusSrc = (PUSHORT)pvConversion;

                for(nSample = 0; nSample < cSamplesOut; nSample++)
                {
                    *pusDst = *pusSrc++;
                    pusDst += m_wfExt.Format.nChannels;
                }

                break;
            }

            case 3:     // 24-bit
            {
                typedef struct {
                    BYTE b[3];
                } S24BITS, *PS24BITS;

                // stagger dest
                PS24BITS psDst = ((PS24BITS)m_pbData) + pdlgSrc->m_nChannel;
                PS24BITS psSrc = (PS24BITS)pvConversion;

                for(nSample = 0; nSample < cSamplesOut; nSample++)
                {
                    *psDst = *psSrc++;
                    psDst += m_wfExt.Format.nChannels;
                }

                break;
            }

            default:
                ASSERT(0);

⌨️ 快捷键说明

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