00001
00002
00005 #include "stdafx.h"
00006 #include "openttd.h"
00007 #include "landscape.h"
00008 #include "mixer.h"
00009 #include "sound_func.h"
00010 #include "fileio.h"
00011 #include "newgrf_sound.h"
00012 #include "fios.h"
00013 #include "window_gui.h"
00014 #include "core/alloc_func.hpp"
00015 #include "map_func.h"
00016 #include "vehicle_base.h"
00017 #include "debug.h"
00018
00019 static uint _file_count;
00020 static FileEntry *_files;
00021 MusicFileSettings msf;
00022
00023
00024 #define PANNING_LEVELS 16
00025
00026
00027 static void OpenBankFile(const char *filename)
00028 {
00029 uint i;
00030
00031 FioOpenFile(SOUND_SLOT, filename);
00032 uint pos = FioGetPos();
00033 uint count = FioReadDword() / 8;
00034
00035
00036 if (count != 73) {
00037 DEBUG(misc, 6, "Incorrect number of sounds in '%s', ignoring.", filename);
00038 _file_count = 0;
00039 _files = NULL;
00040 return;
00041 }
00042
00043 FileEntry *fe = CallocT<FileEntry>(count);
00044
00045 if (fe == NULL) {
00046 _file_count = 0;
00047 _files = NULL;
00048 return;
00049 }
00050
00051 _file_count = count;
00052 _files = fe;
00053
00054 FioSeekTo(pos, SEEK_SET);
00055
00056 for (i = 0; i != count; i++) {
00057 fe[i].file_slot = SOUND_SLOT;
00058 fe[i].file_offset = FioReadDword() + pos;
00059 fe[i].file_size = FioReadDword();
00060 }
00061
00062 for (i = 0; i != count; i++, fe++) {
00063 char name[255];
00064
00065 FioSeekTo(fe->file_offset, SEEK_SET);
00066
00067
00068 FioReadBlock(name, FioReadByte());
00069 if (strcmp(name, "Corrupt sound") != 0) {
00070 FioSeekTo(12, SEEK_CUR);
00071
00072
00073 for (;;) {
00074 uint32 tag = FioReadDword();
00075 uint32 size = FioReadDword();
00076
00077 if (tag == ' tmf') {
00078 FioReadWord();
00079 fe->channels = FioReadWord();
00080 FioReadDword();
00081 fe->rate = 11025;
00082 FioReadDword();
00083 FioReadWord();
00084 fe->bits_per_sample = FioReadByte();
00085 FioSeekTo(size - (2 + 2 + 4 + 4 + 2 + 1), SEEK_CUR);
00086 } else if (tag == 'atad') {
00087 fe->file_size = size;
00088 fe->file_slot = SOUND_SLOT;
00089 fe->file_offset = FioGetPos();
00090 break;
00091 } else {
00092 fe->file_size = 0;
00093 break;
00094 }
00095 }
00096 } else {
00097
00098
00099
00100
00101
00102 fe->channels = 1;
00103 fe->rate = 11025;
00104 fe->bits_per_sample = 8;
00105 fe->file_slot = SOUND_SLOT;
00106 fe->file_offset = FioGetPos();
00107 }
00108 }
00109 }
00110
00111 uint GetNumOriginalSounds()
00112 {
00113 return _file_count;
00114 }
00115
00116 static bool SetBankSource(MixerChannel *mc, const FileEntry *fe)
00117 {
00118 assert(fe != NULL);
00119
00120 if (fe->file_size == 0) return false;
00121
00122 int8 *mem = MallocT<int8>(fe->file_size);
00123 if (mem == NULL) return false;
00124
00125 FioSeekToFile(fe->file_slot, fe->file_offset);
00126 FioReadBlock(mem, fe->file_size);
00127
00128 for (uint i = 0; i != fe->file_size; i++) {
00129 mem[i] += -128;
00130 }
00131
00132 assert(fe->bits_per_sample == 8 && fe->channels == 1 && fe->file_size != 0 && fe->rate != 0);
00133
00134 MxSetChannelRawSrc(mc, mem, fe->file_size, fe->rate, MX_AUTOFREE);
00135
00136 return true;
00137 }
00138
00139 bool SoundInitialize(const char *filename)
00140 {
00141 OpenBankFile(filename);
00142 return true;
00143 }
00144
00145
00146 static void StartSound(uint sound, int panning, uint volume)
00147 {
00148 if (volume == 0) return;
00149
00150 const FileEntry *fe = GetSound(sound);
00151 if (fe == NULL) return;
00152
00153 MixerChannel *mc = MxAllocateChannel();
00154 if (mc == NULL) return;
00155
00156 if (!SetBankSource(mc, fe)) return;
00157
00158
00159 volume = (fe->volume * volume) / 128;
00160
00161 panning = Clamp(panning, -PANNING_LEVELS, PANNING_LEVELS);
00162 uint left_vol = (volume * PANNING_LEVELS) - (volume * panning);
00163 uint right_vol = (volume * PANNING_LEVELS) + (volume * panning);
00164 MxSetChannelVolume(mc, left_vol * 128 / PANNING_LEVELS, right_vol * 128 / PANNING_LEVELS);
00165 MxActivateChannel(mc);
00166 }
00167
00168
00169 static const byte _vol_factor_by_zoom[] = {255, 190, 134, 87};
00170 assert_compile(lengthof(_vol_factor_by_zoom) == ZOOM_LVL_END - ZOOM_LVL_BEGIN);
00171
00172 static const byte _sound_base_vol[] = {
00173 128, 90, 128, 128, 128, 128, 128, 128,
00174 128, 90, 90, 128, 128, 128, 128, 128,
00175 128, 128, 128, 80, 128, 128, 128, 128,
00176 128, 128, 128, 128, 128, 128, 128, 128,
00177 128, 128, 90, 90, 90, 128, 90, 128,
00178 128, 90, 128, 128, 128, 90, 128, 128,
00179 128, 128, 128, 128, 90, 128, 128, 128,
00180 128, 90, 128, 128, 128, 128, 128, 128,
00181 128, 128, 90, 90, 90, 128, 128, 128,
00182 90,
00183 };
00184
00185 static const byte _sound_idx[] = {
00186 2, 3, 4, 5, 6, 7, 8, 9,
00187 10, 11, 12, 13, 14, 15, 16, 17,
00188 18, 19, 20, 21, 22, 23, 24, 25,
00189 26, 27, 28, 29, 30, 31, 32, 33,
00190 34, 35, 36, 37, 38, 39, 40, 0,
00191 1, 41, 42, 43, 44, 45, 46, 47,
00192 48, 49, 50, 51, 52, 53, 54, 55,
00193 56, 57, 58, 59, 60, 61, 62, 63,
00194 64, 65, 66, 67, 68, 69, 70, 71,
00195 72,
00196 };
00197
00198 void SndCopyToPool()
00199 {
00200 uint i;
00201
00202 for (i = 0; i < _file_count; i++) {
00203 FileEntry *orig = &_files[_sound_idx[i]];
00204 FileEntry *fe = AllocateFileEntry();
00205
00206 *fe = *orig;
00207 fe->volume = _sound_base_vol[i];
00208 fe->priority = 0;
00209 }
00210 }
00211
00212 static void SndPlayScreenCoordFx(SoundFx sound, int left, int right, int top, int bottom)
00213 {
00214 Window* const *wz;
00215
00216 if (msf.effect_vol == 0) return;
00217
00218 FOR_ALL_WINDOWS(wz) {
00219 const ViewPort *vp = (*wz)->viewport;
00220
00221 if (vp != NULL &&
00222 left < vp->virtual_left + vp->virtual_width && right > vp->virtual_left &&
00223 top < vp->virtual_top + vp->virtual_height && bottom > vp->virtual_top) {
00224 int screen_x = (left + right) / 2 - vp->virtual_left;
00225 int width = (vp->virtual_width == 0 ? 1 : vp->virtual_width);
00226 int panning = (screen_x * PANNING_LEVELS * 2) / width - PANNING_LEVELS;
00227
00228 StartSound(
00229 sound,
00230 panning,
00231 (msf.effect_vol * _vol_factor_by_zoom[vp->zoom - ZOOM_LVL_BEGIN]) / 256
00232 );
00233 return;
00234 }
00235 }
00236
00237 }
00238
00239 void SndPlayTileFx(SoundFx sound, TileIndex tile)
00240 {
00241
00242 int x = TileX(tile) * TILE_SIZE + TILE_SIZE / 2;
00243 int y = TileY(tile) * TILE_SIZE - TILE_SIZE / 2;
00244 uint z = (y < 0 ? 0 : GetSlopeZ(x, y));
00245 Point pt = RemapCoords(x, y, z);
00246 y += 2 * TILE_SIZE;
00247 Point pt2 = RemapCoords(x, y, GetSlopeZ(x, y));
00248 SndPlayScreenCoordFx(sound, pt.x, pt2.x, pt.y, pt2.y);
00249 }
00250
00251 void SndPlayVehicleFx(SoundFx sound, const Vehicle *v)
00252 {
00253 SndPlayScreenCoordFx(sound,
00254 v->left_coord, v->right_coord,
00255 v->top_coord, v->top_coord
00256 );
00257 }
00258
00259 void SndPlayFx(SoundFx sound)
00260 {
00261 StartSound(sound, 0, msf.effect_vol);
00262 }