On Fri, Jul 19, 2024 at 07:54:37PM -0400, Peter Ross wrote: > can you post a sample file somewhere Of course. Here are some you can try out: gm_us.wve: (Stereo - 15 FPS) https://0x0.st/X97A.wve gm_sp.wve: (Stereo - 15 FPS) https://0x0.st/X97m.wve sims.wve: (Mono - 30 FPS) https://0x0.st/X97b.wve simsne.wve: (Mono - 30 FPS) https://0x0.st/X97B.wve The first two should decode no problem, and are attached for comparison purposes. Strangely, for all except gm_us.wve, the very last SCDl chunk has a number of samples that isn't divisible by 28. So you'll get a single decode error at the end for the rest of them, but they will still play all the way through and sound good. > these whitespace-only changes shouldn't go in the patch. > "count2 < ( channels..." looks out of place. drop the space after the parenthesis. > ditto for these whitespace-only changes above. > av_log trailing "\n" missing Thank you. I have cleaned those up now. > i suggest splitting this into two patches, one for mono adpcm ea, another for the frame rate fix. Done. On Fri, Jul 19, 2024 at 7:54 PM Peter Ross wrote: > On Fri, Jul 19, 2024 at 07:34:18AM -0400, redacted redacted wrote: > > Hello there, > > > > The Sims 1: Unleashed makes use of WVE files for its intro videos. > > Two of the files for the game use Mono ADPCM audio instead of Stereo. > > However, FFmpeg's ADPCM_EA codec always expects the files to be in > Stereo. > > can you post a sample file somewhere > > > In addition, they're supposed to play at 30 fps, but the EA demuxer > assumes > > 15 by default. > > It appears the framerate is set with the use of the 0x1B code in the > SCHl / > > PT00 header. > > nice find > > > I have made changes in the patch attached to fix these problems. > > thx for sharing. > the patch needs a small amount of improvement. see below for my > suggestions. > > > From 306f9db010cf000eb8477aca243fc970f5b95df8 Mon Sep 17 00:00:00 2001 > > From: aaron > > Date: Fri, 19 Jul 2024 07:30:10 -0400 > > Subject: [PATCH 1/1] Mono ADPCM for EA WVE Files / Fix Framerate > > > > --- > > libavcodec/adpcm.c | 57 +++++++++++++++++++++++++----------- > > libavformat/electronicarts.c | 12 ++++++-- > > 2 files changed, 50 insertions(+), 19 deletions(-) > > > > diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c > > index f63afefd63..238214877d 100644 > > --- a/libavcodec/adpcm.c > > +++ b/libavcodec/adpcm.c > > @@ -262,7 +262,7 @@ static av_cold int adpcm_decode_init(AVCodecContext > * avctx) > > break; > > case AV_CODEC_ID_ADPCM_DTK: > > case AV_CODEC_ID_ADPCM_EA: > > - min_channels = 2; > > + min_channels = 1; > > break; > > case AV_CODEC_ID_ADPCM_AFC: > > case AV_CODEC_ID_ADPCM_EA_R1: > > @@ -914,10 +914,12 @@ static int get_nb_samples(AVCodecContext *avctx, > GetByteContext *gb, > > bytestream2_seek(gb, -8, SEEK_CUR); > > break; > > case AV_CODEC_ID_ADPCM_EA: > > + /* Stereo is 30 bytes per block */ > > + /* Mono is 15 bytes per block */ > > has_coded_samples = 1; > > *coded_samples = bytestream2_get_le32(gb); > > *coded_samples -= *coded_samples % 28; > > - nb_samples = (buf_size - 12) / 30 * 28; > > + nb_samples = (buf_size - 12) / (ch == 2 ? 30 : 15) * 28; > > break; > > case AV_CODEC_ID_ADPCM_IMA_EA_EACS: > > has_coded_samples = 1; > > @@ -1652,10 +1654,10 @@ static int adpcm_decode_frame(AVCodecContext > *avctx, AVFrame *frame, > > int coeff1l, coeff2l, coeff1r, coeff2r; > > int shift_left, shift_right; > > > > - /* Each EA ADPCM frame has a 12-byte header followed by 30-byte > pieces, > > - each coding 28 stereo samples. */ > > - > > - if (channels != 2) > > + /* Each EA ADPCM frame has a 12-byte header followed by 30-byte > (stereo) or 15-byte (mono) pieces, > > + each coding 28 stereo/mono samples. */ > > + > > + if (channels != 2 && channels != 1) > > return AVERROR_INVALIDDATA; > > > > current_left_sample = sign_extend(bytestream2_get_le16u(&gb), > 16); > > @@ -1665,37 +1667,58 @@ static int adpcm_decode_frame(AVCodecContext > *avctx, AVFrame *frame, > > > > for (int count1 = 0; count1 < nb_samples / 28; count1++) { > > int byte = bytestream2_get_byteu(&gb); > > - coeff1l = ea_adpcm_table[ byte >> 4 ]; > > - coeff2l = ea_adpcm_table[(byte >> 4 ) + 4]; > > + coeff1l = ea_adpcm_table[ byte >> 4 ]; > > + coeff2l = ea_adpcm_table[(byte >> 4) + 4]; > > these whitespace-only changes shouldn't go in the patch. > > > coeff1r = ea_adpcm_table[ byte & 0x0F]; > > coeff2r = ea_adpcm_table[(byte & 0x0F) + 4]; > > > > - byte = bytestream2_get_byteu(&gb); > > - shift_left = 20 - (byte >> 4); > > - shift_right = 20 - (byte & 0x0F); > > - > > - for (int count2 = 0; count2 < 28; count2++) { > > + if (channels == 2){ > > + byte = bytestream2_get_byteu(&gb); > > + shift_left = 20 - (byte >> 4); > > + shift_right = 20 - (byte & 0x0F); > > + } else{ > > + /* Mono packs the shift into the coefficient byte's > lower nibble instead */ > > + shift_left = 20 - (byte & 0x0F); > > + } > > + > > + for (int count2 = 0; count2 < ( channels == 2 ? 28 : 14); > count2++) { > > "count2 < ( channels..." looks out of place. > drop the space after the parenthesis. > > > byte = bytestream2_get_byteu(&gb); > > next_left_sample = sign_extend(byte >> 4, 4) * (1 << > shift_left); > > - next_right_sample = sign_extend(byte, 4) * (1 << > shift_right); > > + next_right_sample = sign_extend(byte, 4) * (1 << > shift_right); > > > > next_left_sample = (next_left_sample + > > (current_left_sample * coeff1l) + > > (previous_left_sample * coeff2l) + 0x80) >> 8; > > + > > next_right_sample = (next_right_sample + > > (current_right_sample * coeff1r) + > > (previous_right_sample * coeff2r) + 0x80) >> 8; > > > > previous_left_sample = current_left_sample; > > current_left_sample = av_clip_int16(next_left_sample); > > + > > previous_right_sample = current_right_sample; > > current_right_sample = av_clip_int16(next_right_sample); > > + > > *samples++ = current_left_sample; > > - *samples++ = current_right_sample; > > + > > ditto for these whitespace-only changes above. > > > + if (channels == 2){ > > + *samples++ = current_right_sample; > > + } else { > > + next_left_sample = sign_extend(byte, 4) * (1 << > shift_left); > > + > > + next_left_sample = (next_left_sample + > > + (current_left_sample * coeff1l) + > > + (previous_left_sample * coeff2l) + 0x80) >> 8; > > + > > + previous_left_sample = current_left_sample; > > + current_left_sample = > av_clip_int16(next_left_sample); > > + > > + *samples++ = current_left_sample; > > + } > > } > > } > > - > > - bytestream2_skip(&gb, 2); // Skip terminating 0x0000 > > + bytestream2_skip(&gb, channels == 2 ? 2 : 3); // Skip > terminating NULs > > ) /* End of CASE */ > > CASE(ADPCM_EA_MAXIS_XA, > > int coeff[2][2], shift[2]; > > i suggest splitting this into two patches, one for mono adpcm ea, another > for > the frame rate fix. > > > diff --git a/libavformat/electronicarts.c b/libavformat/electronicarts.c > > index f7f6fd4cab..c141a172dd 100644 > > --- a/libavformat/electronicarts.c > > +++ b/libavformat/electronicarts.c > > @@ -86,6 +86,8 @@ typedef struct EaDemuxContext { > > enum AVCodecID audio_codec; > > int audio_stream_index; > > > > + int framerate; > > + > > int bytes; > > int sample_rate; > > int num_channels; > > @@ -198,6 +200,10 @@ static int > process_audio_header_elements(AVFormatContext *s) > > av_log(s, AV_LOG_DEBUG, "end of header block reached\n"); > > in_header = 0; > > break; > > + case 0x1B: > > + ea->framerate = read_arbitrary(pb); > > + av_log(s, AV_LOG_DEBUG, "Setting framerate to %u", > ea->framerate); > > + break; > > av_log trailing "\n" missing > > > default: > > av_log(s, AV_LOG_DEBUG, > > "header element 0x%02x set to 0x%08"PRIx32"\n", > > @@ -367,6 +373,8 @@ static int process_ea_header(AVFormatContext *s) > > AVIOContext *pb = s->pb; > > int i; > > > > + ea->framerate = 15; > > + > > for (i = 0; i < 5 && (!ea->audio_codec || !ea->video.codec); i++) { > > uint64_t startpos = avio_tell(pb); > > int err = 0; > > @@ -427,12 +435,12 @@ static int process_ea_header(AVFormatContext *s) > > case pQGT_TAG: > > case TGQs_TAG: > > ea->video.codec = AV_CODEC_ID_TGQ; > > - ea->video.time_base = (AVRational) { 1, 15 }; > > + ea->video.time_base = (AVRational) { 1, ea->framerate }; > > break; > > > > case pIQT_TAG: > > ea->video.codec = AV_CODEC_ID_TQI; > > - ea->video.time_base = (AVRational) { 1, 15 }; > > + ea->video.time_base = (AVRational) { 1, ea->framerate }; > > break; > > > > case MADk_TAG: > > -- > > -- Peter > (A907 E02F A6E5 0CD2 34CD 20D2 6760 79C5 AC40 DD6B) > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe". >