Annotation of q_a/samples/lowpass/lowpass.c, revision 1.1

1.1     ! root        1: /* lowpass.c - WinMain() and dialog procedures for LOWPASS, along with
        !             2:  *      initialization and support code.
        !             3:  *
        !             4:  * LOWPASS is a sample application illustrating how to use the multimedia
        !             5:  *  file I/O services to read and write RIFF files.
        !             6:  *
        !             7:  * LOWPASS runs a simple low-pass filter over an 8-bit-per-sample
        !             8:  * mono WAVE file.  Note that this program does not copy unknown chunks
        !             9:  * to the output file.
        !            10:  *
        !            11:  *
        !            12:  *     (C) Copyright Microsoft Corp. 1991.  All rights reserved.
        !            13:  *
        !            14:  *     You have a royalty-free right to use, modify, reproduce and
        !            15:  *     distribute the Sample Files (and/or any modified version) in
        !            16:  *     any way you find useful, provided that you agree that
        !            17:  *     Microsoft has no warranty obligations or liability for any
        !            18:  *     Sample Application Files which are modified.
        !            19:  */
        !            20: 
        !            21: #include <windows.h>
        !            22: #include <mmsystem.h>
        !            23: #include "lowpass.h"
        !            24: 
        !            25: 
        !            26: /* Globals
        !            27:  */
        !            28: char        gszAppName[] = "LowPass";   // for title bar, etc.
        !            29: HANDLE      ghInst;                     // app's instance handle
        !            30: 
        !            31: 
        !            32: /* DoLowPass - Gets the name of the input and output WAVE files from
        !            33:  *  the dialog box; reads waveform data from the input file, performs
        !            34:  *  a simple low-pass filter by averaging adjacent samples, and writes
        !            35:  *  the filtered waveform data to the output WAVE file.
        !            36:  *
        !            37:  * Params:  hWnd - Window handle for our dialog box.
        !            38:  *
        !            39:  * Returns:
        !            40:  */
        !            41: void DoLowPass(HWND hWnd)
        !            42: {
        !            43:     char        achInFile[200];     // name of input file
        !            44:     char        achOutFile[200];    // name of output file
        !            45:     HMMIO       hmmioIn = NULL;     // handle to open input WAVE file
        !            46:     HMMIO       hmmioOut = NULL;    // handle to open output WAVE file
        !            47:     MMCKINFO    ckInRIFF;           // chunk info. for input RIFF chunk
        !            48:     MMCKINFO    ckOutRIFF;          // chunk info. for output RIFF chunk
        !            49:     MMCKINFO    ckIn;               // info. for a chunk in input file
        !            50:     MMCKINFO    ckOut;              // info. for a chunk in output file
        !            51:     PCMWAVEFORMAT   pcmWaveFormat;  // contents of 'fmt' chunks
        !            52:     MMIOINFO    mmioinfoIn;         // current status of <hmmioIn>
        !            53:     MMIOINFO    mmioinfoOut;        // current status of <hmmioOut>
        !            54:     long        lSamples;           // number of samples to filter
        !            55:     BYTE        abSamples[3];       // this, last, and before-last sample
        !            56: 
        !            57:     /* Read filenames from dialog box fields.
        !            58:      */
        !            59:     achInFile[0] == 0;
        !            60:     GetDlgItemText(hWnd, ID_INPUTFILEEDIT, achInFile, sizeof(achInFile));
        !            61:     achOutFile[0] == 0;
        !            62:     GetDlgItemText(hWnd, ID_OUTPUTFILEEDIT, achOutFile, sizeof(achOutFile));
        !            63: 
        !            64:     /* Open the input file for reading using buffered I/O.
        !            65:      */
        !            66:     hmmioIn = mmioOpen(achInFile, NULL, MMIO_ALLOCBUF | MMIO_READ);
        !            67:     if (hmmioIn == NULL)
        !            68:         goto ERROR_CANNOT_READ;     // cannot open WAVE file
        !            69: 
        !            70:     /* Open the output file for writing using buffered I/O. Note that
        !            71:      * if the file exists, the MMIO_CREATE flag causes it to be truncated
        !            72:      * to zero length.
        !            73:      */
        !            74:     hmmioOut = mmioOpen(achOutFile, NULL,
        !            75:                         MMIO_ALLOCBUF | MMIO_WRITE | MMIO_CREATE);
        !            76:     if (hmmioOut == NULL)
        !            77:         goto ERROR_CANNOT_WRITE;    // cannot open WAVE file
        !            78: 
        !            79:     /* Descend the input file into the 'RIFF' chunk.
        !            80:      */
        !            81:     if (mmioDescend(hmmioIn, &ckInRIFF, NULL, 0) != 0)
        !            82:         goto ERROR_CANNOT_READ;     // end-of-file, probably
        !            83: 
        !            84:     /* Make sure the input file is a WAVE file.
        !            85:      */
        !            86:     if ((ckInRIFF.ckid != FOURCC_RIFF) ||
        !            87:         (ckInRIFF.fccType != mmioFOURCC('W', 'A', 'V', 'E')))
        !            88:         goto ERROR_FORMAT_BAD;
        !            89: 
        !            90:     /* Search the input file for for the 'fmt ' chunk.
        !            91:      */
        !            92:     ckIn.ckid = mmioFOURCC('f', 'm', 't', ' ');
        !            93:     if (mmioDescend(hmmioIn, &ckIn, &ckInRIFF, MMIO_FINDCHUNK) != 0)
        !            94:         goto ERROR_FORMAT_BAD;      // no 'fmt ' chunk
        !            95: 
        !            96:     /* Expect the 'fmt' chunk to be at least as large as <pcmWaveFormat>;
        !            97:      * if there are extra parameters at the end, we'll ignore them
        !            98:      */
        !            99:     if (ckIn.cksize < (long) sizeof(pcmWaveFormat))
        !           100:         goto ERROR_FORMAT_BAD;      // 'fmt ' chunk too small
        !           101: 
        !           102:     /* Read the 'fmt ' chunk into <pcmWaveFormat>.
        !           103:      */
        !           104:     if (mmioRead(hmmioIn, (HPSTR) &pcmWaveFormat,
        !           105:         (long) sizeof(pcmWaveFormat)) != (long) sizeof(pcmWaveFormat))
        !           106:         goto ERROR_CANNOT_READ;     // truncated file, probably
        !           107: 
        !           108:     /* Ascend the input file out of the 'fmt ' chunk.
        !           109:      */
        !           110:     if (mmioAscend(hmmioIn, &ckIn, 0) != 0)
        !           111:         goto ERROR_CANNOT_READ;     // truncated file, probably
        !           112: 
        !           113:     /* Make sure the input file is an 8-bit mono PCM WAVE file.
        !           114:      */
        !           115:     if ((pcmWaveFormat.wf.wFormatTag != WAVE_FORMAT_PCM) ||
        !           116:         (pcmWaveFormat.wf.nChannels != 1) ||
        !           117:         (pcmWaveFormat.wBitsPerSample != 8))
        !           118:         goto ERROR_FORMAT_BAD;      // bad input file format
        !           119: 
        !           120:     /* Search the input file for for the 'data' chunk.
        !           121:      */
        !           122:     ckIn.ckid = mmioFOURCC('d', 'a', 't', 'a');
        !           123:     if (mmioDescend(hmmioIn, &ckIn, &ckInRIFF, MMIO_FINDCHUNK) != 0)
        !           124:         goto ERROR_FORMAT_BAD;      // no 'data' chunk
        !           125: 
        !           126:     /* Create the output file RIFF chunk of form type 'WAVE'.
        !           127:      */
        !           128:     ckOutRIFF.fccType = mmioFOURCC('W', 'A', 'V', 'E');
        !           129:     if (mmioCreateChunk(hmmioOut, &ckOutRIFF, MMIO_CREATERIFF) != 0)
        !           130:         goto ERROR_CANNOT_WRITE;    // cannot write file, probably
        !           131: 
        !           132:     /* We are now descended into the 'RIFF' chunk we just created.
        !           133:      * Now create the 'fmt ' chunk. Since we know the size of this chunk,
        !           134:      * specify it in the MMCKINFO structure so MMIO doesn't have to seek
        !           135:      * back and set the chunk size after ascending from the chunk.
        !           136:      */
        !           137:     ckOut.ckid = mmioFOURCC('f', 'm', 't', ' ');
        !           138:     ckOut.cksize = sizeof(pcmWaveFormat);   // we know the size of this ck.
        !           139:     if (mmioCreateChunk(hmmioOut, &ckOut, 0) != 0)
        !           140:         goto ERROR_CANNOT_WRITE;    // cannot write file, probably
        !           141: 
        !           142:     /* Write the PCMWAVEFORMAT structure to the 'fmt ' chunk.
        !           143:      */
        !           144:     if (mmioWrite(hmmioOut, (HPSTR) &pcmWaveFormat, sizeof(pcmWaveFormat))
        !           145:         != sizeof(pcmWaveFormat))
        !           146:         goto ERROR_CANNOT_WRITE;    // cannot write file, probably
        !           147: 
        !           148:     /* Ascend out of the 'fmt ' chunk, back into the 'RIFF' chunk.
        !           149:      */
        !           150:     if (mmioAscend(hmmioOut, &ckOut, 0) != 0)
        !           151:         goto ERROR_CANNOT_WRITE;    // cannot write file, probably
        !           152: 
        !           153:     /* Create the 'data' chunk that holds the waveform samples.
        !           154:      */
        !           155:     ckOut.ckid = mmioFOURCC('d', 'a', 't', 'a');
        !           156:     if (mmioCreateChunk(hmmioOut, &ckOut, 0) != 0)
        !           157:         goto ERROR_CANNOT_WRITE;    // cannot write file, probably
        !           158: 
        !           159:     /* Read samples from the 'data' chunk of the input file, and write
        !           160:      * samples to the 'data' chunk of the output file.  Each sample in
        !           161:      * the output file equals the average of the corresponding sample
        !           162:      * in the input file and the previous two samples from the input file.
        !           163:      * Access the I/O buffers of <hmmioIn> and <hmmioOut> directly,
        !           164:      * since this is faster than calling mmioRead() and mmioWrite()
        !           165:      * for each sample.
        !           166:      */
        !           167:     abSamples[0] = abSamples[1] = abSamples[2] = 128;
        !           168: 
        !           169:     /* Begin direct access of the I/O buffers.
        !           170:      */
        !           171:     if (mmioGetInfo(hmmioIn, &mmioinfoIn, 0) != 0)
        !           172:         goto ERROR_UNKNOWN;
        !           173:     if (mmioGetInfo(hmmioOut, &mmioinfoOut, 0) != 0)
        !           174:         goto ERROR_UNKNOWN;
        !           175: 
        !           176:     /* For each input sample, compute and write the output sample.
        !           177:      */
        !           178:     for (lSamples = ckIn.cksize; lSamples > 0; lSamples--)
        !           179:     {
        !           180:         /* If we are at the end of the input file I/O buffer, fill it.
        !           181:          * Test to see that we don't hit end of file while (lSamples > 0).
        !           182:          */
        !           183:         if (mmioinfoIn.pchNext == mmioinfoIn.pchEndRead)
        !           184:         {
        !           185:             if (mmioAdvance(hmmioIn, &mmioinfoIn, MMIO_READ) != 0)
        !           186:                 goto ERROR_CANNOT_READ;
        !           187: 
        !           188:             if (mmioinfoIn.pchNext == mmioinfoIn.pchEndRead)
        !           189:                 goto ERROR_CANNOT_READ;
        !           190:         }
        !           191: 
        !           192:         /* If we are the end of the output file I/O buffer, flush it.
        !           193:          */
        !           194:         if (mmioinfoOut.pchNext == mmioinfoOut.pchEndWrite)
        !           195:         {
        !           196:             mmioinfoOut.dwFlags |= MMIO_DIRTY;
        !           197:             if (mmioAdvance(hmmioOut, &mmioinfoOut, MMIO_WRITE) != 0)
        !           198:                 goto ERROR_CANNOT_WRITE;
        !           199:         }
        !           200: 
        !           201:         /* Keep track of the last 3 samples so we can average.
        !           202:          */
        !           203:         abSamples[2] = abSamples[1];        // next-to-last sample
        !           204:         abSamples[1] = abSamples[0];        // last sample
        !           205:         abSamples[0] = *(mmioinfoIn.pchNext)++; // current sample
        !           206: 
        !           207:         /* The output file sample is the average of the last
        !           208:          * 3 input file samples.
        !           209:          */
        !           210:         *(mmioinfoOut.pchNext)++ = (BYTE) (((int) abSamples[0]
        !           211:             + (int) abSamples[1] + (int) abSamples[2]) / 3);
        !           212:     }
        !           213: 
        !           214:     /* We are through processing samples, end direct access of
        !           215:      * the I/O buffers. Set the MMIO_DIRTY flag for the output buffer
        !           216:      * to flush it.
        !           217:      */
        !           218:     if (mmioSetInfo(hmmioIn, &mmioinfoIn, 0) != 0)
        !           219:         goto ERROR_UNKNOWN;
        !           220:     mmioinfoOut.dwFlags |= MMIO_DIRTY;
        !           221:     if (mmioSetInfo(hmmioOut, &mmioinfoOut, 0) != 0)
        !           222:         goto ERROR_CANNOT_WRITE;    // cannot flush, probably
        !           223: 
        !           224:     /* Ascend the output file out of the 'data' chunk -- this will cause
        !           225:      * the chunk size of the 'data' chunk to be written.
        !           226:      */
        !           227:     if (mmioAscend(hmmioOut, &ckOut, 0) != 0)
        !           228:         goto ERROR_CANNOT_WRITE;    // cannot write file, probably
        !           229: 
        !           230:     /* Ascend the output file out of the 'RIFF' chunk -- this will cause
        !           231:      * the chunk size of the 'RIFF' chunk to be written.
        !           232:      */
        !           233:     if (mmioAscend(hmmioOut, &ckOutRIFF, 0) != 0)
        !           234:         goto ERROR_CANNOT_WRITE;    // cannot write file, probably
        !           235: 
        !           236:     /* We are done -- files are closed below.
        !           237:      */
        !           238:     goto EXIT_FUNCTION;
        !           239: 
        !           240: ERROR_FORMAT_BAD:
        !           241: 
        !           242:     MessageBox(NULL, "Input file must be an 8-bit mono PCM WAVE file",
        !           243:         gszAppName, MB_ICONEXCLAMATION | MB_OK);
        !           244:     goto EXIT_FUNCTION;
        !           245: 
        !           246: ERROR_CANNOT_READ:
        !           247: 
        !           248:     MessageBox(NULL, "Cannot read input WAVE file",
        !           249:         gszAppName, MB_ICONEXCLAMATION | MB_OK);
        !           250:     goto EXIT_FUNCTION;
        !           251: 
        !           252: ERROR_CANNOT_WRITE:
        !           253: 
        !           254:     MessageBox(NULL, "Cannot write output WAVE file",
        !           255:         gszAppName, MB_ICONEXCLAMATION | MB_OK);
        !           256:     goto EXIT_FUNCTION;
        !           257: 
        !           258: ERROR_UNKNOWN:
        !           259: 
        !           260:     MessageBox(NULL, "Unknown error",
        !           261:         gszAppName, MB_ICONEXCLAMATION | MB_OK);
        !           262:     goto EXIT_FUNCTION;
        !           263: 
        !           264: EXIT_FUNCTION:
        !           265: 
        !           266:     /* Close the files (unless they weren't opened successfully).
        !           267:      */
        !           268:     if (hmmioIn != NULL)
        !           269:         mmioClose(hmmioIn, 0);
        !           270:     if (hmmioOut != NULL)
        !           271:         mmioClose(hmmioOut, 0);
        !           272: }
        !           273: 
        !           274: 
        !           275: /* WinMain - Entry point for LowPass.
        !           276:  */
        !           277: int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszCmdLine, int iCmdShow)
        !           278: {
        !           279:     FARPROC     fpfn;
        !           280: 
        !           281:     /* Save instance handle for dialog boxes.
        !           282:      */
        !           283:     ghInst = hInst;
        !           284: 
        !           285:     /* Display our dialog box.
        !           286:      */
        !           287:     fpfn = MakeProcInstance((FARPROC) LowPassDlgProc, ghInst);
        !           288:     DialogBox(ghInst, "LOWPASSBOX", NULL, (DLGPROC)fpfn);
        !           289:     FreeProcInstance(fpfn);
        !           290: 
        !           291:     return TRUE;
        !           292: }
        !           293: 
        !           294: 
        !           295: /* AboutDlgProc - Dialog procedure function for ABOUTBOX dialog box.
        !           296:  */
        !           297: BOOL FAR PASCAL
        !           298:      AboutDlgProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
        !           299: {
        !           300:     switch (wMsg)
        !           301:     {
        !           302:     case WM_INITDIALOG:
        !           303:         return TRUE;
        !           304: 
        !           305:     case WM_COMMAND:
        !           306:         if (LOWORD(wParam) == IDOK)
        !           307:             EndDialog(hWnd, TRUE);
        !           308:         break;
        !           309:     }
        !           310:     return FALSE;
        !           311: }
        !           312: 
        !           313: 
        !           314: /* LowPassDlgProc - Dialog procedure function for LOWPASSBOX dialog box.
        !           315:  */
        !           316: BOOL FAR PASCAL
        !           317:      LowPassDlgProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
        !           318: {
        !           319:     FARPROC     fpfn;
        !           320:     HMENU       hmenuSystem;    // system menu
        !           321:     HCURSOR     ghcurSave;      // previous cursor
        !           322: 
        !           323:     switch (wMsg)
        !           324:     {
        !           325:     case WM_INITDIALOG:
        !           326:         /* Append "About" menu item to system menu.
        !           327:          */
        !           328:         hmenuSystem = GetSystemMenu(hWnd, FALSE);
        !           329:         AppendMenu(hmenuSystem, MF_SEPARATOR, 0, NULL);
        !           330:         AppendMenu(hmenuSystem, MF_STRING, IDM_ABOUT,
        !           331:             "&About LowPass...");
        !           332:         return TRUE;
        !           333: 
        !           334:     case WM_SYSCOMMAND:
        !           335:         switch (wParam)
        !           336:         {
        !           337:         case IDM_ABOUT:
        !           338:             /* Display "About" dialog box.
        !           339:              */
        !           340:             fpfn = MakeProcInstance((FARPROC) AboutDlgProc, ghInst);
        !           341:             DialogBox(ghInst, "ABOUTBOX", hWnd, (DLGPROC)fpfn);
        !           342:             FreeProcInstance(fpfn);
        !           343:             break;
        !           344:         }
        !           345:         break;
        !           346: 
        !           347:     case WM_COMMAND:
        !           348:         switch (LOWORD(wParam))
        !           349:         {
        !           350:         case IDOK:          // "Begin"
        !           351:             /* Set "busy" cursor, filter input file, restore cursor.
        !           352:              */
        !           353:             ghcurSave = SetCursor(LoadCursor(NULL, IDC_WAIT));
        !           354:             DoLowPass(hWnd);
        !           355:             SetCursor(ghcurSave);
        !           356:             break;
        !           357: 
        !           358:         case IDCANCEL:      // "Done"
        !           359:             EndDialog(hWnd, TRUE);
        !           360:             break;
        !           361:         }
        !           362:         break;
        !           363:     }
        !           364:     return FALSE;
        !           365: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.