1 /* 2 * Schism Tracker - a cross-platform Impulse Tracker clone 3 * copyright (c) 2003-2005 Storlek <storlek@rigelseven.com> 4 * copyright (c) 2005-2008 Mrs. Brisby <mrs.brisby@nimh.org> 5 * copyright (c) 2009 Storlek & Mrs. Brisby 6 * copyright (c) 2010-2012 Storlek 7 * URL: http://schismtracker.org/ 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 */ 23 24 #define NEED_BYTESWAP 25 #include "headers.h" 26 #include "fmt.h" 27 #include "it.h" 28 #include "disko.h" 29 #include "sndfile.h" 30 #include "log.h" 31 #include <stdint.h> 32 33 #define WAVE_FORMAT_PCM 0x0001 34 #define WAVE_FORMAT_IEEE_FLOAT 0x0003 // IEEE float 35 #define WAVE_FORMAT_ALAW 0x0006 // 8-bit ITU-T G.711 A-law 36 #define WAVE_FORMAT_MULAW 0x0007 // 8-bit ITU-T G.711 µ-law 37 #define WAVE_FORMAT_EXTENSIBLE 0xFFFE 38 39 // Standard IFF chunks IDs 40 #define IFFID_FORM 0x4d524f46 41 #define IFFID_RIFF 0x46464952 42 #define IFFID_WAVE 0x45564157 43 #define IFFID_LIST 0x5453494C 44 #define IFFID_INFO 0x4F464E49 45 46 // IFF Info fields 47 #define IFFID_ICOP 0x504F4349 48 #define IFFID_IART 0x54524149 49 #define IFFID_IPRD 0x44525049 50 #define IFFID_INAM 0x4D414E49 51 #define IFFID_ICMT 0x544D4349 52 #define IFFID_IENG 0x474E4549 53 #define IFFID_ISFT 0x54465349 54 #define IFFID_ISBJ 0x4A425349 55 #define IFFID_IGNR 0x524E4749 56 #define IFFID_ICRD 0x44524349 57 58 // Wave IFF chunks IDs 59 #define IFFID_wave 0x65766177 60 #define IFFID_fmt 0x20746D66 61 #define IFFID_wsmp 0x706D7377 62 #define IFFID_pcm 0x206d6370 63 #define IFFID_data 0x61746164 64 #define IFFID_smpl 0x6C706D73 65 #define IFFID_xtra 0x61727478 66 67 68 #pragma pack(push, 1) 69 typedef struct { 70 uint32_t id_RIFF; // "RIFF" 71 uint32_t filesize; // file length-8 72 uint32_t id_WAVE; 73 } wave_file_header_t; 74 75 76 77 typedef struct { 78 uint16_t format; // 1 79 uint16_t channels; // 1:mono, 2:stereo 80 uint32_t freqHz; // sampling freq 81 uint32_t bytessec; // bytes/sec=freqHz*samplesize 82 uint16_t samplesize; // sizeof(sample) 83 uint16_t bitspersample; // bits per sample (8/16) 84 } wave_format_t; 85 86 87 typedef struct { 88 uint32_t id; 89 uint32_t length; 90 } wave_chunk_prefix_t; 91 92 93 typedef struct { 94 wave_format_t fmt; // Format 95 wave_chunk_prefix_t data; // Data header 96 uint8_t *buf; 97 } wave_file_t; 98 #pragma pack(pop) 99 100 /* --------------------------------------------------------------------------------------------------------- */ 101 102 static int wav_load(wave_file_t *f, const uint8_t *data, size_t len) 103 { 104 wave_file_header_t phdr; 105 size_t offset; 106 int have_format = 0; 107 108 if (len < sizeof(wave_file_header_t)) { 109 return 0; 110 } 111 112 memcpy(&phdr, data, sizeof(wave_file_header_t)); 113 #if WORDS_BIGENDIAN 114 phdr.id_RIFF = bswapLE32(phdr.id_RIFF); 115 phdr.filesize = bswapLE32(phdr.filesize); 116 phdr.id_WAVE = bswapLE32(phdr.id_WAVE); 117 #endif 118 119 if (phdr.id_RIFF != IFFID_RIFF || 120 phdr.id_WAVE != IFFID_WAVE) { 121 return 0; 122 } 123 124 offset = sizeof(wave_file_header_t); 125 126 while (1) { 127 wave_chunk_prefix_t c; 128 memcpy(&c, data + offset, sizeof(wave_chunk_prefix_t)); 129 130 #if WORDS_BIGENDIAN 131 c.id = bswapLE32(c.id); 132 c.length = bswapLE32(c.length); 133 #endif 134 offset += sizeof(wave_chunk_prefix_t); 135 136 if (offset + c.length > len) { 137 log_appendf(4, "Corrupt WAV file. Chunk points outside of WAV file [%lu + %u > %lu]\n", 138 (unsigned long) offset, c.length, (unsigned long) len); 139 return 0; 140 } 141 142 switch (c.id) { 143 case IFFID_fmt: { 144 if (have_format) { 145 log_appendf(4, "Corrupt WAV file. Found multiple format headers.\n"); 146 return 0; 147 } 148 149 have_format = 1; 150 memcpy(&f->fmt, data + offset, sizeof(wave_format_t)); 151 #if WORDS_BIGENDIAN 152 f->fmt.format = bswapLE16(f->fmt.format); 153 f->fmt.channels = bswapLE16(f->fmt.channels); 154 f->fmt.freqHz = bswapLE32(f->fmt.freqHz); 155 f->fmt.bytessec = bswapLE32(f->fmt.bytessec); 156 f->fmt.samplesize = bswapLE16(f->fmt.samplesize); 157 f->fmt.bitspersample = bswapLE16(f->fmt.bitspersample); 158 #endif 159 break; 160 } 161 162 case IFFID_data: 163 if (!have_format) { 164 log_appendf(4, "WAV file did not specify format before data\n"); 165 return 0; 166 } 167 168 memcpy(&f->data, &c, sizeof(wave_chunk_prefix_t)); 169 f->buf = (uint8_t *)(data + offset); 170 return 1; 171 } 172 173 offset += c.length; 174 175 if (offset == len) 176 break; 177 } 178 179 return 1; 180 } 181 182 /* --------------------------------------------------------------------------------------------------------- */ 183 184 int fmt_wav_load_sample(const uint8_t *data, size_t len, song_sample_t *smp) 185 { 186 wave_file_t f; 187 uint32_t flags; 188 189 if (!wav_load(&f, data, len)) 190 return 0; 191 192 if (f.fmt.format != WAVE_FORMAT_PCM || 193 !f.fmt.freqHz || 194 (f.fmt.channels != 1 && f.fmt.channels != 2)) 195 return 0; 196 197 smp->flags = 0; // flags are set by csf_read_sample 198 flags = 0; 199 200 // endianness 201 flags = SF_LE; 202 // channels 203 flags |= (f.fmt.channels == 2) ? SF_SI : SF_M; // interleaved stereo 204 // bit width 205 switch (f.fmt.bitspersample) { 206 case 8: flags |= SF_8; break; 207 case 16: flags |= SF_16; break; 208 case 24: flags |= SF_24; break; 209 case 32: flags |= SF_32; break; 210 default: return 0; // unsupported 211 } 212 // encoding (8-bit wav is unsigned, everything else is signed -- yeah, it's stupid) 213 flags |= (f.fmt.bitspersample == 8) ? SF_PCMU : SF_PCMS; 214 215 smp->volume = 64 * 4; 216 smp->global_volume = 64; 217 smp->c5speed = f.fmt.freqHz; 218 smp->length = f.data.length / ((f.fmt.bitspersample / 8) * f.fmt.channels); 219 220 return csf_read_sample((song_sample_t *)smp, flags, (const char *) f.buf, f.data.length); 221 } 222 223 int fmt_wav_read_info(dmoz_file_t *file, const uint8_t *data, size_t length) 224 { 225 wave_file_t f; 226 227 if (!wav_load(&f, data, length)) 228 return 0; 229 else if (f.fmt.format != WAVE_FORMAT_PCM || 230 !f.fmt.freqHz || 231 (f.fmt.channels != 1 && f.fmt.channels != 2) || 232 (f.fmt.bitspersample != 8 && f.fmt.bitspersample != 16 && 233 f.fmt.bitspersample != 24 && f.fmt.bitspersample != 32)) 234 return 0; 235 236 file->smp_flags = 0; 237 238 if (f.fmt.channels == 2) 239 file->smp_flags |= CHN_STEREO; 240 241 if (f.fmt.bitspersample == 16) 242 file->smp_flags |= CHN_16BIT; 243 244 file->smp_speed = f.fmt.freqHz; 245 file->smp_length = f.data.length / ((f.fmt.bitspersample / 8) * f.fmt.channels); 246 247 file->description = "IBM/Microsoft RIFF Audio"; 248 file->type = TYPE_SAMPLE_PLAIN; 249 file->smp_filename = file->base; 250 return 1; 251 } 252 253 /* --------------------------------------------------------------------------------------------------------- */ 254 /* wav is like aiff's retarded cousin */ 255 256 struct wav_writedata { 257 long data_size; // seek position for writing data size (in bytes) 258 size_t numbytes; // how many bytes have been written 259 int bps; // bytes per sample 260 int swap; // should be byteswapped? 261 }; 262 263 static int wav_header(disko_t *fp, int bits, int channels, int rate, size_t length, 264 struct wav_writedata *wwd /* out */) 265 { 266 int16_t s; 267 uint32_t ul; 268 int bps = 1; 269 270 bps *= ((bits + 7) / 8) * channels; 271 272 /* write a very large size for now */ 273 disko_write(fp, "RIFF\377\377\377\377WAVEfmt ", 16); 274 ul = bswapLE32(16); // fmt chunk size 275 disko_write(fp, &ul, 4); 276 s = bswapLE16(1); // linear pcm 277 disko_write(fp, &s, 2); 278 s = bswapLE16(channels); // number of channels 279 disko_write(fp, &s, 2); 280 ul = bswapLE32(rate); // sample rate 281 disko_write(fp, &ul, 4); 282 ul = bswapLE32(bps * rate); // "byte rate" (why?! I have no idea) 283 disko_write(fp, &ul, 4); 284 s = bswapLE16(bps); // (oh, come on! the format already stores everything needed to calculate this!) 285 disko_write(fp, &s, 2); 286 s = bswapLE16(bits); // bits per sample 287 disko_write(fp, &s, 2); 288 289 disko_write(fp, "data", 4); 290 if (wwd) 291 wwd->data_size = disko_tell(fp); 292 ul = bswapLE32(bps * length); 293 disko_write(fp, &ul, 4); 294 295 return bps; 296 } 297 298 int fmt_wav_save_sample(disko_t *fp, song_sample_t *smp) 299 { 300 int bps; 301 uint32_t ul; 302 uint32_t flags = SF_LE; 303 flags |= (smp->flags & CHN_16BIT) ? (SF_16 | SF_PCMS) : (SF_8 | SF_PCMU); 304 flags |= (smp->flags & CHN_STEREO) ? SF_SI : SF_M; 305 306 bps = wav_header(fp, (smp->flags & CHN_16BIT) ? 16 : 8, (smp->flags & CHN_STEREO) ? 2 : 1, 307 smp->c5speed, smp->length, NULL); 308 309 if (csf_write_sample(fp, smp, flags, UINT32_MAX) != smp->length * bps) { 310 log_appendf(4, "WAV: unexpected data size written"); 311 return SAVE_INTERNAL_ERROR; 312 } 313 314 /* fix the length in the file header */ 315 ul = disko_tell(fp) - 8; 316 ul = bswapLE32(ul); 317 disko_seek(fp, 4, SEEK_SET); 318 disko_write(fp, &ul, 4); 319 320 return SAVE_SUCCESS; 321 } 322 323 324 int fmt_wav_export_head(disko_t *fp, int bits, int channels, int rate) 325 { 326 struct wav_writedata *wwd = malloc(sizeof(struct wav_writedata)); 327 if (!wwd) 328 return DW_ERROR; 329 fp->userdata = wwd; 330 wwd->bps = wav_header(fp, bits, channels, rate, ~0, wwd); 331 wwd->numbytes = 0; 332 #if WORDS_BIGENDIAN 333 wwd->swap = (bits > 8); 334 #else 335 wwd->swap = 0; 336 #endif 337 338 return DW_OK; 339 } 340 341 int fmt_wav_export_body(disko_t *fp, const uint8_t *data, size_t length) 342 { 343 struct wav_writedata *wwd = fp->userdata; 344 345 if (length % wwd->bps) { 346 log_appendf(4, "WAV export: received uneven length"); 347 return DW_ERROR; 348 } 349 350 wwd->numbytes += length; 351 352 if (wwd->swap) { 353 const int16_t *ptr = (const int16_t *) data; 354 uint16_t v; 355 356 length /= 2; 357 while (length--) { 358 v = *ptr; 359 v = bswapLE16(v); 360 disko_write(fp, &v, 2); 361 ptr++; 362 } 363 } else { 364 disko_write(fp, data, length); 365 } 366 367 return DW_OK; 368 } 369 370 int fmt_wav_export_silence(disko_t *fp, long bytes) 371 { 372 struct wav_writedata *wwd = fp->userdata; 373 wwd->numbytes += bytes; 374 375 disko_seek(fp, bytes, SEEK_CUR); 376 return DW_OK; 377 } 378 379 int fmt_wav_export_tail(disko_t *fp) 380 { 381 struct wav_writedata *wwd = fp->userdata; 382 uint32_t ul; 383 384 /* fix the length in the file header */ 385 ul = disko_tell(fp) - 8; 386 ul= bswapLE32(ul); 387 disko_seek(fp, 4, SEEK_SET); 388 disko_write(fp, &ul, 4); 389 390 /* write the other lengths */ 391 disko_seek(fp, wwd->data_size, SEEK_SET); 392 ul = bswapLE32(wwd->numbytes); 393 disko_write(fp, &ul, 4); 394 395 free(wwd); 396 397 return DW_OK; 398 } 399 400