int write_wav_header(FILE *file, int rate, int mapping_family, int channels, int fp) { int ret; int extensible; /* Multichannel files require a WAVEFORMATEXTENSIBLE header to declare the proper channel meanings. */ extensible = mapping_family == 1 && 3 <= channels && channels <= 8; /* >16 bit audio also requires WAVEFORMATEXTENSIBLE. */ extensible |= fp; ret = fprintf (file, "RIFF") >= 0; ret &= fwrite_le32 (0x7fffffff, file); ret &= fprintf (file, "WAVEfmt ") >= 0; ret &= fwrite_le32 (extensible ? 40 : 16, file); ret &= fwrite_le16 (extensible ? 0xfffe : (fp?3:1), file); ret &= fwrite_le16 (channels, file); ret &= fwrite_le32 (rate, file); ret &= fwrite_le32 ((fp?4:2)*channels*rate, file); ret &= fwrite_le16 ((fp?4:2)*channels, file); ret &= fwrite_le16 (fp?32:16, file); if(extensible) { static const unsigned char ksdataformat_subtype_pcm[16]= { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }; static const unsigned char ksdataformat_subtype_float[16]= { 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }; static const int wav_channel_masks[8] = { 1, /* 1.0 mono */ 1|2, /* 2.0 stereo */ 1|2|4, /* 3.0 channel ('wide') stereo */ 1|2|16|32, /* 4.0 discrete quadrophonic */ 1|2|4|16|32, /* 5.0 */ 1|2|4|8|16|32, /* 5.1 */ 1|2|4|8|256|512|1024, /* 6.1 */ 1|2|4|8|16|32|512|1024, /* 7.1 */ }; ret &= fwrite_le16 (22, file); ret &= fwrite_le16 (fp?32:16, file); ret &= fwrite_le32 (wav_channel_masks[channels-1], file); if (!fp) { ret &= fwrite (ksdataformat_subtype_pcm, 16, 1, file); } else { ret &= fwrite (ksdataformat_subtype_float, 16, 1, file); } } ret &= fprintf (file, "data") >= 0; ret &= fwrite_le32 (0x7fffffff, file); return !ret ? -1 : extensible ? 40 : 16; }
int main(int argc, char *argv[]) { const char *infile, *outfile; FILE *in, *out; static const uint8_t buf[4096]; size_t elems; uint8_t properties; uint32_t dictsize; uint64_t datasize; uint32_t magic = 0xfeed1281L; uint32_t reclength = 0; fpos_t reclengthpos; uint32_t loadaddress = 0; uint32_t type = 0x075a0201L; /* might be 7Z 2.1? */ uint32_t checksum = 0; uint32_t compsize = 0; fpos_t compsizepos; uint32_t datasize32 = 0; uint32_t datacrc32 = crc32(0, 0, 0); uint32_t entry = 0; if (argc != 5) usage(); /* "parse" command line */ loadaddress = strtoul(argv[1], 0, 0); entry = strtoul(argv[2], 0, 0); infile = argv[3]; outfile = argv[4]; in = fopen(infile, "rb"); if (!in) pexit("fopen"); out = fopen(outfile, "w+b"); if (!out) pexit("fopen"); /* read LZMA header */ if (fread_8(&properties, in)) pexit("fread"); if (fread_le32(&dictsize, in)) pexit("fread"); if (fread_le64(&datasize, in)) pexit("fread"); /* write EVA header */ if (fwrite_le32(magic, out)) pexit("fwrite"); if (fgetpos(out, &reclengthpos)) pexit("fgetpos"); if (fwrite_le32(reclength, out)) pexit("fwrite"); if (fwrite_le32(loadaddress, out)) pexit("fwrite"); if (fwrite_le32(type, out)) pexit("fwrite"); /* write EVA LZMA header */ if (fgetpos(out, &compsizepos)) pexit("fgetpos"); if (fwrite_le32(compsize, out)) pexit("fwrite"); /* XXX check length */ datasize32 = (uint32_t)datasize; if (fwrite_le32(datasize32, out)) pexit("fwrite"); if (fwrite_le32(datacrc32, out)) pexit("fwrite"); /* write modified LZMA header */ if (fwrite_8(properties, out)) pexit("fwrite"); if (fwrite_le32(dictsize, out)) pexit("fwrite"); if (fwrite_le32(0, out)) pexit("fwrite"); /* copy compressed data, calculate crc32 */ while (0 < (elems = fread(&buf, sizeof buf[0], sizeof buf, in))) { compsize += elems; if (elems != fwrite(&buf, sizeof buf[0], elems, out)) pexit("fwrite"); datacrc32 = crc32(datacrc32, buf, elems); } if (ferror(in)) pexit("fread"); fclose(in); /* re-write record length */ reclength = compsize + 24; if (fsetpos(out, &reclengthpos)) pexit("fsetpos"); if (fwrite_le32(reclength, out)) pexit("fwrite"); /* re-write EVA LZMA header including size and data crc */ if (fsetpos(out, &compsizepos)) pexit("fsetpos"); if (fwrite_le32(compsize, out)) pexit("fwrite"); if (fwrite_le32(datasize32, out)) pexit("fwrite"); if (fwrite_le32(datacrc32, out)) pexit("fwrite"); /* calculate record checksum */ checksum += reclength; checksum += loadaddress; checksum_add32(checksum, type); checksum_add32(checksum, compsize); checksum_add32(checksum, datasize32); checksum_add32(checksum, datacrc32); if (fseek(out, 0, SEEK_CUR)) pexit("fseek"); while (0 < (elems = fread(&buf, sizeof buf[0], sizeof buf, out))) { size_t i; for (i = 0; i < elems; ++i) checksum += buf[i]; } if (ferror(out)) pexit("fread"); if (fseek(out, 0, SEEK_CUR)) pexit("fseek"); checksum = ~checksum + 1; if (fwrite_le32(checksum, out)) pexit("fwrite"); /* write entry record */ if (fwrite_le32(0, out)) pexit("fwrite"); if (fwrite_le32(entry, out)) pexit("fwrite"); if (fclose(out)) pexit("fclose"); return 0; }