diff --git a/src/coding/coding.h b/src/coding/coding.h index 62d8f78a..d2e25c0b 100644 --- a/src/coding/coding.h +++ b/src/coding/coding.h @@ -163,9 +163,10 @@ void seek_ffmpeg(VGMSTREAM *vgmstream, int32_t num_sample); void ffmpeg_set_skip_samples(ffmpeg_codec_data * data, int skip_samples); int ffmpeg_make_riff_atrac3(uint8_t * buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int block_align, int joint_stereo, int encoder_delay); +int ffmpeg_make_riff_xma1(uint8_t * buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate); int ffmpeg_make_riff_xma2(uint8_t * buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int block_count, int block_size); int ffmpeg_make_riff_xma2_from_fmt(uint8_t * buf, size_t buf_size, off_t fmt_offset, size_t fmt_size, size_t data_size, STREAMFILE *streamFile, int big_endian); - +int ffmpeg_make_riff_xwma(uint8_t * buf, size_t buf_size, int codec, size_t sample_count, size_t data_size, int channels, int sample_rate, int avg_bps, int block_align); #endif #endif /*_CODING_H*/ diff --git a/src/coding/ffmpeg_decoder.c b/src/coding/ffmpeg_decoder.c index f1026af1..a0482b7f 100644 --- a/src/coding/ffmpeg_decoder.c +++ b/src/coding/ffmpeg_decoder.c @@ -328,13 +328,10 @@ void ffmpeg_set_skip_samples(ffmpeg_codec_data * data, int skip_samples) { /* ******************************************** */ /* FAKE RIFF HELPERS */ /* ******************************************** */ +/* All helpers copy a RIFF header to buf and returns the number of bytes in buf or -1 when buf is not big enough */ + static int ffmpeg_fmt_chunk_swap_endian(uint8_t * chunk, uint16_t codec); -/** - * Copies a ATRAC3 riff to buf - * - * returns number of bytes in buf or -1 when buf is not big enough - */ int ffmpeg_make_riff_atrac3(uint8_t * buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int block_align, int joint_stereo, int encoder_delay) { uint16_t codec_ATRAC3 = 0x0270; size_t riff_size = 4+4+ 4 + 0x28 + 0x10 + 4+4; @@ -374,57 +371,89 @@ int ffmpeg_make_riff_atrac3(uint8_t * buf, size_t buf_size, size_t sample_count, return riff_size; } -/** - * Copies a XMA2 riff to buf - * - * returns number of bytes in buf or -1 when buf is not big enough - */ +int ffmpeg_make_riff_xma1(uint8_t * buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate) { + uint16_t codec_XMA1 = 0x0165; + size_t riff_size; + int streams, i; + + streams = (channels + 1) / 2; + + riff_size = 4+4+ 4 + 0x14 + 0x14*streams + 4+4; + + if (buf_size < riff_size) + return -1; + + memcpy(buf+0x00, "RIFF", 4); + put_32bitLE(buf+0x04, (int32_t)(riff_size-4-4 + data_size)); /* riff size */ + memcpy(buf+0x08, "WAVE", 4); + + memcpy(buf+0x0c, "fmt ", 4); + put_32bitLE(buf+0x10, 0xc + 0x14*streams);/*fmt size*/ + put_16bitLE(buf+0x14, codec_XMA1); + put_16bitLE(buf+0x16, 16); /* bits per sample */ + put_16bitLE(buf+0x18, 0x10D6); /* encoder options */ + put_16bitLE(buf+0x1a, 0); /* largest stream skip (wrong, unneeded) */ + put_16bitLE(buf+0x1c, streams); /* number of streams */ + put_8bit (buf+0x1e, 0); /* loop count */ + put_8bit (buf+0x1f, 2); /* version */ + + for (i = 0; i < streams; i++) { + int stream_channels; + uint32_t speakers; + off_t off = 0x20 + 0x14*i;/* stream riff offset */ + + /* with odd channels the last stream is mono */ + stream_channels = channels / streams + (channels%2 != 0 && i+1 != streams ? 1 : 0); + VGM_LOG("sch=%i, %i, %i\n", stream_channels, channels / streams, (channels%2 != 0 && i+1 != streams ? 1 : 0)); + switch(i) { /* per stream, values from xmaencode */ + case 0: speakers = stream_channels == 1 ? 0x0001 : 0x0201; break;/* L R */ + case 1: speakers = stream_channels == 1 ? 0x0004 : 0x0804; break;/* C LFE */ + case 2: speakers = stream_channels == 1 ? 0x0040 : 0x8040; break;/* LB RB */ + case 3: speakers = stream_channels == 1 ? 0x0000 : 0x0000; break;/* somehow empty (maybe should use 0x2010 LS RS) */ + default: speakers = 0; + } + + put_32bitLE(buf+off+0x00, sample_rate*stream_channels / sizeof(sample)); /* average bytes per second (wrong, unneeded) */ + put_32bitLE(buf+off+0x04, sample_rate); + put_32bitLE(buf+off+0x08, 0); /* loop start */ + put_32bitLE(buf+off+0x0c, 0); /* loop end */ + put_8bit (buf+off+0x10, 0); /* loop subframe */ + put_8bit (buf+off+0x11, channels); + put_16bitLE(buf+off+0x12, speakers); + } + + memcpy(buf+riff_size-4-4, "data", 4); + put_32bitLE(buf+riff_size-4, data_size); /* data size */ + + return riff_size; +} + int ffmpeg_make_riff_xma2(uint8_t * buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int block_count, int block_size) { uint16_t codec_XMA2 = 0x0166; size_t riff_size = 4+4+ 4 + 0x3c + 4+4; size_t bytecount; - uint32_t streams = 0; - uint32_t speakers = 0; /* see audiodefs.h */ + int streams; + uint32_t speakers; + + /* info from xma2defs.h, xact3wb.h and audiodefs.h */ + streams = (channels + 1) / 2; + switch (channels) { + case 1: speakers = 0x04; break; /* 1.0: FC */ + case 2: speakers = 0x01 | 0x02; break; /* 2.0: FL FR */ + case 3: speakers = 0x01 | 0x02 | 0x08; break; /* 2.1: FL FR LF */ + case 4: speakers = 0x01 | 0x02 | 0x10 | 0x20; break; /* 4.0: FL FR BL BR */ + case 5: speakers = 0x01 | 0x02 | 0x08 | 0x10 | 0x20; break; /* 4.1: FL FR LF BL BR */ + case 6: speakers = 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20; break; /* 5.1: FL FR FC LF BL BR */ + case 7: speakers = 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x0100; break; /* 6.1: FL FR FC LF BL BR BC */ + case 8: speakers = 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80; break; /* 7.1: FL FR FC LF BL BR FLC FRC */ + default: speakers = 0; break; + } if (buf_size < riff_size) return -1; bytecount = sample_count * channels * sizeof(sample); - /* todo untested */ - switch (channels) { - case 1: - streams = 1; - speakers = 0x00000004; /* FC */ - break; - case 2: - streams = 1; - speakers = 0x00000001 | 0x00000002; /* FL FR */ - break; - case 3: - streams = 3; - speakers = 0x00000001 | 0x00000002 | 0x00000004; /* FL FC FR */ - break; - case 4: - streams = 2; - speakers = 0x00000001 | 0x00000002 | 0x00000010 | 0x00000020; /* FL FR BL BR */ - break; - case 5: - streams = 3; - speakers = 0x00000001 | 0x00000002 | 0x00000010 | 0x00000020 | 0x00000004; /* FL C FR BL BR*/ - break; - case 6: - streams = 3; - speakers = 0x00000001 | 0x00000002 | 0x00000010 | 0x00000020 | 0x00000200 | 0x00000400; /* FL FR BL BR SL SR */ - break; - default: - streams = 1; - speakers = 0x80000000; - break; - } - - /*memset(buf,0, sizeof(uint8_t) * fmt_size);*/ - memcpy(buf+0x00, "RIFF", 4); put_32bitLE(buf+0x04, (int32_t)(riff_size-4-4 + data_size)); /* riff size */ memcpy(buf+0x08, "WAVE", 4); @@ -434,9 +463,9 @@ int ffmpeg_make_riff_xma2(uint8_t * buf, size_t buf_size, size_t sample_count, s put_16bitLE(buf+0x14, codec_XMA2); put_16bitLE(buf+0x16, channels); put_32bitLE(buf+0x18, sample_rate); - put_32bitLE(buf+0x1c, sample_rate*channels / sizeof(sample)); /* average bytes per second (wrong) */ + put_32bitLE(buf+0x1c, sample_rate*channels / sizeof(sample)); /* average bytes per second (wrong unneeded) */ put_16bitLE(buf+0x20, (int16_t)(channels*sizeof(sample))); /* block align */ - put_16bitLE(buf+0x22, sizeof(sample)*8); /* bits per sample */ + put_16bitLE(buf+0x22, 16); /* bits per sample */ put_16bitLE(buf+0x24, 0x22); /* extra data size */ put_16bitLE(buf+0x26, streams); /* number of streams */ @@ -450,7 +479,7 @@ int ffmpeg_make_riff_xma2(uint8_t * buf, size_t buf_size, size_t sample_count, s put_32bitLE(buf+0x40, 0); /* loop length */ put_8bit(buf+0x44, 0); /* loop count */ put_8bit(buf+0x45, 4); /* encoder version */ - put_16bitLE(buf+0x46, block_count); /* blocks count = entried in seek table */ + put_16bitLE(buf+0x46, block_count); /* blocks count = entries in seek table */ memcpy(buf+0x48, "data", 4); put_32bitLE(buf+0x4c, data_size); /* data size */ @@ -458,12 +487,6 @@ int ffmpeg_make_riff_xma2(uint8_t * buf, size_t buf_size, size_t sample_count, s return riff_size; } - -/** - * Copies a XMA2 riff to buf from a fmt chunk offset - * - * returns number of bytes in buf or -1 when buf is not big enough - */ int ffmpeg_make_riff_xma2_from_fmt(uint8_t * buf, size_t buf_size, off_t fmt_offset, size_t fmt_size, size_t data_size, STREAMFILE *streamFile, int big_endian) { size_t riff_size = 4+4+ 4 + 4+4+fmt_size + 4+4; uint8_t chunk[100]; @@ -493,13 +516,36 @@ fail: return -1; } -/** - * Swaps endianness - * - * returns 0 on error - */ +int ffmpeg_make_riff_xwma(uint8_t * buf, size_t buf_size, int codec, size_t sample_count, size_t data_size, int channels, int sample_rate, int avg_bps, int block_align) { + size_t riff_size = 4+4+ 4 + 0x1a + 4+4; + + if (buf_size < riff_size) + return -1; + + memcpy(buf+0x00, "RIFF", 4); + put_32bitLE(buf+0x04, (int32_t)(riff_size-4-4 + data_size)); /* riff size */ + memcpy(buf+0x08, "XWMA", 4); + + memcpy(buf+0x0c, "fmt ", 4); + put_32bitLE(buf+0x10, 0x12);/*fmt size*/ + put_16bitLE(buf+0x14, codec); + put_16bitLE(buf+0x16, channels); + put_32bitLE(buf+0x18, sample_rate); + put_32bitLE(buf+0x1c, avg_bps); /* average bits per second, somehow vital for XWMA */ + put_16bitLE(buf+0x20, block_align); /* block align */ + put_16bitLE(buf+0x22, 16); /* bits per sample */ + put_16bitLE(buf+0x24, 0); /* unk */ + /* here goes the "dpds" table, but it's not needed by FFmpeg */ + + memcpy(buf+0x26, "data", 4); + put_32bitLE(buf+0x2a, data_size); /* data size */ + + return riff_size; +} + + static int ffmpeg_fmt_chunk_swap_endian(uint8_t * chunk, uint16_t codec) { - if (codec != 0x166) + if (codec != 0x166)/* XMA2 */ goto fail; put_16bitLE(chunk + 0x00, get_16bitBE(chunk + 0x00));/*wFormatTag*/