tapiwave.c

来自「一个tapi开发的很好的语音通信程序」· C语言 代码 · 共 1,109 行 · 第 1/3 页

C
1,109
字号
      printf("mmioOpen failed to open file.\n");
      return FALSE;
   }

   // 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 (mmResult = mmioDescend(hmmio, &mmckinfoParent, NULL, MMIO_FINDRIFF))
   {
      waveOutGetErrorText(mmResult, szBuff, sizeof(szBuff));
      printf("mmioDescend RIFF WAVE returned %s\r\n", szBuff);
      mmioClose(hmmio, 0);
      return FALSE;
   }

   //  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))
   {
      printf("Wave file corrupt.\n");
      mmioClose(hmmio, 0);
      return FALSE;
   }

   // Get the size of the format chunk, allocate and lock memory for it.
   dwFmtSize = mmckinfoSubchunk.cksize;
   pFormat = LocalAlloc(LPTR, LOWORD(dwFmtSize));
   if (!pFormat)
   {
      printf("Memory error.\n");
      mmioClose(hmmio, 0);
      return FALSE;
   }

   // Read the format chunk.
   if (mmioRead(hmmio, (HPSTR) pFormat, dwFmtSize) != (LONG) dwFmtSize)
   {
      printf("mmioRead: failed to read FMT chunk.\n");
      LocalFree( pFormat );
      mmioClose(hmmio, 0);
      return FALSE;
   }

   printf("wFormatTag = %lu\n",        (DWORD) pFormat->wFormatTag);
   printf("nChannels = %lu\n",         (DWORD) pFormat->nChannels );
   printf("nSamplesPerSec = %lu\n",    (DWORD) pFormat->nSamplesPerSec);
   printf("nAvgBytesPerSec = %lu\n",   (DWORD) pFormat->nAvgBytesPerSec);
   printf("nBlockAlign = %lu\n",       (DWORD) pFormat->nBlockAlign);
   printf("wBitsPerSample = %lu\n",    (DWORD) pFormat->wBitsPerSample);
   printf("cbSize = %lu\n",            (DWORD) pFormat->cbSize);

   if (WAVE_MAPPER == WaveInID)
      mmResult = waveInOpen(&hWaveIn, WaveInID, pFormat, 0, 0L,
               WAVE_FORMAT_QUERY);
   else
      mmResult = waveInOpen(&hWaveIn, WaveInID, pFormat, 0, 0L,
               dwWaveMapped  | WAVE_FORMAT_QUERY);
   if (mmResult)
   {
      waveInGetErrorText(mmResult, szBuff, sizeof(szBuff));
      printf("waveInOpen while QUERY returned %s\r\n", szBuff);
      LocalFree( pFormat );
      mmioClose(hmmio, 0);
   }
   else
      printf("Valid WaveIn format.\n");


   // Make sure a waveform output device supports this format.
   if (WAVE_MAPPER == WaveOutID)
      mmResult = waveOutOpen(&hWaveOut, WaveOutID, pFormat, 0, 0L,
               WAVE_FORMAT_QUERY);
   else
      mmResult = waveOutOpen(&hWaveOut, WaveOutID, pFormat, 0, 0L,
               dwWaveMapped  | WAVE_FORMAT_QUERY);
   if (mmResult)
   {
      waveOutGetErrorText(mmResult, szBuff, sizeof(szBuff));
      printf("waveOutOpen while QUERY returned %s\r\n", szBuff);
      LocalFree( pFormat );
      mmioClose(hmmio, 0);
      return FALSE;
   }

   // 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))
   {
      printf("mmioDescend: No DATA chunk.\n");
      LocalFree( pFormat );
      mmioClose(hmmio, 0);
      return FALSE;
   }

   //  Get the size of the data subchunk.
   dwDataSize = mmckinfoSubchunk.cksize;
   if (dwDataSize == 0L)
   {
      printf("Data chunk actually has no data.\n");
      LocalFree( pFormat );
      mmioClose(hmmio, 0);
      return FALSE;
   }
   printf("Size of data is %lu\n",dwDataSize);

   // Open a waveform output device.
   if (WaveOutID == WAVE_MAPPER)
      mmResult = waveOutOpen(&hWaveOut, WaveOutID,
         pFormat, 0 /* (UINT)hwndApp */, 0L, 0/*| CALLBACK_WINDOW*/);
   else
      mmResult = waveOutOpen(&hWaveOut, WaveOutID,
         pFormat, 0 /* (UINT)hwndApp */, 0L, 0 /*WAVE_MAPPED*/ /*| CALLBACK_WINDOW*/);

   if (mmResult)
   {
      waveOutGetErrorText(mmResult, szBuff, sizeof(szBuff));
      printf("waveOutOpen returned %s\r\n", szBuff);
      LocalFree( pFormat );
      mmioClose(hmmio, 0);
      return FALSE;
   }

   // Save block alignment info for later use.
   wBlockSize = pFormat->nBlockAlign;

   // We're done with the format header, free it.
   LocalFree( pFormat );

   // Allocate and lock memory for the waveform data.
   lpData = LocalAlloc(LPTR, dwDataSize );
   if (!lpData)
   {
      printf("Memory problems.\n");
      mmioClose(hmmio, 0);
      return FALSE;
   }

   // Read the waveform data subchunk.
   if(mmioRead(hmmio, lpData, dwDataSize) != (LONG) dwDataSize)
   {
      printf("Failed to read waveform data subchunk.\n");
      LocalFree( lpData );
      mmioClose(hmmio, 0);
      return FALSE;
   }

   // We're done with the file, close it.
   mmioClose(hmmio, 0);

   /* 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 = LocalAlloc(LPTR, sizeof(YOURDATA));
   if (!lpYourData)
   {
      printf("Memory issues.\n");
      StopConnectedStuff();
      return FALSE;
   }
   #endif

   // Here is the infinite loop test with multiple buffers
   // note that this test doesn't clean up memory when its done.
   if (dwWaveBuffers)
   {
      LPWAVEHDR * lpWaveHdrs = NULL;
      DWORD i;
      DWORD dwWaveIndex = 0;

      // Round this up to the next nearest whole wBlockSize value;
      dwWaveBuffSize += wBlockSize -1;
      dwWaveBuffSize -= dwWaveBuffSize % wBlockSize;

      printf("Allocating %lu buffers of size %lu\n", dwWaveBuffers, dwWaveBuffSize);

      // allocate our array of wave header pointers
      lpWaveHdrs = (LPWAVEHDR *) LocalAlloc(LPTR, (DWORD) sizeof(LPWAVEHDR) * dwWaveBuffers);
      if (!lpWaveHdrs)
      {
         printf("Memory issues.\n");
         StopConnectedStuff();
         return FALSE;
      }

      // initiate all the buffers
      for(i = 0; (i < dwWaveBuffers) && !(bReadyToEnd || bDropped); i++)
      {
         // allocate each wave header
         if (!(lpWaveHdrs[i] = (LPWAVEHDR) LocalAlloc(LPTR, (DWORD) sizeof(WAVEHDR))))
         {
            printf("Memory issues.\n");
            StopConnectedStuff();
            return FALSE;
         }

         // Set up each WAVEHDR structure
         lpWaveHdrs[i]->lpData = LocalAlloc(LPTR, (DWORD) dwWaveBuffSize);
         lpWaveHdrs[i]->dwBufferLength = dwWaveBuffSize;
         lpWaveHdrs[i]->dwFlags = 0L;
         lpWaveHdrs[i]->dwLoops = 0L;

         if (dwWaveIndex + dwWaveBuffSize >= dwDataSize)
         {
            memcpy(lpWaveHdrs[i]->lpData, &lpData[dwWaveIndex], dwDataSize-dwWaveIndex);
            lpWaveHdrs[i]->dwBufferLength = dwDataSize-dwWaveIndex;
            dwWaveIndex =0;
            printf("End of wave file reached in buffer %lu.  Duplicating.\n", i);
         }
         else
         {
            memcpy(lpWaveHdrs[i]->lpData, &lpData[dwWaveIndex], dwWaveBuffSize);
            dwWaveIndex += dwWaveBuffSize;
         }

         // prepare each WAVEHDR
         if(mmResult = waveOutPrepareHeader(hWaveOut, lpWaveHdrs[i], sizeof(WAVEHDR)))
         {
            waveOutGetErrorText(mmResult, szBuff, sizeof(szBuff));
            printf("waveOutPrepareHeader returned %s\r\n", szBuff);
            StopConnectedStuff();
            return FALSE;
         }
      }

      // force each of the buffers into the driver.

      for(i = 0; (i < dwWaveBuffers) && !(bReadyToEnd || bDropped); i++)
      {
         // Then the data block can be sent to the output device.
         if (mmResult = waveOutWrite(hWaveOut, lpWaveHdrs[i], sizeof(WAVEHDR)))
         {
            waveOutGetErrorText(mmResult, szBuff, sizeof(szBuff));
            printf("waveOutWrite returned %s\r\n", szBuff);
            StopConnectedStuff();
            return FALSE;
         }

         if (!(lpWaveHdrs[i]->dwFlags & WHDR_INQUEUE))
         {
            printf("waveOutWrite %lu not queued.", i);
            break;
         }

         printf("Initial waveOutWrite buffer %lu succeeded!.\n", i);
      }

      // now wait for each buffer to finish
      if (i == dwWaveBuffers)
         i = 0;

      while(!(bReadyToEnd || bDropped))
      {
         if (lpWaveHdrs[i]->dwFlags & WHDR_DONE)
         {
            lpWaveHdrs[i]->dwFlags = 0L;
            
            if (mmResult = waveOutWrite(hWaveOut, lpWaveHdrs[i], sizeof(WAVEHDR)))
            {
               waveOutGetErrorText(mmResult, szBuff, sizeof(szBuff));
               printf("waveOutWrite returned %s\r\n", szBuff);
               StopConnectedStuff();
               return FALSE;
            }
            printf("waveOutWrite buffer %lu succeeded!.\n", i);

            i++;
            if (i >= dwWaveBuffers)
               i=0;
         }
         PumpMessages(FALSE);
         Sleep(0);
      }

      StopConnectedStuff();
      return FALSE;
   } // end of the infinite loop buffer test

   // Allocate a waveform data header. The WAVEHDR must be
   // globally allocated and locked.
   lpWaveHdr = (LPWAVEHDR)LocalAlloc(LPTR, (DWORD) sizeof(WAVEHDR));
   if (!lpWaveHdr)
   {
      printf("Memory issues.\n");
      StopConnectedStuff();
      return FALSE;
   }

   // 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;

   printf("dwDatasize %lu\n",dwDataSize);

   // lpWaveHdr->dwUser = (DWORD) lpYourData; // save instance data ptr
   if(mmResult = waveOutPrepareHeader(hWaveOut, lpWaveHdr, sizeof(WAVEHDR)))
   {
      waveOutGetErrorText(mmResult, szBuff, sizeof(szBuff));
      printf("waveOutPrepareHeader returned %s\r\n", szBuff);
      StopConnectedStuff();
      return FALSE;
   }

   // Then the data block can be sent to the output device.
   if (mmResult = waveOutWrite(hWaveOut, lpWaveHdr, sizeof(WAVEHDR)))
   {
      waveOutGetErrorText(mmResult, szBuff, sizeof(szBuff));
      printf("waveOutWrite returned %s\r\n", szBuff);
   }
   else
   {
      printf("waveOutWrite succeeded!.\n");
     	while (!(lpWaveHdr->dwFlags & WHDR_DONE))
      {
         PumpMessages(FALSE);
         if (bReadyToEnd || bDropped)
            break;
         Sleep(0);	// Release the rest of my time slice.
      }
   }

   StopConnectedStuff();
   return FALSE;
}

void StopConnectedStuff()
{
   MMRESULT mmResult;

   if (lpWaveHdr)
   {
      if(mmResult = waveOutUnprepareHeader(hWaveOut, lpWaveHdr, sizeof(WAVEHDR) ))
      {
         waveOutGetErrorText(mmResult, szBuff, sizeof(szBuff));
         printf("waveOutUnprepareHeader returned %s\r\n", szBuff);
      }
      LocalFree( lpWaveHdr );
      lpWaveHdr = NULL;
   }

   if (mmResult = waveOutReset(hWaveOut))
   {
      waveOutGetErrorText(mmResult, szBuff, sizeof(szBuff));
      printf("waveOutReset returned %s\r\n", szBuff);
   }

   Sleep(500);  // Give it 1/2 sec to actually reset.
   
   if(mmResult = waveOutClose(hWaveOut))
   {
      waveOutGetErrorText(mmResult, szBuff, sizeof(szBuff));
      printf("waveOutClose returned %s\r\n", szBuff);
   }

   Sleep(500); // Give it 1/2 sec to clean up.

   LocalFree( lpData );
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?