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

📄 wave.cpp

📁 C语言编程的不错工具
💻 CPP
字号:
/*****************************************************************************
 * wave.cpp
 *****************************************************************************
 * Copyright (c) Microsoft Corporation.
 */

#include "stdafx.h"
#include "resource.h"
#include "wave.h"
#include <mmreg.h>
#include "ChildView.h"
#include <msacm.h>

// -----------------------------------------------------------------------------------------
/*
 *	WaveOpenFile	:	opens a wave file, validates format, extracts parameters
 */
HANDLE 
WaveOpenFile
(
    IN  LPCSTR          szFileName,
    OUT WAVEFORMATEX**  ppWaveFormatEx,
    OUT PULONG          pcbData
)
{
    HMMIO	        hmmio;              // mmio style file handle
    MMCKINFO        mmckinfoParent;	    // parent chunk info struct
    MMCKINFO        mmckinfoSubchunk;	// sub chunk
    HWND            hwnd = AfxGetMainWnd()->m_hWnd;

    HANDLE          hFile = INVALID_HANDLE_VALUE;
    ULONG	        cbFormat = 0;
    LONG            lDataPos = 0;

    // open the file
    if(!(hmmio = mmioOpen((LPSTR)szFileName, NULL, MMIO_READ | MMIO_ALLOCBUF))) 
    {
        return FALSE;
    }

    // verify that the file is of type "WAVE" 
    mmckinfoParent.fccType = MAKEFOURCC('W', 'A', 'V', 'E');
    if(mmioDescend(hmmio, (LPMMCKINFO)&mmckinfoParent, NULL, MMIO_FINDRIFF))
    {
        // not a "WAVE" file!!
        MessageBox(hwnd, "WaveOpenFile:  Missing 'WAVE' chunk.This does not appear to be a wave file.", "MultiChan : Error opening wave file!", MB_ICONEXCLAMATION | MB_OK);
        goto _error_;
    }

    // find the "fmt " chunk (must be a subchunk of the "WAVE" chunk)
    mmckinfoSubchunk.ckid = MAKEFOURCC('f', 'm', 't', ' ');
    if(mmioDescend(hmmio, (LPMMCKINFO)&mmckinfoSubchunk, (LPMMCKINFO)&mmckinfoParent, MMIO_FINDCHUNK))
    {
        // file has no "fmt " chunk
        MessageBox(hwnd, "WaveOpenFile:  Missing 'fmt ' chunk", "MultiChan : Error opening wave file!", MB_ICONEXCLAMATION | MB_OK);
        goto _error_;
    }

    // get the size of the "fmt " chunk
    cbFormat = mmckinfoSubchunk.cksize;

    // allocate waveformat.  The "max" part ensures that the cbSize member of the WAVEFORMATEX exists and = 0
    *ppWaveFormatEx = (LPWAVEFORMATEX)LocalAlloc(LPTR, max(cbFormat, sizeof(WAVEFORMATEX)));
    if(!*ppWaveFormatEx)
    {
        // failed to allocate
        MessageBox(hwnd, "WaveOpenFile:  Failed to allocate memory", "MultiChan : Error opening wave file!", MB_ICONEXCLAMATION | MB_OK);
        goto _error_;
    }

    // read the "fmt " chunk
    if(mmioRead(hmmio, (HPSTR)*ppWaveFormatEx, cbFormat) != (LONG)cbFormat)
    {
        // failed to read the "fmt " chunk
        MessageBox(hwnd, "WaveOpenFile:  Error reading 'fmt ' chunk", "MultiChan : Error opening wave file!", MB_ICONEXCLAMATION | MB_OK);
        goto _error_;
    }

    // ascend out o' the "fmt " chunk
    mmioAscend(hmmio, &mmckinfoSubchunk, 0);

    // and find the data subchunk.  (current file pos should be at the beginning of the 
    // data chunk, but when you assume...)
    mmckinfoSubchunk.ckid = MAKEFOURCC('d', 'a', 't', 'a');
    if(mmioDescend(hmmio, &mmckinfoSubchunk, &mmckinfoParent, MMIO_FINDCHUNK))
    {
        // wave file doesn't appear to have a data chunk
        MessageBox(hwnd, "WaveOpenFile:  Missing 'data' chunk", "MultiChan : Error opening wave file!", MB_ICONEXCLAMATION | MB_OK);
        goto _error_;
    }

    // get the size of the "data" subchunk
    *pcbData = mmckinfoSubchunk.cksize;
    if(0L == *pcbData)
    {
        // the data chunk contains no data
        MessageBox(hwnd, "WaveOpenFile:  Error reading 'data' chunk", "MultiChan : Error opening wave file!", MB_ICONEXCLAMATION | MB_OK);
        goto _error_;
    }

    // remember the data 
    lDataPos = mmioSeek(hmmio, 0, SEEK_CUR);
    mmioClose(hmmio, 0);

    //
    // now we are done with the mmio functions.  Reopen the file and seek to the data chunk using normal
    // file io routines
    //

    __try
    {
        hFile = 
            CreateFile
            ( 
                szFileName, 
                GENERIC_READ, 
                FILE_SHARE_READ,
                NULL, 
                OPEN_EXISTING, 
                FILE_ATTRIBUTE_NORMAL,
                NULL 
            );
    }    
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        MessageBox(hwnd, "WaveOpenFile : Handling exception thrown by CreateFile!", "MultiChan : Error opening wave file!", MB_ICONEXCLAMATION | MB_OK);
        goto _error_;
    }

    if (!IsValidHandle(hFile))
    {
        goto _error_;
    }

    SetFilePointer
    (
        hFile,
        lDataPos,  
        NULL, 
        FILE_BEGIN
    ); 

    return hFile;
    
_error_:
    SafeCloseHandle(hFile);
    if(hmmio)
    {
        mmioClose(hmmio, 0);
    }

    return INVALID_HANDLE_VALUE;
}

// -----------------------------------------------------------------------------------------
/*
 *	WaveSaveFile	:	creates and writes the mixed wave; returns success code
 */
BOOL
WaveSaveFile
(
    IN  LPCSTR          szFileName,
    OUT WAVEFORMATEX*   pWaveFormatEx,
    IN  PVOID           pvData,
    IN  ULONG           cbData
)
{
    HANDLE          hFile		= INVALID_HANDLE_VALUE;
    ULONG           cbWritten;
	HRSRC           hrsrc		= (HRSRC)INVALID_HANDLE_VALUE;
    void*           pv			= NULL;

    //
    // now we are done with the mmio functions.  Reopen the file and seek to the data chunk using normal
    // file io routines
    //

    __try
    {
        hFile = 
            CreateFile
            ( 
                szFileName, 
                GENERIC_WRITE, 
                0,
                NULL, 
                CREATE_ALWAYS, 
                FILE_ATTRIBUTE_NORMAL,
                NULL 
            );
    }    
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        MessageBox(AfxGetMainWnd()->m_hWnd, "WaveSaveFile : Handling exception thrown by CreateFile!", "MultiChan : Error creating wave file", MB_ICONEXCLAMATION | MB_OK);
        goto _error_;
    }

    if (!IsValidHandle(hFile))
        goto _error_;

	// 
	// write file header
	//

    // standard wave goo
    struct
    {
        DWORD   fourccData;
        DWORD   dwDataLength;
    } DataHeader;

    DataHeader.fourccData         = MAKEFOURCC('d','a','t','a');
    DataHeader.dwDataLength       = cbData;

    struct 
    {
        DWORD       dwRiff;
        DWORD       dwFileSize;
        DWORD       dwWave;
        DWORD       dwFormat;
        DWORD       dwFormatLength;
    }	FileHeader;

    FileHeader.dwRiff             = MAKEFOURCC('R','I','F','F');
    FileHeader.dwWave             = MAKEFOURCC('W','A','V','E');
    FileHeader.dwFormat           = MAKEFOURCC('f','m','t',' ');
    FileHeader.dwFormatLength     = sizeof(WAVEFORMATEX) + pWaveFormatEx->cbSize;
    FileHeader.dwFileSize         = sizeof(FileHeader) + FileHeader.dwFormatLength + sizeof(DataHeader) + cbData;

    if(!WriteFile(hFile, &FileHeader, sizeof(FileHeader), &cbWritten, NULL))
        goto _error_;

    // wave format
    if(!WriteFile(hFile, pWaveFormatEx, sizeof(WAVEFORMATEX) + pWaveFormatEx->cbSize, &cbWritten, NULL))
        goto _error_;

    // data chuck
    if(!WriteFile(hFile, &DataHeader, sizeof(DataHeader), &cbWritten, NULL))
        goto _error_;

    //
    // Write wave data
    //
    if(!WriteFile(hFile, pvData, cbData, &cbWritten, NULL))
        goto _error_;

    SafeCloseHandle( hFile );
    return TRUE;
    
_error_:
    MessageBox(NULL, "WaveSaveFile : Error Writing File", "MultiChan : Error!", MB_ICONEXCLAMATION | MB_OK);
    SafeCloseHandle( hFile );
    return FALSE;
}



// ===============================================================
/*
 *   WavePlayFileCB  
 *   callback for the waveOut functions
 *   notifies the originating window
 */
void 
CALLBACK   
WavePlayFileCB
(
    HWAVEOUT	hwo,
    UINT		uMsg,
    DWORD_PTR	dwInstance,
    DWORD_PTR	dwParam1,
    DWORD_PTR	dwParam2
)
{
    DWORD       mmr = MMSYSERR_BASE;

    ASSERT( ( CDialog * )dwInstance );

    switch( uMsg )
    {
        case    WOM_OPEN:
            {
                //
                //  notify window
                //
                (( CDialog * )dwInstance)->PostMessage( WM_START_PLAYBACK, 0, 0 );

                break;
            }
        case    WOM_DONE:
            {
                //
                //  notify window
                //
                (( CDialog * )dwInstance)->PostMessage( WM_STOP_PLAYBACK, 0, 0 );

                break;
            }

        case    WOM_CLOSE:
            {

                break;
            }


        default:
            ASSERT(0);
    }
    return;
}

/*
 *	WaveDisablePlayback
 *	prevent other channels from being played at this time
 */
void
WaveTogglePlayback
(
			CDlgSrc	*	pdlgSelf,
	const	BOOL		fSwitch
)
{
	CDlgSrc	*	pdlgSrc	= 0;
	//
	//	fSwitch toggles between disable (FALSE) and allow (TRUE)
	//

	for
	( 
		POSITION	position = g_listSources.GetHeadPosition();
		position;
	)
	{
		pdlgSrc = g_listSources.GetNext( position );
		//
		//	disable/enable the play button. the stop button is unaffected
		//
		pdlgSrc->m_fPlayable = fSwitch;
		(pdlgSrc->m_butPlay).EnableWindow( fSwitch );
	}

	//
	//	check target
	//
	if( pdlgSelf )
	{
		//	allow stop
		(pdlgSelf->m_butStop).EnableWindow( !fSwitch );

		//	destination may not be mixed already
		if( g_pdlgDest->m_fPlayable )
		{
			g_pdlgDest->m_fPlayable = fSwitch;
			(g_pdlgDest->m_butPlay).EnableWindow( fSwitch );
		}
		else
		{
			g_pdlgDest->m_fPlayable = fSwitch & (0 != g_pdlgDest->m_pbData);
			(g_pdlgDest->m_butPlay).EnableWindow( g_pdlgDest->m_fPlayable );
		}
	}
	else
	{
		g_pdlgDest->m_fPlayable = fSwitch;
		(g_pdlgDest->m_butPlay).EnableWindow( fSwitch );
		(g_pdlgDest->m_butStop).EnableWindow( !fSwitch );
	}


}	//	WaveTogglePlayback


// ----------------------------------------------------------------------------------
// TrapMMError
// return:          FALSE if it is an error, TRUE otherwise
// ----------------------------------------------------------------------------------
BOOL 
TrapMMError
(
    MMRESULT mmRes,
    LPCSTR   szAPI
)
{
	//	no error
    if(MMSYSERR_NOERROR == mmRes)
    {
        return( TRUE );
    } 

    HWND    hwndMain        = AfxGetMainWnd()->m_hWnd;
    char    szError[128]	= "";
    char    szErrMsg[128]	= "";

	//	basic mmsys error
	if( MMSYSERR_LASTERROR >= mmRes )
	{
		if( MMSYSERR_NOMEM == waveOutGetErrorText( mmRes, szError, 128 ) )
		{
			_snprintf( szErrMsg, 128, "Insufficient memory to complete the task.");
		}
        else
        {
    		_snprintf( szErrMsg, 128, "ERROR : %s returned : %s", szAPI, szError );
        }
	}
    else
    {
	    //	other errors
	    switch( mmRes )
	    {
		    case	WAVERR_BADFORMAT	:
		    {
			    strcpy( szError, " : Attempt to open an unsupported waveform-audio format." );
			    break;
		    }

		    case	WAVERR_STILLPLAYING	:
		    {
			    strcpy( szError, " : There is another waveform resource still playing." );
			    break;
		    }

		    case	WAVERR_UNPREPARED	:
		    {
			    strcpy( szError, " : Header is not prepared." );
			    break;
		    }

		    case	WAVERR_SYNC			:
		    {
			    strcpy( szError, " : Device is synchronous." );
			    break;
		    }

		    case	ACMERR_NOTPOSSIBLE	:
		    {
			    strcpy( szError, " : The specified action is not possible in the current context." );
			    break;
		    }

		    case	ACMERR_BUSY	:
		    {
			    strcpy( szError, " : The driver is currently in use and cannot be reused." );
			    break;
		    }
		    
		    case	ACMERR_UNPREPARED	:
		    {
			    strcpy( szError, " : The stream header is not currently prepared." );
			    break;
		    }

		    case	ACMERR_CANCELED		:
		    {
			    strcpy( szError, " : The action has been canceled." );
			    break;
		    }

		    default	:
		    {
			    //	default
			    _snprintf( szError, 128, "an unrecognized error code (%d).", mmRes );
			    break;
		    }
        }	//	switch

		_snprintf( szErrMsg, 128, "ERROR : %s returned %s.", szAPI, szError );
	}

    // Display the string.
	MessageBox(hwndMain, szErrMsg, "MultiChan : Error!", MB_ICONEXCLAMATION | MB_OK);

	return( FALSE );
}

⌨️ 快捷键说明

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