home *** CD-ROM | disk | FTP | other *** search
/ Windows 95 Secrets / Secrets2.iso / Audio / WAV / MaplayP / _SETUP.1 / wavefile_obuffer.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-06-25  |  7.8 KB  |  299 lines

  1. /* wavefile_obuffer.cpp
  2.  
  3.     Output buffer class for writing to a PCM wave file
  4.    in Win32, written by Jeff Tsay (ctsay@pasteur.eecs.berkeley.edu).
  5.  
  6.    Based on the lowpass filter example by Microsoft.
  7.  
  8.    This program is free software; you can redistribute it and/or modify
  9.    it under the terms of the GNU General Public License as published by
  10.    the Free Software Foundation; either version 2 of the License, or
  11.    (at your option) any later version.
  12.  
  13.    This program is distributed in the hope that it will be useful,
  14.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.    GNU General Public License for more details.
  17.  
  18.    You should have received a copy of the GNU General Public License
  19.    along with this program; if not, write to the Free Software
  20.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
  21.  
  22. #ifdef  __WIN32__
  23. #include <windows.h>
  24.  
  25. #ifndef WIN32GUI
  26. #include <iostream.h>
  27. #endif
  28.  
  29. #include "header.h"
  30. #include "args.h"
  31. #include "obuffer.h"
  32. #include "wavefile_obuffer.h"
  33.  
  34. Wavefile_Obuffer::Wavefile_Obuffer(uint32 number_of_channels,
  35.                                              MPEG_Args *maplay_args)
  36. {
  37.   channels  = number_of_channels;
  38.   data_size = channels * OBUFFERSIZE;
  39.  
  40.   if (maplay_args->MPEGheader->version() == MPEG2_LSF)
  41.      data_size >>= 1;
  42.  
  43.   if (maplay_args->MPEGheader->layer() == 1)
  44.         data_size /= 3;
  45.  
  46.   temp = new BYTE[data_size];
  47.  
  48.   if (!(hmmioOut = mmioOpen(maplay_args->output_filename, NULL,
  49.                          MMIO_ALLOCBUF | MMIO_WRITE | MMIO_CREATE))) {
  50.  
  51. #ifdef WIN32GUI
  52.       MessageBox(NULL, "Could not open file.", "Wave file output error",
  53.                 MB_OK | MB_ICONEXCLAMATION);
  54. #else
  55.       cerr << "could not open file : " << maplay_args->output_filename
  56.           << endl;
  57. #endif
  58.  
  59.       ExitProcess(1);
  60.   }
  61.  
  62.   // Create the output file RIFF chunk of form type WAVE.
  63.  
  64.   ckOutRIFF.fccType = mmioFOURCC('W', 'A', 'V', 'E');
  65.   ckOutRIFF.cksize  = 0;
  66.   if (mmioCreateChunk(hmmioOut, &ckOutRIFF, MMIO_CREATERIFF)
  67.           != MMSYSERR_NOERROR) {
  68.  
  69. #ifdef WIN32GUI
  70.       MessageBox(NULL, "Could not write file.", "Wave file output error",
  71.                 MB_OK | MB_ICONEXCLAMATION);
  72. #else
  73.       cerr << "could not write file : " << maplay_args->output_filename
  74.             << endl;
  75. #endif
  76.  
  77.       ExitProcess(1);
  78.   }
  79.  
  80.   // Initialize the WAVEFORMATEX structure
  81.  
  82.   WAVEFORMATEX pwf;
  83.  
  84.   pwf.wBitsPerSample  = 16;  // No 8-bit support yet
  85.   pwf.wFormatTag      = WAVE_FORMAT_PCM;
  86.   pwf.nChannels       = (WORD) channels;
  87.   pwf.nSamplesPerSec  = (DWORD) maplay_args->MPEGheader->frequency();
  88.   pwf.nAvgBytesPerSec = (DWORD) (channels *
  89.                                 maplay_args->MPEGheader->frequency() << 1);
  90.   pwf.nBlockAlign     = (WORD) (channels << 1);
  91.   pwf.cbSize          = 0;
  92.  
  93.   // Create the fmt chunk
  94.  
  95.   ckOut.ckid = mmioFOURCC('f', 'm', 't', ' ');
  96.   ckOut.cksize = sizeof(pwf);
  97.  
  98.   if (mmioCreateChunk(hmmioOut, &ckOut, 0) != MMSYSERR_NOERROR) {
  99.  
  100. #ifdef WIN32GUI
  101.         MessageBox(NULL, "Could not write file!", "Wave file output error",
  102.                  MB_OK | MB_ICONEXCLAMATION);
  103. #else
  104.      cerr << "could not write file : " << maplay_args->output_filename
  105.           << endl;
  106. #endif
  107.  
  108.      ExitProcess(1);
  109.   }
  110.  
  111.   // Write the WAVEFORMATEX structure to the fmt chunk.
  112.  
  113.   if (mmioWrite(hmmioOut, (HPSTR) &pwf, sizeof(pwf))
  114.       != sizeof(pwf)) {
  115.  
  116. #ifdef WIN32GUI
  117.       MessageBox(NULL, "Could not write file!", "Wave file output error",
  118.                 MB_OK | MB_ICONEXCLAMATION);
  119. #else
  120.       cerr << "could not write file : " << maplay_args->output_filename
  121.             << endl;
  122. #endif
  123.  
  124.       ExitProcess(1);
  125.   }
  126.  
  127.   // Ascend out of the fmt chunk, back into the RIFF chunk.
  128.  
  129.   if (mmioAscend(hmmioOut, &ckOut, 0) != MMSYSERR_NOERROR) {
  130.  
  131. #ifdef WIN32GUI
  132.       MessageBox(NULL, "Could not write file!", "Wave file output error",
  133.                  MB_OK | MB_ICONEXCLAMATION);
  134. #else
  135.      cerr << "could not write file : " << maplay_args->output_filename
  136.           << endl;
  137. #endif
  138.  
  139.       ExitProcess(1);
  140.   }
  141.  
  142.   // Create the data chunk that holds the waveform samples.
  143.  
  144.   ckOut.ckid   = mmioFOURCC('d', 'a', 't', 'a');
  145.   ckOut.cksize = 0;
  146.   if (mmioCreateChunk(hmmioOut, &ckOut, 0) != MMSYSERR_NOERROR)   {
  147.  
  148. #ifdef WIN32GUI
  149.         MessageBox(NULL, "mmioSetInfo() failed!", "Wave file output error",
  150.                  MB_OK | MB_ICONEXCLAMATION);
  151. #else
  152.      cerr << "could not write file : " << maplay_args->output_filename
  153.           << endl;
  154. #endif
  155.  
  156.      ExitProcess(1);
  157.   }
  158.  
  159.   mmioGetInfo(hmmioOut, &mmioinfoOut, 0);
  160.  
  161.   int i;
  162.   for(i=0; i<channels; i++)
  163.        bufferp[i] = i * channels;
  164. }
  165.  
  166. void Wavefile_Obuffer::append (uint32 channel, int16 value)
  167. {
  168.   // Need to break up the 32-bit integer into 2 8-bit bytes.
  169.   // (ignore the first two bytes - either 0x0000 or 0xffff)
  170.   // Note that Intel byte order is backwards!!!
  171.  
  172.   temp[bufferp[channel]]   = (BYTE) (value & 0xff);
  173.   temp[bufferp[channel]+1] = (BYTE) (value >> 8);
  174.  
  175.   bufferp[channel] += channels << 1;
  176.  
  177.   return;
  178. }
  179.  
  180. #pragma argsused
  181. void Wavefile_Obuffer::write_buffer(int32 fd)
  182. {
  183.   int write_pos;
  184.   for (write_pos = 0; write_pos < data_size; write_pos++) {
  185.  
  186.         // Check if we are at the end of the output buffer.
  187.      // If so, flush it.
  188.       if (mmioinfoOut.pchNext == mmioinfoOut.pchEndWrite)
  189.       {
  190.          mmioinfoOut.dwFlags |= MMIO_DIRTY;
  191.  
  192.          if (mmioAdvance(hmmioOut, &mmioinfoOut, MMIO_WRITE)
  193.             != MMSYSERR_NOERROR) {
  194.  
  195. #ifdef WIN32GUI
  196.                 MessageBox(NULL, "mmioAdvance() failed!", "Wave file output error",
  197.                          MB_OK | MB_ICONEXCLAMATION);
  198. #else
  199.                 cerr << "mmioAdvance() failed!" << endl;
  200. #endif
  201.                 ExitProcess(1);
  202.          }
  203.       }
  204.  
  205.      // Copy one byte
  206.       *mmioinfoOut.pchNext++ = temp[write_pos];
  207.   }
  208.  
  209.   // Reset buffer pointers
  210.   int i;
  211.   for(i=0; i<channels; i++)
  212.        bufferp[i] = i * channels;
  213.  
  214.   return;
  215. }
  216.  
  217. #ifdef SEEK_STOP
  218. void Wavefile_Obuffer::clear_buffer()
  219.  
  220. {
  221.     // Since we write each frame, and seeks and stops occur between
  222.    // frames, nothing is needed here.
  223. }
  224.  
  225. void Wavefile_Obuffer::set_stop_flag()
  226.  
  227. {
  228. }
  229. #endif
  230.  
  231.  
  232. Wavefile_Obuffer::~Wavefile_Obuffer()
  233. {
  234.     // Mark the current chunk as dirty and flush it
  235.    mmioinfoOut.dwFlags |= MMIO_DIRTY;
  236.    if (mmioSetInfo(hmmioOut, &mmioinfoOut, 0) != MMSYSERR_NOERROR) {
  237.  
  238. #ifdef WIN32GUI
  239.         MessageBox(NULL, "mmioSetInfo() failed!", "Wave file output error",
  240.                  MB_OK | MB_ICONEXCLAMATION);
  241. #else
  242.         cerr << "mmioSetInfo() failed!" << endl;
  243. #endif
  244.    }
  245.  
  246.    // Ascend out of data chunk
  247.    if (mmioAscend(hmmioOut, &ckOut, 0) != MMSYSERR_NOERROR) {
  248.  
  249. #ifdef WIN32GUI
  250.         MessageBox(NULL, "Ascend on data chunk failed!", "Wave file output error",
  251.                  MB_OK | MB_ICONEXCLAMATION);
  252. #else
  253.         cerr << "mmioAscend() failed!" << endl;
  254. #endif
  255.    }
  256.  
  257.    // Ascend out of RIFF chunk
  258.    if (mmioAscend(hmmioOut, &ckOutRIFF, 0) != MMSYSERR_NOERROR) {
  259.  
  260. #ifdef WIN32GUI
  261.         MessageBox(NULL, "Ascend on RIFF chunk failed!", "Wave file output error",
  262.                  MB_OK | MB_ICONEXCLAMATION);
  263. #else
  264.         cerr << "mmioAscend() failed!" << endl;
  265. #endif
  266.    }
  267.  
  268.    // Close the file
  269.    if (mmioClose(hmmioOut, 0) != MMSYSERR_NOERROR) {
  270.  
  271. #ifdef WIN32GUI
  272.         MessageBox(NULL, "Could not close output file!", "Wave file output error",
  273.                  MB_OK | MB_ICONEXCLAMATION);
  274. #else
  275.         cerr << "mmioClose() failed!" << endl;
  276. #endif
  277.     }
  278.  
  279.    // Free the buffer memory
  280.      delete [] temp;
  281. }
  282.  
  283. Obuffer *create_Wavefile_obuffer(MPEG_Args *maplay_args)
  284. {
  285.     Obuffer *buffer;
  286.  
  287.     enum e_mode mode = maplay_args->MPEGheader->mode();
  288.    enum e_channels which_channels = maplay_args->which_c;
  289.  
  290.     if ((mode == single_channel) || (which_channels != both))
  291.         buffer = new Wavefile_Obuffer(1, maplay_args);    // mono
  292.    else
  293.         buffer = new Wavefile_Obuffer(2, maplay_args);    // stereo
  294.  
  295.    return(buffer);
  296. }
  297.  
  298. #endif // __WIN32__
  299.