home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / sound / players / maplay_t.z / maplay_t / maplay.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-21  |  11.7 KB  |  404 lines

  1. /*
  2.  *  @(#) maplay.c 1.11, last edit: 2/21/94 18:09:58
  3.  *  @(#) Copyright (C) 1993, 1994 Tobias Bading (bading@cs.tu-berlin.de)
  4.  *  @(#) Berlin University of Technology
  5.  *
  6.  *  This program is free software; you can redistribute it and/or modify
  7.  *  it under the terms of the GNU General Public License as published by
  8.  *  the Free Software Foundation; either version 2 of the License, or
  9.  *  (at your option) any later version.
  10.  *
  11.  *  This program is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public License
  17.  *  along with this program; if not, write to the Free Software
  18.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20.  
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <math.h>
  25. #include <iostream.h>
  26. #include <iomanip.h>
  27. #include "all.h"
  28. #include "ibitstream.h"
  29. #include "header.h"
  30. #include "subband.h"
  31. #include "subband_layer_1.h"
  32. #include "subband_layer_2.h"
  33. #include "synthesis_filter.h"
  34. #include "obuffer.h"
  35. #include "crc.h"
  36.  
  37.  
  38. // data extracted from commandline arguments:
  39. static char *filename;
  40. static bool verbose_mode = False, filter_check = False;
  41. static bool stdout_mode = False;
  42. static enum e_channels which_channels = both;
  43. static bool use_speaker = False, use_headphone = False, use_line_out = False;
  44. static bool use_own_scalefactor = False;
  45. static real scalefactor;
  46.  
  47. // data extracted from header of first frame:
  48. static uint32 layer;
  49. static e_mode mode;
  50. static e_sample_frequency sample_frequency;
  51.  
  52. // objects needed for playing a file:
  53. static Ibitstream *stream;
  54. static Header *header;
  55. static Crc16 *crc;
  56. static Subband *subbands[32];
  57. static SynthesisFilter *filter1 = NULL, *filter2 = NULL;
  58. static Obuffer *buffer = NULL;
  59.  
  60.  
  61. static void Exit (int returncode)
  62.   // delete some objects and exit
  63. {
  64.   if (buffer)
  65.     delete buffer;
  66.   if (filter1)
  67.     delete filter1;
  68.   if (filter2)
  69.     delete filter2;
  70.   if (header)
  71.     delete header;
  72.   if (stream)
  73.     delete stream;
  74.   exit (returncode);
  75. }
  76.  
  77.  
  78. main (int argc, char *argv[])
  79. {
  80.   int i;
  81.   bool read_ready = False, write_ready = False;
  82.  
  83.   if (argc < 2 || !strncmp (argv[1], "-h", 2))
  84.   {
  85. usage:
  86.     cerr << "\nusage: " << argv[0]
  87.      << " [-v] [-s] [-l] [-r] [-us] [-uh] [-ul] [-c] [-f ushort] filename\n"
  88.         "  filename   filename of a MPEG audio stream or - for stdin\n"
  89.         "  -v         verbose mode\n"
  90.         "  -s         write raw pcm samples to stdout\n"
  91.         "  -l         decode only the left channel\n"
  92.         "  -r         decode only the right channel\n"
  93.         "  -us        send audio signal to speaker (default)\n"
  94.         "  -uh        send audio signal to headphone\n"
  95.         "  -ul        send audio signal to line out\n"
  96.         "  -c         check for filter range violations\n"
  97.         "  -f ushort  use this scalefactor instead of the default value 32768\n\n"
  98.         "@(#) MPEG Audio Player maplay 1.1, created: 2/21/94 18:28:25\n"
  99.         "@(#) Copyright (C) 1993, 1994 Tobias Bading (bading@cs.tu-berlin.de)\n"
  100.         "@(#) Berlin University of Technology\n"
  101.         "@(#) This program is free software. See the GNU General Public License\n"
  102.         "@(#) in the file COPYING for more details.\n\n";
  103.     exit (0);
  104.   }
  105.  
  106.   // parse arguments:
  107.   for (i = 1; i < argc; ++i)
  108.     if (argv[i][0] == '-' && argv[i][1])
  109.       switch (argv[i][1])
  110.       {
  111.     case 'v':
  112.       verbose_mode = True;
  113.       break;
  114.     case 's':
  115.       stdout_mode = True;
  116.       break;
  117.     case 'l':
  118.       which_channels = left;
  119.       break;
  120.     case 'r':
  121.       which_channels = right;
  122.       break;
  123.     case 'u':
  124.       switch (argv[i][2])
  125.       {
  126.         case 's':
  127.           use_speaker = True;
  128.           break;
  129.         case 'h':
  130.           use_headphone = True;
  131.           break;
  132.         case 'l':
  133.           use_line_out = True;
  134.           break;
  135.       }
  136.       break;
  137.     case 'c':
  138.       filter_check = True;
  139.       break;
  140.     case 'f':
  141.       if (++i == argc)
  142.       {
  143.         cerr << "please specify a new scalefactor after the -f option!\n";
  144.         exit (1);
  145.       }
  146.       use_own_scalefactor = True;
  147.       sscanf (argv[i], "%f", &scalefactor);
  148.       break;
  149.     default:
  150.       goto usage;
  151.       }
  152.     else if (!filename)
  153.       filename = argv[i];
  154.     else
  155.       goto usage;
  156.  
  157.   if (!filename)
  158.     goto usage;
  159.   if (!(use_speaker || use_headphone || use_line_out))
  160.     use_speaker = True;
  161.  
  162.   if (!strcmp (filename, "-"))
  163.     stream = new Ibitstream (0);        // read from stdin
  164.   else
  165.     stream = new Ibitstream (filename);        // read from file
  166.  
  167.   header = new Header;
  168.   if (!header->read_header (stream, &crc))
  169.   {
  170.     cerr << "no header found!\n";
  171.     Exit (1);
  172.   }
  173.  
  174.   // get info from header of first frame:
  175.   layer = header->layer ();
  176.   if ((mode = header->mode ()) == single_channel)
  177.     which_channels = left;
  178.   sample_frequency = header->sample_frequency ();
  179.  
  180.   // create filter(s):
  181.   if (use_own_scalefactor)
  182.     filter1 = new SynthesisFilter (0, scalefactor);
  183.   else
  184.     filter1 = new SynthesisFilter (0);
  185.   if (mode != single_channel && which_channels == both)
  186.     if (use_own_scalefactor)
  187.       filter2 = new SynthesisFilter (1, scalefactor);
  188.     else
  189.       filter2 = new SynthesisFilter (1);
  190.  
  191.   // create buffer:
  192.   if (stdout_mode)
  193.     if (mode == single_channel || which_channels != both)
  194.       buffer = new ShortObuffer (1);
  195.     else
  196.       buffer = new ShortObuffer (2);
  197.   else
  198. #ifdef Indigo
  199.     if (mode == single_channel || which_channels != both)
  200.       buffer = new IndigoObuffer (1, header);
  201.     else
  202.       buffer = new IndigoObuffer (2, header);
  203. #else
  204. #ifdef SPARC
  205.     if (SparcObuffer::class_suitable ())
  206.       if (mode == single_channel || which_channels != both)
  207.     buffer = new SparcObuffer (1, header, use_speaker, use_headphone, use_line_out);
  208.       else
  209.     buffer = new SparcObuffer (2, header, use_speaker, use_headphone, use_line_out);
  210.     else
  211.     {
  212.       cerr << "Sorry, no suitable audio device detected, please use stdout mode.\n";
  213.       Exit (1);
  214.     }
  215. #else
  216. // #ifdef your_machine
  217. //    if (mode == single_channel || which_channels != both)
  218. //      buffer = new your_Obuffer (your_parameters);    // mono
  219. //    else
  220. //      buffer = new your_Obuffer (your_parameters);    // stereo
  221. // #else
  222.   {
  223.     cerr << "Sorry, no suitable audio device detected, please use stdout mode.\n";
  224.     Exit (1);
  225.   }
  226. // #endif  // !your_machine
  227. #endif    // !SPARC
  228. #endif    // !Indigo
  229.  
  230.   if (verbose_mode)
  231.   {
  232.     // print informations about the stream
  233.     char *name = strrchr (filename, '/');
  234.     if (name)
  235.       ++name;
  236.     else
  237.       name = filename;
  238.     cerr << name << " is a layer " << header->layer_string () << ' '
  239.      << header->mode_string () << " MPEG audio stream with";
  240.     if (!header->checksums ())
  241.       cerr << "out";
  242.     cerr << " checksums.\nThe sample frequency is "
  243.      << header->sample_frequency_string () << " at a bitrate of "
  244.      << header->bitrate_string () << ".\n"
  245.         "This stream is ";
  246.     if (header->original ())
  247.       cerr << "an original";
  248.     else
  249.       cerr << "a copy";
  250.     cerr << " and is ";
  251.     if (!header->copyright ())
  252.       cerr << "not ";
  253.     cerr << "copyright protected.\n";
  254.   }
  255.  
  256.   do
  257.   {
  258.     // is there a change in important parameters?
  259.     // (bitrate switching is allowed)
  260.     if (header->layer () != layer)
  261.     {
  262.       // layer switching is allowed
  263.       if (verbose_mode)
  264.     cerr << "switching to layer " << header->layer_string () << ".\n";
  265.       layer = header->layer ();
  266.     }
  267.     if ((mode == single_channel && header->mode () != single_channel) ||
  268.     (mode != single_channel && header->mode () == single_channel))
  269.     {
  270.       // switching from single channel to stereo or vice versa is not allowed
  271.       cerr << "illegal switch from single channel to stereo or vice versa!\n";
  272.       Exit (1);
  273.     }
  274.     if (header->sample_frequency () != sample_frequency)
  275.     {
  276.       // switching the sample frequency is not allowed
  277.       cerr << "sorry, can't switch the sample frequency in the middle of the stream!\n";
  278.       Exit (1);
  279.     }
  280.  
  281.     // create subband objects:
  282.     if (header->layer () == 1)
  283.     {
  284.       if (header->mode () == single_channel)
  285.     for (i = 0; i < header->number_of_subbands (); ++i)
  286.       subbands[i] = new SubbandLayer1 (i);
  287.       else if (header->mode () == joint_stereo)
  288.       {
  289.     for (i = 0; i < header->intensity_stereo_bound (); ++i)
  290.       subbands[i] = new SubbandLayer1Stereo (i);
  291.     for (; i < header->number_of_subbands (); ++i)
  292.       subbands[i] = new SubbandLayer1IntensityStereo (i);
  293.       }
  294.       else
  295.     for (i = 0; i < header->number_of_subbands (); ++i)
  296.       subbands[i] = new SubbandLayer1Stereo (i);
  297.     }
  298.     else if (header->layer () == 2)
  299.     {
  300.       if (header->mode () == single_channel)
  301.     for (i = 0; i < header->number_of_subbands (); ++i)
  302.       subbands[i] = new SubbandLayer2 (i);
  303.       else if (header->mode () == joint_stereo)
  304.       {
  305.     for (i = 0; i < header->intensity_stereo_bound (); ++i)
  306.       subbands[i] = new SubbandLayer2Stereo (i);
  307.     for (; i < header->number_of_subbands (); ++i)
  308.       subbands[i] = new SubbandLayer2IntensityStereo (i);
  309.       }
  310.       else
  311.     for (i = 0; i < header->number_of_subbands (); ++i)
  312.       subbands[i] = new SubbandLayer2Stereo (i);
  313.     }
  314.     else
  315.     {
  316.       cerr << "sorry, layer 3 not implemented!\n";
  317.       Exit (0);
  318.     }
  319.  
  320.     // start to read audio data:
  321.     for (i = 0; i < header->number_of_subbands (); ++i)
  322.       subbands[i]->read_allocation (stream, header, crc);
  323.  
  324.     if (header->layer () == 2)
  325.       for (i = 0; i < header->number_of_subbands (); ++i)
  326.     ((SubbandLayer2 *)subbands[i])->read_scalefactor_selection (stream, crc);
  327.  
  328.     if (!crc || header->checksum_ok ())
  329.     {
  330.       // no checksums or checksum ok, continue reading from stream:
  331.       for (i = 0; i < header->number_of_subbands (); ++i)
  332.     subbands[i]->read_scalefactor (stream, header);
  333.  
  334.       do
  335.       {
  336.     for (i = 0; i < header->number_of_subbands (); ++i)
  337.       read_ready = subbands[i]->read_sampledata (stream);
  338.  
  339.     do
  340.     {
  341.       for (i = 0; i < header->number_of_subbands (); ++i)
  342.         write_ready = subbands[i]->put_next_sample (which_channels, filter1, filter2);
  343.  
  344.       filter1->calculate_pcm_samples (buffer);
  345.       if (which_channels == both && header->mode () != single_channel)
  346.         filter2->calculate_pcm_samples (buffer);
  347.     }
  348.     while (!write_ready);
  349.       }
  350.       while (!read_ready);
  351.  
  352.       buffer->write_buffer (1);        // write to stdout
  353.     }
  354.     else
  355.       // Sh*t! Wrong crc checksum in frame!
  356.       cerr << "WARNING: frame contains wrong crc checksum! (throwing frame away)\n";
  357.  
  358.     for (i = 0; i < header->number_of_subbands (); ++i)
  359.       delete subbands[i];
  360.   }
  361.   while (header->read_header (stream, &crc));
  362.  
  363.   delete buffer;
  364.  
  365.   uint32 range_violations = filter1->violations ();
  366.   if (mode != single_channel && which_channels == both)
  367.    range_violations += filter2->violations ();
  368.  
  369.   if (filter_check)
  370.   {
  371.     // check whether (one of) the filter(s) produced values not in [-1.0, 1.0]:
  372.     if (range_violations)
  373.     {
  374.       cerr << range_violations << " range violations have occured!\n";
  375.       if (stdout_mode)
  376.     cerr << "If you notice these violations,\n";
  377.       else
  378.     cerr << "If you have noticed these violations,\n";
  379.       cerr << "please use the -f option with the value ";
  380.       if (mode != single_channel && which_channels == both &&
  381.       filter2->hardest_violation () > filter1->hardest_violation ())
  382.     cerr << filter2->recommended_scalefactor ();
  383.       else
  384.     cerr << filter1->recommended_scalefactor ();
  385.       cerr << "\nor a greater value up to 32768 and try again.\n";
  386.     }
  387.   }
  388.   if (verbose_mode)
  389.   {
  390.     // print playtime of stream:
  391.     real playtime = filter1->seconds_played (Header::frequency (sample_frequency));
  392.     uint32 minutes = (uint32)(playtime / 60.0);
  393.     uint32 seconds = (uint32)playtime - minutes * 60;
  394.     uint32 centiseconds = (uint32)((playtime - (real)(minutes * 60) - (real)seconds) * 100.0);
  395.     cerr << "end of stream, playtime: " << minutes << ':'
  396.      << setw (2) << setfill ('0')
  397.      << seconds << '.'
  398.      << setw (2) << setfill ('0')
  399.      << centiseconds << '\n';
  400.   }
  401.  
  402.   return 0;
  403. }
  404.