Files @ r4681:f719e26018b5
Branch filter:

Location: cpp/openttd-patchpack/source/sound.c - annotation

bjarni
(svn r6586) -Feature: [depot window] added a vehicle list window with all vehicles having a certain depot in their orders
It got one known issue though. The top bar got a plural issue so expect to see stuff like "1 trains" until we figure out why it behaves this way
Added the button to the depot windows. Made the autoreplace button bigger while I was moving some widgets anyway
Made road vehicle depot windows start with one more row to make room for the buttons
r2186:5ee653b1b5e1
r2186:5ee653b1b5e1
r0:d63b455452f6
r1891:c5c5466afa35
r2163:ae001e2aa5b0
r679:3a7b08cc8504
r1496:eab93f4e2718
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r4656:515f0929a2ed
r0:d63b455452f6
r1496:eab93f4e2718
r4171:bf306290d87e
r0:d63b455452f6
r3898:4ae21ea0fef1
r2594:47101c29af66
r2594:47101c29af66
r0:d63b455452f6
r0:d63b455452f6
r1496:eab93f4e2718
r0:d63b455452f6
r4171:bf306290d87e
r2371:e95ef7a775d8
r2371:e95ef7a775d8
r0:d63b455452f6
r0:d63b455452f6
r2371:e95ef7a775d8
r3716:55e57c9021a4
r2371:e95ef7a775d8
r2371:e95ef7a775d8
r2371:e95ef7a775d8
r2371:e95ef7a775d8
r2372:a11aa4a17996
r2371:e95ef7a775d8
r2371:e95ef7a775d8
r2371:e95ef7a775d8
r2371:e95ef7a775d8
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r1496:eab93f4e2718
r1496:eab93f4e2718
r1496:eab93f4e2718
r0:d63b455452f6
r193:6aa65dc5a4b4
r337:998f55d0b04c
r337:998f55d0b04c
r337:998f55d0b04c
r0:d63b455452f6
r0:d63b455452f6
r337:998f55d0b04c
r337:998f55d0b04c
r337:998f55d0b04c
r337:998f55d0b04c
r337:998f55d0b04c
r337:998f55d0b04c
r337:998f55d0b04c
r2371:e95ef7a775d8
r2371:e95ef7a775d8
r0:d63b455452f6
r337:998f55d0b04c
r337:998f55d0b04c
r337:998f55d0b04c
r337:998f55d0b04c
r337:998f55d0b04c
r337:998f55d0b04c
r337:998f55d0b04c
r337:998f55d0b04c
r337:998f55d0b04c
r337:998f55d0b04c
r337:998f55d0b04c
r337:998f55d0b04c
r337:998f55d0b04c
r337:998f55d0b04c
r337:998f55d0b04c
r337:998f55d0b04c
r337:998f55d0b04c
r0:d63b455452f6
r337:998f55d0b04c
r337:998f55d0b04c
r337:998f55d0b04c
r337:998f55d0b04c
r337:998f55d0b04c
r337:998f55d0b04c
r337:998f55d0b04c
r337:998f55d0b04c
r337:998f55d0b04c
r337:998f55d0b04c
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r4656:515f0929a2ed
r4656:515f0929a2ed
r4656:515f0929a2ed
r4656:515f0929a2ed
r4656:515f0929a2ed
r1496:eab93f4e2718
r0:d63b455452f6
r4171:bf306290d87e
r4171:bf306290d87e
r0:d63b455452f6
r0:d63b455452f6
r4656:515f0929a2ed
r4656:515f0929a2ed
r193:6aa65dc5a4b4
r2371:e95ef7a775d8
r2371:e95ef7a775d8
r2371:e95ef7a775d8
r2371:e95ef7a775d8
r2371:e95ef7a775d8
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r337:998f55d0b04c
r1136:d873c69e7665
r193:6aa65dc5a4b4
r0:d63b455452f6
r0:d63b455452f6
r1496:eab93f4e2718
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r1496:eab93f4e2718
r0:d63b455452f6
r1496:eab93f4e2718
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r2594:47101c29af66
r0:d63b455452f6
r4171:bf306290d87e
r2594:47101c29af66
r2371:e95ef7a775d8
r2371:e95ef7a775d8
r2977:6a8a4298e856
r2371:e95ef7a775d8
r2371:e95ef7a775d8
r2594:47101c29af66
r2594:47101c29af66
r2594:47101c29af66
r2594:47101c29af66
r2594:47101c29af66
r2371:e95ef7a775d8
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r2371:e95ef7a775d8
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r2371:e95ef7a775d8
r2371:e95ef7a775d8
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r4656:515f0929a2ed
r4656:515f0929a2ed
r4656:515f0929a2ed
r4656:515f0929a2ed
r4656:515f0929a2ed
r4656:515f0929a2ed
r4656:515f0929a2ed
r4656:515f0929a2ed
r4656:515f0929a2ed
r4656:515f0929a2ed
r4656:515f0929a2ed
r4656:515f0929a2ed
r4656:515f0929a2ed
r4656:515f0929a2ed
r337:998f55d0b04c
r0:d63b455452f6
r4171:bf306290d87e
r0:d63b455452f6
r2371:e95ef7a775d8
r0:d63b455452f6
r337:998f55d0b04c
r2371:e95ef7a775d8
r2371:e95ef7a775d8
r2371:e95ef7a775d8
r0:d63b455452f6
r0:d63b455452f6
r2594:47101c29af66
r193:6aa65dc5a4b4
r0:d63b455452f6
r4656:515f0929a2ed
r2594:47101c29af66
r4656:515f0929a2ed
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r337:998f55d0b04c
r0:d63b455452f6
r3645:de3cfb719308
r3645:de3cfb719308
r3645:de3cfb719308
r337:998f55d0b04c
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r337:998f55d0b04c
r0:d63b455452f6
r0:d63b455452f6
r337:998f55d0b04c
r337:998f55d0b04c
r0:d63b455452f6
r0:d63b455452f6
r0:d63b455452f6
r337:998f55d0b04c
r0:d63b455452f6
r0:d63b455452f6
r4656:515f0929a2ed
r2594:47101c29af66
r4656:515f0929a2ed
r0:d63b455452f6
r0:d63b455452f6
/* $Id$ */

#include "stdafx.h"
#include "openttd.h"
#include "functions.h"
#include "map.h"
#include "mixer.h"
#include "sound.h"
#include "vehicle.h"
#include "window.h"
#include "viewport.h"
#include "fileio.h"
#include "newgrf_sound.h"

static uint _file_count;
static FileEntry *_files;

#define SOUND_SLOT 63
// Number of levels of panning per side
#define PANNING_LEVELS 16


static void OpenBankFile(const char *filename)
{
	FileEntry *fe;
	uint count;
	uint i;

	FioOpenFile(SOUND_SLOT, filename);
	count = FioReadDword() / 8;
	fe = calloc(count, sizeof(*fe));

	if (fe == NULL) {
		_file_count = 0;
		_files = NULL;
		return;
	}

	_file_count = count;
	_files = fe;

	FioSeekTo(0, SEEK_SET);

	for (i = 0; i != count; i++) {
		fe[i].file_offset = FioReadDword();
		fe[i].file_size = FioReadDword();
	}

	for (i = 0; i != count; i++, fe++) {
		char name[255];

		FioSeekTo(fe->file_offset, SEEK_SET);

		// Check for special case, see else case
		FioReadBlock(name, FioReadByte()); // Read the name of the sound
		if (strcmp(name, "Corrupt sound") != 0) {
			FioSeekTo(12, SEEK_CUR); // Skip past RIFF header

			// Read riff tags
			for (;;) {
				uint32 tag = FioReadDword();
				uint32 size = FioReadDword();

				if (tag == ' tmf') {
					FioReadWord(); // wFormatTag
					fe->channels = FioReadWord(); // wChannels
					FioReadDword();   // samples per second
					fe->rate = 11025; // seems like all samples should be played at this rate.
					FioReadDword();   // avg bytes per second
					FioReadWord();    // alignment
					fe->bits_per_sample = FioReadByte(); // bits per sample
					FioSeekTo(size - (2 + 2 + 4 + 4 + 2 + 1), SEEK_CUR);
				} else if (tag == 'atad') {
					fe->file_size = size;
					fe->file_offset = FioGetPos() | (SOUND_SLOT << 24);
					break;
				} else {
					fe->file_size = 0;
					break;
				}
			}
		} else {
			/*
			 * Special case for the jackhammer sound
			 * (name in sample.cat is "Corrupt sound")
			 * It's no RIFF file, but raw PCM data
			 */
			fe->channels = 1;
			fe->rate = 11025;
			fe->bits_per_sample = 8;
			fe->file_offset = FioGetPos() | (SOUND_SLOT << 24);
		}
	}
}

uint GetNumOriginalSounds(void)
{
	return _file_count;
}

static bool SetBankSource(MixerChannel *mc, uint bank)
{
	const FileEntry *fe;
	int8 *mem;
	uint i;

	if (bank >= GetNumSounds()) return false;
	fe = GetSound(bank);

	if (fe->file_size == 0) return false;

	mem = malloc(fe->file_size);
	if (mem == NULL) return false;

	FioSeekToFile(fe->file_offset);
	FioReadBlock(mem, fe->file_size);

	for (i = 0; i != fe->file_size; i++)
		mem[i] += -128; // Convert unsigned sound data to signed

	assert(fe->bits_per_sample == 8 && fe->channels == 1 && fe->file_size != 0 && fe->rate != 0);

	MxSetChannelRawSrc(mc, mem, fe->file_size, fe->rate, MX_AUTOFREE);

	return true;
}

bool SoundInitialize(const char *filename)
{
	OpenBankFile(filename);
	return true;
}

// Low level sound player
static void StartSound(uint sound, int panning, uint volume)
{
	MixerChannel *mc;
	uint left_vol, right_vol;

	if (volume == 0) return;
	mc = MxAllocateChannel();
	if (mc == NULL) return;
	if (!SetBankSource(mc, sound)) return;

	panning = clamp(panning, -PANNING_LEVELS, PANNING_LEVELS);
	left_vol = (volume * PANNING_LEVELS) - (volume * panning);
	right_vol = (volume * PANNING_LEVELS) + (volume * panning);
	MxSetChannelVolume(mc, left_vol * 128 / PANNING_LEVELS, right_vol * 128 / PANNING_LEVELS);
	MxActivateChannel(mc);
}


static const byte _vol_factor_by_zoom[] = {255, 190, 134};

static const byte _sound_base_vol[] = {
	128,  90, 128, 128, 128, 128, 128, 128,
	128,  90,  90, 128, 128, 128, 128, 128,
	128, 128, 128,  80, 128, 128, 128, 128,
	128, 128, 128, 128, 128, 128, 128, 128,
	128, 128,  90,  90,  90, 128,  90, 128,
	128,  90, 128, 128, 128,  90, 128, 128,
	128, 128, 128, 128,  90, 128, 128, 128,
	128,  90, 128, 128, 128, 128, 128, 128,
	128, 128,  90,  90,  90, 128, 128, 128,
	 90,
};

static const byte _sound_idx[] = {
	 2,  3,  4,  5,  6,  7,  8,  9,
	10, 11, 12, 13, 14, 15, 16, 17,
	18, 19, 20, 21, 22, 23, 24, 25,
	26, 27, 28, 29, 30, 31, 32, 33,
	34, 35, 36, 37, 38, 39, 40,  0,
	 1, 41, 42, 43, 44, 45, 46, 47,
	48, 49, 50, 51, 52, 53, 54, 55,
	56, 57, 58, 59, 60, 61, 62, 63,
	64, 65, 66, 67, 68, 69, 70, 71,
	72,
};

void SndCopyToPool(void)
{
	uint i;

	for (i = 0; i < _file_count; i++) {
		FileEntry *orig = &_files[_sound_idx[i]];
		FileEntry *fe = AllocateFileEntry();

		memcpy(fe, orig, sizeof(*orig));
		fe->volume = _sound_base_vol[i];
		fe->priority = 0;
	}
}

static void SndPlayScreenCoordFx(SoundFx sound, int x, int y)
{
	const Window *w;

	if (msf.effect_vol == 0) return;

	for (w = _windows; w != _last_window; w++) {
		const ViewPort* vp = w->viewport;

		if (vp != NULL &&
				IS_INSIDE_1D(x, vp->virtual_left, vp->virtual_width) &&
				IS_INSIDE_1D(y, vp->virtual_top, vp->virtual_height)) {
			int left = (x - vp->virtual_left);

			StartSound(
				sound,
				left / (vp->virtual_width / ((PANNING_LEVELS << 1) + 1)) - PANNING_LEVELS,
				(GetSound(sound)->volume * msf.effect_vol * _vol_factor_by_zoom[vp->zoom]) >> 15
			);
			return;
		}
	}

}

void SndPlayTileFx(SoundFx sound, TileIndex tile)
{
	/* emits sound from center of the tile */
	int x = TileX(tile) * TILE_SIZE + TILE_SIZE / 2;
	int y = TileY(tile) * TILE_SIZE + TILE_SIZE / 2;
	Point pt = RemapCoords(x, y, GetSlopeZ(x, y));
	SndPlayScreenCoordFx(sound, pt.x, pt.y);
}

void SndPlayVehicleFx(SoundFx sound, const Vehicle *v)
{
	SndPlayScreenCoordFx(sound,
		(v->left_coord + v->right_coord) / 2,
		(v->top_coord + v->bottom_coord) / 2
	);
}

void SndPlayFx(SoundFx sound)
{
	StartSound(
		sound,
		0,
		(GetSound(sound)->volume * msf.effect_vol) >> 7
	);
}