home *** CD-ROM | disk | FTP | other *** search
- /*
- * REVERSE.C -- Plays a WAVE file backwards.
- *
- * (C) Copyright Microsoft Corp. 1991. All rights reserved.
- *
- * You have a royalty-free right to use, modify, reproduce and
- * distribute the Sample Files (and/or any modified version) in
- * any way you find useful, provided that you agree that
- * Microsoft has no warranty obligations or liability for any
- * Sample Application Files which are modified.
- *
- */
-
- #include <windows.h>
- #include <mmsystem.h>
- #include "reverse.h"
-
- #define MAX_FILENAME_SIZE 80
-
- /*
- * 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; // "Quit" button window handle
- HANDLE hData = NULL; // handle to waveform data memory
- HPSTR lpData = NULL; // pointer to waveform data memory
-
-
- /* WinMain - Entry point for Reverse.
- */
- int PASCAL WinMain(hInst, hPrev, szCmdLine, cmdShow)
- HANDLE hInst;
- HANDLE hPrev;
- LPSTR szCmdLine;
- WORD 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 = GetStockObject(LTGRAY_BRUSH);
- wc.hInstance = hInst;
- wc.style = 0;
- wc.lpfnWndProc = WndProc;
- wc.cbWndExtra = 0;
- wc.cbClsExtra = 0;
-
- if (!RegisterClass(&wc))
- return FALSE;
- }
-
- /* Create and show the main window.
- */
- hwndApp = CreateWindow (szAppName, // class name
- szAppName, // caption
- 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
- );
- ShowWindow(hwndApp,cmdShow);
-
- /* Create child windows for the "Play" and "Quit" buttons
- * and for an edit field to enter filenames.
- */
- hwndPlay = CreateWindow( "BUTTON", "Play",
- WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
- PLAY_X, PLAY_Y,
- PLAY_DX, PLAY_DY,
- hwndApp, IDB_PLAY, hInstApp, NULL );
- if( !hwndPlay )
- return( FALSE );
-
- hwndQuit = CreateWindow( "BUTTON", "Quit",
- WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
- QUIT_X, QUIT_Y,
- QUIT_DX, QUIT_DY,
- hwndApp, IDB_QUIT, hInstApp, NULL );
- if( !hwndQuit )
- return( FALSE );
-
- hwndName = CreateWindow("EDIT","",
- WS_CHILD|WS_VISIBLE|WS_BORDER,
- NAME_X, NAME_Y,
- NAME_DX, NAME_DY,
- hwndApp, IDE_NAME, hInstApp, NULL);
- if( !hwndName )
- return( FALSE );
-
-
- /* Enable the buttons for mouse input.
- */
- EnableWindow( hwndPlay, TRUE );
- EnableWindow( hwndQuit, TRUE );
-
- /* Add about dialog
- */
- AppendMenu(GetSystemMenu(hwndApp, NULL),
- MF_STRING | MF_ENABLED, IDM_ABOUT, "About Reverse...");
-
-
- /* 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, msg, wParam, lParam)
- HWND hWnd;
- unsigned msg;
- WORD wParam;
- LONG lParam;
- {
- FARPROC fpfn;
-
- switch (msg)
- {
- case WM_DESTROY:
- PostQuitMessage(0);
- break;
-
- case WM_SYSCOMMAND:
- switch (wParam)
- {
- case IDM_ABOUT:
- fpfn = MakeProcInstance(AppAbout, hInstApp);
- DialogBox(hInstApp, "ABOUTBOX", hWnd, fpfn);
- FreeProcInstance(fpfn);
- break;
- }
- break;
- /* Process messages sent by the child window controls.
- */
-
- case WM_COMMAND:
- switch (wParam)
- {
- case IDE_NAME:
- return( 0L );
-
- case IDB_PLAY:
- ReversePlay();
- break;
-
- case IDB_QUIT:
- PostQuitMessage(0);
- break;
- }
- return( 0L );
-
- case MM_WOM_DONE:
- /* This message indicates a waveform data block has
- * been played and can be freed.
- */
- waveOutUnprepareHeader( (HWAVEOUT) wParam,
- (LPWAVEHDR) lParam, sizeof(WAVEHDR) );
- GlobalUnlock( hData );
- GlobalFree( hData );
- waveOutClose( (HWAVEOUT) wParam );
-
- /* Reenable both button controls.
- */
- EnableWindow( hwndPlay, TRUE );
- EnableWindow( hwndQuit, TRUE );
-
- break;
- }
-
- return DefWindowProc(hWnd,msg,wParam,lParam);
- }
-
-
- /* AppAbout -- Handles "About" dialog box message handling.
- *
- * Params: Standard parameters passed to dialog box function.
- */
- BOOL FAR PASCAL AppAbout(HWND hDlg, unsigned msg, WORD wParam, LONG lParam)
- {
- switch (msg) {
- case WM_COMMAND:
- if (wParam == IDOK)
- {
- EndDialog(hDlg,TRUE);
- }
- break;
-
- case WM_INITDIALOG:
- return TRUE;
- }
- return FALSE;
- }
-
-
- /* ReversePlay - Gets a filename from the edit control, loads the
- * file, and checks to see if it is a proper WAVE file. It then
- * plays the file backwards.
- *
- * Params: void
- *
- * Return: void
- */
- void ReversePlay()
- {
- HWAVEOUT hWaveOut;
- HANDLE hWaveHdr;
- LPWAVEHDR lpWaveHdr;
- HMMIO hmmio;
- MMCKINFO mmckinfoParent;
- MMCKINFO mmckinfoSubchunk;
- DWORD dwFmtSize;
- char szFileName[ MAX_FILENAME_SIZE ];
- WORD wResult;
- HANDLE hFormat;
- WAVEFORMAT *pFormat;
- DWORD dwDataSize;
- HPSTR hpch1, hpch2;
- WORD wBlockSize;
-
-
- /* Get the filename from the edit control.
- */
- if (!GetWindowText( hwndName, (LPSTR)szFileName, MAX_FILENAME_SIZE))
- {
- MessageBox(hwndApp, "Failed to Get Filename",
- 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)))
- {
- MessageBox(hwndApp, "Failed to open file.",
- 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, (LPMMCKINFO) &mmckinfoParent, NULL, MMIO_FINDRIFF))
- {
- MessageBox(hwndApp, "This is not a WAVE file.",
- 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))
- {
- MessageBox(hwndApp, "WAVE file is corrupted.",
- 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, "Out of memory.",
- NULL, MB_OK | MB_ICONEXCLAMATION);
- mmioClose(hmmio, 0);
- return;
- }
- pFormat = (WAVEFORMAT *) LocalLock(hFormat);
- if (!pFormat)
- {
- MessageBox(hwndApp, "Failed to lock memory for format chunk.",
- NULL, MB_OK | MB_ICONEXCLAMATION);
- LocalFree( hFormat );
- mmioClose(hmmio, 0);
- return;
- }
-
- /* Read the format chunk.
- */
- if (mmioRead(hmmio, (HPSTR) pFormat, dwFmtSize) != dwFmtSize)
- {
- MessageBox(hwndApp, "Failed to read format chunk.",
- 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);
- MessageBox(hwndApp, "The file is not a PCM file.",
- NULL, MB_OK | MB_ICONEXCLAMATION);
- return;
- }
-
- /* Make sure a waveform output device supports this format.
- */
- if (waveOutOpen(&hWaveOut, WAVE_MAPPER, (LPWAVEFORMAT)pFormat, NULL, 0L,
- WAVE_FORMAT_QUERY))
- {
- LocalUnlock( hFormat );
- LocalFree( hFormat );
- mmioClose(hmmio, 0);
- MessageBox(hwndApp, "The waveform device can't play this format.",
- 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))
- {
- MessageBox(hwndApp, "WAVE file has no data chunk.",
- 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)
- {
- MessageBox(hwndApp, "The data chunk has no data.",
- NULL, MB_OK | MB_ICONEXCLAMATION);
- LocalUnlock( hFormat );
- LocalFree( hFormat );
- mmioClose(hmmio, 0);
- return;
- }
-
- /* Open a waveform output device.
- */
- if (waveOutOpen( (LPHWAVEOUT)&hWaveOut, WAVE_MAPPER,
- (LPWAVEFORMAT)pFormat,
- (LONG)hwndApp, 0L, CALLBACK_WINDOW))
- {
- MessageBox(hwndApp, "Failed to open waveform output device.",
- NULL, MB_OK | MB_ICONEXCLAMATION);
- LocalUnlock( hFormat );
- LocalFree( hFormat );
- mmioClose(hmmio, 0);
- return;
- }
-
- wBlockSize = pFormat->nBlockAlign;
-
- /* We're done with the format header, free it.
- */
- LocalUnlock( hFormat );
- LocalFree( hFormat );
-
- /* Allocate and lock memory for the waveform data.
- */
- hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, dwDataSize );
- if (!hData)
- {
- MessageBox(hwndApp, "Out of memory.",
- NULL, MB_OK | MB_ICONEXCLAMATION);
- mmioClose(hmmio, 0);
- return;
- }
- lpData = GlobalLock(hData);
- if (!lpData)
- {
- MessageBox(hwndApp, "Failed to lock memory for data chunk.",
- NULL, MB_OK | MB_ICONEXCLAMATION);
- GlobalFree( hData );
- mmioClose(hmmio, 0);
- return;
- }
-
- /* Read the waveform data subchunk.
- */
- if(mmioRead(hmmio, (HPSTR) lpData, dwDataSize) != dwDataSize)
- {
- MessageBox(hwndApp, "Failed to read data chunk.",
- NULL, MB_OK | MB_ICONEXCLAMATION);
- GlobalUnlock( hData );
- GlobalFree( hData );
- 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;
- }
-
- /* The WAVEHDR must be globally allocated and locked.
- */
- hWaveHdr = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE | GMEM_NOT_BANKED,
- (DWORD) sizeof(WAVEHDR));
- if (!hWaveHdr)
- {
- GlobalUnlock( hData );
- GlobalFree( hData );
- MessageBox(hwndApp, "Not enough memory for header.",
- NULL, MB_OK | MB_ICONEXCLAMATION);
- return;
- }
- lpWaveHdr = (LPWAVEHDR) GlobalLock(hWaveHdr);
- if (!lpWaveHdr)
- {
- GlobalUnlock( hData );
- GlobalFree( hData );
- MessageBox(hwndApp, "Failed to lock memory for header.",
- NULL, MB_OK | MB_ICONEXCLAMATION);
- return;
- }
-
- /* After allocation, the data and header must be prepared for use.
- */
- lpWaveHdr->lpData = lpData;
- lpWaveHdr->dwBufferLength = dwDataSize;
- lpWaveHdr->dwFlags = 0L;
- lpWaveHdr->dwLoops = 0L;
- waveOutPrepareHeader(hWaveOut, lpWaveHdr, sizeof(WAVEHDR));
-
- /* Then the data block can be sent to the output device.
- */
- wResult = waveOutWrite(hWaveOut, lpWaveHdr, sizeof(WAVEHDR));
- if (wResult != 0)
- {
- waveOutUnprepareHeader( hWaveOut, lpWaveHdr, sizeof(WAVEHDR));
- GlobalUnlock( hData );
- GlobalFree( hData );
- MessageBox(hwndApp, "Failed to write block to device",
- 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(hpchPos1, hpchPos2, wLength)
- 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;
- }
- }
-
-
-