mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-29 00:34:33 +01:00
Adjust MSF samples and use mpg123 over FFmpeg
Don't adjust loops to frame boundaries since offsets are always aligned and MSF only does CBR. There was a minor bug getting samples: FFmpeg was parsing the MSF and would add its header to the bitrate, which was used for calcs. Now FFmpeg only sees the MP3 data. Use mpg123 if available too since it's easier to setup in non-Windows builds (no audible differences otherwise).
This commit is contained in:
parent
531e8dc9b8
commit
467f7d0b3d
@ -1,6 +1,5 @@
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
#include "../util.h"
|
||||
|
||||
/* MSF - Sony's PS3 SDK format (MultiStream File) */
|
||||
VGMSTREAM * init_vgmstream_ps3_msf(STREAMFILE *streamFile) {
|
||||
@ -11,10 +10,12 @@ VGMSTREAM * init_vgmstream_ps3_msf(STREAMFILE *streamFile) {
|
||||
int loop_flag = 0, channel_count;
|
||||
|
||||
|
||||
/* check extension, case insensitive (.at3: Silent Hill HD Collection, .mp3: Darkstalkers Resurrection) */
|
||||
if (!check_extensions(streamFile,"msf,at3,mp3")) goto fail;
|
||||
/* checks */
|
||||
/* .msf: standard, .at3: Silent Hill HD Collection, .mp3: Darkstalkers Resurrection */
|
||||
if (!check_extensions(streamFile,"msf,at3,mp3"))
|
||||
goto fail;
|
||||
|
||||
/* "WMSF" variation with a mini header over the MSFC header, same extension */
|
||||
/* "WMSF" variation with a mini header over the MSFC header [Dai-2-Ji Super Robot Generations (PS3)] */
|
||||
if (read_32bitBE(0x00,streamFile) == 0x574D5346) {
|
||||
header_offset = 0x10;
|
||||
}
|
||||
@ -35,7 +36,7 @@ VGMSTREAM * init_vgmstream_ps3_msf(STREAMFILE *streamFile) {
|
||||
/* byte flags, not in MSFv1 or v2
|
||||
* 0x01/02/04/08: loop marker 0/1/2/3
|
||||
* 0x10: resample options (force 44/48khz)
|
||||
* 0x20: VBR MP3
|
||||
* 0x20: VBR MP3 source (changed into simplified 0x1a1 CBR)
|
||||
* 0x40: joint stereo MP3 (apparently interleaved stereo for other formats)
|
||||
* 0x80+: (none/reserved) */
|
||||
flags = read_32bitBE(header_offset+0x14,streamFile);
|
||||
@ -57,7 +58,7 @@ VGMSTREAM * init_vgmstream_ps3_msf(STREAMFILE *streamFile) {
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
/* Sample rate hack for strange MSFv1 files that don't have a specified frequency */
|
||||
/* sample rate hack for strange MSFv1 files that don't have it */
|
||||
vgmstream->sample_rate = read_32bitBE(header_offset+0x10,streamFile);
|
||||
if (vgmstream->sample_rate == 0x00000000) /* PS ADPCM only? */
|
||||
vgmstream->sample_rate = 48000;
|
||||
@ -65,43 +66,43 @@ VGMSTREAM * init_vgmstream_ps3_msf(STREAMFILE *streamFile) {
|
||||
vgmstream->meta_type = meta_PS3_MSF;
|
||||
|
||||
switch (codec_id) {
|
||||
case 0x0: /* PCM (Big Endian) */
|
||||
case 0x1: { /* PCM (Little Endian) */
|
||||
case 0x00: /* PCM (Big Endian) */
|
||||
case 0x01: { /* PCM (Little Endian) [Smash Cars (PS3)] */
|
||||
vgmstream->coding_type = codec_id==0 ? coding_PCM16BE : coding_PCM16LE;
|
||||
vgmstream->layout_type = channel_count == 1 ? layout_none : layout_interleave;
|
||||
vgmstream->interleave_block_size = 2;
|
||||
|
||||
vgmstream->num_samples = data_size/2/channel_count;
|
||||
vgmstream->num_samples = pcm_bytes_to_samples(data_size, channel_count,16);
|
||||
if (loop_flag){
|
||||
vgmstream->loop_start_sample = loop_start/2/channel_count;
|
||||
vgmstream->loop_end_sample = loop_end/2/channel_count;
|
||||
vgmstream->loop_start_sample = pcm_bytes_to_samples(loop_start, channel_count,16);
|
||||
vgmstream->loop_end_sample = pcm_bytes_to_samples(loop_end, channel_count,16);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x2: { /* PCM 32 (Float) */
|
||||
goto fail; //probably unused/spec only
|
||||
case 0x02: { /* PCM 32 (Float) */
|
||||
goto fail; /* probably unused/spec only */
|
||||
}
|
||||
|
||||
case 0x3: { /* PS ADPCM */
|
||||
case 0x03: { /* PS ADPCM [Smash Cars (PS3)] */
|
||||
vgmstream->coding_type = coding_PSX;
|
||||
vgmstream->layout_type = channel_count == 1 ? layout_none : layout_interleave;
|
||||
vgmstream->interleave_block_size = 0x10;
|
||||
|
||||
vgmstream->num_samples = data_size*28/16/channel_count;
|
||||
vgmstream->num_samples = ps_bytes_to_samples(data_size, channel_count);
|
||||
if (loop_flag) {
|
||||
vgmstream->loop_start_sample = loop_start*28/16/channel_count;
|
||||
vgmstream->loop_end_sample = loop_end*28/16/channel_count;
|
||||
vgmstream->loop_start_sample = ps_bytes_to_samples(loop_start,channel_count);
|
||||
vgmstream->loop_end_sample = ps_bytes_to_samples(loop_end,channel_count);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
case 0x4: /* ATRAC3 low (66 kbps, frame size 96, Joint Stereo) */
|
||||
case 0x5: /* ATRAC3 mid (105 kbps, frame size 152) */
|
||||
case 0x6: { /* ATRAC3 high (132 kbps, frame size 192) */
|
||||
case 0x04: /* ATRAC3 low (66 kbps, frame size 96, Joint Stereo) [Silent Hill HD (PS3)] */
|
||||
case 0x05: /* ATRAC3 mid (105 kbps, frame size 152) [Atelier Rorona (PS3)] */
|
||||
case 0x06: { /* ATRAC3 high (132 kbps, frame size 192) [Tekken Tag Tournament HD (PS3)] */
|
||||
ffmpeg_codec_data *ffmpeg_data = NULL;
|
||||
uint8_t buf[100];
|
||||
int32_t bytes, block_size, encoder_delay, joint_stereo;
|
||||
@ -141,67 +142,55 @@ VGMSTREAM * init_vgmstream_ps3_msf(STREAMFILE *streamFile) {
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
case 0x7: { /* MPEG (LAME MP3 of any quality) */
|
||||
/* delegate to FFMpeg, it can parse MSF files */
|
||||
ffmpeg_codec_data *ffmpeg_data = init_ffmpeg_offset(streamFile, header_offset, streamFile->get_size(streamFile) );
|
||||
#if defined(VGM_USE_FFMPEG) && !defined(VGM_USE_MPEG)
|
||||
case 0x07: { /* MPEG (CBR LAME MP3) [Dengeki Bunko Fighting Climax (PS3)] */
|
||||
ffmpeg_codec_data *ffmpeg_data = NULL;
|
||||
|
||||
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset, streamFile->get_size(streamFile) );
|
||||
if ( !ffmpeg_data ) goto fail;
|
||||
vgmstream->codec_data = ffmpeg_data;
|
||||
vgmstream->coding_type = coding_FFmpeg;
|
||||
vgmstream->layout_type = layout_none;
|
||||
|
||||
/* vgmstream->num_samples = ffmpeg_data->totalSamples; */ /* duration may not be set/inaccurate */
|
||||
vgmstream->num_samples = (int64_t)data_size * ffmpeg_data->sampleRate * 8 / ffmpeg_data->bitrate;
|
||||
if (loop_flag) {
|
||||
//todo properly apply encoder delay, which seems to vary between 1152 (1f), 528, 576 or 528+576
|
||||
int frame_size = ffmpeg_data->frameSize;
|
||||
vgmstream->loop_start_sample = (int64_t)loop_start * ffmpeg_data->sampleRate * 8 / ffmpeg_data->bitrate;
|
||||
vgmstream->loop_start_sample -= vgmstream->loop_start_sample==frame_size ? frame_size
|
||||
: vgmstream->loop_start_sample % frame_size;
|
||||
vgmstream->loop_end_sample = (int64_t)loop_end * ffmpeg_data->sampleRate * 8 / ffmpeg_data->bitrate;
|
||||
vgmstream->loop_end_sample -= vgmstream->loop_end_sample==frame_size ? frame_size
|
||||
: vgmstream->loop_end_sample % frame_size;
|
||||
/* loops are always CBR frame beginnings */
|
||||
}
|
||||
|
||||
/* encoder delay varies between 1152 (1f), 528, 576, etc; probably not actually skipped */
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if defined(VGM_USE_MPEG) && !defined(VGM_USE_FFMPEG)
|
||||
case 0x7: { /* MPEG (LAME MP3 of any quality) */
|
||||
int frame_size = 576; /* todo incorrect looping calcs */
|
||||
|
||||
#ifdef VGM_USE_MPEG
|
||||
case 0x07: { /* MPEG (CBR LAME MP3) []Dengeki Bunko Fighting Climax (PS3) */
|
||||
mpeg_codec_data *mpeg_data = NULL;
|
||||
coding_t ct;
|
||||
|
||||
mpeg_data = init_mpeg(streamFile, start_offset, &ct, vgmstream->channels);
|
||||
mpeg_data = init_mpeg(streamFile, start_offset, &vgmstream->coding_type, vgmstream->channels);
|
||||
if (!mpeg_data) goto fail;
|
||||
vgmstream->codec_data = mpeg_data;
|
||||
|
||||
vgmstream->coding_type = ct;
|
||||
vgmstream->layout_type = layout_none;
|
||||
|
||||
vgmstream->num_samples = mpeg_bytes_to_samples(data_size, mpeg_data);
|
||||
vgmstream->num_samples -= vgmstream->num_samples % frame_size;
|
||||
if (loop_flag) {
|
||||
vgmstream->loop_start_sample = mpeg_bytes_to_samples(loop_start, mpeg_data);
|
||||
vgmstream->loop_start_sample -= vgmstream->loop_start_sample % frame_size;
|
||||
vgmstream->loop_end_sample = mpeg_bytes_to_samples(loop_end, mpeg_data);
|
||||
vgmstream->loop_end_sample -= vgmstream->loop_end_sample % frame_size;
|
||||
/* loops are always CBR frame beginnings */
|
||||
}
|
||||
vgmstream->interleave_block_size = 0;
|
||||
|
||||
/* encoder delay varies between 1152 (1f), 528, 576, etc; probably not actually skipped */
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
default: /* 8+: not defined */
|
||||
default: /* 0x08+: not defined */
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
/* open the file for reading */
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
goto fail;
|
||||
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
|
Loading…
Reference in New Issue
Block a user