#!/usr/bin/env bash

# Exit on error
set -e

# Query OS and machine
uname=`uname`
machine=`gcc -dumpmachine`

# Number of parallel jobs
if [[ $uname == *MINGW* ]]; then
  jobs=$NUMBER_OF_PROCESSORS
elif [[ $uname == Darwin ]]; then
  jobs=$(sysctl -n hw.activecpu)
else
  jobs=$(nproc)
fi

# macOS target version
if [[ $uname == Darwin ]]; then
  MACOSX_TARGET=$MACOSX_DEPLOYMENT_TARGET
  if [[ -z $MACOSX_TARGET ]]; then
    MACOSX_TARGET=`sw_vers | awk '$1 == "ProductVersion:" { print $2 }'`
  fi
fi

# Standard CFLAGS
cflags="-O3 -DNDEBUG"

if [[ $uname == Darwin ]] && [[ $BUILD_PPC == True ]]; then
  cflags="$cflags -arch ppc -mcpu=G4"
  asflags="-arch ppc"
  ldflags="-Wl,-x -arch ppc"
  ppc=true
elif [[ $uname == Darwin ]] && [[ $BUILD_X86 == True ]]; then
  cflags="$cflags -arch i386 -march=prescott"
  asflags="-arch i386"
  ldflags="-Wl,-x -arch i386"
  x86=true
elif [[ $uname == Darwin ]] && [[ $BUILD_ARM64 == True ]]; then
  cflags="$cflags -arch arm64 -mcpu=apple-m1"
  asflags="-arch arm64"
  ldflags="-Wl,-x -arch arm64"
  host="aarch64-apple-darwin20.1.0"
  arm64=true
elif [[ $uname == Darwin ]]; then
  if [[ ${MACOSX_TARGET%%.*} -ge 11 ]]; then
    cflags="$cflags -arch x86_64 -march=haswell"
  else
    cflags="$cflags -arch x86_64 -march=core2"
  fi
  asflags="-arch x86_64"
  ldflags="-Wl,-x -arch x86_64"
  x86_64=true
elif [[ $machine == *amd64* || $machine == *x86_64* ]] && [[ $BUILD_ARM64 != True ]] && [[ $BUILD_X86 != True ]] && [[ $uname != *MINGW* || $BUILD_X86_64 == True ]]; then
  cflags="$cflags -m64 -march=x86-64"
  ldflags="-m64"
  x86_64=true
elif [[ $machine == *amd64* || $machine == *x86_64* ]] && [[ $BUILD_ARM64 == True ]]; then
  cflags="$cflags -march=armv8-a+simd"
  host="aarch64-w64-mingw32"
  arm64=true
elif [[ $machine == *aarch64* ]]; then
  cflags="$cflags -I/usr/local/include -march=armv8-a+simd"
  arm64=true
elif [[ $machine == *arm* ]]; then
  cflags="$cflags -I/usr/local/include -march=armv7-a+simd"
  arm=true
else
  cflags="$cflags -m32 -march=pentium4"
  ldflags="-m32"
  x86=true
fi

# Include glibc version header on Linux to allow older glibc
if [[ $uname == Linux ]]; then
  export cflags="$cflags -include $(dirname "$(readlink -f "${BASH_SOURCE[0]}")")/headers/glibc_version_header.h"
fi

cflags_unroll="-funroll-loops"

# Set host triple on Linux
if [[ $uname == Linux ]]; then
  if [[ $x86_64 == true ]]; then
    host="x86_64-linux-gnu"
  elif [[ $x86 == true ]]; then
    host="i386-linux-gnu"
  elif [[ $arm64 == true ]]; then
    host="aarch64-linux-gnu"
  elif [[ $arm == true ]]; then
    host="arm-linux-gnueabihf"
  fi
fi

# Set compiler and tools
export CC=gcc
export CXX=g++
export MAKE=make
export SUDO=sudo
export DL="wget -O"
export PATCH="patch --binary"

if [[ $uname == *MINGW* ]] && [[ $arm64 == true ]]; then
  export CC=aarch64-w64-mingw32-clang
  export CXX=aarch64-w64-mingw32-clang++
fi

if [[ $uname == Darwin ]]; then
  MACOSX_MINOR_VERSION=${MACOSX_TARGET#*.}
  if [[ ${MACOSX_TARGET%%.*} -ge 11 ]] || [[ ${MACOSX_MINOR_VERSION%%.*} -ge 7 ]]; then
    export CC=clang
    export CXX=clang++
  fi
fi

if [[ $uname == *FreeBSD* ]]; then
  export CC=clang
  export CXX=clang++
  export MAKE=gmake
  export PATCH=patch
fi

if [[ $uname == Haiku ]]; then
  export SUDO=
fi

if [[ $uname == Darwin ]]; then
  export DL="curl -L -o"
fi

# Setup environment
export CFLAGS="$cflags $cflags_unroll"
export ASFLAGS="$asflags"
export LDFLAGS="$ldflags"

if [[ $uname == *MINGW* ]]; then
  execext=exe
  sharedext=dll
  sharedinfix=-*
else
  execext=
  sharedext=so
  sharedinfix=
fi

if [[ $uname == Haiku ]]; then
  prefix="--prefix=/system/non-packaged"
fi

# Package versions
exhale_version=1.2.0
faac_version=1.30
faad2_version=2.10.0
fdk_aac_version=2.0.2
ffmpeg_version=6.0
flac_version=1.4.2
lame_version=3.100
libcdio_version=2.1.0
libcdio_paranoia_version=10.2+2.0.1
libcdrip_version=2.4a
libogg_version=1.3.5
libsamplerate_version=0.2.2
libsndfile_version=1.2.0
mac_version=9.20
mp4v2_version=2.1.2
mpg123_version=1.31.2
musepack_version=4.75
opus_version=1.3.1
rnnoise_version=9acc1e5
rubberband_version=1.8.2
speex_version=1.2.1
vorbis_version=1.3.7
wavpack_version=5.6.0

# Package locations
exhale_location=https://gitlab.com/ecodis/exhale/-/archive/v$exhale_version/exhale-v$exhale_version.tar.bz2
faac_location=https://github.com/knik0/faac/archive/${faac_version//./_}.tar.gz
faad2_location=https://github.com/knik0/faad2/archive/${faad2_version//./_}.tar.gz
fdk_aac_location=https://sourceforge.net/projects/opencore-amr/files/fdk-aac/fdk-aac-$fdk_aac_version.tar.gz
ffmpeg_location=https://ffmpeg.org/releases/ffmpeg-$ffmpeg_version.tar.xz
flac_location=https://ftp.osuosl.org/pub/xiph/releases/flac/flac-$flac_version.tar.xz
lame_location=https://sourceforge.net/projects/lame/files/lame/$lame_version/lame-$lame_version.tar.gz
libcdio_location=https://ftp.gnu.org/gnu/libcdio/libcdio-$libcdio_version.tar.bz2
libcdio_paranoia_location=https://ftp.gnu.org/gnu/libcdio/libcdio-paranoia-$libcdio_paranoia_version.tar.bz2
libcdrip_location=http://cdrip.org/releases/libcdrip-$libcdrip_version.zip
libogg_location=https://ftp.osuosl.org/pub/xiph/releases/ogg/libogg-$libogg_version.tar.xz
libsamplerate_location=https://github.com/libsndfile/libsamplerate/releases/download/$libsamplerate_version/libsamplerate-$libsamplerate_version.tar.xz
libsndfile_location=https://github.com/libsndfile/libsndfile/releases/download/$libsndfile_version/libsndfile-$libsndfile_version.tar.xz
mac_location=https://freac.org/patches/MAC_${mac_version%.*}${mac_version#*.}_SDK.zip
mp4v2_location=https://github.com/enzo1982/mp4v2/releases/download/v$mp4v2_version/mp4v2-$mp4v2_version.tar.bz2
mpg123_location=https://mpg123.org/download/mpg123-$mpg123_version.tar.bz2
musepack_location=https://files.musepack.net/source/musepack_src_r${musepack_version%.*}${musepack_version#*.}.tar.gz
opus_location=https://ftp.osuosl.org/pub/xiph/releases/opus/opus-$opus_version.tar.gz
rnnoise_location=https://codeload.github.com/xiph/rnnoise/zip/$rnnoise_version
rubberband_location=https://breakfastquay.com/files/releases/rubberband-$rubberband_version.tar.bz2
speex_location=https://ftp.osuosl.org/pub/xiph/releases/speex/speex-$speex_version.tar.gz
vorbis_location=https://ftp.osuosl.org/pub/xiph/releases/vorbis/libvorbis-$vorbis_version.tar.xz
wavpack_location=https://www.wavpack.com/wavpack-$wavpack_version.tar.bz2

# Patch locations
fdk_aac_patches=(https://freac.org/patches/fdk-aac-2.0.2-drcfix.patch)
fdk_aac_patch_levels=(1)

lame_patches=(https://freac.org/patches/lame-$lame_version-sse-20171014.diff https://freac.org/patches/lame-$lame_version-fastcrc.diff)
lame_patch_levels=(0 1)

lame_patches_ppc=(https://freac.org/patches/lame-$lame_version-altivec-20171014.diff https://freac.org/patches/lame-$lame_version-fastcrc.diff)
lame_patch_levels_ppc=(0 1)

libcdio_patches=(https://freac.org/patches/libcdio-$libcdio_version-cdtext-osx.patch https://freac.org/patches/libcdio-$libcdio_version-cdtext-win32.patch)
libcdio_patch_levels=(1 1)

mp4v2_patches=(https://freac.org/patches/mp4v2-2.1.2-sfocache.patch)
mp4v2_patch_levels=(1)

rubberband_patches=(https://freac.org/patches/rubberband-$rubberband_version-fixed.diff)
rubberband_patch_levels=(1)

vorbis_patches=(https://freac.org/patches/libvorbis-$vorbis_version-aotuv-b6.03.patch https://freac.org/patches/libvorbis-$vorbis_version-aotuv-b6.03-lancer.patch)
vorbis_patch_levels=(1 1)

# Keep using FFmpeg 4.3.5 on macOS PPC
if [[ $uname == Darwin ]] && [[ $BUILD_PPC == True ]]; then
  ffmpeg_version=4.3.5
  ffmpeg_location=https://ffmpeg.org/releases/ffmpeg-$ffmpeg_version.tar.xz
fi

# Keep using libsndfile 1.0.30 on macOS x86
if [[ $uname == Darwin ]] && [[ $BUILD_X86 == True ]]; then
  libsndfile_version=1.0.30
  libsndfile_location=https://github.com/libsndfile/libsndfile/releases/download/v$libsndfile_version/libsndfile-$libsndfile_version.tar.bz2
fi

# Main build function
build () {
  archive=${1##*/}

  if [[ -z $folder ]]; then
    if [[ $archive == *.tar.* ]]; then folder=${archive%.tar.*}; fi
    if [[ $archive == *.zip   ]]; then folder=${archive%.zip}; fi
  fi

  if [[ $1 == *://* ]]; then $DL $archive $1; fi

  rm -fr $folder

  if [[ $archive == *.tar.gz  ]]; then tar xfz $archive; fi
  if [[ $archive == *.tar.bz2 ]]; then tar xfj $archive; fi
  if [[ $archive == *.tar.xz  ]]; then tar xfJ $archive; fi
  if [[ $archive == *.zip     ]]; then unzip   $archive; fi

  cd $folder

  index=0

  for patch in ${patches[@]}; do
    $DL ../${patch##*/} $patch

    if [ ${#patch_levels[index]} -gt 0 ]; then
      $PATCH -E -p${patch_levels[index]} < ../${patch##*/}
    else
      $PATCH -E -p1 < ../${patch##*/}
    fi

    set +e
    let index++
    set -e
  done

  eval $prepare

  if [[ ! -f ./configure ]]; then
    if [[ -f ./configure.in ]] || [[ -f ./configure.ac ]]; then
      autoreconf -i
    fi
  fi

  if [[ -f ./configure ]]; then
    chmod a+x configure
    if [[ -z $host_flags && ! -z $host ]]; then
      eval $configure_exports ./configure --host=$host $configure_flags $prefix
    else
      eval $configure_exports ./configure $host_flags $configure_flags $prefix
    fi
  elif [[ -f CMakeLists.txt ]]; then
    if [[ $uname == *MINGW* ]]; then
      cmake . -G "MSYS Makefiles" $cmake_flags
    else
      cmake . $cmake_flags
    fi
  fi
  $MAKE $make_flags -j$jobs

  index=0

  if [[ $uname == *MINGW* ]]; then
    files=($2)
    targets=($3)

    for file in ${files[@]}; do
      strip --strip-all $file
      cp $file ../${targets[index]}

      if [[ ${targets[index]} == *.$sharedext ]]; then
        peflags -d1 -n1 ../${targets[index]}
      else
        peflags -n1 ../${targets[index]}
      fi

      set +e
      let index++
      set -e
    done
  elif [[ -n "$install_script" ]]; then
    $SUDO bash -c "$install_script"
  else
    if [[ -f ./install-sh ]]; then
      chmod a+x install-sh
    fi
    $SUDO $MAKE $make_flags -j$jobs install
  fi

  cd ..

  unset patches
  unset patch_levels
  unset prepare
  unset configure_exports
  unset configure_flags
  unset cmake_flags
  unset host_flags
  unset make_flags
  unset install_script
  unset folder

  export CFLAGS="$cflags $cflags_unroll"
  export ASFLAGS="$asflags"
  export LDFLAGS="$ldflags"
}

packages=$@

if [ ${#packages[0]} -eq 0 ]; then
  echo "Usage: build.sh [{list of packages}|all]"
  echo "Available packages: exhale faac faad2 fdk-aac ffmpeg flac lame libcdio libcdio-paranoia libcdrip libogg libsamplerate libsndfile mac mp4v2 mpg123 musepack opus rnnoise rubberband speex vorbis wavpack"
  echo
elif [ "${packages[0]}" == all ]; then
  if [[ $uname == Darwin ]]; then
    packages=( exhale faad2 fdk-aac ffmpeg flac lame libcdio libcdio-paranoia libogg libsamplerate libsndfile mac mp4v2 mpg123 opus speex vorbis wavpack )
  elif [[ $uname == Haiku ]]; then
    packages=( exhale faac faad2 fdk-aac flac lame libogg mpg123 opus speex vorbis )
  elif [[ $uname == *MINGW* ]]; then
    packages=( exhale faac faad2 fdk-aac ffmpeg flac lame libcdio libcdio-paranoia libcdrip libogg libsamplerate libsndfile mac mp4v2 mpg123 musepack opus rnnoise rubberband speex vorbis wavpack )
  else
    packages=( exhale faac faad2 fdk-aac ffmpeg flac lame libcdio libcdio-paranoia libogg libsamplerate libsndfile mac mp4v2 mpg123 musepack opus rnnoise rubberband speex vorbis wavpack )
  fi
fi

for package in ${packages[@]}; do
  if [ $package == exhale ]; then
    # Build exhale
    if [[ $uname == *MINGW* ]]; then
      prepare="sed -i -e \"s/-fPIC//\" src/makefile.base && sed -i -e \"s/= g../= \$\(CXX\)/\" src/makefile.base && sed -i -e \"s/= .(CPP)/= \$\(CXX\)/\" src/makefile.base && sed -i -e \"s/-ldl//\" src/app/makefile && sed -i -e \"s/printf_s/printf/\" src/app/exhaleApp.cpp && sed -i -e \"s/ú#+/-/\" src/app/exhaleApp.cpp"
      if [[ $arm64 == true ]]; then
        prepare="$prepare; sed -i -e \"s/-l.(PRD_NAME).*/& -lstdc++/\" src/app/makefile"
      else
        prepare="$prepare; sed -i -e \"s/-l.(PRD_NAME).*/& -lstdc++.static/\" src/app/makefile"
      fi
      export CXXFLAGS="$cflags $cflags_unroll -DEXHALE_DYN_LINK"
    fi
    if [[ $uname == Haiku ]]; then
      make_flags="LIBS="
      install_script="mkdir -p /system/non-packaged/bin && cp bin/exhale /system/non-packaged/bin"
    else
      install_script="mkdir -p /usr/local/bin && cp bin/exhale /usr/local/bin"
    fi
    build $exhale_location bin/exhale.$execext exhale.$execext

  elif [ $package == faac ]; then
    # Build FAAC
    folder=faac-${faac_version//./_}
    prepare="sed -i -e \"s/FAACAPI __stdcall/FAACAPI/\" include/faac.h"
    if [[ $uname == *MINGW* ]]; then
      if [[ $arm64 == true ]]; then
        configure_exports="WINDRES=\"aarch64-w64-mingw32-windres\""
        prepare="sed -i -e \"s/-Wl,--add-stdcall-alias//\" libfaac/Makefile.am"
      elif [[ $x86 == true ]]; then
        configure_exports="WINDRES=\"windres -F pe-i386\""
      fi
    fi
    if [[ $x86_64 == true ]]; then
      if [[ $CC != clang ]]; then
        export CFLAGS="$cflags $cflags_unroll -mfpmath=387"
      fi
    fi
    build $faac_location libfaac/.libs/libfaac$sharedinfix.$sharedext FAAC.$sharedext

  elif [ $package == faad2 ]; then
    # Build FAAD2
    folder=faad2-${faad2_version//./_}
    if [[ $uname == *MINGW* ]]; then
      prepare="./utils/win32/ac2ver faad2 configure.ac > libfaad/win32_ver.h"
    elif [[ $uname == Darwin ]]; then
      prepare="sed -i -e \"s/__builtin_bswap16(u16)/((((u16) \\& 0xff) << 8) | ((u16) >> 8))/\" frontend/mp4read.c"
    fi
    build $faad2_location libfaad/.libs/libfaad$sharedinfix.$sharedext FAAD2.$sharedext

  elif [ $package == fdk-aac ]; then
    # Build FDK-AAC
    patches=${fdk_aac_patches[@]}
    patch_levels=(${fdk_aac_patch_levels[@]})
    export CXXFLAGS="$cflags $cflags_unroll"
    build $fdk_aac_location .libs/libfdk-aac$sharedinfix.$sharedext FDK-AAC.$sharedext

  elif [ $package == ffmpeg ]; then
    # Build ffmpeg
    export CFLAGS="$cflags"
    configure_flags="--disable-autodetect --disable-doc --enable-gpl --enable-small --enable-runtime-cpudetect"
    if [[ $arm == true || $arm64 == true ]] && [[ `uname -m` == x86_64 ]]; then
      host_flags="--enable-cross-compile"
      if [[ $arm == true ]]; then
        host_flags="$host_flags --arch=arm"
      else
        host_flags="$host_flags --arch=aarch64"
      fi
      if [[ $uname == Linux ]]; then
        host_flags="$host_flags --target-os=linux"
      elif [[ $uname == *MINGW* ]]; then
        host_flags="$host_flags --target-os=win32 --cross-prefix=aarch64-w64-mingw32-"
      fi
    else
      host_flags=" "
    fi
    if [[ $uname == *MINGW* ]]; then
      make_flags="V=1"
    elif [[ $uname == Darwin ]]; then
      configure_flags="$configure_flags --disable-audiotoolbox"
      if [[ $ppc == true ]]; then
        configure_flags="$configure_flags --disable-swscale"
        host_flags="--arch=ppc"
      elif [[ $x86_64 == true ]]; then
        host_flags="--arch=x86_64"
      elif [[ $x86 == true ]]; then
        host_flags="--arch=i386"
      elif [[ $arm64 == true ]]; then
        configure_flags="$configure_flags --enable-cross-compile --disable-asm"
        host_flags="--arch=aarch64"
      fi
    fi
    build $ffmpeg_location ffmpeg.$execext ffmpeg.$execext

  elif [ $package == flac ]; then
    # Build FLAC
    patches=${flac_patches[@]}
    patch_levels=(${flac_patch_levels[@]})
    export CFLAGS="$CFLAGS -D_FORTIFY_SOURCE=0"
    configure_flags="--disable-cpplibs --disable-doxygen-docs"
    if [[ $x86_64 == true ]] || [[ $arm64 == true ]]; then
      if [[ $uname == *MINGW* ]]; then
        prepare="sed -i -e \"s/#undef FLAC__CPU_IA32//\" config.h.in"
        prepare="$prepare; sed -i -e \"s/ARCH_SUBDIRS = ia32/ARCH_SUBDIRS =/\" src/libFLAC/Makefile.in"
        prepare="$prepare; sed -i -e \"s/LOCAL_EXTRA_LIBADD = ia32\/libFLAC-asm\.la/LOCAL_EXTRA_LIBADD =/\" src/libFLAC/Makefile.in"
        if [[ $x86_64 == true ]]; then
          prepare="$prepare; sed -i -e \"s/#undef FLAC__CPU_X86_64/#define FLAC__CPU_X86_64 1/\" config.h.in"
        else
          prepare="$prepare; sed -i -e \"s/HAVE_SYS_PARAM_H/HAVE_xxx_PARAM_H/\" src/libFLAC/include/private/macros.h"
        fi
      fi
      configure_flags="$configure_flags --enable-64-bit-words"
    fi
    if [[ $uname == Darwin ]]; then
      configure_flags="$configure_flags --disable-asm-optimizations"
    elif [[ $uname == *MINGW* ]]; then
      export CFLAGS="$CFLAGS -I$(pwd)/libogg-$libogg_version/include"
      export LDFLAGS="$LDFLAGS -L$(pwd)/libogg-$libogg_version/src/.libs"
    fi
    build $flac_location src/libFLAC/.libs/libFLAC$sharedinfix.$sharedext FLAC.$sharedext
    if [[ $uname == *MINGW* ]]; then
      sed -i -b -e "s/libogg-0.dll/Ogg.dll\x00\x00\x00\x00\x00/" FLAC.$sharedext
    fi

  elif [ $package == lame ]; then
    # Build LAME
    if [[ $ppc == true ]]; then
      patches=${lame_patches_ppc[@]}
      patch_levels=(${lame_patch_levels_ppc[@]})
    elif [[ $x86 == true ]] || [[ $x86_64 == true ]]; then
      patches=${lame_patches[@]}
      patch_levels=(${lame_patch_levels[@]})
    fi
    if [[ $uname == *MINGW* ]]; then
      prepare="sed -i -e \"/lame_init_old/d\" include/libmp3lame.sym"
    elif [[ $uname == Darwin ]]; then
      prepare="sed -i -e \"/lame_init_old/d\" include/libmp3lame.sym && sed -i -e \"s/strnlen(\\(.*\\),[^)]*)/strlen(\1)/\" frontend/parse.c"
    fi
    if [[ $ppc == true ]]; then
        export CFLAGS="$cflags $cflags_unroll -faltivec -DALTIVEC"
    elif [[ $x86 == true ]]; then
      if [[ $uname == *MINGW* ]] || [[ $uname == FreeBSD ]] || [[ $uname == Darwin ]]; then
        export CFLAGS="$cflags $cflags_unroll -mfpmath=sse"
      fi

      configure_flags="--enable-nasm"
    fi
    build $lame_location libmp3lame/.libs/libmp3lame$sharedinfix.$sharedext LAME.$sharedext

  elif [ $package == libcdio ]; then
    # Build libcdio
    patches=${libcdio_patches[@]}
    patch_levels=(${libcdio_patch_levels[@]})
    export CFLAGS="$cflags -Os"
    configure_flags="--disable-cxx"
    build $libcdio_location lib/driver/.libs/libcdio$sharedinfix.$sharedext libcdio.$sharedext

  elif [ $package == libcdio-paranoia ]; then
    # Build libcdio-paranoia
    export CFLAGS="$cflags -Os"
    if [[ $uname == Darwin ]]; then
      prepare="sed -i -e \"s/-Wl,--version-script=.*\\.la\\.ver//\" lib/*/Makefile.in"
    fi
    if [[ $uname != FreeBSD ]]; then
      configure_exports="LIBCDIO_CFLAGS=\"-I.\" LIBCDIO_LIBS=\"-lcdio\""
    else
      configure_exports="LIBCDIO_CFLAGS=\"-I/usr/local/include\" LIBCDIO_LIBS=\"-L/usr/local/lib -lcdio\""
    fi
    build $libcdio_paranoia_location "lib/cdda_interface/.libs/libcdio_cdda$sharedinfix.$sharedext lib/paranoia/.libs/libcdio_paranoia$sharedinfix.$sharedext" "libcdio_cdda.$sharedext libcdio_paranoia.$sharedext"

  elif [ $package == libcdrip ]; then
    # Build libcdrip
    export CFLAGS="$cflags -Os"
    configure_flags="--disable-cxx"
    if [[ $x86 == true ]]; then
      build $libcdrip_location bin/x86/CDRip.$sharedext CDRip.$sharedext
    elif [[ $x86_64 == true ]]; then
      make_flags="-f Makefile.x64"
      build $libcdrip_location bin/x86-64/CDRip.$sharedext CDRip.$sharedext
    elif [[ $arm64 == true ]]; then
      make_flags="-f Makefile.arm64"
      build $libcdrip_location bin/arm64/CDRip.$sharedext CDRip.$sharedext
    fi

  elif [ $package == libogg ]; then
    # Build Ogg
    build $libogg_location src/.libs/libogg$sharedinfix.$sharedext Ogg.$sharedext

  elif [ $package == libsamplerate ]; then
    # Build libsamplerate
    if [[ $CC != clang ]] && [[ $x86_64 == true ]]; then
      export CFLAGS="$cflags $cflags_unroll -mfpmath=387"
    fi
    build $libsamplerate_location src/.libs/libsamplerate$sharedinfix.$sharedext SampleRate.$sharedext

  elif [ $package == libsndfile ]; then
    # Build libsndfile
    export CFLAGS="$CFLAGS -D_FORTIFY_SOURCE=0"
    prepare="sed -i -e \"s/immintrin\.h/emmintrin.h/\" src/common.h"
    if [[ $uname == *MINGW* ]] && [[ $x86 == true ]]; then
      configure_exports="RC=\"windres -F pe-i386\""
    fi
    configure_flags="--disable-external-libs --disable-mpeg --disable-alsa"
    build $libsndfile_location src/.libs/libsndfile$sharedinfix.$sharedext SndFile.$sharedext

  elif [ $package == mac ]; then
    # Build Monkey's Audio
    archive=${mac_location##*/}
    folder=${archive%.zip}
    $DL $archive $mac_location
    rm -fr $folder; unzip -d $folder $archive
    rm $archive; zip -m -r $archive $folder
    export CXXFLAGS="$cflags $cflags_unroll"
    build $archive MACDll.$sharedext MACDll.$sharedext

  elif [ $package == mp4v2 ]; then
    # Build mp4v2
    patches=${mp4v2_patches[@]}
    patch_levels=(${mp4v2_patch_levels[@]})
    configure_flags="--disable-optimize"
    export CXXFLAGS="$cflags -Os"
    if [[ $uname == *MINGW* ]] && [[ $x86 == true ]]; then
      export LDFLAGS="$ldflags -lstdc++.static"
    elif [[ $uname == *MINGW* ]] && [[ $arm64 == true ]]; then
      export LDFLAGS="$ldflags -lclang_rt.builtins-aarch64"
    fi
    build $mp4v2_location .libs/libmp4v2$sharedinfix.$sharedext MP4v2.$sharedext

  elif [ $package == mpg123 ]; then
    # Build mpg123
    configure_flags="--enable-modules=no"
    if [[ $uname == *MINGW* ]]; then
      export CFLAGS="$cflags $cflags_unroll -DWIN32"
    elif [[ $uname == Darwin ]]; then
      export CFLAGS="$cflags $cflags_unroll -std=c99"
    fi
    if [[ $ppc == true ]]; then
      configure_flags="$configure_flags --with-cpu=altivec"
    elif [[ $x86_64 == true ]]; then
      if [[ $uname == Darwin ]]; then
        configure_flags="$configure_flags --with-cpu=x86-64_alone"
      else
        configure_flags="$configure_flags --with-cpu=x86-64"
      fi
    elif [[ $x86 == true ]]; then
      configure_flags="$configure_flags --with-cpu=sse"
    elif [[ $arm == true ]]; then
      configure_flags="$configure_flags --with-cpu=neon"
    elif [[ $arm64 == true ]]; then
      configure_flags="$configure_flags --with-cpu=neon64"
    fi
    build $mpg123_location src/libmpg123/.libs/libmpg123$sharedinfix.$sharedext mpg123.$sharedext

  elif [ $package == musepack ]; then
    # Build MusePack
    prepare="touch include/config.h.in; head -n 34 configure.in >> configure.ac; echo \"AM_CONDITIONAL([HAVE_VISIBILITY], [false])\" >> configure.ac; echo \"AC_CHECK_LIB([m],[cos])\" >> configure.ac; tail -n 18 configure.in >> configure.ac; rm configure.in; mkdir -p m4"
    configure_flags="--disable-shared"
    if [[ $uname == *MINGW* ]]; then
      prepare="$prepare; sed -i -e \"s/mpc2sv8//\" Makefile.am; sed -i -e \"s/\*mingw32\*/*mingw*/\" configure.ac"
      if [[ $arm64 == true ]]; then
        prepare="$prepare; sed -i -e \"s/const/extern const/\" libmpcdec/requant.h; sed -i -e \"s/__MINGW32__/__MINGWxx__/\" mpcenc/mpcenc.c"
      fi
    fi
    build $musepack_location "mpcenc/mpcenc.$execext mpcdec/mpcdec.$execext" "mpcenc.$execext mpcdec.$execext"

  elif [ $package == opus ]; then
    # Build Opus
    export CFLAGS="$CFLAGS -D_FORTIFY_SOURCE=0"
    if [[ $x86 == true ]]; then
      export CFLAGS="$CFLAGS -mfpmath=sse"
    fi
    configure_flags="--enable-float-approx --disable-hardening"
    if [[ $uname == Darwin ]] && [[ $x86_64 != true ]]; then
      configure_flags="$configure_flags --disable-intrinsics"
    fi
    build $opus_location .libs/libopus$sharedinfix.$sharedext Opus.$sharedext

  elif [ $package == rnnoise ]; then
    # Build RNNoise
    archive=rnnoise-${rnnoise_location##*/}.zip
    $DL $archive $rnnoise_location
    zip -d $archive rnnoise-$rnnoise_version/TRAINING
    build $archive .libs/librnnoise$sharedinfix.$sharedext RNNoise.$sharedext

  elif [ $package == rubberband ]; then
    # Build RubberBand
    export CXXFLAGS="$cflags $cflags_unroll"
    patches=${rubberband_patches[@]}
    patch_levels=(${rubberband_patch_levels[@]})
    configure_exports="FFTW_CFLAGS=\" \" FFTW_LIBS=\" \" SRC_CFLAGS=\" \" SRC_LIBS=\" \" Vamp_CFLAGS=\" \" Vamp_LIBS=\" \""
    if [[ $uname == *MINGW* ]]; then
      prepare="sed -i -e \"s/-fPIC//\" configure && sed -i -e \"s/-DNO_THREAD_CHECKS -DUSE_PTHREADS/-DUSE_OWN_ALIGNED_MALLOC/\" Makefile.in && sed -i -e \"s/-lpthread//\" Makefile.in && sed -i -e \"s/all:.*/all: bin lib \$\(DYNAMIC_TARGET\)/\" Makefile.in && sed -i -e \"s/:= .so/:= .dll/\" Makefile.in"
      configure_exports="$configure_exports SNDFILE_CFLAGS=\" \" SNDFILE_LIBS=\" \""
      if [[ $arm64 == true ]]; then
        prepare="$prepare; sed -i -e \"s/__asm__.*/__builtin_arm_dmb(1);/\" src/system/sysutils.cpp; sed -i -e \"s/: .*=r.*Barrier.*;//\" src/system/sysutils.cpp"
        prepare="$prepare; sed -i -e \"s/-Wl,-Bsymbolic//\" Makefile.in; sed -i -e \"s/-Wl,-soname.*//\" Makefile.in"
      fi
    elif [[ $uname == Darwin ]]; then
      prepare="sed -i -e \"s/-Wl,-Bsymbolic//\" Makefile.in && sed -i -e \"s/ -Wl,-soname=.*//\" Makefile.in && sed -i -e \"s/:= .so/:= .dylib/\" Makefile.in"
      configure_exports="$configure_exports SNDFILE_CFLAGS=\" \" SNDFILE_LIBS=\"-lsndfile\""
    else
      configure_exports="$configure_exports SNDFILE_CFLAGS=\" \" SNDFILE_LIBS=\"-lsndfile\""
    fi
    build $rubberband_location lib/librubberband.$sharedext RubberBand.$sharedext

  elif [ $package == speex ]; then
    # Build Speex
    if [[ $x86 == true ]]; then
      export CFLAGS="$cflags $cflags_unroll -mfpmath=sse"
    fi
    build $speex_location libspeex/.libs/libspeex$sharedinfix.$sharedext Speex.$sharedext

  elif [ $package == vorbis ]; then
    # Build Vorbis
    patches=${vorbis_patches[@]}
    patch_levels=(${vorbis_patch_levels[@]})
    if [[ $x86 != true ]]; then
      export CFLAGS="$cflags"
    else
      if [[ $uname == Darwin ]]; then
        export CFLAGS="$cflags -mno-sse"
      else
        export CFLAGS="$cflags -mfpmath=sse"
      fi
    fi
    if [[ $uname == *MINGW* ]]; then
      export CFLAGS="$CFLAGS -I$(pwd)/libogg-$libogg_version/include"
      export LDFLAGS="$LDFLAGS -L$(pwd)/libogg-$libogg_version/src/.libs"
    fi
    build $vorbis_location "lib/.libs/libvorbis$sharedinfix.$sharedext lib/.libs/libvorbisenc$sharedinfix.$sharedext" "Vorbis.$sharedext VorbisEnc.$sharedext"
    if [[ $uname == *MINGW* ]]; then
      sed -i -b -e "s/libogg-0.dll/Ogg.dll\x00\x00\x00\x00\x00/" Vorbis.$sharedext

      sed -i -b -e "s/libogg-0.dll/Ogg.dll\x00\x00\x00\x00\x00/" VorbisEnc.$sharedext
      sed -i -b -e "s/libvorbis-0.dll/Vorbis.dll\x00\x00\x00\x00\x00/" VorbisEnc.$sharedext
    fi

  elif [ $package == wavpack ]; then
    # Build WavPack
    configure_flags="--disable-shared"
    if [[ $uname == *MINGW* ]]; then
      configure_flags="$configure_flags --disable-asm"
      configure_exports="MSYSTEM=MINGW32"
    elif [[ $uname == Darwin ]]; then
      configure_flags="$configure_flags --disable-asm"
    fi
    build $wavpack_location "cli/wavpack.$execext cli/wvunpack.$execext" "wavpack.$execext wvunpack.$execext"
  fi
done
