20 #define SET_TYPE "sounds"
33 static std::unique_ptr<RandomAccessFile> original_sound_file;
35 memset(_original_sounds, 0,
sizeof(_original_sounds));
38 if (filename.empty())
return;
41 size_t pos = original_sound_file->GetPos();
42 uint count = original_sound_file->ReadDword();
45 bool new_format =
HasBit(count, 31);
54 Debug(misc, 6,
"Incorrect number of sounds in '{}', ignoring.", filename);
58 original_sound_file->SeekTo(pos, SEEK_SET);
61 _original_sounds[i].file = original_sound_file.get();
62 _original_sounds[i].file_offset =
GB(original_sound_file->ReadDword(), 0, 31) + pos;
63 _original_sounds[i].file_size = original_sound_file->ReadDword();
70 original_sound_file->SeekTo(sound->file_offset, SEEK_SET);
73 original_sound_file->ReadBlock(name, original_sound_file->ReadByte());
74 if (new_format || strcmp(name,
"Corrupt sound") != 0) {
75 original_sound_file->SeekTo(12, SEEK_CUR);
79 uint32_t tag = original_sound_file->ReadDword();
80 uint32_t size = original_sound_file->ReadDword();
83 original_sound_file->ReadWord();
84 sound->channels = original_sound_file->ReadWord();
85 sound->rate = original_sound_file->ReadDword();
86 if (!new_format) sound->rate = 11025;
87 original_sound_file->ReadDword();
88 original_sound_file->ReadWord();
89 sound->bits_per_sample = original_sound_file->ReadByte();
90 original_sound_file->SeekTo(size - (2 + 2 + 4 + 4 + 2 + 1), SEEK_CUR);
91 }
else if (tag ==
'atad') {
92 sound->file_size = size;
93 sound->file = original_sound_file.get();
94 sound->file_offset = original_sound_file->GetPos();
109 sound->bits_per_sample = 8;
110 sound->file = original_sound_file.get();
111 sound->file_offset = original_sound_file->GetPos();
118 assert(sound !=
nullptr);
121 if (sound->file_size == 0 || sound->file_size > SIZE_MAX - 2)
return false;
123 int8_t *mem = MallocT<int8_t>(sound->file_size + 2);
126 mem[sound->file_size ] = 0;
127 mem[sound->file_size + 1] = 0;
130 file->
SeekTo(sound->file_offset, SEEK_SET);
134 if (sound->bits_per_sample == 8) {
135 for (uint i = 0; i != sound->file_size; i++) {
140 if constexpr (std::endian::native == std::endian::big) {
141 if (sound->bits_per_sample == 16) {
142 size_t num_samples = sound->file_size / 2;
143 int16_t *samples =
reinterpret_cast<int16_t *
>(mem);
144 for (
size_t i = 0; i < num_samples; i++) {
145 samples[i] =
BSWAP16(samples[i]);
150 assert(sound->bits_per_sample == 8 || sound->bits_per_sample == 16);
151 assert(sound->channels == 1);
152 assert(sound->file_size != 0 && sound->rate != 0);
154 MxSetChannelRawSrc(mc, mem, sound->file_size, sound->rate, sound->bits_per_sample == 16);
159 void InitializeSound()
161 Debug(misc, 1,
"Loading sound effects...");
166 static void StartSound(SoundID sound_id,
float pan, uint volume)
168 if (volume == 0)
return;
171 if (sound ==
nullptr)
return;
174 if (sound->rate == 0 && sound->file !=
nullptr) {
177 sound->file =
nullptr;
183 if (sound->rate == 0)
return;
186 if (mc ==
nullptr)
return;
188 if (!SetBankSource(mc, sound))
return;
191 volume = sound->volume * volume;
194 MxActivateChannel(mc);
198 static const uint8_t _vol_factor_by_zoom[] = {255, 255, 255, 190, 134, 87};
201 static const uint8_t _sound_base_vol[] = {
202 128, 90, 128, 128, 128, 128, 128, 128,
203 128, 90, 90, 128, 128, 128, 128, 128,
204 128, 128, 128, 80, 128, 128, 128, 128,
205 128, 128, 128, 128, 128, 128, 128, 128,
206 128, 128, 90, 90, 90, 128, 90, 128,
207 128, 90, 128, 128, 128, 90, 128, 128,
208 128, 128, 128, 128, 90, 128, 128, 128,
209 128, 90, 128, 128, 128, 128, 128, 128,
210 128, 128, 90, 90, 90, 128, 128, 128,
214 static const uint8_t _sound_idx[] = {
215 2, 3, 4, 5, 6, 7, 8, 9,
216 10, 11, 12, 13, 14, 15, 16, 17,
217 18, 19, 20, 21, 22, 23, 24, 25,
218 26, 27, 28, 29, 30, 31, 32, 33,
219 34, 35, 36, 37, 38, 39, 40, 0,
220 1, 41, 42, 43, 44, 45, 46, 47,
221 48, 49, 50, 51, 52, 53, 54, 55,
222 56, 57, 58, 59, 60, 61, 62, 63,
223 64, 65, 66, 67, 68, 69, 70, 71,
231 sound[i] = _original_sounds[_sound_idx[i]];
232 sound[i].volume = _sound_base_vol[i];
233 sound[i].priority = 0;
259 *sound = _original_sounds[_sound_idx[i]];
260 sound->volume = _sound_base_vol[i];
287 float panning = (float)screen_x / width;
292 _vol_factor_by_zoom[vp->
zoom]
299 void SndPlayTileFx(SoundID sound,
TileIndex tile)
311 void SndPlayVehicleFx(SoundID sound,
const Vehicle *v)
319 void SndPlayFx(SoundID sound)
321 StartSound(sound, 0.5, UINT8_MAX);
330 template <
class T,
size_t Tnum_files,
bool Tsearch_in_tars>
333 template <
class Tbase_set>
339 template <
class Tbase_set>
344 const Tbase_set *best =
nullptr;
347 if (c->GetNumMissing() != 0)
continue;
349 if (best ==
nullptr ||
350 (best->fallback && !c->fallback) ||
351 best->valid_files < c->valid_files ||
352 (best->valid_files == c->valid_files &&
353 (best->shortname == c->shortname && best->version < c->version))) {
constexpr debug_inline bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr static debug_inline uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
static uint16_t BSWAP16(uint16_t x)
Perform a 16 bits endianness bitswap on x.
constexpr T ClrBit(T &x, const uint8_t y)
Clears a bit in a variable.
static std::string ini_set
The set as saved in the config file.
A file from which bytes, words and double words are read in (potentially) a random order.
void ReadBlock(void *ptr, size_t size)
Read a block.
void SeekTo(size_t pos, int mode)
Seek in the current file.
#define Debug(category, level, format_string,...)
Ouptut a line of debugging information.
@ BASESET_DIR
Subdirectory for all base data (base sets, intro game)
int GetSlopePixelZ(int x, int y, bool ground_vehicle)
Return world Z coordinate of a given point of a tile.
Functions related to OTTD's landscape.
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.
static debug_inline uint TileY(TileIndex tile)
Get the Y component of a tile.
static debug_inline uint TileX(TileIndex tile)
Get the X component of a tile.
void MxCloseAllChannels()
Close all mixer channels.
void MxSetChannelVolume(MixerChannel *mc, uint volume, float pan)
Set volume and pan parameters for a sound.
Functions to mix sound samples.
bool LoadNewGRFSound(SoundEntry *sound)
Extract meta data from a NewGRF sound.
SoundEntry * AllocateSound(uint num)
Allocate sound slots.
Functions related to NewGRF provided sounds.
Class related to random access to files.
A number of safeguards to prevent using unsafe methods.
static void SndPlayScreenCoordFx(SoundID sound, int left, int right, int top, int bottom)
Decide 'where' (between left and right speaker) to play the sound effect.
static const char *const _sound_file_names[]
Names corresponding to the sound set's files.
static void OpenBankFile(const std::string &filename)
void ChangeSoundSet(int index)
Change the configured sound set and reset sounds.
static const uint ORIGINAL_SAMPLE_COUNT
The number of sounds in the original sample.cat.
Definition of base types and functions in a cross-platform compatible way.
#define lengthof(array)
Return the length of an fixed size array.
Information about a single base set.
static uint MaxY()
Gets the maximum Y coordinate within the map, including MP_VOID.
static debug_inline uint MaxX()
Gets the maximum X coordinate within the map, including MP_VOID.
Coordinates of a point in 2D.
uint8_t grf_container_ver
NewGRF container version if the sound is from a NewGRF.
All data of a sounds set.
Rect coord
NOSAVE: Graphical bounding box of the vehicle, i.e. what to redraw on moves.
Data structure for viewport, display of a part of the world.
ZoomLevel zoom
The zoom level of the viewport.
int virtual_top
Virtual top coordinate.
int virtual_left
Virtual left coordinate.
int virtual_width
width << zoom
int virtual_height
height << zoom
Iterable ensemble of all valid Windows.
Data structure for an opened window.
static const uint TILE_SIZE
Tile size in world coordinates.
Base class for all vehicles.
void InvalidateWindowData(WindowClass cls, WindowNumber number, int data, bool gui_scope)
Mark window data of the window of a given class and specific window number as invalid (in need of re-...
Window functions not directly related to making/drawing windows.
Functions, definitions and such used only by the GUI.
@ WN_GAME_OPTIONS_GAME_OPTIONS
Game options.
@ WC_GAME_OPTIONS
Game options window; Window numbers:
@ ZOOM_LVL_END
End for iteration.