home *** CD-ROM | disk | FTP | other *** search
- /**************************************************************************
- *
- * 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.
- *
- * Copyright (C) 1993 - 1997 Microsoft Corporation. All Rights Reserved.
- *
- **************************************************************************/
- /* reverse.c - WinMain() and WndProc() for REVERSE, along with
- * initialization and support code.
- *
- * REVERSE is a Windows sample application that illustrates how to use
- * the low-level waveform playback services. It also shows how to use
- * the multimedia file I/O services to read data from a WAVE file.
- *
- * REVERSE plays a WAVE waveform audio file backwards.
- */
-
- #include <windows.h>
- #include <windowsx.h>
- #include <mmsystem.h>
- #include "reverse.h"
- #include "strings.h"
-
- #define MAX_FILENAME_SIZE 128
-
- /* Global variables.
- */
- char szAppName[] = "Reverse"; // application name
- HANDLE hInstApp = NULL; // instance handle
- HWND hwndApp = NULL; // main window handle
- HWND hwndName = NULL; // filename window handle
- HWND hwndPlay = NULL; // "Play" button window handle
- HWND hwndQuit = NULL; // "Exit" button window handle
- HWAVEOUT hWaveOut = NULL;
- LPWAVEHDR lpWaveHdr = NULL;
- HPSTR lpData = NULL; // waveform data block
- LPSTR lpstrLoadStrBuf = NULL;
-
- /* WinMain - Entry point for Reverse.
- */
- int PASCAL WinMain(
- HINSTANCE hInst,
- HINSTANCE hPrev,
- LPSTR szCmdLine,
- int cmdShow)
- {
- MSG msg;
- WNDCLASS wc;
-
- hInstApp = hInst;
-
- /* Define and register a window class for the main window.
- */
- if (!hPrev)
- {
- wc.hCursor = LoadCursor(NULL, IDC_ARROW);
- wc.hIcon = LoadIcon(hInst, szAppName);
- wc.lpszMenuName = szAppName;
- wc.lpszClassName = szAppName;
- wc.hbrBackground = GetStockBrush(LTGRAY_BRUSH);
- wc.hInstance = hInst;
- wc.style = 0;
- wc.lpfnWndProc = WndProc;
- wc.cbWndExtra = 0;
- wc.cbClsExtra = 0;
-
- if (!RegisterClass(&wc))
- return FALSE;
- }
- // Keep string memory out of WIN16 DS.
- lpstrLoadStrBuf = GlobalAllocPtr(GMEM_MOVEABLE, LOADSTRBUFSIZE);
- if(lpstrLoadStrBuf == NULL)
- {
- // don't use LoadString here; it fails when memory is low
- MessageBox(NULL, GetStringRes(IDS_NOMEM),
- NULL, MB_OK | MB_ICONHAND | MB_SYSTEMMODAL);
- return FALSE;
- }
- /* Create and show the main window.
- */
- LoadString(hInstApp, IDS_REVERSEWNDTITLE, lpstrLoadStrBuf,
- LOADSTRBUFSIZE);
- hwndApp = CreateWindow (szAppName, // class name
- lpstrLoadStrBuf, // title from string resource
- WS_OVERLAPPEDWINDOW, // style bits
- CW_USEDEFAULT, // x position
- CW_USEDEFAULT, // y position
- WMAIN_DX, // x size
- WMAIN_DY, // y size
- (HWND)NULL, // parent window
- (HMENU)NULL, // use class menu
- (HANDLE)hInst, // instance handle
- (LPSTR)NULL // no params to pass on
- );
- /* Create child windows for the "Play" and "Exit" buttons
- * and for an edit field to enter filenames.
- */
- LoadString(hInstApp, IDS_PLAYBUTTONTEXT, lpstrLoadStrBuf,
- LOADSTRBUFSIZE);
- hwndPlay = CreateWindow( "BUTTON", lpstrLoadStrBuf,
- WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
- PLAY_X, PLAY_Y,
- PLAY_DX, PLAY_DY,
- hwndApp, (HMENU)IDB_PLAY, hInstApp, NULL );
- if( !hwndPlay )
- return( FALSE );
-
- LoadString(hInstApp, IDS_EXITBUTTONTEXT, lpstrLoadStrBuf,
- LOADSTRBUFSIZE);
- hwndQuit = CreateWindow( "BUTTON", lpstrLoadStrBuf,
- WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
- QUIT_X, QUIT_Y,
- QUIT_DX, QUIT_DY,
- hwndApp, (HMENU)IDB_QUIT, hInstApp, NULL );
- if( !hwndQuit )
- return( FALSE );
-
- hwndName = CreateWindow("EDIT","",
- WS_CHILD|WS_VISIBLE|WS_BORDER|ES_AUTOHSCROLL,
- NAME_X, NAME_Y,
- NAME_DX, NAME_DY,
- hwndApp, (HMENU)IDE_NAME, hInstApp, NULL);
- if( !hwndName )
- return( FALSE );
- Edit_LimitText(hwndName, MAX_FILENAME_SIZE - 1);
-
- ShowWindow(hwndApp,cmdShow);
-
- /* Add about dialog to system menu.
- */
- LoadString(hInstApp, IDS_ABOUTMENUTEXT, lpstrLoadStrBuf,
- LOADSTRBUFSIZE);
- AppendMenu(GetSystemMenu(hwndApp, FALSE),
- MF_STRING | MF_ENABLED, IDM_ABOUT, lpstrLoadStrBuf);
-
-
- /* The main message processing loop. Nothing special here.
- */
- while (GetMessage(&msg,NULL,0,0))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
-
- return msg.wParam;
- }
-
-
- /* WndProc - Main window procedure function.
- */
- LONG FAR PASCAL WndProc(
- HWND hWnd,
- UINT msg,
- WPARAM wParam,
- LPARAM lParam)
- {
- switch (msg)
- {
- HANDLE_MSG(hWnd, WM_DESTROY, ReverseOnDestroy);
-
- HANDLE_MSG(hWnd, WM_SYSCOMMAND, ReverseOnSysCommand);
-
- case WM_SETFOCUS:
- SetFocus(hwndName);
- return 0;
-
- HANDLE_MSG(hWnd, WM_COMMAND, ReverseOnCommand);
- case MM_WOM_DONE:
- /* This message indicates a waveform data block has
- * been played and can be freed. Clean up the
- * preparation done previously on the header.
- */
- waveOutUnprepareHeader( (HWAVEOUT) wParam,
- (LPWAVEHDR) lParam, sizeof(WAVEHDR) );
-
- /* free all memory associated with the data block
- */
- cleanup();
- /* Close the waveform output device.
- */
- waveOutClose( (HWAVEOUT) wParam );
- hWaveOut = NULL;
-
- /* Reenable both button controls.
- */
- EnableWindow( hwndPlay, TRUE );
- EnableWindow( hwndQuit, TRUE );
- SetFocus(hwndName);
-
- break;
- }
- return MyDefProc(hWnd,msg,wParam,lParam);
- }
-
- void ReverseOnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
- {
- /* Process messages sent by the child window controls.
- */
- switch (id)
- {
- case IDE_NAME: // filename edit control
- return;
-
- case IDB_PLAY: // "Play" button
- if (codeNotify == BN_CLICKED)
- ReversePlay();
- break;
-
- case IDB_QUIT: // "Exit" button
- if (codeNotify == BN_CLICKED)
- PostQuitMessage(0);
- break;
- }
- FORWARD_WM_COMMAND(hwnd, id, hwndCtl, codeNotify, MyDefProc);
- }
-
- void ReverseOnDestroy(
- HWND hwnd)
- {
- if(lpstrLoadStrBuf)
- GlobalFreePtr(lpstrLoadStrBuf);
- if (hWaveOut)
- {
- waveOutReset(hWaveOut);
- waveOutUnprepareHeader(hWaveOut, lpWaveHdr,
- sizeof(WAVEHDR) );
- cleanup();
- waveOutClose(hWaveOut);
- }
- PostQuitMessage(0);
- FORWARD_WM_DESTROY(hwnd, MyDefProc);
- }
-
- void ReverseOnSysCommand(
- HWND hwnd,
- UINT cmd,
- int x,
- int y)
- {
- switch (cmd)
- {
- case IDM_ABOUT:
- /* Show ABOUTBOX dialog box.
- */
- DialogBox(hInstApp, "ABOUTBOX", hwnd, AppAbout);
- break;
- }
- FORWARD_WM_SYSCOMMAND(hwnd, cmd, x, y, MyDefProc);
- }
-
-
-
- /* AppAbout -- Dialog procedure for ABOUTBOX dialog box.
- */
- BOOL FAR PASCAL AppAbout(
- HWND hDlg,
- UINT msg,
- WPARAM wParam,
- LPARAM lParam)
- {
- switch (msg)
- {
- case WM_COMMAND:
- if (GET_WM_COMMAND_ID(wParam, lParam) == IDOK
- || GET_WM_COMMAND_ID(wParam, lParam)
- == IDCANCEL)
- EndDialog(hDlg,TRUE);
- break;
-
- case WM_INITDIALOG:
- return TRUE;
- }
- return FALSE;
- }
-
-
-
- /* ReversePlay - Gets a filename from the edit control, then uses
- * the multimedia file I/O services to read data from the requested
- * WAVE file. If the file is a proper WAVE file, ReversePlay() calls
- * the Interchange() function to reverse the order of the waveform
- * samples in the file. It then plays the reversed waveform data.
- *
- * Note that ReversePlay() only handles a single waveform data block.
- * If the requested WAVE file will not fit in a single data block, it
- * will not be played. The size of a single data block depends on the
- * amount of available system memory.
- *
- * Params: void
- *
- * Return: void
- */
- void ReversePlay()
- {
- HMMIO hmmio;
- MMCKINFO mmckinfoParent;
- MMCKINFO mmckinfoSubchunk;
- DWORD dwFmtSize;
- char szFileName[ MAX_FILENAME_SIZE ];
- DWORD dwResult;
- HANDLE hFormat;
- WAVEFORMATEX *pFormat;
- DWORD dwDataSize;
- HPSTR hpch1, hpch2;
- WORD wBlockSize;
- HANDLE hData = NULL;
-
- /* Get the filename from the edit control.
- */
- if (!GetWindowText( hwndName, (LPSTR)szFileName, MAX_FILENAME_SIZE))
- {
- LoadString(hInstApp, IDS_FAILEDTOGETFNAME, lpstrLoadStrBuf,
- LOADSTRBUFSIZE);
- MessageBox(hwndApp, lpstrLoadStrBuf,
- NULL, MB_OK | MB_ICONEXCLAMATION);
- return;
- }
-
- /* Open the given file for reading using buffered I/O.
- */
- if(!(hmmio = mmioOpen(szFileName, NULL, MMIO_READ | MMIO_ALLOCBUF)))
- {
- LoadString(hInstApp, IDS_FAILEDTOOPENFILE, lpstrLoadStrBuf,
- LOADSTRBUFSIZE);
- MessageBox(hwndApp, lpstrLoadStrBuf,
- NULL, MB_OK | MB_ICONEXCLAMATION);
- return;
- }
-
- /* Locate a 'RIFF' chunk with a 'WAVE' form type
- * to make sure it's a WAVE file.
- */
- mmckinfoParent.fccType = mmioFOURCC('W', 'A', 'V', 'E');
- if (mmioDescend(hmmio, &mmckinfoParent, NULL, MMIO_FINDRIFF))
- {
- LoadString(hInstApp, IDS_NOTAWAVEFILE, lpstrLoadStrBuf,
- LOADSTRBUFSIZE);
- MessageBox(hwndApp, lpstrLoadStrBuf,
- NULL, MB_OK | MB_ICONEXCLAMATION);
- mmioClose(hmmio, 0);
- return;
- }
-
- /* Now, find the format chunk (form type 'fmt '). It should be
- * a subchunk of the 'RIFF' parent chunk.
- */
- mmckinfoSubchunk.ckid = mmioFOURCC('f', 'm', 't', ' ');
- if (mmioDescend(hmmio, &mmckinfoSubchunk, &mmckinfoParent,
- MMIO_FINDCHUNK))
- {
- LoadString(hInstApp, IDS_WAVEFILECORRUPT, lpstrLoadStrBuf,
- LOADSTRBUFSIZE);
- MessageBox(hwndApp, lpstrLoadStrBuf,
- NULL, MB_OK | MB_ICONEXCLAMATION);
- mmioClose(hmmio, 0);
- return;
- }
-
- /* Get the size of the format chunk, allocate and lock memory for it.
- */
- dwFmtSize = mmckinfoSubchunk.cksize;
- hFormat = LocalAlloc(LMEM_MOVEABLE, LOWORD(dwFmtSize));
- if (!hFormat)
- {
- MessageBox(hwndApp, GetStringRes(IDS_NOMEM),
- NULL, MB_OK | MB_ICONEXCLAMATION);
- mmioClose(hmmio, 0);
- return;
- }
- pFormat = (WAVEFORMATEX *) LocalLock(hFormat);
- if (!pFormat)
- {
- MessageBox(hwndApp, GetStringRes(IDS_NOMEM_LK),
- NULL, MB_OK | MB_ICONEXCLAMATION);
- LocalFree( hFormat );
- mmioClose(hmmio, 0);
- return;
- }
-
- /* Read the format chunk.
- */
- if (mmioRead(hmmio, (HPSTR) pFormat, dwFmtSize) != (LONG) dwFmtSize)
- {
- LoadString(hInstApp, IDS_FAILEDREADFMTCHNK, lpstrLoadStrBuf,
- LOADSTRBUFSIZE);
- MessageBox(hwndApp, lpstrLoadStrBuf,
- NULL, MB_OK | MB_ICONEXCLAMATION);
- LocalUnlock( hFormat );
- LocalFree( hFormat );
- mmioClose(hmmio, 0);
- return;
- }
-
- /* Make sure it's a PCM file.
- */
- if (pFormat->wFormatTag != WAVE_FORMAT_PCM)
- {
- LocalUnlock( hFormat );
- LocalFree( hFormat );
- mmioClose(hmmio, 0);
- LoadString(hInstApp, IDS_NOTAPCMFILE, lpstrLoadStrBuf,
- LOADSTRBUFSIZE);
- MessageBox(hwndApp, lpstrLoadStrBuf,
- NULL, MB_OK | MB_ICONEXCLAMATION);
- return;
- }
-
- /* Make sure a waveform output device supports this format.
- */
- #if (WINVER >= 0x0400)
- if (waveOutOpen(&hWaveOut, WAVE_MAPPER, pFormat, 0, 0L,
- WAVE_FORMAT_QUERY))
- #else
- if (waveOutOpen(&hWaveOut, WAVE_MAPPER, (LPWAVEFORMAT)pFormat, 0, 0L,
- WAVE_FORMAT_QUERY))
- #endif
- {
- LocalUnlock( hFormat );
- LocalFree( hFormat );
- mmioClose(hmmio, 0);
- LoadString(hInstApp, IDS_CANTPLAYFORMAT, lpstrLoadStrBuf,
- LOADSTRBUFSIZE);
- MessageBox(hwndApp, lpstrLoadStrBuf,
- NULL, MB_OK | MB_ICONEXCLAMATION);
- return;
- }
-
- /* Ascend out of the format subchunk.
- */
- mmioAscend(hmmio, &mmckinfoSubchunk, 0);
-
- /* Find the data subchunk.
- */
- mmckinfoSubchunk.ckid = mmioFOURCC('d', 'a', 't', 'a');
- if (mmioDescend(hmmio, &mmckinfoSubchunk, &mmckinfoParent,
- MMIO_FINDCHUNK))
- {
- LoadString(hInstApp, IDS_NODATACHUNK, lpstrLoadStrBuf,
- LOADSTRBUFSIZE);
- MessageBox(hwndApp, lpstrLoadStrBuf,
- NULL, MB_OK | MB_ICONEXCLAMATION);
- LocalUnlock( hFormat );
- LocalFree( hFormat );
- mmioClose(hmmio, 0);
- return;
- }
-
- /* Get the size of the data subchunk.
- */
- dwDataSize = mmckinfoSubchunk.cksize;
- if (dwDataSize == 0L)
- {
- LoadString(hInstApp, IDS_CHUNKHASNODATA, lpstrLoadStrBuf,
- LOADSTRBUFSIZE);
- MessageBox(hwndApp, lpstrLoadStrBuf,
- NULL, MB_OK | MB_ICONEXCLAMATION);
- LocalUnlock( hFormat );
- LocalFree( hFormat );
- mmioClose(hmmio, 0);
- return;
- }
-
- /* Open a waveform output device.
- */
- #if (WINVER >= 0x0400)
- if (waveOutOpen(&hWaveOut, WAVE_MAPPER,
- pFormat, (UINT)hwndApp, 0L, CALLBACK_WINDOW))
- #else
- if (waveOutOpen(&hWaveOut, WAVE_MAPPER,
- (LPWAVEFORMAT)pFormat, (UINT)hwndApp, 0L, CALLBACK_WINDOW))
- #endif
- {
- LoadString(hInstApp, IDS_FAILEDOPENDEVICE, lpstrLoadStrBuf,
- LOADSTRBUFSIZE);
- MessageBox(hwndApp, lpstrLoadStrBuf,
- NULL, MB_OK | MB_ICONEXCLAMATION);
- LocalUnlock( hFormat );
- LocalFree( hFormat );
- mmioClose(hmmio, 0);
- return;
- }
-
- /* Save block alignment info for later use.
- */
- wBlockSize = pFormat->nBlockAlign;
-
- /* We're done with the format header, free it.
- */
- LocalUnlock( hFormat );
- LocalFree( hFormat );
-
- /* Allocate and lock memory for the waveform data.
- */
- lpData = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_SHARE, dwDataSize );
- if (!lpData)
- {
- MessageBox(hwndApp, GetStringRes(IDS_NOMEM_DT),
- NULL, MB_OK | MB_ICONEXCLAMATION);
- mmioClose(hmmio, 0);
- return;
- }
-
- /* Read the waveform data subchunk.
- */
- if(mmioRead(hmmio, lpData, dwDataSize) != (LONG) dwDataSize)
- {
- LoadString(hInstApp, IDS_FAILEDREADCHUNK, lpstrLoadStrBuf,
- LOADSTRBUFSIZE);
- MessageBox(hwndApp, lpstrLoadStrBuf,
- NULL, MB_OK | MB_ICONEXCLAMATION);
- GlobalFreePtr( lpData );
- mmioClose(hmmio, 0);
- return;
- }
-
- /* We're done with the file, close it.
- */
- mmioClose(hmmio, 0);
-
- /* Reverse the sound for playing.
- */
- hpch1 = lpData;
- hpch2 = lpData + dwDataSize - 1;
- while (hpch1 < hpch2)
- {
- Interchange( hpch1, hpch2, wBlockSize );
- hpch1 += wBlockSize;
- hpch2 -= wBlockSize;
- }
-
- /* Allocate a waveform data header. The WAVEHDR must be
- * globally allocated and locked.
- */
- lpWaveHdr = (LPWAVEHDR)GlobalAllocPtr(GMEM_MOVEABLE | GMEM_SHARE,
- (DWORD) sizeof(WAVEHDR));
- if (!lpWaveHdr)
- {
- GlobalFreePtr( lpData );
- MessageBox(hwndApp, GetStringRes(IDS_NOMEM_HR),
- NULL, MB_OK | MB_ICONEXCLAMATION);
- return;
- }
-
- /* If you need instance data for a waveform data block, allocate some
- * memory and store the pointer in lpWaveHdr->dwUser, before the call
- * to waveOutPrepareHeader(). The code inside the #if 0 / #endif, and
- * the commented-out lpWaveHdr->dwUser = ... illustrate this.
- * Don't forget to free the instance memory when you're done with it,
- * or on error bailout.
- */
- #if 0
- lpYourData = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_SHARE, sizeof(YOURDATA));
- if (!lpYourData)
- {
- GlobalFreePtr( lpData );
- GlobalFreePtr( lpWaveHdr );
- MessageBox(hwndApp, GetStringRes(IDS_NOMEM_IS),
- NULL, MB_OK | MB_ICONEXCLAMATION);
- return;
- }
- #endif
- /* Set up WAVEHDR structure and prepare it to be written to wave device.
- */
- lpWaveHdr->lpData = lpData;
- lpWaveHdr->dwBufferLength = dwDataSize;
- lpWaveHdr->dwFlags = 0L;
- lpWaveHdr->dwLoops = 0L;
- // lpWaveHdr->dwUser = (DWORD) lpYourData; // save instance data ptr
- if(waveOutPrepareHeader(hWaveOut, lpWaveHdr, sizeof(WAVEHDR)))
- {
- cleanup();
- LoadString(hInstApp, IDS_UNABLEPREPAREHDR, lpstrLoadStrBuf,
- LOADSTRBUFSIZE);
- MessageBox(hwndApp, lpstrLoadStrBuf,
- NULL, MB_OK | MB_ICONEXCLAMATION);
-
- return;
- }
-
- /* Then the data block can be sent to the output device.
- */
- dwResult = waveOutWrite(hWaveOut, lpWaveHdr, sizeof(WAVEHDR));
- if (dwResult != 0)
- {
- waveOutUnprepareHeader( hWaveOut, lpWaveHdr, sizeof(WAVEHDR));
- cleanup();
- LoadString(hInstApp, IDS_FAILEDWRITEDEVICE, lpstrLoadStrBuf,
- LOADSTRBUFSIZE);
- MessageBox(hwndApp, lpstrLoadStrBuf,
- NULL, MB_OK | MB_ICONEXCLAMATION);
- return;
- }
-
- /* Disable input to the button controls.
- */
- EnableWindow(hwndPlay, FALSE);
- EnableWindow(hwndQuit, FALSE);
- }
-
- /* Interchange - Interchanges two samples at the given positions.
- *
- * Params: hpchPos1 - Points to one sample.
- * hpchPos2 - Points to the other sample.
- * wLength - The length of a sample in bytes.
- *
- * Return: void
- */
- void Interchange(
- HPSTR hpchPos1,
- HPSTR hpchPos2,
- WORD wLength)
- {
- WORD wPlace;
- BYTE bTemp;
-
- for (wPlace = 0; wPlace < wLength; wPlace++)
- {
- bTemp = hpchPos1[wPlace];
- hpchPos1[wPlace] = hpchPos2[wPlace];
- hpchPos2[wPlace] = bTemp;
- }
- }
-
- VOID cleanup(void)
- {
- // if you add wave instance data, this is a good place to free it.
- GlobalFreePtr( lpWaveHdr );
- GlobalFreePtr( lpData );
- }
-
-
- /******************************************************************************\
- *
- * FUNCTION: GetStringRes (int id INPUT ONLY)
- *
- * COMMENTS: Load the resource string with the ID given, and return a
- * pointer to it. Notice that the buffer is common memory so
- * the string must be used before this call is made a second time.
- *
- \******************************************************************************/
-
- LPTSTR GetStringRes (int id)
- {
- static TCHAR buffer[MAX_PATH];
-
- buffer[0]=0;
- LoadString (GetModuleHandle (NULL), id, buffer, MAX_PATH);
- return buffer;
- }
-