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

  1. /* ibitstr.cpp
  2.  
  3.     Input bitstream class implementation
  4.  
  5.    Changes by Jeff Tsay:
  6.  
  7.     01/26/96 : Modified for Windows file handles.
  8.  
  9.    11/29/96 : Added syncword detection for compatibility with streams produced
  10.    by DALET. Changed at the request of Wilfried Solbach, thanks for the
  11.    donation in advance! However Layer I MPP files playback jerkily.
  12.  
  13.    03/09/97 : Added a routine to read layer III side info. Also not mentioned
  14.    previously are several routines that allow seeking in a stream.
  15.  
  16.    04/14/97 : Moved the side info routine to the layer III decoder object.
  17.    Revamped the seeking mechanism and also included better syncword detection.
  18.    Moved the original file reading mechanisms back for better
  19.    portability, and used John Fehr's implementations of the seeking routines
  20.     for non-Win32 file reading. */
  21.  
  22. /*
  23.  *  @(#) ibitstream.cc 1.8, last edit: 6/15/94 16:51:45
  24.  *  @(#) Copyright (C) 1993, 1994 Tobias Bading (bading@cs.tu-berlin.de)
  25.  *  @(#) Berlin University of Technology
  26.  *
  27.  *  This program is free software; you can redistribute it and/or modify
  28.  *  it under the terms of the GNU General Public License as published by
  29.  *  the Free Software Foundation; either version 2 of the License, or
  30.  *  (at your option) any later version.
  31.  *
  32.  *  This program is distributed in the hope that it will be useful,
  33.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  34.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  35.  *  GNU General Public License for more details.
  36.  *
  37.  *  You should have received a copy of the GNU General Public License
  38.  *  along with this program; if not, write to the Free Software
  39.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  40.  */
  41.  
  42. /*
  43.  *  Changes from version 1.1 to 1.2:
  44.  *    - third argument in open syscall added
  45.  *    - minor bug in get_header() fixed
  46.  */
  47.  
  48. #ifdef  __WIN32__
  49. #include <windows.h>
  50. #else
  51. #include <stdio.h>
  52. #include <stdlib.h>
  53. #include <unistd.h>
  54. #include <errno.h>
  55. #include <fcntl.h>
  56. #endif   // __WIN32__
  57.  
  58. #ifndef GUI
  59. #include <iostream.h>
  60. #endif // GUI
  61.  
  62. #include "all.h"
  63. #include "ibitstr.h"
  64. #include "header.h"
  65.  
  66. #ifdef  DAMN_INTEL_BYTE_ORDER
  67. #define swap_int32(int_32) (((int_32) << 24) | (((int_32) << 8) & 0x00ff0000) | \
  68.                                (((int_32) >> 8) & 0x0000ff00) | ((int_32) >> 24))
  69. #endif
  70.  
  71. Ibitstream::Ibitstream(const char *filename)
  72. {
  73.  
  74. #ifdef __WIN32__
  75.  
  76.   SECURITY_ATTRIBUTES security;
  77.   security.nLength              = sizeof(SECURITY_ATTRIBUTES);
  78.   security.lpSecurityDescriptor = NULL;
  79.   security.bInheritHandle       = FALSE;
  80.  
  81.   FH = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ,
  82.                   &security, OPEN_EXISTING, NULL, NULL);
  83.  
  84.   if (FH == INVALID_HANDLE_VALUE) {
  85.    char bad_file_msg[256];
  86.     lstrcpy(bad_file_msg, "Error opening file: ");
  87. #ifdef WIN32GUI
  88.     MessageBox(NULL, lstrcat(bad_file_msg, filename) , "Invalid handle", MB_OK);
  89. #else
  90.     cerr  << "Error opening file: " << filename << endl;
  91. #endif // WIN32GUI
  92.    return;
  93.   }
  94.  
  95. #else
  96.   // copy any arguments you need, open the file, and check for error
  97.  
  98.   if ((fd = open(filename, O_RDONLY)) == -1)
  99.   {
  100. #ifndef GUI
  101.           cerr << "Error opening file: " << filename << endl;
  102. #endif
  103.       return;
  104.   }
  105.  
  106. #endif // __WIN32__
  107.  
  108.   wordpointer       = buffer;
  109.   bitindex          = 0;
  110.  
  111.   // Seeking variables
  112.   current_frame_number = -1;
  113.  
  114. #ifdef SEEK_STOP
  115.   last_frame_number    = -1;
  116. #endif
  117.  
  118. }
  119.  
  120. Ibitstream::~Ibitstream()
  121. {
  122.   // close the file
  123. #ifdef __WIN32__
  124.   CloseHandle(FH);
  125. #else
  126.   if (fd) close(fd);
  127. #endif
  128.  
  129. }
  130.  
  131. bool Ibitstream::get_header (uint32 *headerstring, enum e_syncmode syncmode)
  132. {
  133.   bool result, sync;
  134.  
  135.   int32 numread;
  136.  
  137.   do {
  138.  
  139.     // Read 4 bytes from the file, placing the number of bytes actually
  140.    // read in numread
  141. #ifdef __WIN32__
  142.    result = (bool) ReadFile(FH, (char *) headerstring, 4,
  143.                                    (DWORD *) &numread, NULL);
  144. #else
  145.     if (fd == -1) return(FALSE); // check for error opening file
  146.     result = (bool) ((numread=read(fd, (char*) headerstring, 4)) == 4);
  147. #endif
  148.  
  149.    if (!(result && (numread == 4)))
  150.       return(FALSE);
  151.  
  152. #ifdef DAMN_INTEL_BYTE_ORDER
  153.     if (syncmode == INITIAL_SYNC) {
  154.        sync =  ((*headerstring & 0x0000F0FF) == 0x0000F0FF);
  155.    } else {
  156.        sync =  ((*headerstring & 0x000CF8FF) == syncword) &&
  157.              (((*headerstring & 0xC0000000) == 0xC0000000) == single_ch_mode);
  158.    }
  159. #else
  160.     if (syncmode == INITIAL_SYNC) {
  161.         sync =  ((*headerstring & 0xFFF00000) == 0xFFF00000);
  162.  
  163.     } else {
  164.        sync =  ((*headerstring & 0xFFF80C00) == syncword) &&
  165.              (((*headerstring & 0x000000C0) == 0x000000C0) == single_ch_mode);
  166.    }
  167. #endif // DAMN_INTEL_BYTE_ORDER
  168.  
  169.    if (!sync)
  170.      // rewind 3 bytes in the file so we can try to sync again, if
  171.    // successful set result to TRUE
  172. #ifdef __WIN32__
  173.       result = (bool) SetFilePointer(FH, -3, NULL, FILE_CURRENT);
  174. #else
  175.         result = (bool) (lseek(fd, -3, SEEK_CUR) != -1);
  176. #endif // __WIN32__
  177.  
  178.   } while (!sync && result);
  179.  
  180.   if (!result)
  181.      return(FALSE);
  182.  
  183. #ifdef DAMN_INTEL_BYTE_ORDER
  184.   uint32 header = *headerstring;
  185.   *headerstring = swap_int32(header);
  186. #endif // DAMN_INTEL_BYTE_ORDER
  187.  
  188.   current_frame_number++;
  189.       
  190. #ifdef SEEK_STOP
  191.   if (last_frame_number < current_frame_number)
  192.       last_frame_number = current_frame_number;
  193. #endif
  194.  
  195.   return(TRUE);
  196. }
  197.  
  198. bool Ibitstream::read_frame(uint32 bytesize)
  199. {
  200.  
  201.   int32 numread;
  202.  
  203.   // read bytesize bytes from the file, placing the number of bytes
  204.   // actually read in numread and setting result to TRUE if
  205.   // successful
  206. #ifdef __WIN32__
  207.   bool result = ReadFile(FH, buffer, bytesize, (DWORD *) &numread, NULL);
  208. #else
  209.   bool result = (bool) ((numread=read(fd,buffer,bytesize)) != -1);
  210. #endif // __WIN32__
  211.  
  212.  
  213. /*  if (bytesize > (bufferintsize << 2))
  214.   {
  215.      cerr << "Internal error: framelength > bufferlength?!\n";
  216.      exit (1);
  217.   } */
  218.  
  219.   wordpointer = buffer;
  220.   bitindex    = 0;
  221.   framesize   = bytesize;
  222.  
  223. #ifdef DAMN_INTEL_BYTE_ORDER
  224.   uint32 *wordp;
  225.   for (wordp = buffer + ((bytesize - 1) >> 2); wordp >= buffer; --wordp)
  226.   {
  227.  
  228. #ifdef INTEL386
  229.  
  230.   // inline 386 assembly doesn't work on Borland compiler
  231.  
  232.   __asm {
  233.       mov eax, wordp
  234.         mov ebx, [eax]
  235.       bswap ebx
  236.       mov [eax], ebx
  237.   }
  238.  
  239. #else
  240.  
  241.      uint32 word   = *wordp;
  242.     *wordp = swap_int32(word);
  243.  
  244. #endif // INTEL386
  245.  
  246.   } // for (wordp ...
  247.  
  248. #endif // DAMN_INTEL_BYTE_ORDER
  249.  
  250.   return((bool) (result && (numread == framesize)));
  251. }
  252.  
  253. uint32 Ibitstream::get_bits(uint32 number_of_bits)
  254. {
  255.   static uint32 bitmask[18] =
  256.   {
  257.      0,    // dummy
  258.      0x00000001, 0x00000003, 0x00000007, 0x0000000F,
  259.      0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF,
  260.      0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF,
  261.      0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF,
  262.     0x0001FFFF
  263.   };
  264.   uint32 returnvalue;
  265.   uint32 sum = bitindex + number_of_bits;
  266.  
  267.   if (sum <= 32)
  268.   {
  269.      // all bits contained in *wordpointer
  270.      returnvalue = (*wordpointer >> (32 - sum)) & bitmask[number_of_bits];
  271.      if ((bitindex += number_of_bits) == 32)
  272.      {
  273.         bitindex = 0;
  274.  
  275. /*        if ((char *)++wordpointer > (char *)buffer + framesize)
  276.         {
  277.     cerr << "Ibitstream::get_bits(): no more bits in buffer!\n";
  278.     exit (1);
  279.         } */
  280.         wordpointer++; // added by me!
  281.      }
  282.      return(returnvalue);
  283.   }
  284.  
  285. #ifdef DAMN_INTEL_BYTE_ORDER
  286.   *((int16 *)&returnvalue + 1) = *(int16 *)wordpointer;
  287.   wordpointer++; // Added by me!
  288.   *(int16 *)&returnvalue = *((int16 *)wordpointer + 1);
  289. #else
  290.   *(int16 *)&returnvalue = *((int16 *)wordpointer + 1);
  291.   wordpointer++; // Added by me!
  292.   *((int16 *)&returnvalue + 1) = *(int16 *)wordpointer;
  293. #endif // DAMN_INTEL_BYTE_ORDER
  294.  
  295.   returnvalue >>= 48 - sum;    // returnvalue >>= 16 - (number_of_bits - (32 - bitindex))
  296.   returnvalue &= bitmask[number_of_bits];
  297.   bitindex = sum - 32;
  298.  
  299.   return(returnvalue);
  300. }
  301.  
  302. void Ibitstream::set_syncword(uint32 syncword0)
  303. {
  304.  
  305. #ifdef DAMN_INTEL_BYTE_ORDER
  306.    syncword = swap_int32(syncword0 & 0xFFFFFF3F);
  307. #else
  308.     syncword = syncword0 & 0xFFFFFF3F;
  309. #endif // DAMN_INTEL_BYTE_ORDER
  310.  
  311.    single_ch_mode = ((syncword0 & 0x000000C0) == 0x000000C0);
  312. }
  313.  
  314. uint32 Ibitstream::file_size()
  315. // return the file size of the file
  316. {
  317.  
  318. #ifdef __WIN32__
  319.     return(GetFileSize(FH, NULL));
  320. #else
  321.     // hmm. I think this should work  -- John Fehr
  322.     off_t o_off;
  323.     off_t len;
  324.     o_off = lseek(fd, 0, SEEK_CUR);
  325.     len   = lseek(fd, 0, SEEK_END);
  326.     lseek(fd, o_off, SEEK_SET);
  327.     return(len);
  328. #endif // __WIN32__
  329.  
  330. }
  331.  
  332. #ifdef SEEK_STOP
  333.  
  334. bool Ibitstream::seek(int32 frame, int32 frame_size)
  335. // set the file pointer to frame * (frame_size + 4) bytes after the
  336. // beginning of the file and return TRUE if successful
  337. {
  338.     current_frame_number = frame - 1;
  339.  
  340. #ifdef __WIN32__
  341.     return(SetFilePointer(FH, frame * (frame_size + 4), NULL, FILE_BEGIN)
  342.            != 0xFFFFFFFF);
  343. #else
  344.  
  345.     return(lseek(fd, frame * (frame_size + 4), SEEK_SET));
  346. #endif // __WIN32__
  347.  
  348. }
  349.  
  350. bool Ibitstream::seek_pad(int32 frame, int32 base_frame_size,
  351.                           Header *header, uint32 *offset)
  352. {
  353.     // base_frame_size is the frame size _without_ padding.
  354.  
  355.     Crc16 *crc = NULL;
  356.  
  357.     int32 total_frame_size = base_frame_size + 4;
  358.     int32 diff;
  359.  
  360.     if (last_frame_number < frame) {
  361.         diff = (last_frame_number >= 0) ?  offset[last_frame_number] : 0;
  362.  
  363.        // set the file pointer to ((last_frame_number+1) * total_frame_size)
  364.       // bytes after the beginning of the file
  365. #ifdef __WIN32__
  366.         SetFilePointer(FH, (last_frame_number + 1) * total_frame_size +
  367.                             diff, NULL, FILE_BEGIN);
  368. #else
  369.         lseek(fd, (last_frame_number + 1) * total_frame_size + diff, SEEK_SET);
  370. #endif // __WIN32__
  371.  
  372.         current_frame_number = last_frame_number;
  373.  
  374.         do {
  375.             if (!header->read_header(this, &crc)) // will increment last_frame_number
  376.                 return(FALSE);
  377.         } while (last_frame_number < frame);
  378.  
  379.       return(TRUE);
  380.  
  381.     } else {
  382.         diff = (frame > 0) ? offset[frame - 1] : 0;
  383.  
  384.        // set the file pointer to (frame * total_frame_size  + diff) bytes
  385.       // after the beginning of the file
  386. #ifdef __WIN32__
  387.         SetFilePointer(FH, frame * total_frame_size + diff, NULL, FILE_BEGIN);
  388. #else
  389.         lseek(fd, frame * total_frame_size + diff, SEEK_SET);
  390. #endif // __WIN32__
  391.  
  392.         current_frame_number = frame - 1;
  393.  
  394.       return(header->read_header(this, &crc));
  395.     }
  396. }
  397.  
  398. #endif // SEEK_STOP
  399.