[Scummvm-cvs-logs] CVS: scummvm scumm.h,1.67,1.68 sound.cpp,1.22,1.23

Lionel Ulmer bbrox at users.sourceforge.net
Wed Mar 6 15:18:03 CET 2002


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

Modified Files:
	scumm.h sound.cpp 
Log Message:
Added possibility to use a '.so3' file instead of a .SOU file. The tool to generate this .SO3 file will be comitted later on :-) (it's available in the mailing list archives for now).



Index: scumm.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm.h,v
retrieving revision 1.67
retrieving revision 1.68
diff -C2 -d -r1.67 -r1.68
*** scumm.h	6 Mar 2002 19:58:06 -0000	1.67
--- scumm.h	6 Mar 2002 23:17:16 -0000	1.68
***************
*** 21,24 ****
--- 21,27 ----
  
  #include "scummsys.h"
+ #ifdef COMPRESSED_SOUND_FILE
+ #include <mad.h>
+ #endif
  
  #define SCUMMVM_VERSION "0.1.0 devel"
***************
*** 742,752 ****
  };
  
  struct MixerChannel {
  	void *_sfx_sound;
! 	uint32 _sfx_pos;
! 	uint32 _sfx_size;
! 	uint32 _sfx_fp_speed;
! 	uint32 _sfx_fp_pos;
! 
  	void mix(int16 *data, uint32 len);
  	void clear();
--- 745,775 ----
  };
  
+ typedef enum {
+   MIXER_STANDARD,
+   MIXER_MP3
+ } MixerType;
+ 
  struct MixerChannel {
  	void *_sfx_sound;
! 	MixerType type;
! 	union {
! 	  struct {
! 	    uint32 _sfx_pos;
! 	    uint32 _sfx_size;
! 	    uint32 _sfx_fp_speed;
! 	    uint32 _sfx_fp_pos;
! 	  } standard;
! #ifdef COMPRESSED_SOUND_FILE
! 	  struct {
! 	    struct mad_stream stream;
! 	    struct mad_frame frame;
! 	    struct mad_synth synth;
! 	    uint32 silence_cut;
! 	    uint32 pos_in_frame;
! 	    uint32 position;
! 	    uint32 size;
! 	  } mp3;
! #endif
! 	} sound_data;
  	void mix(int16 *data, uint32 len);
  	void clear();
***************
*** 814,817 ****
--- 837,849 ----
  };
  
+ #ifdef COMPRESSED_SOUND_FILE
+ struct OffsetTable {
+ 	int org_offset;
+ 	int new_offset;
+ 	int num_tags;
+ 	int compressed_size;
+ };
+ #endif
+ 
  struct Scumm {
  	uint32 _features;
***************
*** 1136,1139 ****
--- 1168,1176 ----
  	OpcodeProc getOpcode(int i) { return _opcodes[i]; }
  
+ #ifdef COMPRESSED_SOUND_FILE
+ 	OffsetTable *offset_table;
+ 	int num_sound_effects;
+ #endif
+   
  	void openRoom(int room);
  	void deleteRoomOffsets();
***************
*** 1826,1830 ****
  	void stopTalkSound();
  	bool isMouthSyncOff(uint pos);
! 	void startSfxSound(void *file);
  	void *openSfxFile();
  	void resourceStats();
--- 1863,1867 ----
  	void stopTalkSound();
  	bool isMouthSyncOff(uint pos);
! 	void startSfxSound(void *file, int size);
  	void *openSfxFile();
  	void resourceStats();
***************
*** 1872,1875 ****
--- 1909,1915 ----
  	bool isSfxFinished();
  	void playSfxSound(void *sound, uint32 size, uint rate);
+ #ifdef COMPRESSED_SOUND_FILE
+   	void playSfxSound_MP3(void *sound, uint32 size);
+ #endif
  	void stopSfxSound();
  

Index: sound.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sound.cpp,v
retrieving revision 1.22
retrieving revision 1.23
diff -C2 -d -r1.22 -r1.23
*** sound.cpp	6 Mar 2002 00:18:22 -0000	1.22
--- sound.cpp	6 Mar 2002 23:17:16 -0000	1.23
***************
*** 140,146 ****
  }
  
  void Scumm::startTalkSound(uint32 offset, uint32 b, int mode) {
! 	int num, i;
  	byte file_byte,file_byte_2;	
  
  	if (!_sfxFile) {
--- 140,153 ----
  }
  
+ #ifdef COMPRESSED_SOUND_FILE
+ static int compar(const void *a, const void *b) {
+   return ((OffsetTable *) a)->org_offset - ((OffsetTable *) b)->org_offset;
+ }
+ #endif
+ 
  void Scumm::startTalkSound(uint32 offset, uint32 b, int mode) {
! 	int num = 0, i;
  	byte file_byte,file_byte_2;	
+ 	int size;
  
  	if (!_sfxFile) {
***************
*** 149,161 ****
  	}
  
- 	fileSeek((FILE*)_sfxFile, offset + 8, SEEK_SET);
- 	i = 0;
  	if (b>8) {
  		num = (b-8)>>1;
! 		do {
! 			fileRead((FILE*)_sfxFile, &file_byte, sizeof(file_byte));
! 			fileRead((FILE*)_sfxFile, &file_byte_2, sizeof(file_byte_2));
! 			_mouthSyncTimes[i++] = file_byte | (file_byte_2<<8);
! 		} while (--num);
  	}
  	_mouthSyncTimes[i] = 0xFFFF;
--- 156,193 ----
  	}
  
  	if (b>8) {
  		num = (b-8)>>1;
! 	}
! 
! #ifdef COMPRESSED_SOUND_FILE
! 	if (offset_table != NULL) {
! 	  OffsetTable *result, key;
! 	  
! 	  key.org_offset = offset;
! 	  result = (OffsetTable *) bsearch(&key, offset_table, num_sound_effects, sizeof(OffsetTable), compar);
! 	  if (result == NULL) {
! 	    warning("startTalkSound: did not find sound at offset %d !", offset);
! 	    return;
! 	  }
! 	  if (2 * num != result->num_tags) {
! 	    warning("startTalkSound: number of tags do not match (%d - %d) !", b, result->num_tags);
! 	    num = result->num_tags;
! 	  }
! 	  offset = result->new_offset;
! 	  size = result->compressed_size;
! 	} else
! #endif
! 	{
! 	  offset += 8;
! 	  size = -1;
! 	}
! 
! 	fileSeek((FILE*)_sfxFile, offset, SEEK_SET);
! 	i = 0;
! 	while (num > 0) {
! 	  fileRead((FILE*)_sfxFile, &file_byte, sizeof(file_byte));
! 	  fileRead((FILE*)_sfxFile, &file_byte_2, sizeof(file_byte_2));
! 	  _mouthSyncTimes[i++] = file_byte | (file_byte_2<<8);
! 	  num--;
  	}
  	_mouthSyncTimes[i] = 0xFFFF;
***************
*** 164,168 ****
  	_mouthSyncMode = true;
  
! 	startSfxSound(_sfxFile);
  }
  
--- 196,200 ----
  	_mouthSyncMode = true;
  
! 	startSfxSound(_sfxFile, size);
  }
  
***************
*** 293,297 ****
   * is needed.
   */
!    
  void Scumm::setupSound() {
  	SoundEngine *se = (SoundEngine*)_soundEngine;
--- 325,329 ----
   * is needed.
   */
! 
  void Scumm::setupSound() {
  	SoundEngine *se = (SoundEngine*)_soundEngine;
***************
*** 315,319 ****
  };
  
! void Scumm::startSfxSound(void *file) {
  	char ident[8];
  	int block_type;
--- 347,351 ----
  };
  
! void Scumm::startSfxSound(void *file, int file_size) {
  	char ident[8];
  	int block_type;
***************
*** 323,326 ****
--- 355,371 ----
  	byte *data;
  
+ #ifdef COMPRESSED_SOUND_FILE
+ 	if (file_size > 0) {
+ 	  data = (byte *) calloc(file_size + MAD_BUFFER_GUARD, 1);
+ 
+ 	  if (fread(data, file_size, 1, (FILE*) file) != 1) {
+ 	    /* no need to free the memory since error will shut down */
+ 	    error("startSfxSound: cannot read %d bytes", size);
+ 	    return;
+ 	  }
+ 	  playSfxSound_MP3(data, file_size);
+ 	  return;
+ 	}
+ #endif
  	if ( fread(ident, 8, 1, (FILE*)file) != 1)
  		goto invalid;
***************
*** 352,356 ****
  		return;
  	}
! 
  	data = (byte*) malloc(size);
  	if (data==NULL) {
--- 397,401 ----
  		return;
  	}
! 	
  	data = (byte*) malloc(size);
  	if (data==NULL) {
***************
*** 366,373 ****
  	for(i=0;i<size; i++)
  		data[i] ^= 0x80;
! 
  	playSfxSound(data, size, 1000000 / (256 - rate) );
  }
  
  void *Scumm::openSfxFile() {
  	char buf[50];
--- 411,434 ----
  	for(i=0;i<size; i++)
  		data[i] ^= 0x80;
! 	
  	playSfxSound(data, size, 1000000 / (256 - rate) );
  }
  
+ 
+ #ifdef COMPRESSED_SOUND_FILE
+ static int get_int(FILE *f) {
+   int ret = 0;
+   for (int size = 0; size < 4; size++) {
+     int c = fgetc(f);
+     if (c == EOF) {
+       error("Unexpected end of file !!!");
+     }
+     ret <<= 8;
+     ret |= c;
+   }
+   return ret;
+ }
+ #endif
+ 
  void *Scumm::openSfxFile() {
  	char buf[50];
***************
*** 377,386 ****
  	 * That way, you can keep .sou files for multiple games in the
  	 * same directory */
  
  	sprintf(buf, "%s%s.sou", _gameDataPath, _exe_name);
  	file = fopen(buf, "rb");
  	if (!file) {
! 		sprintf(buf, "%smonster.sou", _gameDataPath);
! 		file = fopen(buf, "rb");
  	}
  	return file;
--- 438,490 ----
  	 * That way, you can keep .sou files for multiple games in the
  	 * same directory */
+ #ifdef COMPRESSED_SOUND_FILE
+ 	offset_table = NULL;
+ 
+ 	sprintf(buf, "%s%s.so3", _gameDataPath, _exe_name);
+ 	file = fopen(buf, "rb");
+ 	if (!file) {
+ 	  sprintf(buf, "%smonster.so3", _gameDataPath);
+ 	  file = fopen(buf, "rb");
+ 	}
+ 	if (file != NULL) {
+ 	  /* Now load the 'offset' index in memory to be able to find the MP3 data
  
+ 	     The format of the .SO3 file is easy :
+   	       - number of bytes of the 'index' part
+ 	       - N times the following fields (4 bytes each) :
+ 	         + offset in the original sound file
+ 		 + offset of the MP3 data in the .SO3 file WITHOUT taking into account
+ 	           the index field and the 'size' field
+ 		 + the number of 'tags'
+ 		 + the size of the MP3 data
+ 	       - and then N times :
+ 	         + the tags
+ 	         + the MP3 data
+ 	  */
+ 	  int size, compressed_offset;
+ 	  OffsetTable *cur;
+ 	  
+ 	  compressed_offset = get_int(file);
+ 	  offset_table = (OffsetTable *) malloc(compressed_offset);
+ 	  num_sound_effects = compressed_offset / 16;
+ 	  
+ 	  size = compressed_offset;
+ 	  cur = offset_table;
+ 	  while (size > 0) {
+ 	    cur[0].org_offset = get_int(file);
+ 	    cur[0].new_offset = get_int(file) + compressed_offset + 4; /* The + 4 is to take into accound the 'size' field */
+ 	    cur[0].num_tags = get_int(file);
+ 	    cur[0].compressed_size = get_int(file);
+ 	    size -= 4 * 4;
+ 	    cur++;
+ 	  }
+ 	  return file;
+ 	}
+ #endif
  	sprintf(buf, "%s%s.sou", _gameDataPath, _exe_name);
  	file = fopen(buf, "rb");
  	if (!file) {
! 	  sprintf(buf, "%smonster.sou", _gameDataPath);
! 	  file = fopen(buf, "rb");
  	}
  	return file;
***************
*** 415,418 ****
--- 519,556 ----
  }
  
+ #ifdef COMPRESSED_SOUND_FILE
+ void Scumm::playSfxSound_MP3(void *sound, uint32 size) {
+   MixerChannel *mc = allocateMixer();
+ 
+   if (!mc) {
+     warning("No mixer channel available");
+     return;
+   }
+ 
+   mc->type = MIXER_MP3;
+   mc->_sfx_sound = sound;
+ 
+   mad_stream_init(&mc->sound_data.mp3.stream);
+   mad_frame_init(&mc->sound_data.mp3.frame);
+   mad_synth_init(&mc->sound_data.mp3.synth);
+   mc->sound_data.mp3.position = 0;
+   mc->sound_data.mp3.pos_in_frame = 0xFFFFFFFF;
+   mc->sound_data.mp3.size = size;
+   /* This variable is the number of samples to cut at the start of the MP3
+      file. This is needed to have lip-sync as the MP3 file have some miliseconds
+      of blank at the start (as, I suppose, the MP3 compression algorithm need to
+      have some silence at the start to really be efficient and to not distort
+      too much the start of the sample).
+ 
+      This value was found by experimenting out. If you recompress differently your
+      .SO3 file, you may have to change this value.
+ 
+      When using Lame, it seems that the sound starts to have some volume about 50 ms
+      from the start of the sound => we skip about 1024 samples.
+   */
+   mc->sound_data.mp3.silence_cut = 1024; 
+ }
+ #endif
+ 
  void Scumm::playSfxSound(void *sound, uint32 size, uint rate) {
  	MixerChannel *mc = allocateMixer();
***************
*** 423,462 ****
  	}
  
  	mc->_sfx_sound = sound;
! 	mc->_sfx_pos = 0;
! 	mc->_sfx_fp_speed = (1<<16) * rate / 22050;
! 	mc->_sfx_fp_pos = 0;
  
  	while (size&0xFFFF0000) size>>=1, rate>>=1;
! 	mc->_sfx_size = size * 22050 / rate;
  }
  
! void MixerChannel::mix(int16 *data, uint32 len) {
! 	int8 *s;	
! 	uint32 fp_pos, fp_speed;
  
! 	if (!_sfx_sound)
! 		return;
! 	if (len > _sfx_size)
! 		len = _sfx_size;
! 	_sfx_size -= len;
  
! 	s = (int8*)_sfx_sound + _sfx_pos;
! 	fp_pos = _sfx_fp_pos;
! 	fp_speed = _sfx_fp_speed;
  
! 	do {
! 		fp_pos += fp_speed;
! 		*data++ += (*s<<6);
! 		s += fp_pos >> 16;
! 		fp_pos &= 0x0000FFFF;
! 	} while (--len);
  
! 	_sfx_pos = s - (int8*)_sfx_sound;
! 	_sfx_fp_speed = fp_speed;
! 	_sfx_fp_pos = fp_pos;
  
! 	if (!_sfx_size)
  		clear();
  }
  
--- 561,663 ----
  	}
  
+ 	mc->type = MIXER_STANDARD;
  	mc->_sfx_sound = sound;
! 	mc->sound_data.standard._sfx_pos = 0;
! 	mc->sound_data.standard._sfx_fp_speed = (1<<16) * rate / 22050;
! 	mc->sound_data.standard._sfx_fp_pos = 0;
  
  	while (size&0xFFFF0000) size>>=1, rate>>=1;
! 	mc->sound_data.standard._sfx_size = size * 22050 / rate;
  }
  
! #ifdef COMPRESSED_SOUND_FILE
! static inline int scale_sample(mad_fixed_t sample)
! {
!   /* round */
!   sample += (1L << (MAD_F_FRACBITS - 16));
  
!   /* clip */
!   if (sample >= MAD_F_ONE)
!     sample = MAD_F_ONE - 1;
!   else if (sample < -MAD_F_ONE)
!     sample = -MAD_F_ONE;
  
!   /* quantize and scale to not saturate when mixing a lot of channels */
!   return sample >> (MAD_F_FRACBITS + 2 - 16);
! }
! #endif
  
! void MixerChannel::mix(int16 *data, uint32 len) {
! 	if (!_sfx_sound)
! 	  return;
  
! #ifdef COMPRESSED_SOUND_FILE
! 	if (type == MIXER_STANDARD) {
! #endif
! 	  int8 *s;	
! 	  uint32 fp_pos, fp_speed;
! 	  
! 	  if (len > sound_data.standard._sfx_size)
! 	    len = sound_data.standard._sfx_size;
! 	  sound_data.standard._sfx_size -= len;
! 	  
! 	  s = (int8*)_sfx_sound + sound_data.standard._sfx_pos;
! 	  fp_pos = sound_data.standard._sfx_fp_pos;
! 	  fp_speed = sound_data.standard._sfx_fp_speed;
! 	  
! 	  do {
! 	    fp_pos += fp_speed;
! 	    *data++ += (*s<<6);
! 	    s += fp_pos >> 16;
! 	    fp_pos &= 0x0000FFFF;
! 	  } while (--len);
! 	  
! 	  sound_data.standard._sfx_pos = s - (int8*)_sfx_sound;
! 	  sound_data.standard._sfx_fp_speed = fp_speed;
! 	  sound_data.standard._sfx_fp_pos = fp_pos;
! 	  
! 	  if (!sound_data.standard._sfx_size)
! 	    clear();
! #ifdef COMPRESSED_SOUND_FILE
! 	} else {
! 	  mad_fixed_t const *ch;
! 	  while (1) {
! 	    ch = sound_data.mp3.synth.pcm.samples[0] + sound_data.mp3.pos_in_frame;
! 	    while ((sound_data.mp3.pos_in_frame < sound_data.mp3.synth.pcm.length) && 
! 		   (len > 0)) {
! 	      if (sound_data.mp3.silence_cut > 0) {
! 		sound_data.mp3.silence_cut--;
! 	      } else {
! 		*data++ += scale_sample(*ch++);
! 		len--;
! 	      }
! 	      sound_data.mp3.pos_in_frame++;
! 	    }
! 	    if (len == 0) return;
  
! 	    if (sound_data.mp3.position >= sound_data.mp3.size) {
! 	      clear();
! 	      return;
! 	    }
! 
! 	    mad_stream_buffer(&sound_data.mp3.stream, 
! 			      ((unsigned char *) _sfx_sound) + sound_data.mp3.position, 
! 			      sound_data.mp3.size + MAD_BUFFER_GUARD - sound_data.mp3.position);
! 	    
! 	    if (mad_frame_decode(&sound_data.mp3.frame, &sound_data.mp3.stream) == -1) {
! 	      /* End of audio... */
! 	      if (sound_data.mp3.stream.error == MAD_ERROR_BUFLEN) {
  		clear();
+ 		return;
+ 	      } else if (!MAD_RECOVERABLE(sound_data.mp3.stream.error)) {
+ 		error("MAD frame decode error !");
+ 	      }
+ 	    }
+ 	    mad_synth_frame(&sound_data.mp3.synth, &sound_data.mp3.frame);
+ 	    sound_data.mp3.pos_in_frame = 0;
+ 	    sound_data.mp3.position = (unsigned char *) sound_data.mp3.stream.next_frame - (unsigned char *) _sfx_sound;
+ 	  }
+ 	}
+ #endif
  }
  
***************
*** 464,467 ****
--- 665,676 ----
  	free(_sfx_sound);
  	_sfx_sound = NULL;
+ 
+ #ifdef COMPRESSED_SOUND_FILE
+ 	if (type == MIXER_MP3) {
+ 	  mad_synth_finish(&sound_data.mp3.synth);
+ 	  mad_frame_finish(&sound_data.mp3.frame);
+ 	  mad_stream_finish(&sound_data.mp3.stream);
+ 	}
+ #endif
  }
  





More information about the Scummvm-git-logs mailing list