home *** CD-ROM | disk | FTP | other *** search
/ The Best of Windows 95.com 1996 September / WIN95_09964.iso / sound / mpw32-5s.zip / MAPLAY.CPP < prev    next >
C/C++ Source or Header  |  1996-07-29  |  11KB  |  371 lines

  1. /*
  2.  *  @(#) maplay.cc 1.20, last edit: 6/22/94 12:32:55
  3.  *  @(#) Copyright (C) 1993, 1994 Tobias Bading (bading@cs.tu-berlin.de)
  4.  *  @(#) Berlin University of Technology
  5.  *
  6.  *  Many thanks for ideas and implementations to:
  7.  *  -> Jim Boucher (jboucher@flash.bu.edu)
  8.  *     for his idea and first implementation of 8 kHz u-law output
  9.  *  -> Louis P. Kruger (lpkruger@phoenix.princeton.edu)
  10.  *     for his implementation of the LinuxObuffer class
  11.  *
  12.  *  This program is free software; you can redistribute it and/or modify
  13.  *  it under the terms of the GNU General Public License as published by
  14.  *  the Free Software Foundation; either version 2 of the License, or
  15.  *  (at your option) any later version.
  16.  *
  17.  *  This program is distributed in the hope that it will be useful,
  18.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20.  *  GNU General Public License for more details.
  21.  *
  22.  *  You should have received a copy of the GNU General Public License
  23.  *  along with this program; if not, write to the Free Software
  24.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  25.  */
  26.  
  27. /*
  28.  *  Changes from version 1.1 to 1.2:
  29.  *    - minor changes to create a LinuxObuffer object
  30.  *    - minor changes for a u-law version, which creates 8 kHz u-law output
  31.  *      on an amd device or in stdout mode, if compiled with ULAW defined
  32.  *    - option -amd forces maplay to treat /dev/audio as an amd device
  33.  *      in the u-law version. This is helpful on some SPARC clones.
  34.  *    - iostreams manipulator calls like "cerr << setw (2) << ..." replaced by
  35.  *      "cerr.width (2); ..." due to problems with older GNU C++ releases.
  36.  */
  37.  
  38. /* Adapted to Win32 version by Jeff Tsay. Differences: This is a thread
  39.     of the the main program, which is the interface. Header, bitstream, and
  40.     CRC come from the main program. Minimal error checking.
  41.     CRC and range check violations ignored. Playtime not printed. Buffers
  42.     initialized differently. Most global variables have been replaced with
  43.     local ones. Last edit 3/09/96. */
  44.  
  45. #define STRICT
  46. #define WIN32_LEAN_AND_MEAN
  47. #define NOMCX
  48. #define NOIME
  49. // #define NOGDI             GDI APIs and definitions
  50. //#define NOUSER            USER APIs and definitions
  51. #define NOSOUND
  52. #define NOCOMM
  53. #define NODRIVERS
  54. #define OEMRESOURCE
  55. #define NONLS
  56. #define NOSERVICE
  57. #define NOKANJI
  58. #define NOMINMAX
  59. #define NOLOGERROR
  60. #define NOPROFILER
  61. #define NOMEMMGR
  62. #define NOLFILEIO
  63. #define NOOPENFILE
  64. #define NORESOURCE
  65. #define NOATOM
  66. #define NOLANGUAGE
  67. #define NOLSTRING
  68. #define NODBCS
  69. #define NOKEYBOARDINFO
  70. #define NOGDICAPMASKS
  71. #define NOCOLOR
  72. #define NOGDIOBJ
  73. #define NODRAWTEXT
  74. #define NOTEXTMETRIC
  75. #define NOSCALABLEFONT
  76. #define NOBITMAP
  77. #define NORASTEROPS
  78. #define NOMETAFILE
  79. #define NOSYSMETRICS
  80. #define NOSYSTEMPARAMSINFO
  81. #define NOMSG
  82. #define NOWINSTYLES
  83. #define NOWINOFFSETS
  84. #define NOSHOWWINDOW
  85. #define NODEFERWINDOWPOS
  86. #define NOVIRTUALKEYCODES
  87. #define NOKEYSTATES
  88. #define NOWH
  89. #define NOMENUS
  90. #define NOSCROLL
  91. #define NOCLIPBOARD
  92. // #define NOICONS
  93. // #define NOMB
  94. #define NOSYSCOMMANDS
  95. #define NOMDI
  96. #define NOCTLMGR
  97. #define NOWINMESSAGES
  98. #define NOHELP
  99. // #define _WINUSER_
  100. #define __oleidl_h__
  101. #define _OLE2_H_
  102. #include <windows.h>
  103.  
  104. #define MMNODRV
  105. #define MMNOSOUND
  106. #define MMNOMIDI
  107. #define MMNOAUX
  108. #define MMNOTIMER
  109. #define MMNOJOY
  110. #define MMNOMCI
  111. #define MMNOMMIO
  112. #define MMNOMMSYSTEM
  113. #include <mmsystem.h>
  114. #include "all.h"
  115. #include "crc.h"
  116. #include "header.h"
  117. #include "subband.h"
  118. #include "suband1.h"
  119. #include "suband2.h"
  120. #include "synfilt.h"
  121. #pragma hdrstop
  122. #include "ibitstr.h"
  123. #include "obuffer.h"
  124. #include "args.h"
  125. #include "bit_res.h"
  126. #include "scalfact.h"
  127. #include "l3type.h"
  128. #include "layer3.h"
  129. #include "mp2win.h"
  130.  
  131. // data extracted from commandline arguments:
  132.  
  133. SynthesisFilter *filter1 = NULL, *filter2 = NULL;
  134. Obuffer *buffer = NULL;
  135. Bit_Reserve *br = NULL;
  136.  
  137. DWORD Exit (DWORD returncode)
  138.   // delete some objects and exit
  139. {
  140.   delete br;
  141.   br = NULL;
  142.   delete buffer;    // delete on NULL-pointers are harmless
  143.   buffer = NULL;
  144.   delete filter1;
  145.   filter1 = NULL;
  146.   delete filter2;
  147.   filter2 = NULL;
  148.   ExitThread( (DWORD) returncode);
  149.   return(0L);
  150. }
  151.  
  152. DWORD maplay (MPEG_Args *maplay_args)
  153. {
  154.  
  155.     // static bool verbose_mode = False, filter_check = False;
  156.     enum e_channels which_channels = maplay_args->which_c;
  157.  
  158.     // data extracted from header of first frame:
  159.     uint32 layer;
  160.     e_mode mode;
  161.     e_sample_frequency sample_frequency;
  162.     Subband *subbands[32];
  163.  
  164.   int i;
  165.   BOOL read_ready = FALSE, write_ready = FALSE;
  166.  
  167.   Crc16 *crc = maplay_args->crc;
  168.   Ibitstream *stream = maplay_args->stream;
  169.   Header *header = maplay_args->MPEGheader;
  170.   HWND hWnd = maplay_args->hWnd;
  171.   HWAVEOUT *phwo=maplay_args->phwo;
  172.  
  173.   // Layer III objects
  174.   III_side_info_t III_side_info;
  175.   III_scalefac_t III_scalefac
  176.   ;
  177.  
  178.   // get info from header of first frame:
  179.   layer = header->layer ();
  180.   if ((mode = header->mode ()) == single_channel)
  181.      which_channels = left;
  182.   sample_frequency = header->sample_frequency ();
  183.  
  184.   // create filter(s):
  185.      filter1 = new SynthesisFilter (0);
  186.  
  187.   if (mode != single_channel && which_channels == both)
  188.      filter2 = new SynthesisFilter (1);
  189.  
  190.  
  191.   // create buffer:
  192.  
  193.      if (mode == single_channel || which_channels != both)
  194.         buffer = new MCIbuffer (1, header, phwo);    // mono
  195.      else
  196.         buffer = new MCIbuffer (2, header, phwo);    // stereo
  197.  
  198.   // Layer III : initialize Bit Reserve
  199.  
  200.   br = new Bit_Reserve();
  201.  
  202.   do
  203.   {
  204.  
  205.      if (maplay_args->position_change) {
  206.  
  207.         buffer->clear_buffer();
  208.  
  209.         if (header->sample_frequency() != fourtyfour_point_one)
  210.             stream->seek(maplay_args->desired_position,
  211.                          header->calculate_framesize());
  212.         else
  213.             stream->seek_pad(maplay_args->desired_position,
  214.                          header->calculate_framesize() - header->padding());
  215.  
  216.         maplay_args->position_change = FALSE;
  217.  
  218.         if (!header->read_header (stream, &crc))
  219.             goto quit;
  220.         SendMessage(hWnd, SEEK_ACK, NULL, NULL);
  221.         SendMessage(hWnd, SCROLL_POS, stream->current_frame, 0);
  222.      }
  223.  
  224.      // is there a change in important parameters?
  225.      // (bitrate switching is allowed)
  226.      if (header->layer () != layer)
  227.      {
  228.         // layer switching is allowed
  229.         layer = header->layer ();
  230.      }
  231.      if ((mode == single_channel && header->mode () != single_channel) ||
  232.     (mode != single_channel && header->mode () == single_channel))
  233.      {
  234.         MessageBox(hWnd,"Illegal switch from single channel to stereo \
  235. or vice versa.",
  236.                       "Decoding Error", MB_ICONEXCLAMATION);
  237.         Exit (1L);
  238.      }
  239.      if (header->sample_frequency () != sample_frequency)
  240.      {
  241.         MessageBox(hWnd, "Sorry, can't switch the sample frequency in the \
  242. middle of the stream.",
  243.                       "Decoding Error", MB_ICONEXCLAMATION);
  244.         Exit (1L);
  245.      }
  246.  
  247. if (header->layer() != 3) {
  248.  
  249.      // create subband objects:
  250.      if (header->layer () == 1)
  251.      {
  252.         if (header->mode () == single_channel)
  253.     for (i = 0; i < header->number_of_subbands (); ++i)
  254.       subbands[i] = new SubbandLayer1 (i);
  255.         else if (header->mode () == joint_stereo)
  256.         {
  257.     for (i = 0; i < header->intensity_stereo_bound (); ++i)
  258.       subbands[i] = new SubbandLayer1Stereo (i);
  259.     for (; i < header->number_of_subbands (); ++i)
  260.       subbands[i] = new SubbandLayer1IntensityStereo (i);
  261.         }
  262.         else
  263.     for (i = 0; i < header->number_of_subbands (); ++i)
  264.       subbands[i] = new SubbandLayer1Stereo (i);
  265.      }
  266.      else if (header->layer () == 2)
  267.      {
  268.         if (header->mode () == single_channel)
  269.     for (i = 0; i < header->number_of_subbands (); ++i)
  270.       subbands[i] = new SubbandLayer2 (i);
  271.         else if (header->mode () == joint_stereo)
  272.         {
  273.     for (i = 0; i < header->intensity_stereo_bound (); ++i)
  274.       subbands[i] = new SubbandLayer2Stereo (i);
  275.     for (; i < header->number_of_subbands (); ++i)
  276.       subbands[i] = new SubbandLayer2IntensityStereo (i);
  277.         }
  278.         else
  279.     for (i = 0; i < header->number_of_subbands (); ++i)
  280.       subbands[i] = new SubbandLayer2Stereo (i);
  281.      }
  282. /*     else
  283.      {
  284.         MessageBox(hWnd, "Sorry, layer 3 not implemented (yet!)",
  285.                       "Decoding Error", MB_ICONEXCLAMATION);
  286.         Exit (1L);
  287.      }           */
  288.  
  289.      // start to read audio data:
  290.      for (i = 0; i < header->number_of_subbands (); ++i)
  291.         subbands[i]->read_allocation (stream, header, crc);
  292.  
  293.      if (header->layer () == 2)
  294.         for (i = 0; i < header->number_of_subbands (); ++i)
  295.     ((SubbandLayer2 *)subbands[i])->read_scalefactor_selection (stream, crc);
  296.  
  297.      if (!crc || header->checksum_ok ())
  298.      {
  299.         // no checksums or checksum ok, continue reading from stream:
  300.         for (i = 0; i < header->number_of_subbands (); ++i)
  301.     subbands[i]->read_scalefactor (stream, header);
  302.  
  303.         do
  304.         {
  305.             for (i = 0; i < header->number_of_subbands (); ++i)
  306.                 read_ready = subbands[i]->read_sampledata (stream);
  307.  
  308.             do
  309.             {
  310.                 for (i = 0; i < header->number_of_subbands (); ++i)
  311.                     write_ready = subbands[i]->put_next_sample (which_channels,
  312.                                                                               filter1, filter2);
  313.  
  314.                 filter1->calculate_pcm_samples (buffer);
  315.                 if (which_channels == both && header->mode () != single_channel)
  316.                      filter2->calculate_pcm_samples (buffer);
  317.             } while (!write_ready);
  318.         } while (!read_ready);
  319.  
  320.         buffer->write_buffer (1);        // write to stdout
  321.      }
  322.      // Don't let user know if crc violated.
  323. //     else
  324.         // Sh*t! Wrong crc checksum in frame!
  325. //        cerr << "WARNING: frame contains wrong crc checksum! (throwing frame away)\n";
  326.      for (i = 0; i < header->number_of_subbands (); ++i)
  327.         delete subbands[i];
  328.  
  329. } else {  // Layer III
  330.     l3decoder(stream, header, br, &III_side_info, &III_scalefac,
  331.                  filter1, filter2, buffer);
  332. }
  333.  
  334.      // Send notification to the scroll bar every 16 frames
  335.      if (!(stream->current_frame & 0xf))
  336.          SendMessage(hWnd, SCROLL_POS, stream->current_frame, 0);
  337.  
  338.   }
  339.   while (header->read_header (stream, &crc));
  340.  
  341.   quit:
  342.   // Saturate the scroll bar
  343.   SendMessage(hWnd, SCROLL_POS, stream->current_frame, 0);
  344.  
  345.   delete buffer;
  346.   buffer = NULL;
  347.  
  348.   delete br;
  349.   br = NULL;
  350.  
  351. /*  if (verbose_mode)
  352.   {
  353.      // print playtime of stream:
  354.      real playtime = filter1->seconds_played (Header::frequency (sample_frequency));
  355.      uint32 minutes = (uint32)(playtime / 60.0);
  356.      uint32 seconds = (uint32)playtime - minutes * 60;
  357.      uint32 centiseconds = (uint32)((playtime - (real)(minutes * 60) - (real)seconds) * 100.0);
  358.      cerr << "end of stream, playtime: " << minutes << ':';
  359.      cerr.width (2);
  360.      cerr.fill ('0');
  361.      cerr << seconds << '.';
  362.      cerr.width (2);
  363.      cerr.fill ('0');
  364.      cerr << centiseconds << '\n';
  365.   } */
  366.  
  367.   PostMessage(hWnd, WM_THREADEND, NULL, NULL);
  368.   ExitThread(0L);
  369.   return(0L);
  370. }
  371.