OpenTTD

sound.cpp
Go to the documentation of this file.
1 /* $Id: sound.cpp 26482 2014-04-23 20:13:33Z rubidium $ */
2
3 /*
4 * This file is part of OpenTTD.
5 * OpenTTD 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, version 2.
6 * OpenTTD 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.
7 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8 */
9
12 #include "stdafx.h"
13 #include "landscape.h"
14 #include "mixer.h"
15 #include "newgrf_sound.h"
16 #include "fios.h"
17 #include "window_gui.h"
18 #include "vehicle_base.h"
19
20 /* The type of set we're replacing */
21 #define SET_TYPE "sounds"
22 #include "base_media_func.h"
23
24 #include "safeguards.h"
25
26 static SoundEntry _original_sounds[ORIGINAL_SAMPLE_COUNT];
27
28 static void OpenBankFile(const char *filename)
29 {
30 memset(_original_sounds, 0, sizeof(_original_sounds));
31
32 /* If there is no sound file (nosound set), don't load anything */
33 if (filename == NULL) return;
34
35 FioOpenFile(SOUND_SLOT, filename, BASESET_DIR);
36 size_t pos = FioGetPos();
37 uint count = FioReadDword();
38
39 /* The new format has the highest bit always set */
40 bool new_format = HasBit(count, 31);
41 ClrBit(count, 31);
42 count /= 8;
43
44 /* Simple check for the correct number of original sounds. */
45 if (count != ORIGINAL_SAMPLE_COUNT) {
46 /* Corrupt sample data? Just leave the allocated memory as those tell
47 * there is no sound to play (size = 0 due to calloc). Not allocating
48 * the memory disables valid NewGRFs that replace sounds. */
49 DEBUG(misc, 6, "Incorrect number of sounds in '%s', ignoring.", filename);
50 return;
51 }
52
53 FioSeekTo(pos, SEEK_SET);
54
55 for (uint i = 0; i != ORIGINAL_SAMPLE_COUNT; i++) {
56 _original_sounds[i].file_slot = SOUND_SLOT;
57 _original_sounds[i].file_offset = GB(FioReadDword(), 0, 31) + pos;
58 _original_sounds[i].file_size = FioReadDword();
59 }
60
61 for (uint i = 0; i != ORIGINAL_SAMPLE_COUNT; i++) {
62 SoundEntry *sound = &_original_sounds[i];
63 char name[255];
64
65 FioSeekTo(sound->file_offset, SEEK_SET);
66
67 /* Check for special case, see else case */
68 FioReadBlock(name, FioReadByte()); // Read the name of the sound
69 if (new_format || strcmp(name, "Corrupt sound") != 0) {
70 FioSeekTo(12, SEEK_CUR); // Skip past RIFF header
71
72 /* Read riff tags */
73 for (;;) {
74 uint32 tag = FioReadDword();
75 uint32 size = FioReadDword();
76
77 if (tag == ' tmf') {
78 FioReadWord(); // wFormatTag
79 sound->channels = FioReadWord(); // wChannels
80 sound->rate = FioReadDword(); // samples per second
81 if (!new_format) sound->rate = 11025; // seems like all old samples should be played at this rate.
82 FioReadDword(); // avg bytes per second
83 FioReadWord(); // alignment
84 sound->bits_per_sample = FioReadByte(); // bits per sample
85 FioSeekTo(size - (2 + 2 + 4 + 4 + 2 + 1), SEEK_CUR);
86 } else if (tag == 'atad') {
87 sound->file_size = size;
88 sound->file_slot = SOUND_SLOT;
89 sound->file_offset = FioGetPos();
90 break;
91 } else {
92 sound->file_size = 0;
93 break;
94 }
95 }
96 } else {
97 /*
98 * Special case for the jackhammer sound
99 * (name in sample.cat is "Corrupt sound")
100 * It's no RIFF file, but raw PCM data
101 */
102 sound->channels = 1;
103 sound->rate = 11025;
104 sound->bits_per_sample = 8;
105 sound->file_slot = SOUND_SLOT;
106 sound->file_offset = FioGetPos();
107 }
108 }
109 }
110
111 static bool SetBankSource(MixerChannel *mc, const SoundEntry *sound)
112 {
113 assert(sound != NULL);
114
115 /* Check for valid sound size. */
116 if (sound->file_size == 0 || sound->file_size > ((size_t)-1) - 2) return false;
117
118 int8 *mem = MallocT<int8>(sound->file_size + 2);
119 /* Add two extra bytes so rate conversion can read these
120 * without reading out of its input buffer. */
121 mem[sound->file_size ] = 0;
122 mem[sound->file_size + 1] = 0;
123
124 FioSeekToFile(sound->file_slot, sound->file_offset);
125 FioReadBlock(mem, sound->file_size);
126
127 /* 16-bit PCM WAV files should be signed by default */
128 if (sound->bits_per_sample == 8) {
129 for (uint i = 0; i != sound->file_size; i++) {
130 mem[i] += -128; // Convert unsigned sound data to signed
131 }
132 }
133
134 #if TTD_ENDIAN == TTD_BIG_ENDIAN
135 if (sound->bits_per_sample == 16) {
136 uint num_samples = sound->file_size / 2;
137 int16 *samples = (int16 *)mem;
138 for (uint i = 0; i < num_samples; i++) {
139 samples[i] = BSWAP16(samples[i]);
140 }
141 }
142 #endif
143
144 assert(sound->bits_per_sample == 8 || sound->bits_per_sample == 16);
145 assert(sound->channels == 1);
146 assert(sound->file_size != 0 && sound->rate != 0);
147
148 MxSetChannelRawSrc(mc, mem, sound->file_size, sound->rate, sound->bits_per_sample == 16);
149
150 return true;
151 }
152
153 void InitializeSound()
154 {
155 DEBUG(misc, 1, "Loading sound effects...");
156 OpenBankFile(BaseSounds::GetUsedSet()->files->filename);
157 }
158
159 /* Low level sound player */
160 static void StartSound(SoundID sound_id, float pan, uint volume)
161 {
162 if (volume == 0) return;
163
164 SoundEntry *sound = GetSound(sound_id);
165 if (sound == NULL) return;
166
167 /* NewGRF sound that wasn't loaded yet? */
168 if (sound->rate == 0 && sound->file_slot != 0) {
169 if (!LoadNewGRFSound(sound)) {
170 /* Mark as invalid. */
171 sound->file_slot = 0;
172 return;
173 }
174 }
175
176 /* Empty sound? */
177 if (sound->rate == 0) return;
178
179 MixerChannel *mc = MxAllocateChannel();
180 if (mc == NULL) return;
181
182 if (!SetBankSource(mc, sound)) return;
183
184 /* Apply the sound effect's own volume. */
185 volume = sound->volume * volume;
186
187 MxSetChannelVolume(mc, volume, pan);
188 MxActivateChannel(mc);
189 }
190
191
192 static const byte _vol_factor_by_zoom[] = {255, 255, 255, 190, 134, 87};
193 assert_compile(lengthof(_vol_factor_by_zoom) == ZOOM_LVL_COUNT);
194
195 static const byte _sound_base_vol[] = {
196 128, 90, 128, 128, 128, 128, 128, 128,
197 128, 90, 90, 128, 128, 128, 128, 128,
198 128, 128, 128, 80, 128, 128, 128, 128,
199 128, 128, 128, 128, 128, 128, 128, 128,
200 128, 128, 90, 90, 90, 128, 90, 128,
201 128, 90, 128, 128, 128, 90, 128, 128,
202 128, 128, 128, 128, 90, 128, 128, 128,
203 128, 90, 128, 128, 128, 128, 128, 128,
204 128, 128, 90, 90, 90, 128, 128, 128,
205 90,
206 };
207
208 static const byte _sound_idx[] = {
209 2, 3, 4, 5, 6, 7, 8, 9,
210 10, 11, 12, 13, 14, 15, 16, 17,
211 18, 19, 20, 21, 22, 23, 24, 25,
212 26, 27, 28, 29, 30, 31, 32, 33,
213 34, 35, 36, 37, 38, 39, 40, 0,
214 1, 41, 42, 43, 44, 45, 46, 47,
215 48, 49, 50, 51, 52, 53, 54, 55,
216 56, 57, 58, 59, 60, 61, 62, 63,
217 64, 65, 66, 67, 68, 69, 70, 71,
218 72,
219 };
220
221 void SndCopyToPool()
222 {
223 SoundEntry *sound = AllocateSound(ORIGINAL_SAMPLE_COUNT);
224 for (uint i = 0; i < ORIGINAL_SAMPLE_COUNT; i++) {
225 sound[i] = _original_sounds[_sound_idx[i]];
226 sound[i].volume = _sound_base_vol[i];
227 sound[i].priority = 0;
228 }
229 }
230
239 static void SndPlayScreenCoordFx(SoundID sound, int left, int right, int top, int bottom)
240 {
241 if (_settings_client.music.effect_vol == 0) return;
242
243 const Window *w;
244 FOR_ALL_WINDOWS_FROM_BACK(w) {
245 const ViewPort *vp = w->viewport;
246
247 if (vp != NULL &&
248 left < vp->virtual_left + vp->virtual_width && right > vp->virtual_left &&
249 top < vp->virtual_top + vp->virtual_height && bottom > vp->virtual_top) {
250 int screen_x = (left + right) / 2 - vp->virtual_left;
251 int width = (vp->virtual_width == 0 ? 1 : vp->virtual_width);
252 float panning = (float)screen_x / width;
253
254 StartSound(
255 sound,
256 panning,
257 (_settings_client.music.effect_vol * _vol_factor_by_zoom[vp->zoom - ZOOM_LVL_BEGIN]) / 256
258 );
259 return;
260 }
261 }
262 }
263
264 void SndPlayTileFx(SoundID sound, TileIndex tile)
265 {
266 /* emits sound from center of the tile */
267 int x = min(MapMaxX() - 1, TileX(tile)) * TILE_SIZE + TILE_SIZE / 2;
268 int y = min(MapMaxY() - 1, TileY(tile)) * TILE_SIZE - TILE_SIZE / 2;
269 int z = (y < 0 ? 0 : GetSlopePixelZ(x, y));
270 Point pt = RemapCoords(x, y, z);
271 y += 2 * TILE_SIZE;
272 Point pt2 = RemapCoords(x, y, GetSlopePixelZ(x, y));
273 SndPlayScreenCoordFx(sound, pt.x, pt2.x, pt.y, pt2.y);
274 }
275
276 void SndPlayVehicleFx(SoundID sound, const Vehicle *v)
277 {
278 SndPlayScreenCoordFx(sound,
279 v->coord.left, v->coord.right,
280 v->coord.top, v->coord.bottom
281 );
282 }
283
284 void SndPlayFx(SoundID sound)
285 {
286 StartSound(sound, 0.5, _settings_client.music.effect_vol);
287 }
288
289 INSTANTIATE_BASE_MEDIA_METHODS(BaseMedia<SoundsSet>, SoundsSet)
290
291
292 static const char * const _sound_file_names[] = { "samples" };
293
294
295 template <class T, size_t Tnum_files, bool Tsearch_in_tars>
296 /* static */ const char * const *BaseSet<T, Tnum_files, Tsearch_in_tars>::file_names = _sound_file_names;
297
298 template <class Tbase_set>
299 /* static */ const char *BaseMedia<Tbase_set>::GetExtension()
300 {
301 return ".obs"; // OpenTTD Base Sounds
302 }
303
304 template <class Tbase_set>
305 /* static */ bool BaseMedia<Tbase_set>::DetermineBestSet()
306 {
307 if (BaseMedia<Tbase_set>::used_set != NULL) return true;
308
309 const Tbase_set *best = NULL;
310 for (const Tbase_set *c = BaseMedia<Tbase_set>::available_sets; c != NULL; c = c->next) {
311 /* Skip unusable sets */
312 if (c->GetNumMissing() != 0) continue;
313
314 if (best == NULL ||
315 (best->fallback && !c->fallback) ||
316 best->valid_files < c->valid_files ||
317 (best->valid_files == c->valid_files &&
318 (best->shortname == c->shortname && best->version < c->version))) {
319 best = c;
320 }
321 }
322
323 BaseMedia<Tbase_set>::used_set = best;
324 return BaseMedia<Tbase_set>::used_set != NULL;
325 }
326
SOUND_SLOT
Slot for the sound.
Definition: fios.h:90
ViewPort::virtual_left
int virtual_left
Virtual left coordinate.
Definition: viewport_type.h:30
ZOOM_LVL_BEGIN
Begin for iteration.
Definition: zoom_type.h:23
base_media_func.h
Generic function implementations for base data (graphics, sounds).
RemapCoords
static Point RemapCoords(int x, int y, int z)
Map 3D world or tile coordinate to equivalent 2D coordinate as used in the viewports and smallmap...
Definition: landscape.h:83
BaseMedia::GetExtension
static const char * GetExtension()
Get the extension that is used to identify this set.
Definition: gfxinit.cpp:456
FioReadWord
uint16 FioReadWord()
Read a word (16 bits) from the file (in low endian format).
Definition: fileio.cpp:166
SndPlayScreenCoordFx
static void SndPlayScreenCoordFx(SoundID sound, int left, int right, int top, int bottom)
Decide &#39;where&#39; (between left and right speaker) to play the sound effect.
Definition: sound.cpp:239
ORIGINAL_SAMPLE_COUNT
static const uint ORIGINAL_SAMPLE_COUNT
The number of sounds in the original sample.cat.
Definition: sound_type.h:118
ViewPort::virtual_height
int virtual_height
height << zoom
Definition: viewport_type.h:33
ClientSettings::music
MusicSettings music
settings related to music/sound
Definition: settings_type.h:565
TileX
static uint TileX(TileIndex tile)
Get the X component of a tile.
Definition: map_func.h:207
Vehicle
Vehicle data structure.
Definition: vehicle_base.h:212
BASESET_DIR
Subdirectory for all base data (base sets, intro game)
Definition: fileio_type.h:118
FioReadByte
byte FioReadByte()
Read a byte from the file.
Definition: fileio.cpp:133
TILE_SIZE
static const uint TILE_SIZE
Tile size in world coordinates.
Definition: tile_type.h:15
window_gui.h
Functions, definitions and such used only by the GUI.
Window
Data structure for an opened window.
Definition: window_gui.h:271
ZOOM_LVL_COUNT
Number of zoom levels.
Definition: zoom_type.h:32
LoadNewGRFSound
bool LoadNewGRFSound(SoundEntry *sound)
Extract meta data from a NewGRF sound.
Definition: newgrf_sound.cpp:68
_sound_file_names
static const char *const _sound_file_names[]
Names corresponding to the sound set&#39;s files.
Definition: sound.cpp:292
_settings_client
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:76
stdafx.h
Definition of base types and functions in a cross-platform compatible way.
safeguards.h
A number of safeguards to prevent using unsafe methods.
FioSeekTo
void FioSeekTo(size_t pos, int mode)
Seek in the current file.
Definition: fileio.cpp:88
MxSetChannelVolume
void MxSetChannelVolume(MixerChannel *mc, uint volume, float pan)
Set volume and pan parameters for a sound.
Definition: mixer.cpp:198
FioSeekToFile
void FioSeekToFile(uint8 slot, size_t pos)
Switch to a different file and seek to a position.
Definition: fileio.cpp:115
ViewPort::virtual_width
int virtual_width
width << zoom
Definition: viewport_type.h:32
FioReadBlock
void FioReadBlock(void *ptr, size_t size)
Read a block.
Definition: fileio.cpp:187
lengthof
#define lengthof(x)
Return the length of an fixed size array.
Definition: depend.cpp:42
min
static T min(const T a, const T b)
Returns the minimum of two values.
Definition: math_func.hpp:42
BaseMedia< SoundsSet >
AllocateSound
SoundEntry * AllocateSound(uint num)
Allocate sound slots.
Definition: newgrf_sound.cpp:33
DEBUG
#define DEBUG(name, level,...)
Output a line of debugging information.
Definition: debug.h:39
FioOpenFile
void FioOpenFile(int slot, const char *filename, Subdirectory subdir)
Open a slotted file.
Definition: fileio.cpp:250
MixerChannel
Definition: mixer.cpp:18
FioReadDword
uint32 FioReadDword()
Read a double word (32 bits) from the file (in low endian format).
Definition: fileio.cpp:176
ClrBit
static T ClrBit(T &x, const uint8 y)
Clears a bit in a variable.
Definition: bitmath_func.hpp:153
vehicle_base.h
Base class for all vehicles.
ViewPort
Data structure for viewport, display of a part of the world.
Definition: viewport_type.h:24
fios.h
Declarations for savegames operations.
TileIndex
uint32 TileIndex
The index/ID of a Tile.
Definition: tile_type.h:80
TileY
static uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition: map_func.h:217
SoundsSet
All data of a sounds set.
Definition: base_media_base.h:265
INSTANTIATE_BASE_MEDIA_METHODS
#define INSTANTIATE_BASE_MEDIA_METHODS(repl_type, set_type)
Force instantiation of methods so we don&#39;t get linker errors.
Definition: base_media_func.h:400
GB
static uint GB(const T x, const uint8 s, const uint8 n)
Fetch n bits from x, started at bit s.
Definition: bitmath_func.hpp:34
MapMaxY
static uint MapMaxY()
Gets the maximum Y coordinate within the map, including MP_VOID.
Definition: map_func.h:113
landscape.h
Functions related to OTTD&#39;s landscape.
BSWAP16
static uint16 BSWAP16(uint16 x)
Perform a 16 bits endianness bitswap on x.
Definition: bitmath_func.hpp:395
BaseSet
Information about a single base set.
Definition: base_media_base.h:48
Point
Coordinates of a point in 2D.
Definition: geometry_type.hpp:28
mixer.h
Functions to mix sound samples.
ViewPort::zoom
ZoomLevel zoom
The zoom level of the viewport.
Definition: viewport_type.h:35
HasBit
static bool HasBit(const T x, const uint8 y)
Checks if a bit in a value is set.
Definition: bitmath_func.hpp:105
newgrf_sound.h
Functions related to NewGRF provided sounds.
ViewPort::virtual_top
int virtual_top
Virtual top coordinate.
Definition: viewport_type.h:31
MapMaxX
static uint MapMaxX()
Gets the maximum X coordinate within the map, including MP_VOID.
Definition: map_func.h:104
FioGetPos
size_t FioGetPos()
Get position in the current file.
Definition: fileio.cpp:68
SoundEntry
Definition: sound_type.h:15
Window::viewport
ViewportData * viewport
Pointer to viewport data, if present.
Definition: window_gui.h:321
Vehicle::coord
Rect coord
NOSAVE: Graphical bounding box of the vehicle, i.e. what to redraw on moves.
Definition: vehicle_base.h:245
MusicSettings::effect_vol
byte effect_vol
The requested effects volume.
Definition: settings_type.h:188
BaseMedia< SoundsSet >::GetUsedSet
static const SoundsSet * GetUsedSet()
Return the used set.
Definition: base_media_func.h:380
BaseMedia::DetermineBestSet
static bool DetermineBestSet()
Determine the graphics pack that has to be used.
Definition: gfxinit.cpp:432