src/sound.cpp
branchcustombridgeheads
changeset 5649 55c8267c933f
parent 5643 3778051e8095
child 5650 aefc131bf5ce
equal deleted inserted replaced
5648:1608018c5ff2 5649:55c8267c933f
       
     1 /* $Id$ */
       
     2 
       
     3 #include "stdafx.h"
       
     4 #include "openttd.h"
       
     5 #include "functions.h"
       
     6 #include "map.h"
       
     7 #include "mixer.h"
       
     8 #include "sound.h"
       
     9 #include "vehicle.h"
       
    10 #include "window.h"
       
    11 #include "viewport.h"
       
    12 #include "fileio.h"
       
    13 #include "newgrf_sound.h"
       
    14 
       
    15 static uint _file_count;
       
    16 static FileEntry *_files;
       
    17 
       
    18 #define SOUND_SLOT 63
       
    19 // Number of levels of panning per side
       
    20 #define PANNING_LEVELS 16
       
    21 
       
    22 
       
    23 static void OpenBankFile(const char *filename)
       
    24 {
       
    25 	FileEntry *fe;
       
    26 	uint count;
       
    27 	uint i;
       
    28 
       
    29 	FioOpenFile(SOUND_SLOT, filename);
       
    30 	count = FioReadDword() / 8;
       
    31 	fe = calloc(count, sizeof(*fe));
       
    32 
       
    33 	if (fe == NULL) {
       
    34 		_file_count = 0;
       
    35 		_files = NULL;
       
    36 		return;
       
    37 	}
       
    38 
       
    39 	_file_count = count;
       
    40 	_files = fe;
       
    41 
       
    42 	FioSeekTo(0, SEEK_SET);
       
    43 
       
    44 	for (i = 0; i != count; i++) {
       
    45 		fe[i].file_offset = FioReadDword();
       
    46 		fe[i].file_size = FioReadDword();
       
    47 	}
       
    48 
       
    49 	for (i = 0; i != count; i++, fe++) {
       
    50 		char name[255];
       
    51 
       
    52 		FioSeekTo(fe->file_offset, SEEK_SET);
       
    53 
       
    54 		// Check for special case, see else case
       
    55 		FioReadBlock(name, FioReadByte()); // Read the name of the sound
       
    56 		if (strcmp(name, "Corrupt sound") != 0) {
       
    57 			FioSeekTo(12, SEEK_CUR); // Skip past RIFF header
       
    58 
       
    59 			// Read riff tags
       
    60 			for (;;) {
       
    61 				uint32 tag = FioReadDword();
       
    62 				uint32 size = FioReadDword();
       
    63 
       
    64 				if (tag == ' tmf') {
       
    65 					FioReadWord(); // wFormatTag
       
    66 					fe->channels = FioReadWord(); // wChannels
       
    67 					FioReadDword();   // samples per second
       
    68 					fe->rate = 11025; // seems like all samples should be played at this rate.
       
    69 					FioReadDword();   // avg bytes per second
       
    70 					FioReadWord();    // alignment
       
    71 					fe->bits_per_sample = FioReadByte(); // bits per sample
       
    72 					FioSeekTo(size - (2 + 2 + 4 + 4 + 2 + 1), SEEK_CUR);
       
    73 				} else if (tag == 'atad') {
       
    74 					fe->file_size = size;
       
    75 					fe->file_offset = FioGetPos() | (SOUND_SLOT << 24);
       
    76 					break;
       
    77 				} else {
       
    78 					fe->file_size = 0;
       
    79 					break;
       
    80 				}
       
    81 			}
       
    82 		} else {
       
    83 			/*
       
    84 			 * Special case for the jackhammer sound
       
    85 			 * (name in sample.cat is "Corrupt sound")
       
    86 			 * It's no RIFF file, but raw PCM data
       
    87 			 */
       
    88 			fe->channels = 1;
       
    89 			fe->rate = 11025;
       
    90 			fe->bits_per_sample = 8;
       
    91 			fe->file_offset = FioGetPos() | (SOUND_SLOT << 24);
       
    92 		}
       
    93 	}
       
    94 }
       
    95 
       
    96 uint GetNumOriginalSounds(void)
       
    97 {
       
    98 	return _file_count;
       
    99 }
       
   100 
       
   101 static bool SetBankSource(MixerChannel *mc, uint bank)
       
   102 {
       
   103 	const FileEntry *fe;
       
   104 	int8 *mem;
       
   105 	uint i;
       
   106 
       
   107 	if (bank >= GetNumSounds()) return false;
       
   108 	fe = GetSound(bank);
       
   109 
       
   110 	if (fe->file_size == 0) return false;
       
   111 
       
   112 	mem = malloc(fe->file_size);
       
   113 	if (mem == NULL) return false;
       
   114 
       
   115 	FioSeekToFile(fe->file_offset);
       
   116 	FioReadBlock(mem, fe->file_size);
       
   117 
       
   118 	for (i = 0; i != fe->file_size; i++)
       
   119 		mem[i] += -128; // Convert unsigned sound data to signed
       
   120 
       
   121 	assert(fe->bits_per_sample == 8 && fe->channels == 1 && fe->file_size != 0 && fe->rate != 0);
       
   122 
       
   123 	MxSetChannelRawSrc(mc, mem, fe->file_size, fe->rate, MX_AUTOFREE);
       
   124 
       
   125 	return true;
       
   126 }
       
   127 
       
   128 bool SoundInitialize(const char *filename)
       
   129 {
       
   130 	OpenBankFile(filename);
       
   131 	return true;
       
   132 }
       
   133 
       
   134 // Low level sound player
       
   135 static void StartSound(uint sound, int panning, uint volume)
       
   136 {
       
   137 	MixerChannel *mc;
       
   138 	uint left_vol, right_vol;
       
   139 
       
   140 	if (volume == 0) return;
       
   141 	mc = MxAllocateChannel();
       
   142 	if (mc == NULL) return;
       
   143 	if (!SetBankSource(mc, sound)) return;
       
   144 
       
   145 	panning = clamp(panning, -PANNING_LEVELS, PANNING_LEVELS);
       
   146 	left_vol = (volume * PANNING_LEVELS) - (volume * panning);
       
   147 	right_vol = (volume * PANNING_LEVELS) + (volume * panning);
       
   148 	MxSetChannelVolume(mc, left_vol * 128 / PANNING_LEVELS, right_vol * 128 / PANNING_LEVELS);
       
   149 	MxActivateChannel(mc);
       
   150 }
       
   151 
       
   152 
       
   153 static const byte _vol_factor_by_zoom[] = {255, 190, 134};
       
   154 
       
   155 static const byte _sound_base_vol[] = {
       
   156 	128,  90, 128, 128, 128, 128, 128, 128,
       
   157 	128,  90,  90, 128, 128, 128, 128, 128,
       
   158 	128, 128, 128,  80, 128, 128, 128, 128,
       
   159 	128, 128, 128, 128, 128, 128, 128, 128,
       
   160 	128, 128,  90,  90,  90, 128,  90, 128,
       
   161 	128,  90, 128, 128, 128,  90, 128, 128,
       
   162 	128, 128, 128, 128,  90, 128, 128, 128,
       
   163 	128,  90, 128, 128, 128, 128, 128, 128,
       
   164 	128, 128,  90,  90,  90, 128, 128, 128,
       
   165 	 90,
       
   166 };
       
   167 
       
   168 static const byte _sound_idx[] = {
       
   169 	 2,  3,  4,  5,  6,  7,  8,  9,
       
   170 	10, 11, 12, 13, 14, 15, 16, 17,
       
   171 	18, 19, 20, 21, 22, 23, 24, 25,
       
   172 	26, 27, 28, 29, 30, 31, 32, 33,
       
   173 	34, 35, 36, 37, 38, 39, 40,  0,
       
   174 	 1, 41, 42, 43, 44, 45, 46, 47,
       
   175 	48, 49, 50, 51, 52, 53, 54, 55,
       
   176 	56, 57, 58, 59, 60, 61, 62, 63,
       
   177 	64, 65, 66, 67, 68, 69, 70, 71,
       
   178 	72,
       
   179 };
       
   180 
       
   181 void SndCopyToPool(void)
       
   182 {
       
   183 	uint i;
       
   184 
       
   185 	for (i = 0; i < _file_count; i++) {
       
   186 		FileEntry *orig = &_files[_sound_idx[i]];
       
   187 		FileEntry *fe = AllocateFileEntry();
       
   188 
       
   189 		*fe = *orig;
       
   190 		fe->volume = _sound_base_vol[i];
       
   191 		fe->priority = 0;
       
   192 	}
       
   193 }
       
   194 
       
   195 static void SndPlayScreenCoordFx(SoundFx sound, int x, int y)
       
   196 {
       
   197 	Window* const *wz;
       
   198 
       
   199 	if (msf.effect_vol == 0) return;
       
   200 
       
   201 	FOR_ALL_WINDOWS(wz) {
       
   202 		const ViewPort *vp = (*wz)->viewport;
       
   203 
       
   204 		if (vp != NULL &&
       
   205 				IS_INSIDE_1D(x, vp->virtual_left, vp->virtual_width) &&
       
   206 				IS_INSIDE_1D(y, vp->virtual_top, vp->virtual_height)) {
       
   207 			int left = (x - vp->virtual_left);
       
   208 
       
   209 			StartSound(
       
   210 				sound,
       
   211 				left / (vp->virtual_width / ((PANNING_LEVELS << 1) + 1)) - PANNING_LEVELS,
       
   212 				(GetSound(sound)->volume * msf.effect_vol * _vol_factor_by_zoom[vp->zoom]) >> 15
       
   213 			);
       
   214 			return;
       
   215 		}
       
   216 	}
       
   217 
       
   218 }
       
   219 
       
   220 void SndPlayTileFx(SoundFx sound, TileIndex tile)
       
   221 {
       
   222 	/* emits sound from center of the tile */
       
   223 	int x = TileX(tile) * TILE_SIZE + TILE_SIZE / 2;
       
   224 	int y = TileY(tile) * TILE_SIZE + TILE_SIZE / 2;
       
   225 	Point pt = RemapCoords(x, y, GetSlopeZ(x, y));
       
   226 	SndPlayScreenCoordFx(sound, pt.x, pt.y);
       
   227 }
       
   228 
       
   229 void SndPlayVehicleFx(SoundFx sound, const Vehicle *v)
       
   230 {
       
   231 	SndPlayScreenCoordFx(sound,
       
   232 		(v->left_coord + v->right_coord) / 2,
       
   233 		(v->top_coord + v->bottom_coord) / 2
       
   234 	);
       
   235 }
       
   236 
       
   237 void SndPlayFx(SoundFx sound)
       
   238 {
       
   239 	StartSound(
       
   240 		sound,
       
   241 		0,
       
   242 		(GetSound(sound)->volume * msf.effect_vol) >> 7
       
   243 	);
       
   244 }