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 >
Wrap
C/C++ Source or Header
|
1996-07-29
|
11KB
|
371 lines
/*
* @(#) maplay.cc 1.20, last edit: 6/22/94 12:32:55
* @(#) Copyright (C) 1993, 1994 Tobias Bading (bading@cs.tu-berlin.de)
* @(#) Berlin University of Technology
*
* Many thanks for ideas and implementations to:
* -> Jim Boucher (jboucher@flash.bu.edu)
* for his idea and first implementation of 8 kHz u-law output
* -> Louis P. Kruger (lpkruger@phoenix.princeton.edu)
* for his implementation of the LinuxObuffer class
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* Changes from version 1.1 to 1.2:
* - minor changes to create a LinuxObuffer object
* - minor changes for a u-law version, which creates 8 kHz u-law output
* on an amd device or in stdout mode, if compiled with ULAW defined
* - option -amd forces maplay to treat /dev/audio as an amd device
* in the u-law version. This is helpful on some SPARC clones.
* - iostreams manipulator calls like "cerr << setw (2) << ..." replaced by
* "cerr.width (2); ..." due to problems with older GNU C++ releases.
*/
/* Adapted to Win32 version by Jeff Tsay. Differences: This is a thread
of the the main program, which is the interface. Header, bitstream, and
CRC come from the main program. Minimal error checking.
CRC and range check violations ignored. Playtime not printed. Buffers
initialized differently. Most global variables have been replaced with
local ones. Last edit 3/09/96. */
#define STRICT
#define WIN32_LEAN_AND_MEAN
#define NOMCX
#define NOIME
// #define NOGDI GDI APIs and definitions
//#define NOUSER USER APIs and definitions
#define NOSOUND
#define NOCOMM
#define NODRIVERS
#define OEMRESOURCE
#define NONLS
#define NOSERVICE
#define NOKANJI
#define NOMINMAX
#define NOLOGERROR
#define NOPROFILER
#define NOMEMMGR
#define NOLFILEIO
#define NOOPENFILE
#define NORESOURCE
#define NOATOM
#define NOLANGUAGE
#define NOLSTRING
#define NODBCS
#define NOKEYBOARDINFO
#define NOGDICAPMASKS
#define NOCOLOR
#define NOGDIOBJ
#define NODRAWTEXT
#define NOTEXTMETRIC
#define NOSCALABLEFONT
#define NOBITMAP
#define NORASTEROPS
#define NOMETAFILE
#define NOSYSMETRICS
#define NOSYSTEMPARAMSINFO
#define NOMSG
#define NOWINSTYLES
#define NOWINOFFSETS
#define NOSHOWWINDOW
#define NODEFERWINDOWPOS
#define NOVIRTUALKEYCODES
#define NOKEYSTATES
#define NOWH
#define NOMENUS
#define NOSCROLL
#define NOCLIPBOARD
// #define NOICONS
// #define NOMB
#define NOSYSCOMMANDS
#define NOMDI
#define NOCTLMGR
#define NOWINMESSAGES
#define NOHELP
// #define _WINUSER_
#define __oleidl_h__
#define _OLE2_H_
#include <windows.h>
#define MMNODRV
#define MMNOSOUND
#define MMNOMIDI
#define MMNOAUX
#define MMNOTIMER
#define MMNOJOY
#define MMNOMCI
#define MMNOMMIO
#define MMNOMMSYSTEM
#include <mmsystem.h>
#include "all.h"
#include "crc.h"
#include "header.h"
#include "subband.h"
#include "suband1.h"
#include "suband2.h"
#include "synfilt.h"
#pragma hdrstop
#include "ibitstr.h"
#include "obuffer.h"
#include "args.h"
#include "bit_res.h"
#include "scalfact.h"
#include "l3type.h"
#include "layer3.h"
#include "mp2win.h"
// data extracted from commandline arguments:
SynthesisFilter *filter1 = NULL, *filter2 = NULL;
Obuffer *buffer = NULL;
Bit_Reserve *br = NULL;
DWORD Exit (DWORD returncode)
// delete some objects and exit
{
delete br;
br = NULL;
delete buffer; // delete on NULL-pointers are harmless
buffer = NULL;
delete filter1;
filter1 = NULL;
delete filter2;
filter2 = NULL;
ExitThread( (DWORD) returncode);
return(0L);
}
DWORD maplay (MPEG_Args *maplay_args)
{
// static bool verbose_mode = False, filter_check = False;
enum e_channels which_channels = maplay_args->which_c;
// data extracted from header of first frame:
uint32 layer;
e_mode mode;
e_sample_frequency sample_frequency;
Subband *subbands[32];
int i;
BOOL read_ready = FALSE, write_ready = FALSE;
Crc16 *crc = maplay_args->crc;
Ibitstream *stream = maplay_args->stream;
Header *header = maplay_args->MPEGheader;
HWND hWnd = maplay_args->hWnd;
HWAVEOUT *phwo=maplay_args->phwo;
// Layer III objects
III_side_info_t III_side_info;
III_scalefac_t III_scalefac
;
// get info from header of first frame:
layer = header->layer ();
if ((mode = header->mode ()) == single_channel)
which_channels = left;
sample_frequency = header->sample_frequency ();
// create filter(s):
filter1 = new SynthesisFilter (0);
if (mode != single_channel && which_channels == both)
filter2 = new SynthesisFilter (1);
// create buffer:
if (mode == single_channel || which_channels != both)
buffer = new MCIbuffer (1, header, phwo); // mono
else
buffer = new MCIbuffer (2, header, phwo); // stereo
// Layer III : initialize Bit Reserve
br = new Bit_Reserve();
do
{
if (maplay_args->position_change) {
buffer->clear_buffer();
if (header->sample_frequency() != fourtyfour_point_one)
stream->seek(maplay_args->desired_position,
header->calculate_framesize());
else
stream->seek_pad(maplay_args->desired_position,
header->calculate_framesize() - header->padding());
maplay_args->position_change = FALSE;
if (!header->read_header (stream, &crc))
goto quit;
SendMessage(hWnd, SEEK_ACK, NULL, NULL);
SendMessage(hWnd, SCROLL_POS, stream->current_frame, 0);
}
// is there a change in important parameters?
// (bitrate switching is allowed)
if (header->layer () != layer)
{
// layer switching is allowed
layer = header->layer ();
}
if ((mode == single_channel && header->mode () != single_channel) ||
(mode != single_channel && header->mode () == single_channel))
{
MessageBox(hWnd,"Illegal switch from single channel to stereo \
or vice versa.",
"Decoding Error", MB_ICONEXCLAMATION);
Exit (1L);
}
if (header->sample_frequency () != sample_frequency)
{
MessageBox(hWnd, "Sorry, can't switch the sample frequency in the \
middle of the stream.",
"Decoding Error", MB_ICONEXCLAMATION);
Exit (1L);
}
if (header->layer() != 3) {
// create subband objects:
if (header->layer () == 1)
{
if (header->mode () == single_channel)
for (i = 0; i < header->number_of_subbands (); ++i)
subbands[i] = new SubbandLayer1 (i);
else if (header->mode () == joint_stereo)
{
for (i = 0; i < header->intensity_stereo_bound (); ++i)
subbands[i] = new SubbandLayer1Stereo (i);
for (; i < header->number_of_subbands (); ++i)
subbands[i] = new SubbandLayer1IntensityStereo (i);
}
else
for (i = 0; i < header->number_of_subbands (); ++i)
subbands[i] = new SubbandLayer1Stereo (i);
}
else if (header->layer () == 2)
{
if (header->mode () == single_channel)
for (i = 0; i < header->number_of_subbands (); ++i)
subbands[i] = new SubbandLayer2 (i);
else if (header->mode () == joint_stereo)
{
for (i = 0; i < header->intensity_stereo_bound (); ++i)
subbands[i] = new SubbandLayer2Stereo (i);
for (; i < header->number_of_subbands (); ++i)
subbands[i] = new SubbandLayer2IntensityStereo (i);
}
else
for (i = 0; i < header->number_of_subbands (); ++i)
subbands[i] = new SubbandLayer2Stereo (i);
}
/* else
{
MessageBox(hWnd, "Sorry, layer 3 not implemented (yet!)",
"Decoding Error", MB_ICONEXCLAMATION);
Exit (1L);
} */
// start to read audio data:
for (i = 0; i < header->number_of_subbands (); ++i)
subbands[i]->read_allocation (stream, header, crc);
if (header->layer () == 2)
for (i = 0; i < header->number_of_subbands (); ++i)
((SubbandLayer2 *)subbands[i])->read_scalefactor_selection (stream, crc);
if (!crc || header->checksum_ok ())
{
// no checksums or checksum ok, continue reading from stream:
for (i = 0; i < header->number_of_subbands (); ++i)
subbands[i]->read_scalefactor (stream, header);
do
{
for (i = 0; i < header->number_of_subbands (); ++i)
read_ready = subbands[i]->read_sampledata (stream);
do
{
for (i = 0; i < header->number_of_subbands (); ++i)
write_ready = subbands[i]->put_next_sample (which_channels,
filter1, filter2);
filter1->calculate_pcm_samples (buffer);
if (which_channels == both && header->mode () != single_channel)
filter2->calculate_pcm_samples (buffer);
} while (!write_ready);
} while (!read_ready);
buffer->write_buffer (1); // write to stdout
}
// Don't let user know if crc violated.
// else
// Sh*t! Wrong crc checksum in frame!
// cerr << "WARNING: frame contains wrong crc checksum! (throwing frame away)\n";
for (i = 0; i < header->number_of_subbands (); ++i)
delete subbands[i];
} else { // Layer III
l3decoder(stream, header, br, &III_side_info, &III_scalefac,
filter1, filter2, buffer);
}
// Send notification to the scroll bar every 16 frames
if (!(stream->current_frame & 0xf))
SendMessage(hWnd, SCROLL_POS, stream->current_frame, 0);
}
while (header->read_header (stream, &crc));
quit:
// Saturate the scroll bar
SendMessage(hWnd, SCROLL_POS, stream->current_frame, 0);
delete buffer;
buffer = NULL;
delete br;
br = NULL;
/* if (verbose_mode)
{
// print playtime of stream:
real playtime = filter1->seconds_played (Header::frequency (sample_frequency));
uint32 minutes = (uint32)(playtime / 60.0);
uint32 seconds = (uint32)playtime - minutes * 60;
uint32 centiseconds = (uint32)((playtime - (real)(minutes * 60) - (real)seconds) * 100.0);
cerr << "end of stream, playtime: " << minutes << ':';
cerr.width (2);
cerr.fill ('0');
cerr << seconds << '.';
cerr.width (2);
cerr.fill ('0');
cerr << centiseconds << '\n';
} */
PostMessage(hWnd, WM_THREADEND, NULL, NULL);
ExitThread(0L);
return(0L);
}