Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
From: Aaron <aaronrules5alt@gmail.com>
To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org>
Subject: Re: [FFmpeg-devel] Mono ADPCM for EA WVE Files / Fix Framerate
Date: Sat, 20 Jul 2024 10:19:18 -0400
Message-ID: <CANC4H7BUh-wXfKi0-XFtBXnnVCRYNZHJxUOzjM6Y_VN1Rt6S=g@mail.gmail.com> (raw)
In-Reply-To: <Zpr8vJxGcGGOOd_S@9e5d27e4b9fe9ef6ae1fbb02e4373de4>

[-- Attachment #1: Type: text/plain, Size: 10510 bytes --]

 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 <pross@xvid.org> 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 <aaronrules5alt@gmail.com>
> > 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".
>

[-- Attachment #2: EA-ADPCM-Mono.patch --]
[-- Type: application/octet-stream, Size: 4006 bytes --]

[-- Attachment #3: EA-FPS.patch --]
[-- Type: application/octet-stream, Size: 1738 bytes --]

[-- Attachment #4: Type: text/plain, Size: 251 bytes --]

_______________________________________________
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".

  reply	other threads:[~2024-07-20 14:19 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-07-19 11:34 redacted redacted
2024-07-19 23:54 ` Peter Ross
2024-07-20 14:19   ` Aaron [this message]
2024-07-22  9:36     ` Peter Ross

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CANC4H7BUh-wXfKi0-XFtBXnnVCRYNZHJxUOzjM6Y_VN1Rt6S=g@mail.gmail.com' \
    --to=aaronrules5alt@gmail.com \
    --cc=ffmpeg-devel@ffmpeg.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
		ffmpegdev@gitmailbox.com
	public-inbox-index ffmpegdev

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git