home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c480 / 18.ddi / SAMPLES / REVERSE / REVERSE.C_ / REVERSE.C
Encoding:
C/C++ Source or Header  |  1993-02-08  |  18.4 KB  |  597 lines

  1. /* reverse.c - WinMain() and WndProc() for REVERSE, along with
  2.  *      initialization and support code.
  3.  *
  4.  * REVERSE is a Windows with Multimedia sample application that 
  5.  *  illustrates how to use the low-level waveform playback services.
  6.  *  It also shows how to use the multimedia file I/O services to read 
  7.  *  data from a WAVE file.
  8.  *
  9.  *  REVERSE plays a WAVE waveform audio file backwards.
  10.  *
  11.  *    (C) Copyright Microsoft Corp. 1991.  All rights reserved.
  12.  *
  13.  *    You have a royalty-free right to use, modify, reproduce and 
  14.  *    distribute the Sample Files (and/or any modified version) in 
  15.  *    any way you find useful, provided that you agree that 
  16.  *    Microsoft has no warranty obligations or liability for any 
  17.  *    Sample Application Files which are modified. 
  18.  *
  19.  */
  20.  
  21. #include <windows.h>
  22. #include <mmsystem.h>
  23. #include "reverse.h"
  24.  
  25. #define MAX_FILENAME_SIZE   128
  26.  
  27. /* Global variables.
  28.  */
  29. char        szAppName[] = "Reverse";    // application name
  30. HANDLE      hInstApp    = NULL;         // instance handle
  31. HWND        hwndApp     = NULL;         // main window handle
  32. HWND        hwndName    = NULL;         // filename window handle
  33. HWND        hwndPlay    = NULL;         // "Play" button window handle
  34. HWND        hwndQuit    = NULL;         // "Exit" button window handle
  35. HWAVEOUT    hWaveOut    = NULL;
  36. LPWAVEHDR   lpWaveHdr   = NULL;    
  37. VOID        cleanup(LPWAVEINST lpWaveInst);
  38.  
  39.  
  40. /* WinMain - Entry point for Reverse.
  41.  */
  42. int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int cmdShow)
  43. {
  44.     MSG         msg;
  45.     WNDCLASS    wc;
  46.     
  47.     hInstApp =  hInst;
  48.  
  49.     /* Define and register a window class for the main window.
  50.      */
  51.     if (!hPrev)
  52.     {
  53.         wc.hCursor        = LoadCursor(NULL, IDC_ARROW);
  54.         wc.hIcon          = LoadIcon(hInst, szAppName);
  55.         wc.lpszMenuName   = szAppName;
  56.         wc.lpszClassName  = szAppName;
  57.         wc.hbrBackground  = GetStockObject(LTGRAY_BRUSH);
  58.         wc.hInstance      = hInst;
  59.         wc.style          = 0;
  60.         wc.lpfnWndProc    = WndProc;
  61.         wc.cbWndExtra     = 0;
  62.         wc.cbClsExtra     = 0;
  63.  
  64.         if (!RegisterClass(&wc))
  65.         return FALSE;
  66.     }
  67.  
  68.     /* Create and show the main window.
  69.      */
  70.     hwndApp = CreateWindow (szAppName,              // class name
  71.                             szAppName,              // caption
  72.                             WS_OVERLAPPEDWINDOW,    // style bits
  73.                             CW_USEDEFAULT,          // x position
  74.                             CW_USEDEFAULT,          // y position
  75.                             WMAIN_DX,               // x size
  76.                             WMAIN_DY,               // y size
  77.                             (HWND)NULL,             // parent window
  78.                             (HMENU)NULL,            // use class menu
  79.                             (HANDLE)hInst,          // instance handle
  80.                             (LPSTR)NULL             // no params to pass on
  81.                            );
  82.     /* Create child windows for the "Play" and "Exit" buttons
  83.      * and for an edit field to enter filenames.
  84.      */
  85.     hwndPlay = CreateWindow( "BUTTON", "Play", 
  86.             WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
  87.             PLAY_X, PLAY_Y,
  88.             PLAY_DX, PLAY_DY,
  89.             hwndApp, (HMENU)IDB_PLAY, hInstApp, NULL );
  90.     if( !hwndPlay )
  91.         return( FALSE );
  92.  
  93.     hwndQuit = CreateWindow( "BUTTON", "Exit",
  94.             WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
  95.             QUIT_X, QUIT_Y,
  96.             QUIT_DX, QUIT_DY,
  97.             hwndApp, (HMENU)IDB_QUIT, hInstApp, NULL );
  98.     if( !hwndQuit )
  99.         return( FALSE );
  100.  
  101.     hwndName = CreateWindow("EDIT","",
  102.             WS_CHILD|WS_VISIBLE|WS_BORDER|ES_AUTOHSCROLL,
  103.             NAME_X, NAME_Y,
  104.             NAME_DX, NAME_DY,
  105.             hwndApp, (HMENU)IDE_NAME, hInstApp, NULL);
  106.     if( !hwndName )
  107.         return( FALSE );
  108.     SendMessage(hwndName, EM_LIMITTEXT, MAX_FILENAME_SIZE - 1, 0);
  109.  
  110.     ShowWindow(hwndApp,cmdShow);
  111.  
  112.     /* Add about dialog to system menu.
  113.      */
  114.     AppendMenu(GetSystemMenu(hwndApp, NULL),
  115.         MF_STRING | MF_ENABLED, IDM_ABOUT, "About Reverse...");
  116.  
  117.  
  118.   /* The main message processing loop. Nothing special here.
  119.    */
  120.   while (GetMessage(&msg,NULL,0,0))
  121.   {
  122.       TranslateMessage(&msg);
  123.       DispatchMessage(&msg);
  124.   }
  125.   
  126.   return msg.wParam;
  127. }
  128.  
  129.  
  130. /* WndProc - Main window procedure function.
  131.  */
  132. LONG FAR PASCAL __export WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  133. {
  134.     FARPROC fpfn;
  135.     LPWAVEINST lpWaveInst;
  136.  
  137.     switch (msg)
  138.     {
  139.     case WM_DESTROY:
  140.         if (hWaveOut)
  141.     {
  142.        waveOutReset(hWaveOut);      
  143.            waveOutUnprepareHeader(hWaveOut, lpWaveHdr, sizeof(WAVEHDR) );
  144.            lpWaveInst = (LPWAVEINST) lpWaveHdr->dwUser;
  145.        cleanup(lpWaveInst);
  146.            waveOutClose(hWaveOut);      
  147.         }
  148.         PostQuitMessage(0);
  149.         break;
  150.  
  151.     case WM_SYSCOMMAND:
  152.         switch (wParam)
  153.         {
  154.         case IDM_ABOUT:
  155.             /* Show ABOUTBOX dialog box.
  156.              */
  157.             fpfn = MakeProcInstance((FARPROC)AppAbout, hInstApp);
  158.             DialogBox(hInstApp, "ABOUTBOX", hWnd, (DLGPROC)fpfn);
  159.             FreeProcInstance(fpfn);
  160.             break;
  161.         }
  162.         break;
  163.                 
  164.     /* Process messages sent by the child window controls.
  165.      */
  166.     case WM_SETFOCUS:
  167.         SetFocus(hwndName);
  168.         return 0;
  169.  
  170.     case WM_COMMAND:
  171.         switch (wParam)
  172.         {
  173.         case IDE_NAME:              // filename edit control
  174.             return( 0L );
  175.  
  176.         case IDB_PLAY:              // "Play" button
  177.             if (HIWORD(lParam) == BN_CLICKED)
  178.                 ReversePlay();
  179.             break;
  180.  
  181.         case IDB_QUIT:              // "Exit" button
  182.             if (HIWORD(lParam) == BN_CLICKED)
  183.                 PostQuitMessage(0);
  184.             break;
  185.         }
  186.         return( 0L );
  187.  
  188.     case MM_WOM_DONE:
  189.         /* This message indicates a waveform data block has
  190.          * been played and can be freed. Clean up the preparation
  191.          * done previously on the header.
  192.          */
  193.         waveOutUnprepareHeader( (HWAVEOUT) wParam,
  194.                                 (LPWAVEHDR) lParam, sizeof(WAVEHDR) );
  195.  
  196.         /* Get a pointer to the instance data, then unlock and free
  197.          * all memory associated with the data block, including the
  198.          * memory for the instance data itself.
  199.          */
  200.         lpWaveInst = (LPWAVEINST) ((LPWAVEHDR)lParam)->dwUser;
  201.     cleanup(lpWaveInst);
  202.         /* Close the waveform output device.
  203.          */
  204.         waveOutClose( (HWAVEOUT) wParam );
  205.             
  206.         /* Reenable both button controls.
  207.          */
  208.         EnableWindow( hwndPlay, TRUE );
  209.         EnableWindow( hwndQuit, TRUE );
  210.         SetFocus(hwndName);
  211.     
  212.         break;
  213.     }
  214.  
  215.     return DefWindowProc(hWnd,msg,wParam,lParam);
  216. }
  217.  
  218.  
  219. /* AppAbout -- Dialog procedure for ABOUTBOX  dialog box.
  220.  */
  221. BOOL FAR PASCAL __export AppAbout(HWND hDlg, unsigned msg, WORD wParam, LONG lParam)
  222. {
  223.     switch (msg)
  224.     {
  225.     case WM_COMMAND:
  226.         if (wParam == IDOK)
  227.             EndDialog(hDlg,TRUE);
  228.         break;
  229.  
  230.     case WM_INITDIALOG:
  231.         return TRUE;
  232.     }
  233.     return FALSE;
  234. }
  235.  
  236. /* ReversePlay - Gets a filename from the edit control, then uses
  237.  *  the multimedia file I/O services to read data from the requested
  238.  *  WAVE file. If the file is a proper WAVE file, ReversePlay() calls
  239.  *  the Interchange() function to reverse the order of the waveform
  240.  *  samples in the file. It then plays the reversed waveform data.
  241.  * 
  242.  *  Note that ReversePlay() only handles a single waveform data block.
  243.  *  If the requested WAVE file will not fit in a single data block, it
  244.  *  will not be played. The size of a single data block depends on the
  245.  *  amount of available system memory.
  246.  *
  247.  * Params:  void
  248.  *
  249.  * Return:  void
  250.  */
  251. void ReversePlay() 
  252. {
  253.     HANDLE          hWaveHdr;
  254.     LPWAVEINST      lpWaveInst;    
  255.     HMMIO           hmmio;
  256.     MMCKINFO        mmckinfoParent;
  257.     MMCKINFO        mmckinfoSubchunk;
  258.     DWORD           dwFmtSize;
  259.     char            szFileName[ MAX_FILENAME_SIZE ];
  260.     WORD            wResult;
  261.     HANDLE          hFormat;
  262.     WAVEFORMAT      *pFormat;
  263.     DWORD           dwDataSize;
  264.     HPSTR           hpch1, hpch2;
  265.     WORD            wBlockSize;
  266.     HANDLE          hWaveInst;
  267.     HANDLE          hData       = NULL;
  268.     HPSTR           lpData      = NULL;
  269.         
  270.     /* Get the filename from the edit control.
  271.      */
  272.     if (!GetWindowText( hwndName, (LPSTR)szFileName, MAX_FILENAME_SIZE))
  273.     {
  274.         MessageBox(hwndApp, "Failed to Get Filename",
  275.                    NULL, MB_OK | MB_ICONEXCLAMATION);
  276.         return;
  277.     }
  278.     
  279.     /* Open the given file for reading using buffered I/O.
  280.      */
  281.     if(!(hmmio = mmioOpen(szFileName, NULL, MMIO_READ | MMIO_ALLOCBUF)))
  282.     {
  283.         MessageBox(hwndApp, "Failed to open file.",
  284.                    NULL, MB_OK | MB_ICONEXCLAMATION);
  285.         return;
  286.     }
  287.  
  288.     /* Locate a 'RIFF' chunk with a 'WAVE' form type 
  289.      * to make sure it's a WAVE file.
  290.      */
  291.     mmckinfoParent.fccType = mmioFOURCC('W', 'A', 'V', 'E');
  292.     if (mmioDescend(hmmio, (LPMMCKINFO) &mmckinfoParent, NULL, MMIO_FINDRIFF))
  293.     {
  294.         MessageBox(hwndApp, "This is not a WAVE file.",
  295.                    NULL, MB_OK | MB_ICONEXCLAMATION);
  296.         mmioClose(hmmio, 0);
  297.         return;
  298.     }
  299.     
  300.     /* Now, find the format chunk (form type 'fmt '). It should be
  301.      * a subchunk of the 'RIFF' parent chunk.
  302.      */
  303.     mmckinfoSubchunk.ckid = mmioFOURCC('f', 'm', 't', ' ');
  304.     if (mmioDescend(hmmio, &mmckinfoSubchunk, &mmckinfoParent, 
  305.         MMIO_FINDCHUNK))
  306.     {
  307.         MessageBox(hwndApp, "WAVE file is corrupted.",
  308.                    NULL, MB_OK | MB_ICONEXCLAMATION);
  309.         mmioClose(hmmio, 0);
  310.         return;
  311.     }
  312.  
  313.     /* Get the size of the format chunk, allocate and lock memory for it.
  314.      */
  315.     dwFmtSize = mmckinfoSubchunk.cksize;
  316.     hFormat = LocalAlloc(LMEM_MOVEABLE, LOWORD(dwFmtSize));
  317.     if (!hFormat)
  318.     {
  319.         MessageBox(hwndApp, "Out of memory.",
  320.                    NULL, MB_OK | MB_ICONEXCLAMATION);
  321.         mmioClose(hmmio, 0);
  322.         return;
  323.     }
  324.     pFormat = (WAVEFORMAT *) LocalLock(hFormat);
  325.     if (!pFormat)
  326.     {
  327.         MessageBox(hwndApp, "Failed to lock memory for format chunk.",
  328.                    NULL, MB_OK | MB_ICONEXCLAMATION);
  329.         LocalFree( hFormat );
  330.         mmioClose(hmmio, 0);
  331.         return;
  332.     }
  333.  
  334.     /* Read the format chunk.
  335.      */
  336.     if (mmioRead(hmmio, (HPSTR) pFormat, dwFmtSize) != (LONG) dwFmtSize)
  337.     {
  338.         MessageBox(hwndApp, "Failed to read format chunk.",
  339.                    NULL, MB_OK | MB_ICONEXCLAMATION);
  340.         LocalUnlock( hFormat );
  341.         LocalFree( hFormat );
  342.         mmioClose(hmmio, 0);
  343.         return;
  344.     }
  345.     
  346.     /* Make sure it's a PCM file.
  347.      */
  348.     if (pFormat->wFormatTag != WAVE_FORMAT_PCM)
  349.     {
  350.         LocalUnlock( hFormat );
  351.         LocalFree( hFormat );
  352.         mmioClose(hmmio, 0);
  353.         MessageBox(hwndApp, "The file is not a PCM file.",
  354.                    NULL, MB_OK | MB_ICONEXCLAMATION);
  355.         return;
  356.     }
  357.  
  358.     /* Make sure a waveform output device supports this format.
  359.      */
  360.     if (waveOutOpen(&hWaveOut, (UINT)WAVE_MAPPER, (LPWAVEFORMAT)pFormat, NULL, 0L,
  361.             (DWORD)WAVE_FORMAT_QUERY))
  362.     {
  363.         LocalUnlock( hFormat );
  364.         LocalFree( hFormat );
  365.         mmioClose(hmmio, 0);
  366.         MessageBox(hwndApp, "The waveform device can't play this format.",
  367.                    NULL, MB_OK | MB_ICONEXCLAMATION);
  368.         return;
  369.     }
  370.     
  371.     /* Ascend out of the format subchunk.
  372.      */
  373.     mmioAscend(hmmio, &mmckinfoSubchunk, 0);
  374.     
  375.     /* Find the data subchunk.
  376.      */
  377.     mmckinfoSubchunk.ckid = mmioFOURCC('d', 'a', 't', 'a');
  378.     if (mmioDescend(hmmio, &mmckinfoSubchunk, &mmckinfoParent,
  379.         MMIO_FINDCHUNK))
  380.     {
  381.         MessageBox(hwndApp, "WAVE file has no data chunk.",
  382.                    NULL, MB_OK | MB_ICONEXCLAMATION);
  383.         LocalUnlock( hFormat );
  384.         LocalFree( hFormat );
  385.         mmioClose(hmmio, 0);
  386.         return;
  387.     }
  388.  
  389.     /* Get the size of the data subchunk.
  390.      */
  391.     dwDataSize = mmckinfoSubchunk.cksize;
  392.     if (dwDataSize == 0L)
  393.     {
  394.         MessageBox(hwndApp, "The data chunk has no data.",
  395.                    NULL, MB_OK | MB_ICONEXCLAMATION);
  396.         LocalUnlock( hFormat );
  397.         LocalFree( hFormat );
  398.         mmioClose(hmmio, 0);
  399.         return;
  400.     }
  401.     
  402.     /* Open a waveform output device.
  403.      */
  404.     if (waveOutOpen((LPHWAVEOUT)&hWaveOut, (UINT)WAVE_MAPPER,
  405.           (LPWAVEFORMAT)pFormat, (UINT)hwndApp, 0L, (DWORD)CALLBACK_WINDOW))
  406.     {
  407.         MessageBox(hwndApp, "Failed to open waveform output device.",
  408.                    NULL, MB_OK | MB_ICONEXCLAMATION);
  409.         LocalUnlock( hFormat );
  410.         LocalFree( hFormat );
  411.         mmioClose(hmmio, 0);
  412.         return;
  413.     }
  414.  
  415.     /* Save block alignment info for later use.
  416.      */
  417.     wBlockSize = pFormat->nBlockAlign;
  418.  
  419.     /* We're done with the format header, free it.
  420.      */
  421.     LocalUnlock( hFormat );
  422.     LocalFree( hFormat );
  423.     
  424.     /* Allocate and lock memory for the waveform data.
  425.      */
  426.     hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, dwDataSize );
  427.     if (!hData)
  428.     {
  429.         MessageBox(hwndApp, "Out of memory.",
  430.                    NULL, MB_OK | MB_ICONEXCLAMATION);
  431.         mmioClose(hmmio, 0);
  432.         return;
  433.     }
  434.     lpData = GlobalLock(hData);
  435.     if (!lpData)
  436.     {
  437.         MessageBox(hwndApp, "Failed to lock memory for data chunk.",
  438.                    NULL, MB_OK | MB_ICONEXCLAMATION);
  439.         GlobalFree( hData );
  440.         mmioClose(hmmio, 0);
  441.         return;
  442.     }
  443.  
  444.     /* Read the waveform data subchunk.
  445.      */
  446.     if(mmioRead(hmmio, (HPSTR) lpData, dwDataSize) != (LONG) dwDataSize)
  447.     {
  448.         MessageBox(hwndApp, "Failed to read data chunk.",
  449.                    NULL, MB_OK | MB_ICONEXCLAMATION);
  450.         GlobalUnlock( hData );
  451.         GlobalFree( hData );
  452.         mmioClose(hmmio, 0);
  453.         return;
  454.     }
  455.  
  456.     /* We're done with the file, close it.
  457.      */
  458.     mmioClose(hmmio, 0);
  459.  
  460.     /* Reverse the sound for playing.
  461.      */
  462.     hpch1 = lpData;
  463.     hpch2 = lpData + dwDataSize - 1;
  464.     while (hpch1 < hpch2)
  465.     {
  466.         Interchange( hpch1, hpch2, wBlockSize );
  467.         hpch1 += wBlockSize;
  468.         hpch2 -= wBlockSize;
  469.     }
  470.     
  471.     /* Allocate a waveform data header. The WAVEHDR must be 
  472.      * globally allocated and locked.
  473.      */
  474.     hWaveHdr = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE,
  475.                            (DWORD) sizeof(WAVEHDR));
  476.     if (!hWaveHdr)
  477.     {
  478.         GlobalUnlock( hData );
  479.         GlobalFree( hData );
  480.         MessageBox(hwndApp, "Not enough memory for header.",
  481.                    NULL, MB_OK | MB_ICONEXCLAMATION);
  482.         return;
  483.     }
  484.     lpWaveHdr = (LPWAVEHDR) GlobalLock(hWaveHdr);
  485.     if (!lpWaveHdr)
  486.     {
  487.         GlobalUnlock( hData );
  488.         GlobalFree( hData );
  489.         GlobalFree( hWaveHdr );
  490.         MessageBox(hwndApp, "Failed to lock memory for header.",
  491.                    NULL, MB_OK | MB_ICONEXCLAMATION);
  492.         return;
  493.     }
  494.  
  495.     /* Allocate and set up instance data for waveform data block.
  496.      * This information is needed by the routine that frees the
  497.      * data block after it has been played.
  498.      */
  499.     hWaveInst = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE,
  500.                             (DWORD) sizeof(WAVEHDR));
  501.     if (!hWaveInst)
  502.     {
  503.         GlobalUnlock( hData );
  504.         GlobalFree( hData );
  505.         GlobalUnlock( hWaveHdr );
  506.         GlobalFree( hWaveHdr );
  507.         MessageBox(hwndApp, "Not enough memory for instance data.",
  508.                    NULL, MB_OK | MB_ICONEXCLAMATION);
  509.         return;
  510.     }
  511.     lpWaveInst = (LPWAVEINST) GlobalLock(hWaveInst);
  512.     if (!lpWaveInst)
  513.     {
  514.         GlobalUnlock( hData );
  515.         GlobalFree( hData );
  516.         GlobalUnlock( hWaveHdr );
  517.         GlobalFree( hWaveHdr );
  518.         GlobalFree( hWaveInst );
  519.         MessageBox(hwndApp, "Failed to lock memory for instance data.",
  520.                    NULL, MB_OK | MB_ICONEXCLAMATION);
  521.         return;
  522.     }
  523.     lpWaveInst->hWaveInst = hWaveInst;
  524.     lpWaveInst->hWaveHdr = hWaveHdr;
  525.     lpWaveInst->hWaveData = hData;
  526.         
  527.     /* Set up WAVEHDR structure and prepare it to be written to wave device.
  528.      */
  529.     lpWaveHdr->lpData = lpData;
  530.     lpWaveHdr->dwBufferLength = dwDataSize;
  531.     lpWaveHdr->dwFlags = 0L;
  532.     lpWaveHdr->dwLoops = 0L;
  533.     lpWaveHdr->dwUser = (DWORD) lpWaveInst;
  534.     if(waveOutPrepareHeader(hWaveOut, lpWaveHdr, sizeof(WAVEHDR)))
  535.     {
  536.         GlobalUnlock( hData );
  537.         GlobalFree( hData );
  538.         GlobalUnlock( hWaveHdr );
  539.         GlobalFree( hWaveHdr );
  540.         GlobalUnlock( hWaveInst );
  541.         GlobalFree( hWaveInst );
  542.         MessageBox(hwndApp, "Unable to prepare wave header.",
  543.                    NULL, MB_OK | MB_ICONEXCLAMATION);
  544.                
  545.         return;
  546.     }
  547.         
  548.     /* Then the data block can be sent to the output device.
  549.      */
  550.     wResult = waveOutWrite(hWaveOut, lpWaveHdr, sizeof(WAVEHDR));
  551.     if (wResult != 0)
  552.     {
  553.         waveOutUnprepareHeader( hWaveOut, lpWaveHdr, sizeof(WAVEHDR));
  554.         GlobalUnlock( hData );
  555.         GlobalFree( hData );
  556.         MessageBox(hwndApp, "Failed to write block to device",
  557.                    NULL, MB_OK | MB_ICONEXCLAMATION);
  558.         return;
  559.     }
  560.  
  561.     /* Disable input to the button controls.
  562.      */
  563.     EnableWindow(hwndPlay, FALSE);
  564.     EnableWindow(hwndQuit, FALSE);
  565. }
  566.  
  567. /* Interchange - Interchanges two samples at the given positions.
  568.  *
  569.  * Params:  hpchPos1 - Points to one sample.
  570.  *          hpchPos2 - Points to the other sample.
  571.  *          wLength  - The length of a sample in bytes.
  572.  *
  573.  * Return:  void
  574.  */
  575. void Interchange(HPSTR hpchPos1, HPSTR hpchPos2, WORD wLength)
  576. {
  577.     WORD    wPlace;
  578.     BYTE    bTemp;
  579.     
  580.     for (wPlace = 0; wPlace < wLength; wPlace++)
  581.     {
  582.         bTemp = hpchPos1[wPlace];
  583.         hpchPos1[wPlace] = hpchPos2[wPlace];
  584.         hpchPos2[wPlace] = bTemp;
  585.     }
  586. }
  587.  
  588. VOID cleanup(LPWAVEINST lpWaveInst)
  589. {
  590.     GlobalUnlock( lpWaveInst->hWaveData );
  591.     GlobalFree( lpWaveInst->hWaveData );
  592.     GlobalUnlock( lpWaveInst->hWaveHdr );
  593.     GlobalFree( lpWaveInst->hWaveHdr );
  594.     GlobalUnlock( lpWaveInst->hWaveInst );
  595.     GlobalFree( lpWaveInst->hWaveInst );
  596. }
  597.