mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-29 19:37:30 +01:00
Add TXTH mpeg bytes-to-samples and tweaks
This commit is contained in:
parent
fa9d7e6cc1
commit
fd9a33d2d0
@ -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. */
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user