yui0 / slibs

Single file libraries for C/C++
117 stars 12 forks source link

Unable to decode Fraunhofer FDK AAC -encoded files #3

Open davidgrisham opened 11 months ago

davidgrisham commented 11 months ago

Hi!

I'm working on integrating uaac.h as an AAC decoder for miniaudio, but I'm having issues getting uaac to decode my AAC files in the first place. I'm using ffmpeg and libfdk_aac (Fraunhofer FDK AAC) to encode my files. I've tested with your aplay+ program and am getting the same issue.

I have two files in the following test:

$ ./aplay+ files/

/home/grish/scratch/aplay-/files/output.m4a
[moov] is not found!
[trak] is not found!
[mdia] is not found!
[hdlr] is not found!
type:4d344120/736f756e 0 fffffff8
Error: cannot read AAC data

/home/grish/scratch/aplay-/files/output-moov.m4a
[mdat] is not found!
Error: cannot read AAC data

I've been playing around with the uaac_extract_aac function, but am not well-versed in decoding audio files. Curious if you have any ideas here, or at least a sense of how much work it would be to get this working. I have a rather large audio library that's encoded in the same way, so I'm hoping to get this working without modifying the audio files.

davidgrisham commented 11 months ago

I've now gotten aplay+ to output very clicky/noisy audio, and I can sort of hear the actual song underneath. I updated the uaac_extract_aac function to:

uint8_t *uaac_extract_aac(int fd, int *len, int *samplerate, int *channels)
{
    _ATOM ftyp = uaac_findMp4Atom("ftyp", 0, 0, fd);
    if (!ftyp.size) return 0; // no mp4/m4a file
    _ATOM free = uaac_findMp4Atom("free", ftyp.pos + ftyp.size, 1, fd);
    if (!free.size) return 0; // no mp4/m4a file

    _ATOM mdat = uaac_findMp4Atom("mdat", free.pos + free.size, 1, fd);
    printf("mdat.size: %d\n", mdat.size);
    *len = mdat.size;
    uint8_t *data = (uint8_t*)malloc(mdat.size);
    if (!data) return 0; // memory error!

    ssize_t bytes_read = read(fd, data, mdat.size);
    printf("bytes_read: %zd\n", bytes_read);

    _ATOM moov = uaac_findMp4Atom("moov", mdat.pos + mdat.size, 0, fd);
    _ATOM trak = uaac_findMp4Atom("trak", moov.pos + 8, 1, fd);
    _ATOM mdia = uaac_findMp4Atom("mdia", trak.pos + 8, 1, fd);
    _ATOM mdhd = uaac_findMp4Atom("mdhd", mdia.pos + 8, 1, fd);
    _ATOM hdlr = uaac_findMp4Atom("hdlr", mdhd.pos + mdhd.size, 1, fd);
    _ATOM minf = uaac_findMp4Atom("minf", hdlr.pos + hdlr.size, 1, fd);
    _ATOM stbl = uaac_findMp4Atom("stbl", minf.pos + 8, 1, fd);
    _ATOM stsd = uaac_findMp4Atom("stsd", stbl.pos + 8, 1, fd);
    if (!stsd.size) return 0; // something is not ok

    *channels = uaac_read16(stsd.pos + 8 + 0x20, fd);
    *samplerate = uaac_read32(stsd.pos + 8 + 0x26, fd);

    printf("channels: %d\n", *channels);
    printf("samplerate: %d\n", *samplerate);

    return data;
}

And after recompiling + running aplay+ the terminal output is:

$ ./aplay+ -d 'hw:2,0' files/

/home/grish/scratch/aplay-/files/output.m4a
mdat.size: 7727795
bytes_read: 7727795
channels: 2
samplerate: 48000
48000Hz 2ch

In case it's helpful, here's the data ffmpeg extracts from the same audio file:

$ ffprobe -i output.m4a
ffprobe version n6.0 Copyright (c) 2007-2023 the FFmpeg developers
  built with gcc 13.2.1 (GCC) 20230801
  configuration: --prefix=/usr --disable-debug --disable-static --disable-stripping --enable-amf --enable-avisynth --enable-cuda-llvm --enable-lto --enable-fontconfig --enable-gmp --enable-gpl --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libdav1d --enable-libdrm --enable-libfreetype --enable-libfribidi --enable-libgsm --enable-libiec61883 --enable-libjack --enable-libjxl --enable-libmodplug --enable-libmp3lame --enable-libopencore_amrnb --enable-libopencore_amrwb --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librav1e --enable-librsvg --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libssh --enable-libsvtav1 --enable-libtheora --enable-libv4l2 --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvpl --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxcb --enable-libxml2 --enable-libxvid --enable-libzimg --enable-nvdec --enable-nvenc --enable-opencl --enable-opengl --enable-openssl --enable-shared --enable-vaapi --enable-version3 --enable-vulkan --enable-libfdk_aac --enable-nonfree --disable-htmlpages
  libavutil      58.  2.100 / 58.  2.100
  libavcodec     60.  3.100 / 60.  3.100
  libavformat    60.  3.100 / 60.  3.100
  libavdevice    60.  1.100 / 60.  1.100
  libavfilter     9.  3.100 /  9.  3.100
  libswscale      7.  1.100 /  7.  1.100
  libswresample   4. 10.100 /  4. 10.100
  libpostproc    57.  1.100 / 57.  1.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'output.m4a':
  Metadata:
    major_brand     : M4A
    minor_version   : 512
    compatible_brands: M4A isomiso2
    title           : Irresistible
    artist          : Deafheaven
    composer        : George Clarke/Kerry McCoy
    album           : Sunbather (10th Anniversary Remix / Remaster)
    genre           : Black Metal
    track           : 2
    disc            : 0
    date            : 2023
    compilation     : 0
    encoder         : Lavf60.3.100
    ORIGINAL YEAR   : 0000
    lyrics          :
    sort_album_artist:
    sort_artist     :
    sort_composer   :
    grouping        :
    comment         : ~ N ~
    album_artist    : Deafheaven
  Duration: 00:03:13.15, start: 0.000000, bitrate: 321 kb/s
  Stream #0:0[0x1](und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 320 kb/s (default)
    Metadata:
      handler_name    : SoundHandler
      vendor_id       : [0][0][0][0]