sound.cpp

Go to the documentation of this file.
00001 /* $Id: sound.cpp 12186 2008-02-19 17:45:30Z smatz $ */
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 // Number of levels of panning per side
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   /* Simple check for the correct number of original sounds. */
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     /* Check for special case, see else case */
00068     FioReadBlock(name, FioReadByte()); // Read the name of the sound
00069     if (strcmp(name, "Corrupt sound") != 0) {
00070       FioSeekTo(12, SEEK_CUR); // Skip past RIFF header
00071 
00072       /* Read riff tags */
00073       for (;;) {
00074         uint32 tag = FioReadDword();
00075         uint32 size = FioReadDword();
00076 
00077         if (tag == ' tmf') {
00078           FioReadWord(); // wFormatTag
00079           fe->channels = FioReadWord(); // wChannels
00080           FioReadDword();   // samples per second
00081           fe->rate = 11025; // seems like all samples should be played at this rate.
00082           FioReadDword();   // avg bytes per second
00083           FioReadWord();    // alignment
00084           fe->bits_per_sample = FioReadByte(); // bits per sample
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        * Special case for the jackhammer sound
00099        * (name in sample.cat is "Corrupt sound")
00100        * It's no RIFF file, but raw PCM data
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; // Convert unsigned sound data to signed
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 /* Low level sound player */
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   /* Apply the sound effect's own volume. */
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   /* emits sound from center of the tile */
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 }

Generated on Mon Sep 22 20:34:18 2008 for openttd by  doxygen 1.5.6