Add TXTH mpeg bytes-to-samples and tweaks

This commit is contained in:
bnnm 2019-03-11 01:22:49 +01:00
parent fa9d7e6cc1
commit fd9a33d2d0
4 changed files with 77 additions and 9 deletions

View File

@ -353,8 +353,9 @@ int riff_get_fact_skip_samples(STREAMFILE * streamFile, off_t start_offset);
size_t atrac3_bytes_to_samples(size_t bytes, int full_block_align);
size_t atrac3plus_bytes_to_samples(size_t bytes, int full_block_align);
size_t ac3_bytes_to_samples(size_t bytes, int full_block_align, int channels);
size_t aac_get_samples(STREAMFILE *streamFile, off_t start_offset, size_t bytes);
size_t mpeg_get_samples(STREAMFILE *streamFile, off_t start_offset, size_t bytes);
/* An internal struct to pass around and simulate a bitstream. */

View File

@ -1006,22 +1006,34 @@ fail:
/* ******************************************** */
size_t atrac3_bytes_to_samples(size_t bytes, int full_block_align) {
if (full_block_align <= 0) return 0;
/* ATRAC3 expects full block align since as is can mix joint stereo with mono blocks;
* so (full_block_align / channels) DOESN'T give the size of a single channel (uncommon in ATRAC3 though) */
return (bytes / full_block_align) * 1024;
}
size_t atrac3plus_bytes_to_samples(size_t bytes, int full_block_align) {
if (full_block_align <= 0) return 0;
/* ATRAC3plus expects full block align since as is can mix joint stereo with mono blocks;
* so (full_block_align / channels) DOESN'T give the size of a single channel (common in ATRAC3plus) */
return (bytes / full_block_align) * 2048;
}
size_t ac3_bytes_to_samples(size_t bytes, int full_block_align, int channels) {
if (full_block_align <= 0) return 0;
return (bytes / full_block_align) * 256 * channels;
}
size_t aac_get_samples(STREAMFILE *streamFile, off_t start_offset, size_t bytes) {
const int samples_per_frame = 1024; /* theoretically 960 exists in .MP4 so may need a flag */
int frames = 0;
off_t offset = start_offset;
off_t max_offset = start_offset + bytes;
if (!streamFile)
return 0;
if (max_offset > get_streamfile_size(streamFile))
max_offset = get_streamfile_size(streamFile);

View File

@ -302,5 +302,64 @@ fail:
return 0;
}
size_t mpeg_get_samples(STREAMFILE *streamFile, off_t start_offset, size_t bytes) {
off_t offset = start_offset;
off_t max_offset = start_offset + bytes;
int samples = 0;
mpeg_frame_info info;
size_t prev_size = 0;
int cbr_count = 0;
int is_vbr = 0;
if (!streamFile)
return 0;
if (max_offset > get_streamfile_size(streamFile))
max_offset = get_streamfile_size(streamFile);
/* MPEG may use VBR so must read all frames */
while (offset < max_offset) {
/* skip ID3v2 */
if ((read_32bitBE(offset+0x00, streamFile) & 0xFFFFFF00) == 0x49443300) { /* "ID3\0" */
size_t frame_size = 0;
uint8_t flags = read_8bit(offset+0x05, streamFile);
/* this is how it's officially read :/ */
frame_size += read_8bit(offset+0x06, streamFile) << 21;
frame_size += read_8bit(offset+0x07, streamFile) << 14;
frame_size += read_8bit(offset+0x08, streamFile) << 7;
frame_size += read_8bit(offset+0x09, streamFile) << 0;
frame_size += 0x0a;
if (flags & 0x10) /* footer? */
frame_size += 0x0a;
offset += frame_size;
continue;
}
/* this may fail with unknown ID3 tags */
if (!mpeg_get_frame_info(streamFile, offset, &info))
break;
if (prev_size && prev_size != info.frame_size) {
is_vbr = 1;
}
else if (!is_vbr) {
cbr_count++;
}
if (cbr_count >= 10) {
/* must be CBR, don't bother counting */
samples = (bytes / info.frame_size) * info.frame_samples;
break;
}
offset += info.frame_size;
prev_size = info.frame_size;
samples += info.frame_samples; /* header frames may be 0? */
}
return samples;
}
#endif

View File

@ -1174,24 +1174,21 @@ static int get_bytes_to_samples(txth_header * txth, uint32_t bytes) {
if (!txth->interleave) return 0;
return msadpcm_bytes_to_samples(bytes, txth->interleave, txth->channels);
case ATRAC3:
if (!txth->interleave) return 0;
return atrac3_bytes_to_samples(bytes, txth->interleave);
case ATRAC3PLUS:
if (!txth->interleave) return 0;
return atrac3plus_bytes_to_samples(bytes, txth->interleave);
case AAC:
if (!txth->streamBody) return 0;
return aac_get_samples(txth->streamBody, txth->start_offset, bytes);
case MPEG:
return mpeg_get_samples(txth->streamBody, txth->start_offset, bytes);
case AC3:
return ac3_bytes_to_samples(bytes, txth->interleave, txth->channels);
/* XMA bytes-to-samples is done at the end as the value meanings are a bit different */
case XMA1:
case XMA2:
return bytes; /* preserve */
case AC3:
if (!txth->interleave) return 0;
return bytes / txth->interleave * 256 * txth->channels;
case IMA:
case DVI_IMA:
return ima_bytes_to_samples(bytes, txth->channels);
@ -1210,7 +1207,6 @@ static int get_bytes_to_samples(txth_header * txth, uint32_t bytes) {
if (!txth->interleave) return 0;
return (bytes / txth->interleave) * (txth->interleave - 2) * 2;
case MPEG: /* a bit complex */
case FFMPEG: /* too complex, try after init */
default:
return 0;