00001
00002
00003
00004
00005
00006
00007
00008
00009
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00030
00031
00032
00033
00034
00035 #include "stratagus.h"
00036
00037 #include <stdlib.h>
00038 #include <stdio.h>
00039 #include <string.h>
00040
00041 #include "SDL.h"
00042 #include "SDL_endian.h"
00043
00044 #include "iolib.h"
00045 #include "sound_server.h"
00046 #include "wav.h"
00047
00048
00049
00050
00051
00055 struct WavData {
00056 CFile *WavFile;
00057 int ChunkRem;
00058 };
00059
00060 class CSampleWav : public CSample
00061 {
00062 public:
00063 ~CSampleWav();
00064 int Read(void *buf, int len);
00065
00066 WavData Data;
00067 };
00068
00069 class CSampleWavStream : public CSample
00070 {
00071 public:
00072 ~CSampleWavStream();
00073 int Read(void *buf, int len);
00074
00075 WavData Data;
00076 };
00077
00078
00079
00080
00081
00082 int CSampleWavStream::Read(void *buf, int len)
00083 {
00084 WavChunk chunk;
00085 unsigned char *sndbuf;
00086 int comp;
00087 int i;
00088 int read;
00089 int bufrem;
00090
00091 if (this->Pos > SOUND_BUFFER_SIZE / 2) {
00092 memcpy(this->Buffer, this->Buffer + this->Pos, this->Len);
00093 this->Pos = 0;
00094 }
00095
00096 while (this->Len < SOUND_BUFFER_SIZE / 4) {
00097 if (!this->Data.ChunkRem) {
00098
00099 comp = this->Data.WavFile->read(&chunk, sizeof(chunk));
00100
00101 if (!comp) {
00102
00103 this->Data.ChunkRem = 0;
00104 break;
00105 }
00106
00107 chunk.Magic = SDL_SwapLE32(chunk.Magic);
00108 chunk.Length = SDL_SwapLE32(chunk.Length);
00109 if (chunk.Magic != DATA) {
00110 this->Data.WavFile->seek(chunk.Length, SEEK_CUR);
00111 continue;
00112 }
00113 this->Data.ChunkRem = chunk.Length;
00114 }
00115
00116 bufrem = SOUND_BUFFER_SIZE - (this->Pos + this->Len);
00117 if (this->Data.ChunkRem > bufrem) {
00118 read = bufrem;
00119 } else {
00120 read = this->Data.ChunkRem;
00121 }
00122 this->Data.ChunkRem -= read;
00123
00124 sndbuf = this->Buffer + this->Pos + this->Len;
00125
00126 comp = this->Data.WavFile->read(sndbuf, read);
00127 if (!comp) {
00128 break;
00129 }
00130
00131 read >>= 1;
00132 for (i = 0; i < read; ++i) {
00133 ((unsigned short *)sndbuf)[i] = SDL_SwapLE16(((unsigned short *)sndbuf)[i]);
00134 }
00135
00136 this->Len += comp;
00137 }
00138
00139 if (this->Len < len) {
00140 len = this->Len;
00141 }
00142
00143 memcpy(buf, this->Buffer + this->Pos, len);
00144 this->Pos += len;
00145 this->Len -= len;
00146
00147 return len;
00148 }
00149
00150 CSampleWavStream::~CSampleWavStream()
00151 {
00152 this->Data.WavFile->close();
00153 delete this->Data.WavFile;
00154 delete[] this->Buffer;
00155 }
00156
00157 int CSampleWav::Read(void *buf, int len)
00158 {
00159 if (len > this->Len) {
00160 len = this->Len;
00161 }
00162
00163 memcpy(buf, this->Buffer + this->Pos, len);
00164 this->Pos += len;
00165 this->Len -= len;
00166
00167 return len;
00168 }
00169
00170 CSampleWav::~CSampleWav()
00171 {
00172 delete[] this->Buffer;
00173 }
00174
00175
00186 CSample *LoadWav(const std::string &name, int flags)
00187 {
00188 CSample *sample;
00189 WavData *data;
00190 CFile *f;
00191 WavChunk chunk;
00192 WavFMT wavfmt;
00193 unsigned int t;
00194
00195 f = new CFile;
00196 if (f->open(name.c_str(), CL_OPEN_READ) == -1) {
00197 printf("Can't open file `%s'\n", name.c_str());
00198 delete f;
00199 return NULL;
00200 }
00201 f->read(&chunk, sizeof(chunk));
00202
00203
00204
00205 chunk.Magic = SDL_SwapLE32(chunk.Magic);
00206 chunk.Length = SDL_SwapLE32(chunk.Length);
00207
00208 if (chunk.Magic != RIFF) {
00209 f->close();
00210 delete f;
00211 return NULL;
00212 }
00213
00214 f->read(&t, sizeof(t));
00215 t = SDL_SwapLE32(t);
00216 if (t != WAVE) {
00217 printf("Wrong magic %x (not %x)\n", t, WAVE);
00218 f->close();
00219 delete f;
00220 return NULL;
00221 }
00222
00223 f->read(&wavfmt, sizeof(wavfmt));
00224
00225
00226
00227 wavfmt.FMTchunk = SDL_SwapLE32(wavfmt.FMTchunk);
00228 wavfmt.FMTlength = SDL_SwapLE32(wavfmt.FMTlength);
00229 wavfmt.Encoding = SDL_SwapLE16(wavfmt.Encoding);
00230 wavfmt.Channels = SDL_SwapLE16(wavfmt.Channels);
00231 wavfmt.Frequency = SDL_SwapLE32(wavfmt.Frequency);
00232 wavfmt.ByteRate = SDL_SwapLE32(wavfmt.ByteRate);
00233 wavfmt.SampleSize = SDL_SwapLE16(wavfmt.SampleSize);
00234 wavfmt.BitsPerSample = SDL_SwapLE16(wavfmt.BitsPerSample);
00235
00236 if (wavfmt.FMTchunk != FMT) {
00237 printf("Wrong magic %x (not %x)\n", wavfmt.FMTchunk, FMT);
00238 f->close();
00239 delete f;
00240 return NULL;
00241 }
00242 if (wavfmt.FMTlength != 16 && wavfmt.FMTlength != 18) {
00243 printf("Wrong length %d (not %d)\n", wavfmt.FMTlength, 16);
00244 f->close();
00245 delete f;
00246 return NULL;
00247 }
00248
00249 if (wavfmt.FMTlength == 18) {
00250 if (f->read(&chunk, 2) != 2) {
00251 f->close();
00252 delete f;
00253 return NULL;
00254 }
00255 }
00256
00257
00258
00259
00260 if (wavfmt.Encoding != WAV_PCM_CODE) {
00261 printf("Unsupported encoding %d\n", wavfmt.Encoding);
00262 f->close();
00263 delete f;
00264 return NULL;
00265 }
00266 if (wavfmt.Channels != WAV_MONO && wavfmt.Channels != WAV_STEREO) {
00267 printf("Unsupported channels %d\n", wavfmt.Channels);
00268 f->close();
00269 delete f;
00270 return NULL;
00271 }
00272 if (wavfmt.SampleSize != 1 && wavfmt.SampleSize != 2 && wavfmt.SampleSize != 4) {
00273 printf("Unsupported sample size %d\n", wavfmt.SampleSize);
00274 f->close();
00275 delete f;
00276 return NULL;
00277 }
00278 if (wavfmt.BitsPerSample != 8 && wavfmt.BitsPerSample != 16) {
00279 printf("Unsupported bits per sample %d\n", wavfmt.BitsPerSample);
00280 f->close();
00281 delete f;
00282 return NULL;
00283 }
00284 Assert(wavfmt.Frequency == 44100 || wavfmt.Frequency == 22050 ||
00285 wavfmt.Frequency == 11025);
00286
00287
00288
00289
00290 if (flags & PlayAudioStream) {
00291 sample = new CSampleWavStream;
00292 ((CSampleWavStream *)sample)->Data.WavFile = f;
00293 data = &((CSampleWavStream *)sample)->Data;
00294 } else {
00295 sample = new CSampleWav;
00296 ((CSampleWav *)sample)->Data.WavFile = f;
00297 data = &((CSampleWav *)sample)->Data;
00298 }
00299 sample->Channels = (unsigned char)wavfmt.Channels;
00300 sample->SampleSize = wavfmt.SampleSize * 8 / sample->Channels;
00301 sample->Frequency = wavfmt.Frequency;
00302 sample->BitsPerSample = wavfmt.BitsPerSample;
00303 sample->Len = 0;
00304 sample->Pos = 0;
00305
00306 if (flags & PlayAudioStream) {
00307 data->ChunkRem = 0;
00308 sample->Buffer = new unsigned char[SOUND_BUFFER_SIZE];
00309 } else {
00310 int comp;
00311 int i;
00312 int rem;
00313 int read;
00314 int bufrem;
00315 char sndbuf[SOUND_BUFFER_SIZE];
00316
00317 sample->Buffer = NULL;
00318 read = 0;
00319 rem = 0;
00320 while (1) {
00321 if (!rem) {
00322
00323 comp = f->read(&chunk, sizeof(chunk));
00324
00325 if (!comp) {
00326
00327 break;
00328 }
00329
00330 chunk.Magic = SDL_SwapLE32(chunk.Magic);
00331 chunk.Length = SDL_SwapLE32(chunk.Length);
00332 if (chunk.Magic != DATA) {
00333 f->seek(chunk.Length, SEEK_CUR);
00334 continue;
00335 }
00336 rem = chunk.Length;
00337 }
00338
00339 bufrem = SOUND_BUFFER_SIZE;
00340 if (rem > bufrem) {
00341 read = bufrem;
00342 } else {
00343 read = rem;
00344 }
00345 rem -= read;
00346
00347 unsigned char *b = new unsigned char[sample->Len + read];
00348 Assert(b);
00349 memcpy(b, sample->Buffer, sample->Len);
00350 delete[] sample->Buffer;
00351 sample->Buffer = b;
00352
00353 comp = data->WavFile->read(sndbuf, read);
00354 Assert(comp == read);
00355
00356 if (sample->SampleSize == 16) {
00357 read >>= 1;
00358 for (i = 0; i < read; ++i) {
00359 ((unsigned short *)(sample->Buffer + sample->Pos + sample->Len))[i] =
00360 SDL_SwapLE16(((unsigned short *)sndbuf)[i]);
00361 }
00362 } else {
00363 memcpy((sample->Buffer + sample->Pos + sample->Len), sndbuf, comp);
00364 }
00365
00366 sample->Len += comp;
00367 }
00368
00369 data->WavFile->close();
00370 delete data->WavFile;
00371 }
00372
00373 return sample;
00374 }
00375