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