[Scummvm-cvs-logs] CVS: scummvm mp3_cd.cpp,NONE,1.1 mp3_cd.h,NONE,1.1 sdl.cpp,1.71,1.72 x11.cpp,1.8,1.9

Nicolas Bacca arisme at users.sourceforge.net
Thu Apr 4 22:45:08 CEST 2002


Update of /cvsroot/scummvm/scummvm
In directory usw-pr-cvs1:/tmp/cvs-serv1233

Modified Files:
	sdl.cpp x11.cpp 
Added Files:
	mp3_cd.cpp mp3_cd.h 
Log Message:
MP3 CD patch reorganized

--- NEW FILE: mp3_cd.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2002 The ScummVM project
 *
 * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/mp3_cd.cpp,v 1.1 2002/04/05 00:00:45 arisme Exp $
 */

#include "stdafx.h"
#include "scumm.h"
#include "mp3_cd.h"

#ifdef COMPRESSED_SOUND_FILE

int _current_mp3_cd_track;
struct xing _vbr_header;
struct mad_header _mad_header;
long _mp3_size;
FILE *_mp3_track;
MixerChannel *_mc;

// From xing.c in MAD

int xing_parse(struct xing *xing, struct mad_bitptr ptr, unsigned int bitlen)
{

  xing->flags = 0;

  if (bitlen < 64 || mad_bit_read(&ptr, 32) != XING_MAGIC)
    goto fail;

  xing->flags = mad_bit_read(&ptr, 32);
  bitlen -= 64;

  if (xing->flags & XING_FRAMES) {
    if (bitlen < 32)
      goto fail;

    xing->frames = mad_bit_read(&ptr, 32);
    bitlen -= 32;
  }

  if (xing->flags & XING_BYTES) {
    if (bitlen < 32)
      goto fail;

    xing->bytes = mad_bit_read(&ptr, 32);
    bitlen -= 32;
  }

  if (xing->flags & XING_TOC) {
    int i;

    if (bitlen < 800)
      goto fail;

    for (i = 0; i < 100; ++i)
      xing->toc[i] = (unsigned char)mad_bit_read(&ptr, 8);

    bitlen -= 800;
  }

  if (xing->flags & XING_SCALE) {
    if (bitlen < 32)
      goto fail;

    xing->scale = mad_bit_read(&ptr, 32);
    bitlen -= 32;
  }

  return 0;

 fail:
  xing->flags = 0;
  return -1;
}

// Borrowed from Winamp plugin in_mad.c

BOOL parse_xing_vbr_tag()
{
  struct mad_stream stream;
  struct mad_frame frame;
  unsigned char buffer[8192];
  unsigned int buflen = 0;
  int count = 0, result = 0;

  _vbr_header.flags = 0;

  mad_stream_init(&stream);
  mad_frame_init(&frame);
  
  fseek(_mp3_track, 0, SEEK_SET);

  while (1) {
    if (buflen < sizeof(buffer)) {
      DWORD bytes;	  

	  bytes = fread(buffer + buflen, 1, sizeof(buffer) - buflen, _mp3_track);
      if (bytes <= 0) {
	if (bytes == -1)
	  result = -1;
	break;
      }

      buflen += bytes;
    }

    mad_stream_buffer(&stream, buffer, buflen);

    while (1) {
      if (mad_frame_decode(&frame, &stream) == -1) {
	if (!MAD_RECOVERABLE(stream.error))
	  break;

	if (stream.error != MAD_ERROR_BADCRC)
	  continue;
      }

      if (count++ || 
		  xing_parse(&_vbr_header, stream.anc_ptr, stream.anc_bitlen) 
			== -1)
	break;
    }

    if (count || stream.error != MAD_ERROR_BUFLEN)
      break;

    memmove(buffer, stream.next_frame,
	    buflen = &buffer[buflen] - stream.next_frame);
  }

  if (count)
	  memcpy(&_mad_header, &frame.header, sizeof(mad_header));
  else
	  result = -1;

  mad_frame_finish(&frame);
  mad_stream_finish(&stream);

  return (result != -1);
}

uint32 calc_cd_file_offset(int start_frame) {
	long offset;

	if (!_vbr_header.flags) {
		float frame_size;
		//mad_timer_t timer;  - recode with timer

		/* Constant bit rate - perhaps not fully accurate */
		frame_size = (float)144 * _mad_header.bitrate / _mad_header.samplerate;
		offset = (long)((float)start_frame / (float)CD_FPS * 1000 / 
				 (float)((float)1152 / (float)_mad_header.samplerate * 1000) *
				 (float)(frame_size + 0.5));			
	}
	else {
        /* DOES NOT WORK AT THE MOMENT */
		/* see Xing SDK */
		long a;
		float fa, fb, fx;
		float percent = (float)start_frame / (float)CD_FPS * 1000 /
						((float)((float)1152 / (float)_mad_header.samplerate * 1000) * _vbr_header.frames) *
						100;

		if( percent < 0.0f )   percent = 0.0f;
		if( percent > 100.0f ) percent = 100.0f;

		a = (int)percent;
		if( a > 99 ) a = 99;
		fa = _vbr_header.toc[a];
		if( a < 99 ) {
			fb = _vbr_header.toc[a+1];
		}
		else {
			fb = 256.0f;
		}

		fx = fa + (fb-fa)*(percent-a);

		offset = (int)((1.0f/256.0f)*fx*_vbr_header.bytes); 

	}

	return offset;
}

BOOL mp3_cd_play(Scumm *s, int track, int num_loops, int start_frame, int end_frame) {

	// See if we are already playing this track, else try to open it

	if (_current_mp3_cd_track != track) {
		char track_name[1024];				

		sprintf(track_name, "%strack%d.mp3", s->_gameDataPath, track);
		_mp3_track = fopen(track_name, "rb");
		if (!_mp3_track) {
			warning("No CD and track %d not available in mp3 format", track);
			return FALSE;
		}

		if (!parse_xing_vbr_tag()) {
				warning("Error parsing file header - ignoring file", 
							track);
				fclose(_mp3_track);
				return FALSE;
		}

		if (_vbr_header.flags) {
			if (!(
				    (_vbr_header.flags & XING_TOC) &&
					(_vbr_header.flags & XING_BYTES) &&
					(_vbr_header.flags & XING_FRAMES)
				)) {
				warning("Missing required part of VBR header - ignoring file");
				fclose(_mp3_track);
				_vbr_header.flags = 0;
				return FALSE;
			}
		}

		// Allocate the music mixer if necessary

		if (!_mc) {
			_mc = s->allocateMixer();
			if (!_mc) {
				warning("No mixer channel available for MP3 music");
				return FALSE;
			}
		}

		fseek(_mp3_track, 0, SEEK_END);
		_mp3_size = ftell(_mp3_track);
		fseek(_mp3_track, 0, SEEK_SET);

		_mc->type = MIXER_MP3_CDMUSIC;
		_mc->sound_data.mp3_cdmusic.file = _mp3_track;
		_mc->sound_data.mp3_cdmusic.playing = FALSE;
		_mc->sound_data.mp3_cdmusic.buffer_size = 200000;
		_mc->_sfx_sound = malloc(_mc->sound_data.mp3_cdmusic.buffer_size); 

														/* see if it's enough */
		mad_stream_init(&_mc->sound_data.mp3.stream);
		if (_mad_header.samplerate == 44100) 
			mad_stream_options((mad_stream*)&_mc->sound_data.mp3.stream, 
								MAD_OPTION_HALFSAMPLERATE);

		mad_frame_init(&_mc->sound_data.mp3.frame);
		mad_synth_init(&_mc->sound_data.mp3.synth);

		_current_mp3_cd_track = track;		
	}


	if (_current_mp3_cd_track == track) {

		uint32 where;

		// See where we want to go
		where = calc_cd_file_offset(start_frame);

		if (start_frame < 0 || end_frame < 0) {
			warning("Negative index in frame");
			return FALSE;
		}

		mad_timer_set(&_mc->sound_data.mp3_cdmusic.duration,
					  0,
					  end_frame,
					  CD_FPS);

		fseek(_mp3_track, where, SEEK_SET);
		_mc->sound_data.mp3_cdmusic.playing = TRUE;		

		return TRUE;
	}

	return FALSE;
}

#endif


--- NEW FILE: mp3_cd.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2002 The ScummVM project
 *
 * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/mp3_cd.h,v 1.1 2002/04/05 00:00:46 arisme Exp $
 */

#ifndef MP3_CD_H
#define MP3_CD_H

// From xing.h in MAD

# define XING_MAGIC	(('X' << 24) | ('i' << 16) | ('n' << 8) | 'g')

struct xing {
  long flags;			/* valid fields (see below) */
  unsigned long frames;		/* total number of frames */
  unsigned long bytes;		/* total number of bytes */
  unsigned char toc[100];	/* 100-point seek table */
  long scale;			/* ?? */
};

enum {
  XING_FRAMES = 0x00000001L,
  XING_BYTES  = 0x00000002L,
  XING_TOC    = 0x00000004L,
  XING_SCALE  = 0x00000008L
};

BOOL mp3_cd_play(Scumm *s, int track, int num_loops, int start_frame, int end_frame);

#endif
Index: sdl.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sdl.cpp,v
retrieving revision 1.71
retrieving revision 1.72
diff -C2 -d -r1.71 -r1.72
*** sdl.cpp	4 Apr 2002 22:47:03 -0000	1.71
--- sdl.cpp	5 Apr 2002 00:00:46 -0000	1.72
***************
*** 30,33 ****
--- 30,34 ----
  
  #include "cdmusic.h"
+ #include "mp3_cd.h"
  
  static unsigned int scale;
***************
*** 677,997 ****
  static Uint32 cd_end_time, cd_stop_time, cd_next_second;
  
! #ifdef COMPRESSED_SOUND_FILE
! 
! // MP3 CD track support
! 
! 
! // From xing.h in MAD
! 
! # define XING_MAGIC	(('X' << 24) | ('i' << 16) | ('n' << 8) | 'g')
! 
! struct xing {
!   long flags;			/* valid fields (see below) */
!   unsigned long frames;		/* total number of frames */
!   unsigned long bytes;		/* total number of bytes */
!   unsigned char toc[100];	/* 100-point seek table */
!   long scale;			/* ?? */
! };
! 
! enum {
!   XING_FRAMES = 0x00000001L,
!   XING_BYTES  = 0x00000002L,
!   XING_TOC    = 0x00000004L,
!   XING_SCALE  = 0x00000008L
! };
! 
! 
! int _current_mp3_cd_track;
! struct xing _vbr_header;
! struct mad_header _mad_header;
! long _mp3_size;
! FILE *_mp3_track;
! MixerChannel *_mc;
! 
! // From xing.c in MAD
! 
! int xing_parse(struct xing *xing, struct mad_bitptr ptr, unsigned int bitlen)
! {
! 
!   xing->flags = 0;
! 
!   if (bitlen < 64 || mad_bit_read(&ptr, 32) != XING_MAGIC)
!     goto fail;
! 
!   xing->flags = mad_bit_read(&ptr, 32);
!   bitlen -= 64;
! 
!   if (xing->flags & XING_FRAMES) {
!     if (bitlen < 32)
!       goto fail;
! 
!     xing->frames = mad_bit_read(&ptr, 32);
!     bitlen -= 32;
!   }
! 
!   if (xing->flags & XING_BYTES) {
!     if (bitlen < 32)
!       goto fail;
! 
!     xing->bytes = mad_bit_read(&ptr, 32);
!     bitlen -= 32;
!   }
! 
!   if (xing->flags & XING_TOC) {
!     int i;
! 
!     if (bitlen < 800)
!       goto fail;
! 
!     for (i = 0; i < 100; ++i)
!       xing->toc[i] = (unsigned char)mad_bit_read(&ptr, 8);
! 
!     bitlen -= 800;
!   }
! 
!   if (xing->flags & XING_SCALE) {
!     if (bitlen < 32)
!       goto fail;
! 
!     xing->scale = mad_bit_read(&ptr, 32);
!     bitlen -= 32;
!   }
! 
!   return 0;
! 
!  fail:
!   xing->flags = 0;
!   return -1;
! }
! 
! // Borrowed from Winamp plugin in_mad.c
! 
! BOOL parse_xing_vbr_tag()
! {
!   struct mad_stream stream;
!   struct mad_frame frame;
!   unsigned char buffer[8192];
!   unsigned int buflen = 0;
!   int count = 0, result = 0;
! 
!   _vbr_header.flags = 0;
! 
!   mad_stream_init(&stream);
!   mad_frame_init(&frame);
!   
!   fseek(_mp3_track, 0, SEEK_SET);
! 
!   while (1) {
!     if (buflen < sizeof(buffer)) {
!       DWORD bytes;	  
! 
! 	  bytes = fread(buffer + buflen, 1, sizeof(buffer) - buflen, _mp3_track);
!       if (bytes <= 0) {
! 	if (bytes == -1)
! 	  result = -1;
! 	break;
!       }
! 
!       buflen += bytes;
!     }
! 
!     mad_stream_buffer(&stream, buffer, buflen);
! 
!     while (1) {
!       if (mad_frame_decode(&frame, &stream) == -1) {
! 	if (!MAD_RECOVERABLE(stream.error))
! 	  break;
! 
! 	if (stream.error != MAD_ERROR_BADCRC)
! 	  continue;
!       }
! 
!       if (count++ || 
! 		  xing_parse(&_vbr_header, stream.anc_ptr, stream.anc_bitlen) 
! 			== -1)
! 	break;
!     }
! 
!     if (count || stream.error != MAD_ERROR_BUFLEN)
!       break;
! 
!     memmove(buffer, stream.next_frame,
! 	    buflen = &buffer[buflen] - stream.next_frame);
!   }
! 
!   if (count)
! 	  memcpy(&_mad_header, &frame.header, sizeof(mad_header));
!   else
! 	  result = -1;
! 
!   mad_frame_finish(&frame);
!   mad_stream_finish(&stream);
! 
!   return (result != -1);
! }
! 
! uint32 calc_cd_file_offset(int start_frame) {
! 	long offset;
! 
! 	if (!_vbr_header.flags) {
! 		float frame_size;
! 		//mad_timer_t timer;  - recode with timer
! 
! 		/* Constant bit rate - perhaps not fully accurate, recheck */
! 		frame_size = (float)(144 * _mad_header.bitrate / _mad_header.samplerate);
! 		offset = (float)(float)start_frame / (float)CD_FPS * 1000 / 
! 				 (float)((float)1152 / (float)_mad_header.samplerate * 1000) *
! 				 (float)(frame_size + 0.5);			
! 	}
! 	else {
!          /* DOES NOT WORK AT THE MOMENT */
! 		/* see Xing SDK */
! 		long a;
! 		float fa, fb, fx;
! 		float percent = (float)start_frame / (float)CD_FPS * 1000 /
! 						((float)((float)1152 / (float)_mad_header.samplerate * 1000) * _vbr_header.frames) *
! 						100;
! 
! 		if( percent < 0.0f )   percent = 0.0f;
! 		if( percent > 100.0f ) percent = 100.0f;
! 
! 		a = (int)percent;
! 		if( a > 99 ) a = 99;
! 		fa = _vbr_header.toc[a];
! 		if( a < 99 ) {
! 			fb = _vbr_header.toc[a+1];
! 		}
! 		else {
! 			fb = 256.0f;
! 		}
! 
! 		fx = fa + (fb-fa)*(percent-a);
! 
! 		offset = (int)((1.0f/256.0f)*fx*_vbr_header.bytes); 
! 
! 	}
! 
! 	return offset;
! }
! 
! 
! #endif
! 
! void real_cd_play(int track, int num_loops, int start_frame, int end_frame) {
! 	// warning("cd_play(%d,%d,%d,%d)", track, num_loops, start_frame, end_frame);
! 	if (!cdrom) return;
! 
! 	cd_track = track;
! 	cd_num_loops = num_loops;
! 	cd_start_frame = start_frame;
! 	
! 	SDL_CDStatus(cdrom);
! 	SDL_CDPlayTracks(cdrom, track, start_frame, 0, end_frame);
! 	cd_end_frame = end_frame;
! 	cd_stop_time = 0;
! 	cd_end_time = SDL_GetTicks() +
! 		cdrom->track[track].length * 1000 / CD_FPS;
! }
! 
! void cd_play(Scumm *s, int track, int num_loops, int start_frame, int end_frame) {
! 	scumm->_vars[14] = 0;
  
  #ifdef COMPRESSED_SOUND_FILE
  
! 	// See if we are already playing this track, else try to open it
! 
! 	if (_current_mp3_cd_track != track) {
! 		char track_name[1024];				
! 
! 		sprintf(track_name, "%strack%d.mp3", s->_gameDataPath, track);
! 		_mp3_track = fopen(track_name, "rb");
! 		if (!_mp3_track) {
! 			warning("No CD and track %d not available in mp3 format", track);
! 			real_cd_play(track, num_loops, start_frame, end_frame);
! 			return;
! 		}
! 
! 		if (!parse_xing_vbr_tag()) {
! 				warning("Error parsing file header - ignoring file", 
! 							track);
! 				fclose(_mp3_track);
! 				real_cd_play(track, num_loops, start_frame, end_frame);
! 				return;
! 		}
! 
! 		if (_vbr_header.flags) {
! 			if (!(
! 				    (_vbr_header.flags & XING_TOC) &&
! 					(_vbr_header.flags & XING_BYTES) &&
! 					(_vbr_header.flags & XING_FRAMES)
! 				)) {
! 				warning("Missing required part of VBR header - ignoring file");
! 				fclose(_mp3_track);
! 				_vbr_header.flags = 0;
! 				real_cd_play(track, num_loops, start_frame, end_frame);
! 				return;
! 			}
! 		}
! 
! 		// Allocate the music mixer if necessary
! 
! 		if (!_mc) {
! 			_mc = s->allocateMixer();
! 			if (!_mc) {
! 				warning("No mixer channel available for MP3 music");
! 				real_cd_play(track, num_loops, start_frame, end_frame);
! 				return;
! 			}
! 		}
! 
! 		fseek(_mp3_track, 0, SEEK_END);
! 		_mp3_size = ftell(_mp3_track);
! 		fseek(_mp3_track, 0, SEEK_SET);
! 
! 		_mc->type = MIXER_MP3_CDMUSIC;
! 		_mc->sound_data.mp3_cdmusic.file = _mp3_track;
! 		_mc->sound_data.mp3_cdmusic.playing = FALSE;
! 		_mc->sound_data.mp3_cdmusic.buffer_size = 200000;
! 		_mc->_sfx_sound = malloc(_mc->sound_data.mp3_cdmusic.buffer_size); 
! 
! 														/* see if it's enough */
! 		mad_stream_init(&_mc->sound_data.mp3.stream);
! 		if (_mad_header.samplerate == 44100) 
! 			mad_stream_options((mad_stream*)&_mc->sound_data.mp3.stream, 
! 								MAD_OPTION_HALFSAMPLERATE);
! 
! 		mad_frame_init(&_mc->sound_data.mp3.frame);
! 		mad_synth_init(&_mc->sound_data.mp3.synth);
! 
! 		_current_mp3_cd_track = track;
! 	}
! 
! 
! 	if (_current_mp3_cd_track == track) {
! 
! 		uint32 where;
! 
! 		// See where we want to go
! 		where = calc_cd_file_offset(start_frame);
! 
! 		if (start_frame < 0 || end_frame < 0) {
! 			warning("Negative index in frame");
! 			return;
! 		}
  
! 		mad_timer_set(&_mc->sound_data.mp3_cdmusic.duration,
! 					  0,
! 					  end_frame,
! 					  CD_FPS);
  
! 		fseek(_mp3_track, where, SEEK_SET);
! 		_mc->sound_data.mp3_cdmusic.playing = TRUE;		
! 
! 		return;
! 	}
  
! #endif
! 
! 	real_cd_play(track, num_loops, start_frame, end_frame);
  }
  
--- 678,704 ----
  static Uint32 cd_end_time, cd_stop_time, cd_next_second;
  
! void cd_play(Scumm *s, int track, int num_loops, int start_frame, int end_frame) {
  
  #ifdef COMPRESSED_SOUND_FILE
  
! 	if (mp3_cd_play(s, track, num_loops, start_frame, end_frame))
! 		return;
  
! #endif
  
! 	// warning("cd_play(%d,%d,%d,%d)", track, num_loops, start_frame, end_frame);
! 	if (!cdrom) return;
  
! 	scumm->_vars[14] = 0;
! 	cd_track = track;
! 	cd_num_loops = num_loops;
! 	cd_start_frame = start_frame;
! 	
! 	SDL_CDStatus(cdrom);
! 	SDL_CDPlayTracks(cdrom, track, start_frame, 0, end_frame);
! 	cd_end_frame = end_frame;
! 	cd_stop_time = 0;
! 	cd_end_time = SDL_GetTicks() +
! 		cdrom->track[track].length * 1000 / CD_FPS;
  }
  

Index: x11.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/x11.cpp,v
retrieving revision 1.8
retrieving revision 1.9
diff -C2 -d -r1.8 -r1.9
*** x11.cpp	4 Apr 2002 22:47:03 -0000	1.8
--- x11.cpp	5 Apr 2002 00:00:46 -0000	1.9
***************
*** 27,30 ****
--- 27,31 ----
  #include "sound.h"
  #include "cdmusic.h"
+ #include "mp3_cd.h"
  
  #include <sys/time.h>
***************
*** 188,192 ****
  /* No CD on the iPAQ => stub functions */
  void cd_play(Scumm *s, int track, int num_loops, int start_frame, int end_frame) {
! /* Insert SDL.cpp MP3 code here :) */
  }
  int cd_is_running(void) {
--- 189,196 ----
  /* No CD on the iPAQ => stub functions */
  void cd_play(Scumm *s, int track, int num_loops, int start_frame, int end_frame) {
! 
! #ifdef COMPRESSED_SOUND_FILE
! 	mp3_cd_play(s, track, num_loops, start_frame, end_frame);
! #endif
  }
  int cd_is_running(void) {





More information about the Scummvm-git-logs mailing list