home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Multimedia Development Kit 0.9 beta / MDKBeta_Release3.iso / mdk / mmsample / reverse / reverse.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-15  |  14.9 KB  |  521 lines

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