diff --git a/Libraries/FLAC/flac-src/src/flac/.deps/analyze.Po b/Libraries/FLAC/flac-src/src/flac/.deps/analyze.Po new file mode 100644 index 000000000..9ce06a81e --- /dev/null +++ b/Libraries/FLAC/flac-src/src/flac/.deps/analyze.Po @@ -0,0 +1 @@ +# dummy diff --git a/Libraries/FLAC/flac-src/src/flac/.deps/decode.Po b/Libraries/FLAC/flac-src/src/flac/.deps/decode.Po new file mode 100644 index 000000000..9ce06a81e --- /dev/null +++ b/Libraries/FLAC/flac-src/src/flac/.deps/decode.Po @@ -0,0 +1 @@ +# dummy diff --git a/Libraries/FLAC/flac-src/src/flac/.deps/encode.Po b/Libraries/FLAC/flac-src/src/flac/.deps/encode.Po new file mode 100644 index 000000000..9ce06a81e --- /dev/null +++ b/Libraries/FLAC/flac-src/src/flac/.deps/encode.Po @@ -0,0 +1 @@ +# dummy diff --git a/Libraries/FLAC/flac-src/src/flac/.deps/local_string_utils.Po b/Libraries/FLAC/flac-src/src/flac/.deps/local_string_utils.Po new file mode 100644 index 000000000..9ce06a81e --- /dev/null +++ b/Libraries/FLAC/flac-src/src/flac/.deps/local_string_utils.Po @@ -0,0 +1 @@ +# dummy diff --git a/Libraries/FLAC/flac-src/src/flac/.deps/main.Po b/Libraries/FLAC/flac-src/src/flac/.deps/main.Po new file mode 100644 index 000000000..9ce06a81e --- /dev/null +++ b/Libraries/FLAC/flac-src/src/flac/.deps/main.Po @@ -0,0 +1 @@ +# dummy diff --git a/Libraries/FLAC/flac-src/src/flac/.deps/utils.Po b/Libraries/FLAC/flac-src/src/flac/.deps/utils.Po new file mode 100644 index 000000000..9ce06a81e --- /dev/null +++ b/Libraries/FLAC/flac-src/src/flac/.deps/utils.Po @@ -0,0 +1 @@ +# dummy diff --git a/Libraries/FLAC/flac-src/src/flac/.deps/vorbiscomment.Po b/Libraries/FLAC/flac-src/src/flac/.deps/vorbiscomment.Po new file mode 100644 index 000000000..9ce06a81e --- /dev/null +++ b/Libraries/FLAC/flac-src/src/flac/.deps/vorbiscomment.Po @@ -0,0 +1 @@ +# dummy diff --git a/Libraries/FLAC/flac-src/src/flac/Makefile b/Libraries/FLAC/flac-src/src/flac/Makefile new file mode 100644 index 000000000..587cea80f --- /dev/null +++ b/Libraries/FLAC/flac-src/src/flac/Makefile @@ -0,0 +1,577 @@ +# Makefile.in generated by automake 1.8.5 from Makefile.am. +# src/flac/Makefile. Generated from Makefile.in by configure. + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + + +# flac - Command-line FLAC encoder/decoder +# Copyright (C) 2000,2001,2002,2003,2004,2005 Josh Coalson +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +SOURCES = $(flac_SOURCES) + +srcdir = . +top_srcdir = ../.. + +pkgdatadir = $(datadir)/flac +pkglibdir = $(libdir)/flac +pkgincludedir = $(includedir)/flac +top_builddir = ../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = /usr/bin/install -c +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_triplet = powerpc-apple-darwin8.4.0 +bin_PROGRAMS = flac$(EXEEXT) +subdir = src/flac +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(mkdir_p) +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) +PROGRAMS = $(bin_PROGRAMS) +am_flac_OBJECTS = analyze.$(OBJEXT) decode.$(OBJEXT) encode.$(OBJEXT) \ + main.$(OBJEXT) local_string_utils.$(OBJEXT) utils.$(OBJEXT) \ + vorbiscomment.$(OBJEXT) +flac_OBJECTS = $(am_flac_OBJECTS) +#am__DEPENDENCIES_1 = $(top_builddir)/src/libOggFLAC/libOggFLAC.la +flac_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(top_builddir)/src/share/grabbag/libgrabbag.la \ + $(top_builddir)/src/share/getopt/libgetopt.a \ + $(top_builddir)/src/share/replaygain_analysis/libreplaygain_analysis.la \ + $(top_builddir)/src/share/replaygain_synthesis/libreplaygain_synthesis.la \ + $(top_builddir)/src/share/utf8/libutf8.la \ + $(top_builddir)/src/libFLAC/libFLAC.la +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +DEP_FILES = ./$(DEPDIR)/analyze.Po ./$(DEPDIR)/decode.Po \ + ./$(DEPDIR)/encode.Po \ + ./$(DEPDIR)/local_string_utils.Po \ + ./$(DEPDIR)/main.Po ./$(DEPDIR)/utils.Po \ + ./$(DEPDIR)/vorbiscomment.Po +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = $(flac_SOURCES) +DIST_SOURCES = $(flac_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = ${SHELL} /Users/me/Development/Frameworks/flac/flac-src/missing --run aclocal-1.8 +AMDEP_FALSE = # +AMDEP_TRUE = +AMTAR = ${SHELL} /Users/me/Development/Frameworks/flac/flac-src/missing --run tar +AS = as +AUTOCONF = ${SHELL} /Users/me/Development/Frameworks/flac/flac-src/missing --run autoconf +AUTOHEADER = ${SHELL} /Users/me/Development/Frameworks/flac/flac-src/missing --run autoheader +AUTOMAKE = ${SHELL} /Users/me/Development/Frameworks/flac/flac-src/missing --run automake-1.8 +AWK = awk +CC = gcc +CCAS = gcc +CCASFLAGS = -g -O2 +CCDEPMODE = depmode=gcc3 +CFLAGS = -I$(top_builddir) -I$(srcdir)/include -I$(top_srcdir)/include -O2 -DNDEBUG -O3 -fomit-frame-pointer -funroll-loops -finline-functions -Wall -W -Winline -DFLaC__INLINE=__inline__ -g -O2 +CPP = gcc -E +CPPFLAGS = +CXX = g++ +CXXDEPMODE = depmode=gcc3 +CXXFLAGS = -I$(top_builddir) -I$(srcdir)/include -I$(top_srcdir)/include -O2 -DNDEBUG -O3 -fomit-frame-pointer -funroll-loops -finline-functions -Wall -W -Winline -DFLaC__INLINE=__inline__ -g -O2 +CYGPATH_W = echo +DEBUG_FALSE = +DEBUG_TRUE = # +DEFS = -DHAVE_CONFIG_H +DEPDIR = .deps +DOCBOOK_TO_MAN = +DOXYGEN = +ECHO = echo +ECHO_C = +ECHO_N = -n +ECHO_T = +EGREP = grep -E +EXEEXT = +FLaC__CPU_IA32_FALSE = +FLaC__CPU_IA32_TRUE = # +FLaC__CPU_PPC_FALSE = # +FLaC__CPU_PPC_TRUE = +FLaC__CPU_SPARC_FALSE = +FLaC__CPU_SPARC_TRUE = # +FLaC__EXHAUSTIVE_TESTS_FALSE = +FLaC__EXHAUSTIVE_TESTS_TRUE = # +FLaC__HAS_AS_FALSE = # +FLaC__HAS_AS_TRUE = +FLaC__HAS_AS__TEMPORARILY_DISABLED_FALSE = +FLaC__HAS_AS__TEMPORARILY_DISABLED_TRUE = # +FLaC__HAS_DOCBOOK_TO_MAN_FALSE = +FLaC__HAS_DOCBOOK_TO_MAN_TRUE = # +FLaC__HAS_DOXYGEN_FALSE = +FLaC__HAS_DOXYGEN_TRUE = # +FLaC__HAS_GAS_FALSE = +FLaC__HAS_GAS_TRUE = # +FLaC__HAS_GAS__TEMPORARILY_DISABLED_FALSE = +FLaC__HAS_GAS__TEMPORARILY_DISABLED_TRUE = # +FLaC__HAS_NASM_FALSE = # +FLaC__HAS_NASM_TRUE = +FLaC__HAS_OGG_FALSE = +FLaC__HAS_OGG_TRUE = # +FLaC__HAS_XMMS_FALSE = +FLaC__HAS_XMMS_TRUE = # +FLaC__INSTALL_XMMS_PLUGIN_LOCALLY_FALSE = +FLaC__INSTALL_XMMS_PLUGIN_LOCALLY_TRUE = # +FLaC__NO_ASM_FALSE = +FLaC__NO_ASM_TRUE = # +FLaC__SSE_OS_FALSE = +FLaC__SSE_OS_TRUE = # +FLaC__SYS_DARWIN_FALSE = # +FLaC__SYS_DARWIN_TRUE = +FLaC__SYS_LINUX_FALSE = +FLaC__SYS_LINUX_TRUE = # +FLaC__USE_3DNOW_FALSE = # +FLaC__USE_3DNOW_TRUE = +FLaC__USE_ALTIVEC_FALSE = # +FLaC__USE_ALTIVEC_TRUE = +FLaC__VALGRIND_TESTING_FALSE = +FLaC__VALGRIND_TESTING_TRUE = # +GAS = +INSTALL_DATA = ${INSTALL} -m 644 +INSTALL_PROGRAM = ${INSTALL} +INSTALL_SCRIPT = ${INSTALL} +INSTALL_STRIP_PROGRAM = ${SHELL} $(install_sh) -c -s +LDFLAGS = +LIBICONV = -liconv +LIBOBJS = +LIBS = +LIBTOOL = $(SHELL) $(top_builddir)/libtool +LN_S = ln -s +LTLIBICONV = -liconv +LTLIBOBJS = +MAINT = # +MAINTAINER_MODE_FALSE = +MAINTAINER_MODE_TRUE = # +MAKEINFO = ${SHELL} /Users/me/Development/Frameworks/flac/flac-src/missing --run makeinfo +NASM = nasm +OBJEXT = o +OBJ_FORMAT = elf +OGG_CFLAGS = +OGG_LIBS = +PACKAGE = flac +PACKAGE_BUGREPORT = +PACKAGE_NAME = +PACKAGE_STRING = +PACKAGE_TARNAME = +PACKAGE_VERSION = +PATH_SEPARATOR = : +RANLIB = ranlib +SET_MAKE = +SHELL = /bin/sh +STRIP = strip +VERSION = 1.1.2 +XMMS_CFLAGS = +XMMS_CONFIG = no +XMMS_DATA_DIR = +XMMS_EFFECT_PLUGIN_DIR = +XMMS_GENERAL_PLUGIN_DIR = +XMMS_INPUT_PLUGIN_DIR = +XMMS_LIBS = +XMMS_OUTPUT_PLUGIN_DIR = +XMMS_PLUGIN_DIR = +XMMS_VERSION = +XMMS_VISUALIZATION_PLUGIN_DIR = +ac_ct_CC = gcc +ac_ct_CXX = g++ +ac_ct_RANLIB = ranlib +ac_ct_STRIP = strip +am__fastdepCC_FALSE = # +am__fastdepCC_TRUE = +am__fastdepCXX_FALSE = # +am__fastdepCXX_TRUE = +am__include = include +am__leading_dot = . +am__quote = +bindir = ${exec_prefix}/bin +build = powerpc-apple-darwin8.4.0 +build_alias = +build_cpu = powerpc +build_os = darwin8.4.0 +build_vendor = apple +datadir = ${prefix}/share +exec_prefix = ${prefix} +host = powerpc-apple-darwin8.4.0 +host_alias = +host_cpu = powerpc +host_os = darwin8.4.0 +host_vendor = apple +includedir = ${prefix}/include +infodir = ${prefix}/info +install_sh = /Users/me/Development/Frameworks/flac/flac-src/install-sh +libdir = ${exec_prefix}/lib +libexecdir = ${exec_prefix}/libexec +localstatedir = ${prefix}/var +mandir = ${prefix}/man +mkdir_p = $(install_sh) -d +oldincludedir = /usr/include +prefix = /usr/local +program_transform_name = s,x,x, +sbindir = ${exec_prefix}/sbin +sharedstatedir = ${prefix}/com +sysconfdir = ${prefix}/etc +target_alias = +AM_CFLAGS = +#NEED_OGGFLAC_LIB = $(top_builddir)/src/libOggFLAC/libOggFLAC.la +EXTRA_DIST = \ + Makefile.lite \ + flac.dsp + +flac_SOURCES = \ + analyze.c \ + decode.c \ + encode.c \ + main.c \ + local_string_utils.c \ + utils.c \ + vorbiscomment.c \ + analyze.h \ + decode.h \ + encode.h \ + local_string_utils.h \ + utils.h \ + vorbiscomment.h + +flac_LDADD = \ + $(NEED_OGGFLAC_LIB) \ + $(top_builddir)/src/share/grabbag/libgrabbag.la \ + $(top_builddir)/src/share/getopt/libgetopt.a \ + $(top_builddir)/src/share/replaygain_analysis/libreplaygain_analysis.la \ + $(top_builddir)/src/share/replaygain_synthesis/libreplaygain_synthesis.la \ + $(top_builddir)/src/share/utf8/libutf8.la \ + $(top_builddir)/src/libFLAC/libFLAC.la \ + \ + -liconv \ + -lm + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: # $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/flac/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/flac/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: # $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): # $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)" + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + || test -f $$p1 \ + ; then \ + f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ + rm -f "$(DESTDIR)$(bindir)/$$f"; \ + done + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f $$p $$f"; \ + rm -f $$p $$f ; \ + done +flac$(EXEEXT): $(flac_OBJECTS) $(flac_DEPENDENCIES) + @rm -f flac$(EXEEXT) + $(LINK) $(flac_LDFLAGS) $(flac_OBJECTS) $(flac_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +include ./$(DEPDIR)/analyze.Po +include ./$(DEPDIR)/decode.Po +include ./$(DEPDIR)/encode.Po +include ./$(DEPDIR)/local_string_utils.Po +include ./$(DEPDIR)/main.Po +include ./$(DEPDIR)/utils.Po +include ./$(DEPDIR)/vorbiscomment.Po + +.c.o: + if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ + then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +# source='$<' object='$@' libtool=no \ +# depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' \ +# $(CCDEPMODE) $(depcomp) \ +# $(COMPILE) -c $< + +.c.obj: + if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ + then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +# source='$<' object='$@' libtool=no \ +# depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' \ +# $(CCDEPMODE) $(depcomp) \ +# $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: + if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ + then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +# source='$<' object='$@' libtool=yes \ +# depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' \ +# $(CCDEPMODE) $(depcomp) \ +# $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: install-binPROGRAMS + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS uninstall-info-am + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ + clean-generic clean-libtool ctags distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-binPROGRAMS install-data install-data-am install-exec \ + install-exec-am install-info install-info-am install-man \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am \ + uninstall-binPROGRAMS uninstall-info-am + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/Libraries/FLAC/flac-src/src/flac/Makefile.am b/Libraries/FLAC/flac-src/src/flac/Makefile.am new file mode 100644 index 000000000..e685c0b01 --- /dev/null +++ b/Libraries/FLAC/flac-src/src/flac/Makefile.am @@ -0,0 +1,55 @@ +# flac - Command-line FLAC encoder/decoder +# Copyright (C) 2000,2001,2002,2003,2004,2005 Josh Coalson +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +bin_PROGRAMS = flac + +AM_CFLAGS = @OGG_CFLAGS@ + +if FLaC__HAS_OGG +NEED_OGGFLAC_LIB = $(top_builddir)/src/libOggFLAC/libOggFLAC.la +endif + +EXTRA_DIST = \ + Makefile.lite \ + flac.dsp + +flac_SOURCES = \ + analyze.c \ + decode.c \ + encode.c \ + main.c \ + local_string_utils.c \ + utils.c \ + vorbiscomment.c \ + analyze.h \ + decode.h \ + encode.h \ + local_string_utils.h \ + utils.h \ + vorbiscomment.h + +flac_LDADD = \ + $(NEED_OGGFLAC_LIB) \ + $(top_builddir)/src/share/grabbag/libgrabbag.la \ + $(top_builddir)/src/share/getopt/libgetopt.a \ + $(top_builddir)/src/share/replaygain_analysis/libreplaygain_analysis.la \ + $(top_builddir)/src/share/replaygain_synthesis/libreplaygain_synthesis.la \ + $(top_builddir)/src/share/utf8/libutf8.la \ + $(top_builddir)/src/libFLAC/libFLAC.la \ + @OGG_LIBS@ \ + @LIBICONV@ \ + -lm diff --git a/Libraries/FLAC/flac-src/src/flac/Makefile.in b/Libraries/FLAC/flac-src/src/flac/Makefile.in new file mode 100644 index 000000000..a3b359448 --- /dev/null +++ b/Libraries/FLAC/flac-src/src/flac/Makefile.in @@ -0,0 +1,577 @@ +# Makefile.in generated by automake 1.8.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# flac - Command-line FLAC encoder/decoder +# Copyright (C) 2000,2001,2002,2003,2004,2005 Josh Coalson +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +SOURCES = $(flac_SOURCES) + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_triplet = @host@ +bin_PROGRAMS = flac$(EXEEXT) +subdir = src/flac +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(mkdir_p) +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) +PROGRAMS = $(bin_PROGRAMS) +am_flac_OBJECTS = analyze.$(OBJEXT) decode.$(OBJEXT) encode.$(OBJEXT) \ + main.$(OBJEXT) local_string_utils.$(OBJEXT) utils.$(OBJEXT) \ + vorbiscomment.$(OBJEXT) +flac_OBJECTS = $(am_flac_OBJECTS) +@FLaC__HAS_OGG_TRUE@am__DEPENDENCIES_1 = $(top_builddir)/src/libOggFLAC/libOggFLAC.la +flac_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(top_builddir)/src/share/grabbag/libgrabbag.la \ + $(top_builddir)/src/share/getopt/libgetopt.a \ + $(top_builddir)/src/share/replaygain_analysis/libreplaygain_analysis.la \ + $(top_builddir)/src/share/replaygain_synthesis/libreplaygain_synthesis.la \ + $(top_builddir)/src/share/utf8/libutf8.la \ + $(top_builddir)/src/libFLAC/libFLAC.la +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/analyze.Po ./$(DEPDIR)/decode.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/encode.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/local_string_utils.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/main.Po ./$(DEPDIR)/utils.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/vorbiscomment.Po +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = $(flac_SOURCES) +DIST_SOURCES = $(flac_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEBUG_FALSE = @DEBUG_FALSE@ +DEBUG_TRUE = @DEBUG_TRUE@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DOCBOOK_TO_MAN = @DOCBOOK_TO_MAN@ +DOXYGEN = @DOXYGEN@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FLaC__CPU_IA32_FALSE = @FLaC__CPU_IA32_FALSE@ +FLaC__CPU_IA32_TRUE = @FLaC__CPU_IA32_TRUE@ +FLaC__CPU_PPC_FALSE = @FLaC__CPU_PPC_FALSE@ +FLaC__CPU_PPC_TRUE = @FLaC__CPU_PPC_TRUE@ +FLaC__CPU_SPARC_FALSE = @FLaC__CPU_SPARC_FALSE@ +FLaC__CPU_SPARC_TRUE = @FLaC__CPU_SPARC_TRUE@ +FLaC__EXHAUSTIVE_TESTS_FALSE = @FLaC__EXHAUSTIVE_TESTS_FALSE@ +FLaC__EXHAUSTIVE_TESTS_TRUE = @FLaC__EXHAUSTIVE_TESTS_TRUE@ +FLaC__HAS_AS_FALSE = @FLaC__HAS_AS_FALSE@ +FLaC__HAS_AS_TRUE = @FLaC__HAS_AS_TRUE@ +FLaC__HAS_AS__TEMPORARILY_DISABLED_FALSE = @FLaC__HAS_AS__TEMPORARILY_DISABLED_FALSE@ +FLaC__HAS_AS__TEMPORARILY_DISABLED_TRUE = @FLaC__HAS_AS__TEMPORARILY_DISABLED_TRUE@ +FLaC__HAS_DOCBOOK_TO_MAN_FALSE = @FLaC__HAS_DOCBOOK_TO_MAN_FALSE@ +FLaC__HAS_DOCBOOK_TO_MAN_TRUE = @FLaC__HAS_DOCBOOK_TO_MAN_TRUE@ +FLaC__HAS_DOXYGEN_FALSE = @FLaC__HAS_DOXYGEN_FALSE@ +FLaC__HAS_DOXYGEN_TRUE = @FLaC__HAS_DOXYGEN_TRUE@ +FLaC__HAS_GAS_FALSE = @FLaC__HAS_GAS_FALSE@ +FLaC__HAS_GAS_TRUE = @FLaC__HAS_GAS_TRUE@ +FLaC__HAS_GAS__TEMPORARILY_DISABLED_FALSE = @FLaC__HAS_GAS__TEMPORARILY_DISABLED_FALSE@ +FLaC__HAS_GAS__TEMPORARILY_DISABLED_TRUE = @FLaC__HAS_GAS__TEMPORARILY_DISABLED_TRUE@ +FLaC__HAS_NASM_FALSE = @FLaC__HAS_NASM_FALSE@ +FLaC__HAS_NASM_TRUE = @FLaC__HAS_NASM_TRUE@ +FLaC__HAS_OGG_FALSE = @FLaC__HAS_OGG_FALSE@ +FLaC__HAS_OGG_TRUE = @FLaC__HAS_OGG_TRUE@ +FLaC__HAS_XMMS_FALSE = @FLaC__HAS_XMMS_FALSE@ +FLaC__HAS_XMMS_TRUE = @FLaC__HAS_XMMS_TRUE@ +FLaC__INSTALL_XMMS_PLUGIN_LOCALLY_FALSE = @FLaC__INSTALL_XMMS_PLUGIN_LOCALLY_FALSE@ +FLaC__INSTALL_XMMS_PLUGIN_LOCALLY_TRUE = @FLaC__INSTALL_XMMS_PLUGIN_LOCALLY_TRUE@ +FLaC__NO_ASM_FALSE = @FLaC__NO_ASM_FALSE@ +FLaC__NO_ASM_TRUE = @FLaC__NO_ASM_TRUE@ +FLaC__SSE_OS_FALSE = @FLaC__SSE_OS_FALSE@ +FLaC__SSE_OS_TRUE = @FLaC__SSE_OS_TRUE@ +FLaC__SYS_DARWIN_FALSE = @FLaC__SYS_DARWIN_FALSE@ +FLaC__SYS_DARWIN_TRUE = @FLaC__SYS_DARWIN_TRUE@ +FLaC__SYS_LINUX_FALSE = @FLaC__SYS_LINUX_FALSE@ +FLaC__SYS_LINUX_TRUE = @FLaC__SYS_LINUX_TRUE@ +FLaC__USE_3DNOW_FALSE = @FLaC__USE_3DNOW_FALSE@ +FLaC__USE_3DNOW_TRUE = @FLaC__USE_3DNOW_TRUE@ +FLaC__USE_ALTIVEC_FALSE = @FLaC__USE_ALTIVEC_FALSE@ +FLaC__USE_ALTIVEC_TRUE = @FLaC__USE_ALTIVEC_TRUE@ +FLaC__VALGRIND_TESTING_FALSE = @FLaC__VALGRIND_TESTING_FALSE@ +FLaC__VALGRIND_TESTING_TRUE = @FLaC__VALGRIND_TESTING_TRUE@ +GAS = @GAS@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBICONV = @LIBICONV@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ +MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ +MAKEINFO = @MAKEINFO@ +NASM = @NASM@ +OBJEXT = @OBJEXT@ +OBJ_FORMAT = @OBJ_FORMAT@ +OGG_CFLAGS = @OGG_CFLAGS@ +OGG_LIBS = @OGG_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +XMMS_CFLAGS = @XMMS_CFLAGS@ +XMMS_CONFIG = @XMMS_CONFIG@ +XMMS_DATA_DIR = @XMMS_DATA_DIR@ +XMMS_EFFECT_PLUGIN_DIR = @XMMS_EFFECT_PLUGIN_DIR@ +XMMS_GENERAL_PLUGIN_DIR = @XMMS_GENERAL_PLUGIN_DIR@ +XMMS_INPUT_PLUGIN_DIR = @XMMS_INPUT_PLUGIN_DIR@ +XMMS_LIBS = @XMMS_LIBS@ +XMMS_OUTPUT_PLUGIN_DIR = @XMMS_OUTPUT_PLUGIN_DIR@ +XMMS_PLUGIN_DIR = @XMMS_PLUGIN_DIR@ +XMMS_VERSION = @XMMS_VERSION@ +XMMS_VISUALIZATION_PLUGIN_DIR = @XMMS_VISUALIZATION_PLUGIN_DIR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_RANLIB = @ac_ct_RANLIB@ +ac_ct_STRIP = @ac_ct_STRIP@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +AM_CFLAGS = @OGG_CFLAGS@ +@FLaC__HAS_OGG_TRUE@NEED_OGGFLAC_LIB = $(top_builddir)/src/libOggFLAC/libOggFLAC.la +EXTRA_DIST = \ + Makefile.lite \ + flac.dsp + +flac_SOURCES = \ + analyze.c \ + decode.c \ + encode.c \ + main.c \ + local_string_utils.c \ + utils.c \ + vorbiscomment.c \ + analyze.h \ + decode.h \ + encode.h \ + local_string_utils.h \ + utils.h \ + vorbiscomment.h + +flac_LDADD = \ + $(NEED_OGGFLAC_LIB) \ + $(top_builddir)/src/share/grabbag/libgrabbag.la \ + $(top_builddir)/src/share/getopt/libgetopt.a \ + $(top_builddir)/src/share/replaygain_analysis/libreplaygain_analysis.la \ + $(top_builddir)/src/share/replaygain_synthesis/libreplaygain_synthesis.la \ + $(top_builddir)/src/share/utf8/libutf8.la \ + $(top_builddir)/src/libFLAC/libFLAC.la \ + @OGG_LIBS@ \ + @LIBICONV@ \ + -lm + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/flac/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/flac/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)" + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + || test -f $$p1 \ + ; then \ + f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ + rm -f "$(DESTDIR)$(bindir)/$$f"; \ + done + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f $$p $$f"; \ + rm -f $$p $$f ; \ + done +flac$(EXEEXT): $(flac_OBJECTS) $(flac_DEPENDENCIES) + @rm -f flac$(EXEEXT) + $(LINK) $(flac_LDFLAGS) $(flac_OBJECTS) $(flac_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/analyze.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decode.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encode.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/local_string_utils.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vorbiscomment.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: install-binPROGRAMS + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS uninstall-info-am + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ + clean-generic clean-libtool ctags distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-binPROGRAMS install-data install-data-am install-exec \ + install-exec-am install-info install-info-am install-man \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am \ + uninstall-binPROGRAMS uninstall-info-am + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/Libraries/FLAC/flac-src/src/flac/Makefile.lite b/Libraries/FLAC/flac-src/src/flac/Makefile.lite new file mode 100644 index 000000000..48231f462 --- /dev/null +++ b/Libraries/FLAC/flac-src/src/flac/Makefile.lite @@ -0,0 +1,46 @@ +# flac - Command-line FLAC encoder/decoder +# Copyright (C) 2000,2001,2002,2003,2004,2005 Josh Coalson +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# +# GNU makefile +# + +topdir = ../.. +libdir = $(topdir)/obj/$(BUILD)/lib + +PROGRAM_NAME = flac + +INCLUDES = -I./include -I$(topdir)/include -I$(OGG_INCLUDE_DIR) + +ifeq ($(DARWIN_BUILD),yes) +EXPLICIT_LIBS = $(libdir)/libgrabbag.a $(libdir)/libOggFLAC.a $(libdir)/libFLAC.a $(libdir)/libreplaygain_analysis.a $(libdir)/libreplaygain_synthesis.a $(libdir)/libgetopt.a $(libdir)/libutf8.a $(OGG_LIB_DIR)/libogg.a -L$(ICONV_LIB_DIR) -liconv -lm +else +LIBS = -lgrabbag -lOggFLAC -lFLAC -lreplaygain_analysis -lreplaygain_synthesis -lgetopt -lutf8 -L$(OGG_LIB_DIR) -logg -L$(ICONV_LIB_DIR) -liconv -lm +endif + +SRCS_C = \ + analyze.c \ + decode.c \ + encode.c \ + local_string_utils.c \ + main.c \ + utils.c \ + vorbiscomment.c + +include $(topdir)/build/exe.mk + +# DO NOT DELETE THIS LINE -- make depend depends on it. diff --git a/Libraries/FLAC/flac-src/src/flac/analyze.c b/Libraries/FLAC/flac-src/src/flac/analyze.c new file mode 100644 index 000000000..f12abb2a3 --- /dev/null +++ b/Libraries/FLAC/flac-src/src/flac/analyze.c @@ -0,0 +1,234 @@ +/* flac - Command-line FLAC encoder/decoder + * Copyright (C) 2000,2001,2002,2003,2004,2005 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include "FLAC/all.h" +#include "analyze.h" + +typedef struct { + FLAC__int32 residual; + unsigned count; +} pair_t; + +typedef struct { + pair_t buckets[FLAC__MAX_BLOCK_SIZE]; + int peak_index; + unsigned nbuckets; + unsigned nsamples; + double sum, sos; + double variance; + double mean; + double stddev; +} subframe_stats_t; + +static subframe_stats_t all_; + +static void init_stats(subframe_stats_t *stats); +static void update_stats(subframe_stats_t *stats, FLAC__int32 residual, unsigned incr); +static void compute_stats(subframe_stats_t *stats); +static FLAC__bool dump_stats(const subframe_stats_t *stats, const char *filename); + +void flac__analyze_init(analysis_options aopts) +{ + if(aopts.do_residual_gnuplot) { + init_stats(&all_); + } +} + +void flac__analyze_frame(const FLAC__Frame *frame, unsigned frame_number, analysis_options aopts, FILE *fout) +{ + const unsigned channels = frame->header.channels; + char outfilename[1024]; + subframe_stats_t stats; + unsigned i, channel; + + /* do the human-readable part first */ + fprintf(fout, "frame=%u\tblocksize=%u\tsample_rate=%u\tchannels=%u\tchannel_assignment=%s\n", frame_number, frame->header.blocksize, frame->header.sample_rate, channels, FLAC__ChannelAssignmentString[frame->header.channel_assignment]); + for(channel = 0; channel < channels; channel++) { + const FLAC__Subframe *subframe = frame->subframes+channel; + fprintf(fout, "\tsubframe=%u\twasted_bits=%u\ttype=%s", channel, subframe->wasted_bits, FLAC__SubframeTypeString[subframe->type]); + switch(subframe->type) { + case FLAC__SUBFRAME_TYPE_CONSTANT: + fprintf(fout, "\tvalue=%d\n", subframe->data.constant.value); + break; + case FLAC__SUBFRAME_TYPE_FIXED: + FLAC__ASSERT(subframe->data.fixed.entropy_coding_method.type == FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE); + fprintf(fout, "\torder=%u\tpartition_order=%u\n", subframe->data.fixed.order, subframe->data.fixed.entropy_coding_method.data.partitioned_rice.order); + for(i = 0; i < subframe->data.fixed.order; i++) + fprintf(fout, "\t\twarmup[%u]=%d\n", i, subframe->data.fixed.warmup[i]); + if(aopts.do_residual_text) { + const unsigned partitions = (1u << subframe->data.fixed.entropy_coding_method.data.partitioned_rice.order); + for(i = 0; i < partitions; i++) { + unsigned parameter = subframe->data.fixed.entropy_coding_method.data.partitioned_rice.contents->parameters[i]; + if(parameter == FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) + fprintf(fout, "\t\tparameter[%u]=ESCAPE, raw_bits=%u\n", i, subframe->data.fixed.entropy_coding_method.data.partitioned_rice.contents->raw_bits[i]); + else + fprintf(fout, "\t\tparameter[%u]=%u\n", i, parameter); + } + for(i = 0; i < frame->header.blocksize-subframe->data.fixed.order; i++) + fprintf(fout, "\t\tresidual[%u]=%d\n", i, subframe->data.fixed.residual[i]); + } + break; + case FLAC__SUBFRAME_TYPE_LPC: + FLAC__ASSERT(subframe->data.lpc.entropy_coding_method.type == FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE); + fprintf(fout, "\torder=%u\tpartition_order=%u\tqlp_coeff_precision=%u\tquantization_level=%d\n", subframe->data.lpc.order, subframe->data.lpc.entropy_coding_method.data.partitioned_rice.order, subframe->data.lpc.qlp_coeff_precision, subframe->data.lpc.quantization_level); + for(i = 0; i < subframe->data.lpc.order; i++) + fprintf(fout, "\t\twarmup[%u]=%d\n", i, subframe->data.lpc.warmup[i]); + if(aopts.do_residual_text) { + const unsigned partitions = (1u << subframe->data.lpc.entropy_coding_method.data.partitioned_rice.order); + for(i = 0; i < partitions; i++) { + unsigned parameter = subframe->data.lpc.entropy_coding_method.data.partitioned_rice.contents->parameters[i]; + if(parameter == FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) + fprintf(fout, "\t\tparameter[%u]=ESCAPE, raw_bits=%u\n", i, subframe->data.lpc.entropy_coding_method.data.partitioned_rice.contents->raw_bits[i]); + else + fprintf(fout, "\t\tparameter[%u]=%u\n", i, parameter); + } + for(i = 0; i < frame->header.blocksize-subframe->data.lpc.order; i++) + fprintf(fout, "\t\tresidual[%u]=%d\n", i, subframe->data.lpc.residual[i]); + } + break; + case FLAC__SUBFRAME_TYPE_VERBATIM: + fprintf(fout, "\n"); + break; + } + } + + /* now do the residual distributions if requested */ + if(aopts.do_residual_gnuplot) { + for(channel = 0; channel < channels; channel++) { + const FLAC__Subframe *subframe = frame->subframes+channel; + unsigned residual_samples; + + init_stats(&stats); + + switch(subframe->type) { + case FLAC__SUBFRAME_TYPE_FIXED: + residual_samples = frame->header.blocksize - subframe->data.fixed.order; + for(i = 0; i < residual_samples; i++) + update_stats(&stats, subframe->data.fixed.residual[i], 1); + break; + case FLAC__SUBFRAME_TYPE_LPC: + residual_samples = frame->header.blocksize - subframe->data.lpc.order; + for(i = 0; i < residual_samples; i++) + update_stats(&stats, subframe->data.lpc.residual[i], 1); + break; + default: + break; + } + + /* update all_ */ + for(i = 0; i < stats.nbuckets; i++) { + update_stats(&all_, stats.buckets[i].residual, stats.buckets[i].count); + } + + /* write the subframe */ + sprintf(outfilename, "f%06u.s%u.gp", frame_number, channel); + compute_stats(&stats); + + (void)dump_stats(&stats, outfilename); + } + } +} + +void flac__analyze_finish(analysis_options aopts) +{ + if(aopts.do_residual_gnuplot) { + compute_stats(&all_); + (void)dump_stats(&all_, "all"); + } +} + +void init_stats(subframe_stats_t *stats) +{ + stats->peak_index = -1; + stats->nbuckets = 0; + stats->nsamples = 0; + stats->sum = 0.0; + stats->sos = 0.0; +} + +void update_stats(subframe_stats_t *stats, FLAC__int32 residual, unsigned incr) +{ + unsigned i; + const double r = (double)residual, a = r*incr; + + stats->nsamples += incr; + stats->sum += a; + stats->sos += (a*r); + + for(i = 0; i < stats->nbuckets; i++) { + if(stats->buckets[i].residual == residual) { + stats->buckets[i].count += incr; + goto find_peak; + } + } + /* not found, make a new bucket */ + i = stats->nbuckets; + stats->buckets[i].residual = residual; + stats->buckets[i].count = incr; + stats->nbuckets++; +find_peak: + if(stats->peak_index < 0 || stats->buckets[i].count > stats->buckets[stats->peak_index].count) + stats->peak_index = i; +} + +void compute_stats(subframe_stats_t *stats) +{ + stats->mean = stats->sum / (double)stats->nsamples; + stats->variance = (stats->sos - (stats->sum * stats->sum / stats->nsamples)) / stats->nsamples; + stats->stddev = sqrt(stats->variance); +} + +FLAC__bool dump_stats(const subframe_stats_t *stats, const char *filename) +{ + FILE *outfile; + unsigned i; + const double m = stats->mean; + const double s1 = stats->stddev, s2 = s1*2, s3 = s1*3, s4 = s1*4, s5 = s1*5, s6 = s1*6; + const double p = stats->buckets[stats->peak_index].count; + + outfile = fopen(filename, "w"); + + if(0 == outfile) { + fprintf(stderr, "ERROR opening %s\n", filename); + return false; + } + + fprintf(outfile, "plot '-' title 'PDF', '-' title 'mean' with impulses, '-' title '1-stddev' with histeps, '-' title '2-stddev' with histeps, '-' title '3-stddev' with histeps, '-' title '4-stddev' with histeps, '-' title '5-stddev' with histeps, '-' title '6-stddev' with histeps\n"); + + for(i = 0; i < stats->nbuckets; i++) { + fprintf(outfile, "%d %u\n", stats->buckets[i].residual, stats->buckets[i].count); + } + fprintf(outfile, "e\n"); + + fprintf(outfile, "%f %f\ne\n", stats->mean, p); + fprintf(outfile, "%f %f\n%f %f\ne\n", m-s1, p*0.8, m+s1, p*0.8); + fprintf(outfile, "%f %f\n%f %f\ne\n", m-s2, p*0.7, m+s2, p*0.7); + fprintf(outfile, "%f %f\n%f %f\ne\n", m-s3, p*0.6, m+s3, p*0.6); + fprintf(outfile, "%f %f\n%f %f\ne\n", m-s4, p*0.5, m+s4, p*0.5); + fprintf(outfile, "%f %f\n%f %f\ne\n", m-s5, p*0.4, m+s5, p*0.4); + fprintf(outfile, "%f %f\n%f %f\ne\n", m-s6, p*0.3, m+s6, p*0.3); + + fprintf(outfile, "pause -1 'waiting...'\n"); + + fclose(outfile); + return true; +} diff --git a/Libraries/FLAC/flac-src/src/flac/analyze.h b/Libraries/FLAC/flac-src/src/flac/analyze.h new file mode 100644 index 000000000..eccbeaa46 --- /dev/null +++ b/Libraries/FLAC/flac-src/src/flac/analyze.h @@ -0,0 +1,31 @@ +/* flac - Command-line FLAC encoder/decoder + * Copyright (C) 2000,2001,2002,2003,2004,2005 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef flac__analyze_h +#define flac__analyze_h + +typedef struct { + FLAC__bool do_residual_text; + FLAC__bool do_residual_gnuplot; +} analysis_options; + +void flac__analyze_init(analysis_options aopts); +void flac__analyze_frame(const FLAC__Frame *frame, unsigned frame_number, analysis_options aopts, FILE *fout); +void flac__analyze_finish(analysis_options aopts); + +#endif diff --git a/Libraries/FLAC/flac-src/src/flac/decode.c b/Libraries/FLAC/flac-src/src/flac/decode.c new file mode 100644 index 000000000..c1ca7abb5 --- /dev/null +++ b/Libraries/FLAC/flac-src/src/flac/decode.c @@ -0,0 +1,1207 @@ +/* flac - Command-line FLAC encoder/decoder + * Copyright (C) 2000,2001,2002,2003,2004,2005 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#if defined _WIN32 && !defined __CYGWIN__ +/* where MSVC puts unlink() */ +# include +#else +# include +#endif +#include +#include /* for floor() */ +#include /* for FILE et al. */ +#include /* for strcmp() */ +#include "FLAC/all.h" +#include "share/grabbag.h" +#include "share/replaygain_synthesis.h" +#include "decode.h" + +#ifdef FLAC__HAS_OGG +#include "OggFLAC/file_decoder.h" +#endif + +typedef struct { +#ifdef FLAC__HAS_OGG + FLAC__bool is_ogg; +#endif + + FLAC__bool is_aiff_out; + FLAC__bool is_wave_out; + FLAC__bool continue_through_decode_errors; + + struct { + replaygain_synthesis_spec_t spec; + FLAC__bool apply; /* 'spec.apply' is just a request; this 'apply' means we actually parsed the RG tags and are ready to go */ + double scale; + DitherContext dither_context; + } replaygain; + + FLAC__bool test_only; + FLAC__bool analysis_mode; + analysis_options aopts; + utils__SkipUntilSpecification *skip_specification; + utils__SkipUntilSpecification *until_specification; /* a canonicalized value of 0 mean end-of-stream (i.e. --until=-0) */ + utils__CueSpecification *cue_specification; + + const char *inbasefilename; + const char *outfilename; + + FLAC__uint64 samples_processed; + unsigned frame_counter; + FLAC__bool abort_flag; + FLAC__bool aborting_due_to_until; /* true if we intentionally abort decoding prematurely because we hit the --until point */ + + struct { + FLAC__bool needs_fixup; + unsigned riff_offset; /* or FORM offset for AIFF */ + unsigned data_offset; /* or SSND offset for AIFF */ + unsigned frames_offset; /* AIFF only */ + } wave_chunk_size_fixup; + + FLAC__bool is_big_endian; + FLAC__bool is_unsigned_samples; + FLAC__uint64 total_samples; + unsigned bps; + unsigned channels; + unsigned sample_rate; + + union { + union { + FLAC__FileDecoder *file; + } flac; +#ifdef FLAC__HAS_OGG + union { + OggFLAC__FileDecoder *file; + } ogg; +#endif + } decoder; + + FILE *fout; +} DecoderSession; + + +static FLAC__bool is_big_endian_host_; + + +/* + * local routines + */ +static FLAC__bool DecoderSession_construct(DecoderSession *d, FLAC__bool is_ogg, FLAC__bool is_aiff_out, FLAC__bool is_wave_out, FLAC__bool continue_through_decode_errors, replaygain_synthesis_spec_t replaygain_synthesis_spec, FLAC__bool analysis_mode, analysis_options aopts, utils__SkipUntilSpecification *skip_specification, utils__SkipUntilSpecification *until_specification, utils__CueSpecification *cue_specification, const char *infilename, const char *outfilename); +static void DecoderSession_destroy(DecoderSession *d, FLAC__bool error_occurred); +static FLAC__bool DecoderSession_init_decoder(DecoderSession *d, decode_options_t decode_options, const char *infilename); +static FLAC__bool DecoderSession_process(DecoderSession *d); +static int DecoderSession_finish_ok(DecoderSession *d); +static int DecoderSession_finish_error(DecoderSession *d); +static FLAC__bool canonicalize_until_specification(utils__SkipUntilSpecification *spec, const char *inbasefilename, unsigned sample_rate, FLAC__uint64 skip, FLAC__uint64 total_samples_in_input); +static FLAC__bool write_necessary_headers(DecoderSession *decoder_session); +static FLAC__bool write_little_endian_uint16(FILE *f, FLAC__uint16 val); +static FLAC__bool write_little_endian_uint32(FILE *f, FLAC__uint32 val); +static FLAC__bool write_big_endian_uint16(FILE *f, FLAC__uint16 val); +static FLAC__bool write_big_endian_uint32(FILE *f, FLAC__uint32 val); +static FLAC__bool write_sane_extended(FILE *f, unsigned val); +static FLAC__bool fixup_wave_chunk_size(const char *outfilename, FLAC__bool is_wave_out, unsigned riff_offset, unsigned data_offset, unsigned frames_offset, FLAC__uint32 total_samples, unsigned channels, unsigned bps); +/* + * We use 'void *' so that we can use the same callbacks for the + * FLAC__StreamDecoder and FLAC__FileDecoder. The 'decoder' argument is + * actually never used in the callbacks. + */ +static FLAC__StreamDecoderWriteStatus write_callback(const void *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data); +static void metadata_callback(const void *decoder, const FLAC__StreamMetadata *metadata, void *client_data); +static void error_callback(const void *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data); +static void print_error_with_state(const DecoderSession *d, const char *message); +static void print_stats(const DecoderSession *decoder_session); + + +/* + * public routines + */ +int flac__decode_aiff(const char *infilename, const char *outfilename, FLAC__bool analysis_mode, analysis_options aopts, wav_decode_options_t options) +{ + DecoderSession decoder_session; + + if(! + DecoderSession_construct( + &decoder_session, +#ifdef FLAC__HAS_OGG + options.common.is_ogg, +#else + /*is_ogg=*/false, +#endif + /*is_aiff_out=*/true, + /*is_wave_out=*/false, + options.common.continue_through_decode_errors, + options.common.replaygain_synthesis_spec, + analysis_mode, + aopts, + &options.common.skip_specification, + &options.common.until_specification, + options.common.has_cue_specification? &options.common.cue_specification : 0, + infilename, + outfilename + ) + ) + return 1; + + if(!DecoderSession_init_decoder(&decoder_session, options.common, infilename)) + return DecoderSession_finish_error(&decoder_session); + + if(!DecoderSession_process(&decoder_session)) + return DecoderSession_finish_error(&decoder_session); + + return DecoderSession_finish_ok(&decoder_session); +} + +int flac__decode_wav(const char *infilename, const char *outfilename, FLAC__bool analysis_mode, analysis_options aopts, wav_decode_options_t options) +{ + DecoderSession decoder_session; + + if(! + DecoderSession_construct( + &decoder_session, +#ifdef FLAC__HAS_OGG + options.common.is_ogg, +#else + /*is_ogg=*/false, +#endif + /*is_aiff_out=*/false, + /*is_wave_out=*/true, + options.common.continue_through_decode_errors, + options.common.replaygain_synthesis_spec, + analysis_mode, + aopts, + &options.common.skip_specification, + &options.common.until_specification, + options.common.has_cue_specification? &options.common.cue_specification : 0, + infilename, + outfilename + ) + ) + return 1; + + if(!DecoderSession_init_decoder(&decoder_session, options.common, infilename)) + return DecoderSession_finish_error(&decoder_session); + + if(!DecoderSession_process(&decoder_session)) + return DecoderSession_finish_error(&decoder_session); + + return DecoderSession_finish_ok(&decoder_session); +} + +int flac__decode_raw(const char *infilename, const char *outfilename, FLAC__bool analysis_mode, analysis_options aopts, raw_decode_options_t options) +{ + DecoderSession decoder_session; + + decoder_session.is_big_endian = options.is_big_endian; + decoder_session.is_unsigned_samples = options.is_unsigned_samples; + + if(! + DecoderSession_construct( + &decoder_session, +#ifdef FLAC__HAS_OGG + options.common.is_ogg, +#else + /*is_ogg=*/false, +#endif + /*is_aiff_out=*/false, + /*is_wave_out=*/false, + options.common.continue_through_decode_errors, + options.common.replaygain_synthesis_spec, + analysis_mode, + aopts, + &options.common.skip_specification, + &options.common.until_specification, + options.common.has_cue_specification? &options.common.cue_specification : 0, + infilename, + outfilename + ) + ) + return 1; + + if(!DecoderSession_init_decoder(&decoder_session, options.common, infilename)) + return DecoderSession_finish_error(&decoder_session); + + if(!DecoderSession_process(&decoder_session)) + return DecoderSession_finish_error(&decoder_session); + + return DecoderSession_finish_ok(&decoder_session); +} + +FLAC__bool DecoderSession_construct(DecoderSession *d, FLAC__bool is_ogg, FLAC__bool is_aiff_out, FLAC__bool is_wave_out, FLAC__bool continue_through_decode_errors, replaygain_synthesis_spec_t replaygain_synthesis_spec, FLAC__bool analysis_mode, analysis_options aopts, utils__SkipUntilSpecification *skip_specification, utils__SkipUntilSpecification *until_specification, utils__CueSpecification *cue_specification, const char *infilename, const char *outfilename) +{ +#ifdef FLAC__HAS_OGG + d->is_ogg = is_ogg; +#else + (void)is_ogg; +#endif + + d->is_aiff_out = is_aiff_out; + d->is_wave_out = is_wave_out; + d->continue_through_decode_errors = continue_through_decode_errors; + d->replaygain.spec = replaygain_synthesis_spec; + d->replaygain.apply = false; + d->replaygain.scale = 0.0; + /* d->replaygain.dither_context gets initialized later once we know the sample resolution */ + d->test_only = (0 == outfilename); + d->analysis_mode = analysis_mode; + d->aopts = aopts; + d->skip_specification = skip_specification; + d->until_specification = until_specification; + d->cue_specification = cue_specification; + + d->inbasefilename = grabbag__file_get_basename(infilename); + d->outfilename = outfilename; + + d->samples_processed = 0; + d->frame_counter = 0; + d->abort_flag = false; + d->aborting_due_to_until = false; + + d->wave_chunk_size_fixup.needs_fixup = false; + + d->decoder.flac.file = 0; +#ifdef FLAC__HAS_OGG + d->decoder.ogg.file = 0; +#endif + + d->fout = 0; /* initialized with an open file later if necessary */ + + FLAC__ASSERT(!(d->test_only && d->analysis_mode)); + + if(!d->test_only) { + if(0 == strcmp(outfilename, "-")) { + d->fout = grabbag__file_get_binary_stdout(); + } + else { + if(0 == (d->fout = fopen(outfilename, "wb"))) { + flac__utils_printf(stderr, 1, "%s: ERROR: can't open output file %s\n", d->inbasefilename, outfilename); + DecoderSession_destroy(d, /*error_occurred=*/true); + return false; + } + } + } + + if(analysis_mode) + flac__analyze_init(aopts); + + return true; +} + +void DecoderSession_destroy(DecoderSession *d, FLAC__bool error_occurred) +{ + if(0 != d->fout && d->fout != stdout) { + fclose(d->fout); + if(error_occurred) + unlink(d->outfilename); + } +} + +FLAC__bool DecoderSession_init_decoder(DecoderSession *decoder_session, decode_options_t decode_options, const char *infilename) +{ + FLAC__uint32 test = 1; + + is_big_endian_host_ = (*((FLAC__byte*)(&test)))? false : true; + +#ifdef FLAC__HAS_OGG + if(decoder_session->is_ogg) { + decoder_session->decoder.ogg.file = OggFLAC__file_decoder_new(); + + if(0 == decoder_session->decoder.ogg.file) { + flac__utils_printf(stderr, 1, "%s: ERROR creating the decoder instance\n", decoder_session->inbasefilename); + return false; + } + + OggFLAC__file_decoder_set_md5_checking(decoder_session->decoder.ogg.file, true); + OggFLAC__file_decoder_set_filename(decoder_session->decoder.ogg.file, infilename); + if(!decode_options.use_first_serial_number) + OggFLAC__file_decoder_set_serial_number(decoder_session->decoder.ogg.file, decode_options.serial_number); + if (0 != decoder_session->cue_specification) + OggFLAC__file_decoder_set_metadata_respond(decoder_session->decoder.ogg.file, FLAC__METADATA_TYPE_CUESHEET); + if (decoder_session->replaygain.spec.apply) + OggFLAC__file_decoder_set_metadata_respond(decoder_session->decoder.ogg.file, FLAC__METADATA_TYPE_VORBIS_COMMENT); + + /* + * The three ugly casts here are to 'downcast' the 'void *' argument of + * the callback down to 'OggFLAC__FileDecoder *'. In C++ this would be + * unnecessary but here the cast makes the C compiler happy. + */ + OggFLAC__file_decoder_set_write_callback(decoder_session->decoder.ogg.file, (FLAC__StreamDecoderWriteStatus (*)(const OggFLAC__FileDecoder *, const FLAC__Frame *, const FLAC__int32 * const [], void *))write_callback); + OggFLAC__file_decoder_set_metadata_callback(decoder_session->decoder.ogg.file, (void (*)(const OggFLAC__FileDecoder *, const FLAC__StreamMetadata *, void *))metadata_callback); + OggFLAC__file_decoder_set_error_callback(decoder_session->decoder.ogg.file, (void (*)(const OggFLAC__FileDecoder *, FLAC__StreamDecoderErrorStatus, void *))error_callback); + OggFLAC__file_decoder_set_client_data(decoder_session->decoder.ogg.file, decoder_session); + + if(OggFLAC__file_decoder_init(decoder_session->decoder.ogg.file) != OggFLAC__FILE_DECODER_OK) { + print_error_with_state(decoder_session, "ERROR initializing decoder"); + return false; + } + } + else +#else + (void)decode_options; +#endif + { + decoder_session->decoder.flac.file = FLAC__file_decoder_new(); + + if(0 == decoder_session->decoder.flac.file) { + flac__utils_printf(stderr, 1, "%s: ERROR creating the decoder instance\n", decoder_session->inbasefilename); + return false; + } + + FLAC__file_decoder_set_md5_checking(decoder_session->decoder.flac.file, true); + FLAC__file_decoder_set_filename(decoder_session->decoder.flac.file, infilename); + if (0 != decoder_session->cue_specification) + FLAC__file_decoder_set_metadata_respond(decoder_session->decoder.flac.file, FLAC__METADATA_TYPE_CUESHEET); + if (decoder_session->replaygain.spec.apply) + FLAC__file_decoder_set_metadata_respond(decoder_session->decoder.flac.file, FLAC__METADATA_TYPE_VORBIS_COMMENT); + /* + * The three ugly casts here are to 'downcast' the 'void *' argument of + * the callback down to 'FLAC__FileDecoder *'. + */ + FLAC__file_decoder_set_write_callback(decoder_session->decoder.flac.file, (FLAC__StreamDecoderWriteStatus (*)(const FLAC__FileDecoder *, const FLAC__Frame *, const FLAC__int32 * const [], void *))write_callback); + FLAC__file_decoder_set_metadata_callback(decoder_session->decoder.flac.file, (void (*)(const FLAC__FileDecoder *, const FLAC__StreamMetadata *, void *))metadata_callback); + FLAC__file_decoder_set_error_callback(decoder_session->decoder.flac.file, (void (*)(const FLAC__FileDecoder *, FLAC__StreamDecoderErrorStatus, void *))error_callback); + FLAC__file_decoder_set_client_data(decoder_session->decoder.flac.file, decoder_session); + + if(FLAC__file_decoder_init(decoder_session->decoder.flac.file) != FLAC__FILE_DECODER_OK) { + print_error_with_state(decoder_session, "ERROR initializing decoder"); + return false; + } + } + + return true; +} + +FLAC__bool DecoderSession_process(DecoderSession *d) +{ +#ifdef FLAC__HAS_OGG + if(d->is_ogg) { + if(!OggFLAC__file_decoder_process_until_end_of_metadata(d->decoder.ogg.file)) { + flac__utils_printf(stderr, 2, "\n"); + print_error_with_state(d, "ERROR while decoding metadata"); + return false; + } + if(OggFLAC__file_decoder_get_state(d->decoder.ogg.file) != OggFLAC__FILE_DECODER_OK && OggFLAC__file_decoder_get_state(d->decoder.ogg.file) != OggFLAC__FILE_DECODER_END_OF_FILE) { + flac__utils_printf(stderr, 2, "\n"); + print_error_with_state(d, "ERROR during metadata decoding"); + return false; + } + } + else +#endif + { + if(!FLAC__file_decoder_process_until_end_of_metadata(d->decoder.flac.file)) { + flac__utils_printf(stderr, 2, "\n"); + print_error_with_state(d, "ERROR while decoding metadata"); + return false; + } + if(FLAC__file_decoder_get_state(d->decoder.flac.file) != FLAC__FILE_DECODER_OK && FLAC__file_decoder_get_state(d->decoder.flac.file) != FLAC__FILE_DECODER_END_OF_FILE) { + flac__utils_printf(stderr, 2, "\n"); + print_error_with_state(d, "ERROR during metadata decoding"); + return false; + } + } + if(d->abort_flag) + return false; + + /* write the WAVE/AIFF headers if necessary */ + if(!write_necessary_headers(d)) { + d->abort_flag = true; + return false; + } + + if(d->skip_specification->value.samples > 0) { + const FLAC__uint64 skip = (FLAC__uint64)d->skip_specification->value.samples; + +#ifdef FLAC__HAS_OGG + if(d->is_ogg) { + if(!OggFLAC__file_decoder_seek_absolute(d->decoder.ogg.file, skip)) { + print_error_with_state(d, "ERROR seeking while skipping bytes"); + return false; + } + if(!OggFLAC__file_decoder_process_until_end_of_file(d->decoder.ogg.file) && !d->aborting_due_to_until) { + flac__utils_printf(stderr, 2, "\n"); + print_error_with_state(d, "ERROR while decoding frames"); + return false; + } + if(OggFLAC__file_decoder_get_state(d->decoder.ogg.file) != OggFLAC__FILE_DECODER_OK && OggFLAC__file_decoder_get_state(d->decoder.ogg.file) != OggFLAC__FILE_DECODER_END_OF_FILE && !d->aborting_due_to_until) { + flac__utils_printf(stderr, 2, "\n"); + print_error_with_state(d, "ERROR during decoding"); + return false; + } + } + else +#endif + { + if(!FLAC__file_decoder_seek_absolute(d->decoder.flac.file, skip)) { + print_error_with_state(d, "ERROR seeking while skipping bytes"); + return false; + } + if(!FLAC__file_decoder_process_until_end_of_file(d->decoder.flac.file) && !d->aborting_due_to_until) { + flac__utils_printf(stderr, 2, "\n"); + print_error_with_state(d, "ERROR while decoding frames"); + return false; + } + if(FLAC__file_decoder_get_state(d->decoder.flac.file) != FLAC__FILE_DECODER_OK && FLAC__file_decoder_get_state(d->decoder.flac.file) != FLAC__FILE_DECODER_END_OF_FILE && !d->aborting_due_to_until) { + flac__utils_printf(stderr, 2, "\n"); + print_error_with_state(d, "ERROR during decoding"); + return false; + } + } + } + else { +#ifdef FLAC__HAS_OGG + if(d->is_ogg) { + if(!OggFLAC__file_decoder_process_until_end_of_file(d->decoder.ogg.file) && !d->aborting_due_to_until) { + flac__utils_printf(stderr, 2, "\n"); + print_error_with_state(d, "ERROR while decoding data"); + return false; + } + if(OggFLAC__file_decoder_get_state(d->decoder.ogg.file) != OggFLAC__FILE_DECODER_OK && OggFLAC__file_decoder_get_state(d->decoder.ogg.file) != OggFLAC__FILE_DECODER_END_OF_FILE && !d->aborting_due_to_until) { + flac__utils_printf(stderr, 2, "\n"); + print_error_with_state(d, "ERROR during decoding"); + return false; + } + } + else +#endif + { + if(!FLAC__file_decoder_process_until_end_of_file(d->decoder.flac.file) && !d->aborting_due_to_until) { + flac__utils_printf(stderr, 2, "\n"); + print_error_with_state(d, "ERROR while decoding data"); + return false; + } + if(FLAC__file_decoder_get_state(d->decoder.flac.file) != FLAC__FILE_DECODER_OK && FLAC__file_decoder_get_state(d->decoder.flac.file) != FLAC__FILE_DECODER_END_OF_FILE && !d->aborting_due_to_until) { + flac__utils_printf(stderr, 2, "\n"); + print_error_with_state(d, "ERROR during decoding"); + return false; + } + } + } + + if((d->is_wave_out || d->is_aiff_out) && ((d->total_samples * d->channels * ((d->bps+7)/8)) & 1)) { + if(flac__utils_fwrite("\000", 1, 1, d->fout) != 1) { + print_error_with_state(d, d->is_wave_out? + "ERROR writing pad byte to WAVE data chunk" : + "ERROR writing pad byte to AIFF SSND chunk" + ); + return false; + } + } + + return true; +} + +int DecoderSession_finish_ok(DecoderSession *d) +{ + FLAC__bool md5_failure = false; + +#ifdef FLAC__HAS_OGG + if(d->is_ogg) { + if(d->decoder.ogg.file) { + md5_failure = !OggFLAC__file_decoder_finish(d->decoder.ogg.file) && !d->aborting_due_to_until; + print_stats(d); + OggFLAC__file_decoder_delete(d->decoder.ogg.file); + } + } + else +#endif + { + if(d->decoder.flac.file) { + md5_failure = !FLAC__file_decoder_finish(d->decoder.flac.file) && !d->aborting_due_to_until; + print_stats(d); + FLAC__file_decoder_delete(d->decoder.flac.file); + } + } + if(d->analysis_mode) + flac__analyze_finish(d->aopts); + if(md5_failure) { + flac__utils_printf(stderr, 1, "\r%s: WARNING, MD5 signature mismatch\n", d->inbasefilename); + } + else { + flac__utils_printf(stderr, 2, "\r%s: %s \n", d->inbasefilename, d->test_only? "ok ":d->analysis_mode?"done ":"done"); + } + DecoderSession_destroy(d, /*error_occurred=*/false); + if((d->is_wave_out || d->is_aiff_out) && d->wave_chunk_size_fixup.needs_fixup) + if(!fixup_wave_chunk_size(d->outfilename, d->is_wave_out, d->wave_chunk_size_fixup.riff_offset, d->wave_chunk_size_fixup.data_offset, d->wave_chunk_size_fixup.frames_offset, (FLAC__uint32)d->samples_processed, d->channels, d->bps)) + return 1; + return 0; +} + +int DecoderSession_finish_error(DecoderSession *d) +{ +#ifdef FLAC__HAS_OGG + if(d->is_ogg) { + if(d->decoder.ogg.file) { + OggFLAC__file_decoder_finish(d->decoder.ogg.file); + OggFLAC__file_decoder_delete(d->decoder.ogg.file); + } + } + else +#endif + { + if(d->decoder.flac.file) { + FLAC__file_decoder_finish(d->decoder.flac.file); + FLAC__file_decoder_delete(d->decoder.flac.file); + } + } + if(d->analysis_mode) + flac__analyze_finish(d->aopts); + DecoderSession_destroy(d, /*error_occurred=*/true); + return 1; +} + +FLAC__bool canonicalize_until_specification(utils__SkipUntilSpecification *spec, const char *inbasefilename, unsigned sample_rate, FLAC__uint64 skip, FLAC__uint64 total_samples_in_input) +{ + /* convert from mm:ss.sss to sample number if necessary */ + flac__utils_canonicalize_skip_until_specification(spec, sample_rate); + + /* special case: if "--until=-0", use the special value '0' to mean "end-of-stream" */ + if(spec->is_relative && spec->value.samples == 0) { + spec->is_relative = false; + return true; + } + + /* in any other case the total samples in the input must be known */ + if(total_samples_in_input == 0) { + flac__utils_printf(stderr, 1, "%s: ERROR, cannot use --until when FLAC metadata has total sample count of 0\n", inbasefilename); + return false; + } + + FLAC__ASSERT(spec->value_is_samples); + + /* convert relative specifications to absolute */ + if(spec->is_relative) { + if(spec->value.samples <= 0) + spec->value.samples += (FLAC__int64)total_samples_in_input; + else + spec->value.samples += skip; + spec->is_relative = false; + } + + /* error check */ + if(spec->value.samples < 0) { + flac__utils_printf(stderr, 1, "%s: ERROR, --until value is before beginning of input\n", inbasefilename); + return false; + } + if((FLAC__uint64)spec->value.samples <= skip) { + flac__utils_printf(stderr, 1, "%s: ERROR, --until value is before --skip point\n", inbasefilename); + return false; + } + if((FLAC__uint64)spec->value.samples > total_samples_in_input) { + flac__utils_printf(stderr, 1, "%s: ERROR, --until value is after end of input\n", inbasefilename); + return false; + } + + return true; +} + +FLAC__bool write_necessary_headers(DecoderSession *decoder_session) +{ + /* write the WAVE/AIFF headers if necessary */ + if(!decoder_session->analysis_mode && !decoder_session->test_only && (decoder_session->is_wave_out || decoder_session->is_aiff_out)) { + const char *fmt_desc = decoder_session->is_wave_out? "WAVE" : "AIFF"; + FLAC__uint64 data_size = decoder_session->total_samples * decoder_session->channels * ((decoder_session->bps+7)/8); + const FLAC__uint32 aligned_data_size = (FLAC__uint32)((data_size+1) & (~1U)); /* we'll check for overflow later */ + if(decoder_session->total_samples == 0) { + if(decoder_session->fout == stdout) { + flac__utils_printf(stderr, 1, "%s: WARNING, don't have accurate sample count available for %s header.\n", decoder_session->inbasefilename, fmt_desc); + flac__utils_printf(stderr, 1, " Generated %s file will have a data chunk size of 0. Try\n", fmt_desc); + flac__utils_printf(stderr, 1, " decoding directly to a file instead.\n"); + } + else { + decoder_session->wave_chunk_size_fixup.needs_fixup = true; + } + } + if(data_size >= 0xFFFFFFDC) { + flac__utils_printf(stderr, 1, "%s: ERROR: stream is too big to fit in a single %s file chunk\n", decoder_session->inbasefilename, fmt_desc); + return false; + } + if(decoder_session->is_wave_out) { + if(flac__utils_fwrite("RIFF", 1, 4, decoder_session->fout) != 4) + return false; + + if(decoder_session->wave_chunk_size_fixup.needs_fixup) + decoder_session->wave_chunk_size_fixup.riff_offset = ftell(decoder_session->fout); + + if(!write_little_endian_uint32(decoder_session->fout, aligned_data_size+36)) /* filesize-8 */ + return false; + + if(flac__utils_fwrite("WAVEfmt ", 1, 8, decoder_session->fout) != 8) + return false; + + if(flac__utils_fwrite("\020\000\000\000", 1, 4, decoder_session->fout) != 4) /* chunk size = 16 */ + return false; + + if(flac__utils_fwrite("\001\000", 1, 2, decoder_session->fout) != 2) /* compression code == 1 */ + return false; + + if(!write_little_endian_uint16(decoder_session->fout, (FLAC__uint16)(decoder_session->channels))) + return false; + + if(!write_little_endian_uint32(decoder_session->fout, decoder_session->sample_rate)) + return false; + + if(!write_little_endian_uint32(decoder_session->fout, decoder_session->sample_rate * decoder_session->channels * ((decoder_session->bps+7) / 8))) /* @@@ or is it (sample_rate*channels*bps) / 8 ??? */ + return false; + + if(!write_little_endian_uint16(decoder_session->fout, (FLAC__uint16)(decoder_session->channels * ((decoder_session->bps+7) / 8)))) /* block align */ + return false; + + if(!write_little_endian_uint16(decoder_session->fout, (FLAC__uint16)(decoder_session->bps))) /* bits per sample */ + return false; + + if(flac__utils_fwrite("data", 1, 4, decoder_session->fout) != 4) + return false; + + if(decoder_session->wave_chunk_size_fixup.needs_fixup) + decoder_session->wave_chunk_size_fixup.data_offset = ftell(decoder_session->fout); + + if(!write_little_endian_uint32(decoder_session->fout, (FLAC__uint32)data_size)) /* data size */ + return false; + } + else { + if(flac__utils_fwrite("FORM", 1, 4, decoder_session->fout) != 4) + return false; + + if(decoder_session->wave_chunk_size_fixup.needs_fixup) + decoder_session->wave_chunk_size_fixup.riff_offset = ftell(decoder_session->fout); + + if(!write_big_endian_uint32(decoder_session->fout, aligned_data_size+46)) /* filesize-8 */ + return false; + + if(flac__utils_fwrite("AIFFCOMM", 1, 8, decoder_session->fout) != 8) + return false; + + if(flac__utils_fwrite("\000\000\000\022", 1, 4, decoder_session->fout) != 4) /* chunk size = 18 */ + return false; + + if(!write_big_endian_uint16(decoder_session->fout, (FLAC__uint16)(decoder_session->channels))) + return false; + + if(decoder_session->wave_chunk_size_fixup.needs_fixup) + decoder_session->wave_chunk_size_fixup.frames_offset = ftell(decoder_session->fout); + + if(!write_big_endian_uint32(decoder_session->fout, (FLAC__uint32)decoder_session->total_samples)) + return false; + + if(!write_big_endian_uint16(decoder_session->fout, (FLAC__uint16)(decoder_session->bps))) + return false; + + if(!write_sane_extended(decoder_session->fout, decoder_session->sample_rate)) + return false; + + if(flac__utils_fwrite("SSND", 1, 4, decoder_session->fout) != 4) + return false; + + if(decoder_session->wave_chunk_size_fixup.needs_fixup) + decoder_session->wave_chunk_size_fixup.data_offset = ftell(decoder_session->fout); + + if(!write_big_endian_uint32(decoder_session->fout, (FLAC__uint32)data_size+8)) /* data size */ + return false; + + if(!write_big_endian_uint32(decoder_session->fout, 0/*offset*/)) + return false; + + if(!write_big_endian_uint32(decoder_session->fout, 0/*block_size*/)) + return false; + } + } + + return true; +} + +FLAC__bool write_little_endian_uint16(FILE *f, FLAC__uint16 val) +{ + FLAC__byte *b = (FLAC__byte*)(&val); + if(is_big_endian_host_) { + FLAC__byte tmp; + tmp = b[1]; b[1] = b[0]; b[0] = tmp; + } + return flac__utils_fwrite(b, 1, 2, f) == 2; +} + +FLAC__bool write_little_endian_uint32(FILE *f, FLAC__uint32 val) +{ + FLAC__byte *b = (FLAC__byte*)(&val); + if(is_big_endian_host_) { + FLAC__byte tmp; + tmp = b[3]; b[3] = b[0]; b[0] = tmp; + tmp = b[2]; b[2] = b[1]; b[1] = tmp; + } + return flac__utils_fwrite(b, 1, 4, f) == 4; +} + +FLAC__bool write_big_endian_uint16(FILE *f, FLAC__uint16 val) +{ + FLAC__byte *b = (FLAC__byte*)(&val); + if(!is_big_endian_host_) { + FLAC__byte tmp; + tmp = b[1]; b[1] = b[0]; b[0] = tmp; + } + return flac__utils_fwrite(b, 1, 2, f) == 2; +} + +FLAC__bool write_big_endian_uint32(FILE *f, FLAC__uint32 val) +{ + FLAC__byte *b = (FLAC__byte*)(&val); + if(!is_big_endian_host_) { + FLAC__byte tmp; + tmp = b[3]; b[3] = b[0]; b[0] = tmp; + tmp = b[2]; b[2] = b[1]; b[1] = tmp; + } + return flac__utils_fwrite(b, 1, 4, f) == 4; +} + +FLAC__bool write_sane_extended(FILE *f, unsigned val) + /* Write to 'f' a SANE extended representation of 'val'. Return false if + * the write succeeds; return true otherwise. + * + * SANE extended is an 80-bit IEEE-754 representation with sign bit, 15 bits + * of exponent, and 64 bits of significand (mantissa). Unlike most IEEE-754 + * representations, it does not imply a 1 above the MSB of the significand. + * + * Preconditions: + * val!=0U + */ +{ + unsigned int shift, exponent; + + FLAC__ASSERT(val!=0U); /* handling 0 would require a special case */ + + for(shift= 0U; (val>>(31-shift))==0U; ++shift) + ; + val<<= shift; + exponent= 63U-(shift+32U); /* add 32 for unused second word */ + + if(!write_big_endian_uint16(f, (FLAC__uint16)(exponent+0x3FFF))) + return false; + if(!write_big_endian_uint32(f, val)) + return false; + if(!write_big_endian_uint32(f, 0)) /* unused second word */ + return false; + + return true; +} + +FLAC__bool fixup_wave_chunk_size(const char *outfilename, FLAC__bool is_wave_out, unsigned riff_offset, unsigned data_offset, unsigned frames_offset, FLAC__uint32 total_samples, unsigned channels, unsigned bps) +{ + const char *fmt_desc = (is_wave_out? "WAVE" : "AIFF"); + FLAC__bool (*write_it)(FILE *, FLAC__uint32) = (is_wave_out? write_little_endian_uint32 : write_big_endian_uint32); + FILE *f = fopen(outfilename, "r+b"); + FLAC__uint32 data_size, aligned_data_size; + + if(0 == f) { + flac__utils_printf(stderr, 1, "ERROR, couldn't open file %s while fixing up %s chunk size\n", outfilename, fmt_desc); + return false; + } + + data_size = aligned_data_size = total_samples * channels * ((bps+7)/8); + if(aligned_data_size & 1) + aligned_data_size++; + + if(fseek(f, riff_offset, SEEK_SET) < 0) { + flac__utils_printf(stderr, 1, "ERROR, couldn't seek in file %s while fixing up %s chunk size\n", outfilename, fmt_desc); + fclose(f); + return false; + } + if(!write_it(f, aligned_data_size + (is_wave_out? 36 : 46))) { + flac__utils_printf(stderr, 1, "ERROR, couldn't write size in file %s while fixing up %s chunk size\n", outfilename, fmt_desc); + fclose(f); + return false; + } + if(!is_wave_out) { + if(fseek(f, frames_offset, SEEK_SET) < 0) { + flac__utils_printf(stderr, 1, "ERROR, couldn't seek in file %s while fixing up %s chunk size\n", outfilename, fmt_desc); + fclose(f); + return false; + } + if(!write_it(f, total_samples)) { + flac__utils_printf(stderr, 1, "ERROR, couldn't write size in file %s while fixing up %s chunk size\n", outfilename, fmt_desc); + fclose(f); + return false; + } + } + if(fseek(f, data_offset, SEEK_SET) < 0) { + flac__utils_printf(stderr, 1, "ERROR, couldn't seek in file %s while fixing up %s chunk size\n", outfilename, fmt_desc); + fclose(f); + return false; + } + if(!write_it(f, data_size + (is_wave_out? 0 : 8))) { + flac__utils_printf(stderr, 1, "ERROR, couldn't write size in file %s while fixing up %s chunk size\n", outfilename, fmt_desc); + fclose(f); + return false; + } + fclose(f); + return true; +} + +FLAC__StreamDecoderWriteStatus write_callback(const void *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) +{ + DecoderSession *decoder_session = (DecoderSession*)client_data; + FILE *fout = decoder_session->fout; + const unsigned bps = frame->header.bits_per_sample, channels = frame->header.channels; + FLAC__bool is_big_endian = (decoder_session->is_aiff_out? true : (decoder_session->is_wave_out? false : decoder_session->is_big_endian)); + FLAC__bool is_unsigned_samples = (decoder_session->is_aiff_out? false : (decoder_session->is_wave_out? bps<=8 : decoder_session->is_unsigned_samples)); + unsigned wide_samples = frame->header.blocksize, wide_sample, sample, channel, byte; + static FLAC__int8 s8buffer[FLAC__MAX_BLOCK_SIZE * FLAC__MAX_CHANNELS * sizeof(FLAC__int32)]; /* WATCHOUT: can be up to 2 megs */ + FLAC__uint8 *u8buffer = (FLAC__uint8 *)s8buffer; + FLAC__int16 *s16buffer = (FLAC__int16 *)s8buffer; + FLAC__uint16 *u16buffer = (FLAC__uint16 *)s8buffer; + FLAC__int32 *s32buffer = (FLAC__int32 *)s8buffer; + FLAC__uint32 *u32buffer = (FLAC__uint32 *)s8buffer; + size_t bytes_to_write = 0; + + (void)decoder; + + if(decoder_session->abort_flag) + return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; + + if(bps != decoder_session->bps) { + flac__utils_printf(stderr, 1, "%s: ERROR, bits-per-sample is %u in frame but %u in STREAMINFO\n", decoder_session->inbasefilename, bps, decoder_session->bps); + return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; + } + if(channels != decoder_session->channels) { + flac__utils_printf(stderr, 1, "%s: ERROR, channels is %u in frame but %u in STREAMINFO\n", decoder_session->inbasefilename, channels, decoder_session->channels); + return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; + } + if(frame->header.sample_rate != decoder_session->sample_rate) { + flac__utils_printf(stderr, 1, "%s: ERROR, sample rate is %u in frame but %u in STREAMINFO\n", decoder_session->inbasefilename, frame->header.sample_rate, decoder_session->sample_rate); + return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; + } + + /* + * limit the number of samples to accept based on --until + */ + FLAC__ASSERT(!decoder_session->skip_specification->is_relative); + FLAC__ASSERT(decoder_session->skip_specification->value.samples >= 0); + FLAC__ASSERT(!decoder_session->until_specification->is_relative); + FLAC__ASSERT(decoder_session->until_specification->value.samples >= 0); + if(decoder_session->until_specification->value.samples > 0) { + const FLAC__uint64 skip = (FLAC__uint64)decoder_session->skip_specification->value.samples; + const FLAC__uint64 until = (FLAC__uint64)decoder_session->until_specification->value.samples; + const FLAC__uint64 input_samples_passed = skip + decoder_session->samples_processed; + FLAC__ASSERT(until >= input_samples_passed); + if(input_samples_passed + wide_samples > until) + wide_samples = (unsigned)(until - input_samples_passed); + if (wide_samples == 0) { + decoder_session->abort_flag = true; + decoder_session->aborting_due_to_until = true; + return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; + } + } + + if(wide_samples > 0) { + decoder_session->samples_processed += wide_samples; + decoder_session->frame_counter++; + + if(!(decoder_session->frame_counter & 0x3f)) + print_stats(decoder_session); + + if(decoder_session->analysis_mode) { + flac__analyze_frame(frame, decoder_session->frame_counter-1, decoder_session->aopts, fout); + } + else if(!decoder_session->test_only) { + if (decoder_session->replaygain.apply) { + bytes_to_write = FLAC__replaygain_synthesis__apply_gain( + u8buffer, + !is_big_endian, + is_unsigned_samples, + buffer, + wide_samples, + channels, + bps, /* source_bps */ + bps, /* target_bps */ + decoder_session->replaygain.scale, + decoder_session->replaygain.spec.limiter == RGSS_LIMIT__HARD, /* hard_limit */ + decoder_session->replaygain.spec.noise_shaping != NOISE_SHAPING_NONE, /* do_dithering */ + &decoder_session->replaygain.dither_context + ); + } + else if(bps == 8) { + if(is_unsigned_samples) { + for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) + for(channel = 0; channel < channels; channel++, sample++) + u8buffer[sample] = (FLAC__uint8)(buffer[channel][wide_sample] + 0x80); + } + else { + for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) + for(channel = 0; channel < channels; channel++, sample++) + s8buffer[sample] = (FLAC__int8)(buffer[channel][wide_sample]); + } + bytes_to_write = sample; + } + else if(bps == 16) { + if(is_unsigned_samples) { + for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) + for(channel = 0; channel < channels; channel++, sample++) + u16buffer[sample] = (FLAC__uint16)(buffer[channel][wide_sample] + 0x8000); + } + else { + for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) + for(channel = 0; channel < channels; channel++, sample++) + s16buffer[sample] = (FLAC__int16)(buffer[channel][wide_sample]); + } + if(is_big_endian != is_big_endian_host_) { + unsigned char tmp; + const unsigned bytes = sample * 2; + for(byte = 0; byte < bytes; byte += 2) { + tmp = u8buffer[byte]; + u8buffer[byte] = u8buffer[byte+1]; + u8buffer[byte+1] = tmp; + } + } + bytes_to_write = 2 * sample; + } + else if(bps == 24) { + if(is_unsigned_samples) { + for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) + for(channel = 0; channel < channels; channel++, sample++) + u32buffer[sample] = buffer[channel][wide_sample] + 0x800000; + } + else { + for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) + for(channel = 0; channel < channels; channel++, sample++) + s32buffer[sample] = buffer[channel][wide_sample]; + } + if(is_big_endian != is_big_endian_host_) { + unsigned char tmp; + const unsigned bytes = sample * 4; + for(byte = 0; byte < bytes; byte += 4) { + tmp = u8buffer[byte]; + u8buffer[byte] = u8buffer[byte+3]; + u8buffer[byte+3] = tmp; + tmp = u8buffer[byte+1]; + u8buffer[byte+1] = u8buffer[byte+2]; + u8buffer[byte+2] = tmp; + } + } + if(is_big_endian) { + unsigned lbyte; + const unsigned bytes = sample * 4; + for(lbyte = byte = 0; byte < bytes; ) { + byte++; + u8buffer[lbyte++] = u8buffer[byte++]; + u8buffer[lbyte++] = u8buffer[byte++]; + u8buffer[lbyte++] = u8buffer[byte++]; + } + } + else { + unsigned lbyte; + const unsigned bytes = sample * 4; + for(lbyte = byte = 0; byte < bytes; ) { + u8buffer[lbyte++] = u8buffer[byte++]; + u8buffer[lbyte++] = u8buffer[byte++]; + u8buffer[lbyte++] = u8buffer[byte++]; + byte++; + } + } + bytes_to_write = 3 * sample; + } + else { + FLAC__ASSERT(0); + } + } + } + if(bytes_to_write > 0) { + if(flac__utils_fwrite(u8buffer, 1, bytes_to_write, fout) != bytes_to_write) { + /* if a pipe closed when writing to stdout, we let it go without an error message */ + if(errno == EPIPE && decoder_session->fout == stdout) + decoder_session->aborting_due_to_until = true; + decoder_session->abort_flag = true; + return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; + } + } + return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; +} + +void metadata_callback(const void *decoder, const FLAC__StreamMetadata *metadata, void *client_data) +{ + DecoderSession *decoder_session = (DecoderSession*)client_data; + (void)decoder; + if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) { + FLAC__uint64 skip, until; + decoder_session->bps = metadata->data.stream_info.bits_per_sample; + decoder_session->channels = metadata->data.stream_info.channels; + decoder_session->sample_rate = metadata->data.stream_info.sample_rate; + + flac__utils_canonicalize_skip_until_specification(decoder_session->skip_specification, decoder_session->sample_rate); + FLAC__ASSERT(decoder_session->skip_specification->value.samples >= 0); + skip = (FLAC__uint64)decoder_session->skip_specification->value.samples; + + /* remember, metadata->data.stream_info.total_samples can be 0, meaning 'unknown' */ + if(metadata->data.stream_info.total_samples > 0 && skip >= metadata->data.stream_info.total_samples) { + flac__utils_printf(stderr, 1, "%s: ERROR trying to --skip more samples than in stream\n", decoder_session->inbasefilename); + decoder_session->abort_flag = true; + return; + } + else if(metadata->data.stream_info.total_samples == 0 && skip > 0) { + flac__utils_printf(stderr, 1, "%s: ERROR, can't --skip when FLAC metadata has total sample count of 0\n", decoder_session->inbasefilename); + decoder_session->abort_flag = true; + return; + } + FLAC__ASSERT(skip == 0 || 0 == decoder_session->cue_specification); + decoder_session->total_samples = metadata->data.stream_info.total_samples - skip; + + /* note that we use metadata->data.stream_info.total_samples instead of decoder_session->total_samples */ + if(!canonicalize_until_specification(decoder_session->until_specification, decoder_session->inbasefilename, decoder_session->sample_rate, skip, metadata->data.stream_info.total_samples)) { + decoder_session->abort_flag = true; + return; + } + FLAC__ASSERT(decoder_session->until_specification->value.samples >= 0); + until = (FLAC__uint64)decoder_session->until_specification->value.samples; + + if(until > 0) { + FLAC__ASSERT(decoder_session->total_samples != 0); + FLAC__ASSERT(0 == decoder_session->cue_specification); + decoder_session->total_samples -= (metadata->data.stream_info.total_samples - until); + } + + if(decoder_session->bps != 8 && decoder_session->bps != 16 && decoder_session->bps != 24) { + flac__utils_printf(stderr, 1, "%s: ERROR: bits per sample is not 8/16/24\n", decoder_session->inbasefilename); + decoder_session->abort_flag = true; + return; + } + } + else if(metadata->type == FLAC__METADATA_TYPE_CUESHEET) { + /* remember, at this point, decoder_session->total_samples can be 0, meaning 'unknown' */ + if(decoder_session->total_samples == 0) { + flac__utils_printf(stderr, 1, "%s: ERROR can't use --cue when FLAC metadata has total sample count of 0\n", decoder_session->inbasefilename); + decoder_session->abort_flag = true; + return; + } + + flac__utils_canonicalize_cue_specification(decoder_session->cue_specification, &metadata->data.cue_sheet, decoder_session->total_samples, decoder_session->skip_specification, decoder_session->until_specification); + + FLAC__ASSERT(!decoder_session->skip_specification->is_relative); + FLAC__ASSERT(decoder_session->skip_specification->value_is_samples); + + FLAC__ASSERT(!decoder_session->until_specification->is_relative); + FLAC__ASSERT(decoder_session->until_specification->value_is_samples); + + FLAC__ASSERT(decoder_session->skip_specification->value.samples >= 0); + FLAC__ASSERT(decoder_session->until_specification->value.samples >= 0); + FLAC__ASSERT((FLAC__uint64)decoder_session->until_specification->value.samples <= decoder_session->total_samples); + FLAC__ASSERT(decoder_session->skip_specification->value.samples <= decoder_session->until_specification->value.samples); + + decoder_session->total_samples = decoder_session->until_specification->value.samples - decoder_session->skip_specification->value.samples; + } + else if(metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) { + if (decoder_session->replaygain.spec.apply) { + double gain, peak; + if (!(decoder_session->replaygain.apply = grabbag__replaygain_load_from_vorbiscomment(metadata, decoder_session->replaygain.spec.use_album_gain, &gain, &peak))) { + flac__utils_printf(stderr, 1, "%s: WARNING: can't get %s ReplayGain tag\n", decoder_session->inbasefilename, decoder_session->replaygain.spec.use_album_gain? "album":"track"); + } + else { + const char *ls[] = { "no", "peak", "hard" }; + const char *ns[] = { "no", "low", "medium", "high" }; + decoder_session->replaygain.scale = grabbag__replaygain_compute_scale_factor(peak, gain, decoder_session->replaygain.spec.preamp, decoder_session->replaygain.spec.limiter == RGSS_LIMIT__PEAK); + FLAC__ASSERT(decoder_session->bps > 0 && decoder_session->bps <= 32); + FLAC__replaygain_synthesis__init_dither_context(&decoder_session->replaygain.dither_context, decoder_session->bps, decoder_session->replaygain.spec.noise_shaping); + flac__utils_printf(stderr, 1, "%s: INFO: applying %s ReplayGain (gain=%0.2fdB+preamp=%0.1fdB, %s noise shaping, %s limiting) to output\n", decoder_session->inbasefilename, decoder_session->replaygain.spec.use_album_gain? "album":"track", gain, decoder_session->replaygain.spec.preamp, ns[decoder_session->replaygain.spec.noise_shaping], ls[decoder_session->replaygain.spec.limiter]); + flac__utils_printf(stderr, 1, "%s: WARNING: applying ReplayGain is not lossless\n", decoder_session->inbasefilename); + } + } + } +} + +void error_callback(const void *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) +{ + DecoderSession *decoder_session = (DecoderSession*)client_data; + (void)decoder; + flac__utils_printf(stderr, 1, "%s: *** Got error code %d:%s\n", decoder_session->inbasefilename, status, FLAC__StreamDecoderErrorStatusString[status]); + if(!decoder_session->continue_through_decode_errors) + decoder_session->abort_flag = true; +} + +void print_error_with_state(const DecoderSession *d, const char *message) +{ + const int ilen = strlen(d->inbasefilename) + 1; + const char *state_string; + + flac__utils_printf(stderr, 1, "\n%s: %s\n", d->inbasefilename, message); + +#ifdef FLAC__HAS_OGG + if(d->is_ogg) { + state_string = OggFLAC__file_decoder_get_resolved_state_string(d->decoder.ogg.file); + } + else +#endif + { + state_string = FLAC__file_decoder_get_resolved_state_string(d->decoder.flac.file); + } + + flac__utils_printf(stderr, 1, "%*s state = %s\n", ilen, "", state_string); + + /* print out some more info for some errors: */ + if (0 == strcmp(state_string, FLAC__StreamDecoderStateString[FLAC__STREAM_DECODER_UNPARSEABLE_STREAM])) { + flac__utils_printf(stderr, 1, + "\n" + "The FLAC stream may have been created by a more advanced encoder. Try\n" + " metaflac --show-vendor-tag %s\n" + "If the version number is greater than %s, this decoder is probably\n" + "not able to decode the file. If the version number is not, the file\n" + "may be corrupted, or you may have found a bug. In this case please\n" + "submit a bug report to\n" + " http://sourceforge.net/bugs/?func=addbug&group_id=13478\n" + "Make sure to include an email contact in the comment and/or use the\n" + "\"Monitor\" feature to monitor the bug status.\n", + d->inbasefilename, FLAC__VERSION_STRING + ); + } + else if ( + 0 == strcmp(state_string, FLAC__FileDecoderStateString[FLAC__FILE_DECODER_ERROR_OPENING_FILE]) +#ifdef FLAC__HAS_OGG + || 0 == strcmp(state_string, OggFLAC__FileDecoderStateString[OggFLAC__FILE_DECODER_ERROR_OPENING_FILE]) +#endif + ) { + flac__utils_printf(stderr, 1, + "\n" + "An error occurred opening the input file; it is likely that it does not exist\n" + "or is not readable.\n" + ); + } +} + +void print_stats(const DecoderSession *decoder_session) +{ + if(flac__utils_verbosity_ >= 2) { +#if defined _MSC_VER || defined __MINGW32__ + /* with MSVC you have to spoon feed it the casting */ + const double progress = (double)(FLAC__int64)decoder_session->samples_processed / (double)(FLAC__int64)decoder_session->total_samples * 100.0; +#else + const double progress = (double)decoder_session->samples_processed / (double)decoder_session->total_samples * 100.0; +#endif + if(decoder_session->total_samples > 0) { + fprintf(stderr, "\r%s: %s%u%% complete", + decoder_session->inbasefilename, + decoder_session->test_only? "testing, " : decoder_session->analysis_mode? "analyzing, " : "", + (unsigned)floor(progress + 0.5) + ); + } + else { + fprintf(stderr, "\r%s: %s %u samples", + decoder_session->inbasefilename, + decoder_session->test_only? "tested" : decoder_session->analysis_mode? "analyzed" : "wrote", + (unsigned)decoder_session->samples_processed + ); + } + } +} diff --git a/Libraries/FLAC/flac-src/src/flac/decode.h b/Libraries/FLAC/flac-src/src/flac/decode.h new file mode 100644 index 000000000..159158289 --- /dev/null +++ b/Libraries/FLAC/flac-src/src/flac/decode.h @@ -0,0 +1,69 @@ +/* flac - Command-line FLAC encoder/decoder + * Copyright (C) 2000,2001,2002,2003,2004,2005 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef flac__decode_h +#define flac__decode_h + +#include "analyze.h" +#include "utils.h" +#include "share/replaygain_synthesis.h" + +#ifdef HAVE_CONFIG_H +#include +#endif + +typedef struct { + FLAC__bool apply; + FLAC__bool use_album_gain; /* false => use track gain */ + enum { RGSS_LIMIT__NONE, RGSS_LIMIT__PEAK, RGSS_LIMIT__HARD} limiter; + NoiseShaping noise_shaping; + double preamp; +} replaygain_synthesis_spec_t; + +typedef struct { + FLAC__bool continue_through_decode_errors; + replaygain_synthesis_spec_t replaygain_synthesis_spec; +#ifdef FLAC__HAS_OGG + FLAC__bool is_ogg; + FLAC__bool use_first_serial_number; + long serial_number; +#endif + utils__SkipUntilSpecification skip_specification; + utils__SkipUntilSpecification until_specification; + FLAC__bool has_cue_specification; + utils__CueSpecification cue_specification; +} decode_options_t; + +/* used for AIFF also */ +typedef struct { + decode_options_t common; +} wav_decode_options_t; + +typedef struct { + decode_options_t common; + + FLAC__bool is_big_endian; + FLAC__bool is_unsigned_samples; +} raw_decode_options_t; + +/* outfile == 0 => test only */ +int flac__decode_aiff(const char *infilename, const char *outfilename, FLAC__bool analysis_mode, analysis_options aopts, wav_decode_options_t options); +int flac__decode_wav(const char *infilename, const char *outfilename, FLAC__bool analysis_mode, analysis_options aopts, wav_decode_options_t options); +int flac__decode_raw(const char *infilename, const char *outfilename, FLAC__bool analysis_mode, analysis_options aopts, raw_decode_options_t options); + +#endif diff --git a/Libraries/FLAC/flac-src/src/flac/encode.c b/Libraries/FLAC/flac-src/src/flac/encode.c new file mode 100644 index 000000000..eb88b0269 --- /dev/null +++ b/Libraries/FLAC/flac-src/src/flac/encode.c @@ -0,0 +1,2129 @@ +/* flac - Command-line FLAC encoder/decoder + * Copyright (C) 2000,2001,2002,2003,2004,2005 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#if defined _WIN32 && !defined __CYGWIN__ +/* where MSVC puts unlink() */ +# include +#else +# include +#endif +#include /* for LONG_MAX */ +#include /* for floor() */ +#include /* for FILE etc. */ +#include /* for malloc */ +#include /* for strcmp() */ +#include "FLAC/all.h" +#include "share/grabbag.h" +#include "encode.h" + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef FLAC__HAS_OGG +#include "OggFLAC/stream_encoder.h" +#include "OggFLAC/file_encoder.h" +#endif + +#ifdef min +#undef min +#endif +#define min(x,y) ((x)<(y)?(x):(y)) +#ifdef max +#undef max +#endif +#define max(x,y) ((x)>(y)?(x):(y)) + +/* this MUST be >= 588 so that sector aligning can take place with one read */ +#define CHUNK_OF_SAMPLES 2048 + +typedef struct { +#ifdef FLAC__HAS_OGG + FLAC__bool use_ogg; +#endif + FLAC__bool verify; + FLAC__bool is_stdout; + const char *inbasefilename; + const char *outfilename; + + FLAC__uint64 skip; + FLAC__uint64 until; /* a value of 0 mean end-of-stream (i.e. --until=-0) */ + FLAC__bool replay_gain; + unsigned channels; + unsigned bits_per_sample; + unsigned sample_rate; + FLAC__uint64 unencoded_size; + FLAC__uint64 total_samples_to_encode; + FLAC__uint64 bytes_written; + FLAC__uint64 samples_written; + unsigned blocksize; + unsigned stats_mask; + + /* + * We use *.stream for encoding to stdout + * We use *.file for encoding to a regular file + */ + union { + union { + FLAC__StreamEncoder *stream; + FLAC__FileEncoder *file; + } flac; +#ifdef FLAC__HAS_OGG + union { + OggFLAC__StreamEncoder *stream; + OggFLAC__FileEncoder *file; + } ogg; +#endif + } encoder; + + FILE *fin; + FILE *fout; + FLAC__StreamMetadata *seek_table_template; +} EncoderSession; + + +static FLAC__bool is_big_endian_host_; + +static unsigned char ucbuffer_[CHUNK_OF_SAMPLES*FLAC__MAX_CHANNELS*((FLAC__REFERENCE_CODEC_MAX_BITS_PER_SAMPLE+7)/8)]; +static signed char *scbuffer_ = (signed char *)ucbuffer_; +static FLAC__uint16 *usbuffer_ = (FLAC__uint16 *)ucbuffer_; +static FLAC__int16 *ssbuffer_ = (FLAC__int16 *)ucbuffer_; + +static FLAC__int32 in_[FLAC__MAX_CHANNELS][CHUNK_OF_SAMPLES]; +static FLAC__int32 *input_[FLAC__MAX_CHANNELS]; + + +/* + * unpublished debug routines from the FLAC libs + */ +extern FLAC__bool FLAC__stream_encoder_disable_constant_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value); +extern FLAC__bool FLAC__stream_encoder_disable_fixed_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value); +extern FLAC__bool FLAC__stream_encoder_disable_verbatim_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value); +extern FLAC__bool FLAC__file_encoder_disable_constant_subframes(FLAC__FileEncoder *encoder, FLAC__bool value); +extern FLAC__bool FLAC__file_encoder_disable_fixed_subframes(FLAC__FileEncoder *encoder, FLAC__bool value); +extern FLAC__bool FLAC__file_encoder_disable_verbatim_subframes(FLAC__FileEncoder *encoder, FLAC__bool value); +#ifdef FLAC__HAS_OGG +extern FLAC__bool OggFLAC__stream_encoder_disable_constant_subframes(OggFLAC__StreamEncoder *encoder, FLAC__bool value); +extern FLAC__bool OggFLAC__stream_encoder_disable_fixed_subframes(OggFLAC__StreamEncoder *encoder, FLAC__bool value); +extern FLAC__bool OggFLAC__stream_encoder_disable_verbatim_subframes(OggFLAC__StreamEncoder *encoder, FLAC__bool value); +extern FLAC__bool OggFLAC__file_encoder_disable_constant_subframes(OggFLAC__FileEncoder *encoder, FLAC__bool value); +extern FLAC__bool OggFLAC__file_encoder_disable_fixed_subframes(OggFLAC__FileEncoder *encoder, FLAC__bool value); +extern FLAC__bool OggFLAC__file_encoder_disable_verbatim_subframes(OggFLAC__FileEncoder *encoder, FLAC__bool value); +#endif + +/* + * local routines + */ +static FLAC__bool EncoderSession_construct(EncoderSession *e, FLAC__bool use_ogg, FLAC__bool verify, FILE *infile, const char *infilename, const char *outfilename); +static void EncoderSession_destroy(EncoderSession *e); +static int EncoderSession_finish_ok(EncoderSession *e, int info_align_carry, int info_align_zero); +static int EncoderSession_finish_error(EncoderSession *e); +static FLAC__bool EncoderSession_init_encoder(EncoderSession *e, encode_options_t options, unsigned channels, unsigned bps, unsigned sample_rate); +static FLAC__bool EncoderSession_process(EncoderSession *e, const FLAC__int32 * const buffer[], unsigned samples); +static FLAC__bool convert_to_seek_table_template(const char *requested_seek_points, int num_requested_seek_points, FLAC__StreamMetadata *cuesheet, EncoderSession *e); +static FLAC__bool canonicalize_until_specification(utils__SkipUntilSpecification *spec, const char *inbasefilename, unsigned sample_rate, FLAC__uint64 skip, FLAC__uint64 total_samples_in_input); +static void format_input(FLAC__int32 *dest[], unsigned wide_samples, FLAC__bool is_big_endian, FLAC__bool is_unsigned_samples, unsigned channels, unsigned bps); +#ifdef FLAC__HAS_OGG +static FLAC__StreamEncoderWriteStatus ogg_stream_encoder_write_callback(const OggFLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data); +static void ogg_stream_encoder_metadata_callback(const OggFLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data); +static void ogg_file_encoder_progress_callback(const OggFLAC__FileEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data); +#endif +static FLAC__StreamEncoderWriteStatus flac_stream_encoder_write_callback(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data); +static void flac_stream_encoder_metadata_callback(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data); +static void flac_file_encoder_progress_callback(const FLAC__FileEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data); +static FLAC__bool parse_cuesheet_(FLAC__StreamMetadata **cuesheet, const char *cuesheet_filename, const char *inbasefilename, FLAC__bool is_cdda, FLAC__uint64 lead_out_offset); +static void print_stats(const EncoderSession *encoder_session); +static void print_error_with_state(const EncoderSession *e, const char *message); +static void print_verify_error(EncoderSession *e); +static FLAC__bool read_little_endian_uint16(FILE *f, FLAC__uint16 *val, FLAC__bool eof_ok, const char *fn); +static FLAC__bool read_little_endian_uint32(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn); +static FLAC__bool read_big_endian_uint16(FILE *f, FLAC__uint16 *val, FLAC__bool eof_ok, const char *fn); +static FLAC__bool read_big_endian_uint32(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn); +static FLAC__bool read_sane_extended(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn); +static FLAC__bool fskip_ahead(FILE *f, FLAC__uint64 offset); + +/* + * public routines + */ +int +flac__encode_aif(FILE *infile, long infilesize, const char *infilename, const char *outfilename, + const FLAC__byte *lookahead, unsigned lookahead_length, wav_encode_options_t options) +{ + EncoderSession encoder_session; + FLAC__uint16 x; + FLAC__uint32 xx; + unsigned int channels= 0U, bps= 0U, sample_rate= 0U, sample_frames= 0U; + FLAC__bool got_comm_chunk= false, got_ssnd_chunk= false; + int info_align_carry= -1, info_align_zero= -1; + + (void)infilesize; /* silence compiler warning about unused parameter */ + (void)lookahead; /* silence compiler warning about unused parameter */ + (void)lookahead_length; /* silence compiler warning about unused parameter */ + + if(! + EncoderSession_construct( + &encoder_session, +#ifdef FLAC__HAS_OGG + options.common.use_ogg, +#else + /*use_ogg=*/false, +#endif + options.common.verify, + infile, + infilename, + outfilename + ) + ) + return 1; + + /* lookahead[] already has "FORMxxxxAIFF", do sub-chunks */ + + while(1) { + size_t c= 0U; + char chunk_id[4]; + + /* chunk identifier; really conservative about behavior of fread() and feof() */ + if(feof(infile) || ((c= fread(chunk_id, 1U, 4U, infile)), c==0U && feof(infile))) + break; + else if(c<4U || feof(infile)) { + flac__utils_printf(stderr, 1, "%s: ERROR: incomplete chunk identifier\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + + if(got_comm_chunk==false && !strncmp(chunk_id, "COMM", 4)) { /* common chunk */ + unsigned long skip; + + /* COMM chunk size */ + if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + else if(xx<18U) { + flac__utils_printf(stderr, 1, "%s: ERROR: non-standard 'COMM' chunk has length = %u\n", encoder_session.inbasefilename, (unsigned int)xx); + return EncoderSession_finish_error(&encoder_session); + } + else if(xx!=18U) { + flac__utils_printf(stderr, 1, "%s: WARNING: non-standard 'COMM' chunk has length = %u\n", encoder_session.inbasefilename, (unsigned int)xx); + } + skip= (xx-18U)+(xx & 1U); + + /* number of channels */ + if(!read_big_endian_uint16(infile, &x, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + else if(x==0U || x>FLAC__MAX_CHANNELS) { + flac__utils_printf(stderr, 1, "%s: ERROR: unsupported number channels %u\n", encoder_session.inbasefilename, (unsigned int)x); + return EncoderSession_finish_error(&encoder_session); + } + else if(options.common.sector_align && x!=2U) { + flac__utils_printf(stderr, 1, "%s: ERROR: file has %u channels, must be 2 for --sector-align\n", encoder_session.inbasefilename, (unsigned int)x); + return EncoderSession_finish_error(&encoder_session); + } + channels= x; + + /* number of sample frames */ + if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + sample_frames= xx; + + /* bits per sample */ + if(!read_big_endian_uint16(infile, &x, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + else if(x!=8U && x!=16U && x!=24U) { + flac__utils_printf(stderr, 1, "%s: ERROR: unsupported bits per sample %u\n", encoder_session.inbasefilename, (unsigned int)x); + return EncoderSession_finish_error(&encoder_session); + } + else if(options.common.sector_align && x!=16U) { + flac__utils_printf(stderr, 1, "%s: ERROR: file has %u bits per sample, must be 16 for --sector-align\n", encoder_session.inbasefilename, (unsigned int)x); + return EncoderSession_finish_error(&encoder_session); + } + bps= x; + + /* sample rate */ + if(!read_sane_extended(infile, &xx, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + else if(!FLAC__format_sample_rate_is_valid(xx)) { + flac__utils_printf(stderr, 1, "%s: ERROR: unsupported sample rate %u\n", encoder_session.inbasefilename, (unsigned int)xx); + return EncoderSession_finish_error(&encoder_session); + } + else if(options.common.sector_align && xx!=44100U) { + flac__utils_printf(stderr, 1, "%s: ERROR: file's sample rate is %u, must be 44100 for --sector-align\n", encoder_session.inbasefilename, (unsigned int)xx); + return EncoderSession_finish_error(&encoder_session); + } + sample_rate= xx; + + /* skip any extra data in the COMM chunk */ + if(!fskip_ahead(infile, skip)) { + flac__utils_printf(stderr, 1, "%s: ERROR during read while skipping extra COMM data\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + + /* + * now that we know the sample rate, canonicalize the + * --skip string to a number of samples: + */ + flac__utils_canonicalize_skip_until_specification(&options.common.skip_specification, sample_rate); + FLAC__ASSERT(options.common.skip_specification.value.samples >= 0); + encoder_session.skip = (FLAC__uint64)options.common.skip_specification.value.samples; + FLAC__ASSERT(!options.common.sector_align || encoder_session.skip == 0); + + got_comm_chunk= true; + } + else if(got_ssnd_chunk==false && !strncmp(chunk_id, "SSND", 4)) { /* sound data chunk */ + unsigned int offset= 0U, block_size= 0U, align_remainder= 0U, data_bytes; + size_t bytes_per_frame= channels*(bps>>3); + FLAC__uint64 total_samples_in_input, trim = 0; + FLAC__bool pad= false; + + if(got_comm_chunk==false) { + flac__utils_printf(stderr, 1, "%s: ERROR: got 'SSND' chunk before 'COMM' chunk\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + + /* SSND chunk size */ + if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + data_bytes= xx; + pad= (data_bytes & 1U) ? true : false; + data_bytes-= 8U; /* discount the offset and block size fields */ + + /* offset */ + if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + offset= xx; + data_bytes-= offset; + + /* block size */ + if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + else if(xx!=0U) { + flac__utils_printf(stderr, 1, "%s: ERROR: block size is %u; must be 0\n", encoder_session.inbasefilename, (unsigned int)xx); + return EncoderSession_finish_error(&encoder_session); + } + block_size= xx; + + /* skip any SSND offset bytes */ + FLAC__ASSERT(offset<=LONG_MAX); + if(!fskip_ahead(infile, offset)) { + flac__utils_printf(stderr, 1, "%s: ERROR: skipping offset in SSND chunk\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + if(data_bytes!=(sample_frames*bytes_per_frame)) { + flac__utils_printf(stderr, 1, "%s: ERROR: SSND chunk size inconsistent with sample frame count\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + + /* *options.common.align_reservoir_samples will be 0 unless --sector-align is used */ + FLAC__ASSERT(options.common.sector_align || *options.common.align_reservoir_samples == 0); + total_samples_in_input = data_bytes / bytes_per_frame + *options.common.align_reservoir_samples; + + /* + * now that we know the input size, canonicalize the + * --until string to an absolute sample number: + */ + if(!canonicalize_until_specification(&options.common.until_specification, encoder_session.inbasefilename, sample_rate, encoder_session.skip, total_samples_in_input)) + return EncoderSession_finish_error(&encoder_session); + encoder_session.until = (FLAC__uint64)options.common.until_specification.value.samples; + FLAC__ASSERT(!options.common.sector_align || encoder_session.until == 0); + + if(encoder_session.skip>0U) { + if(!fskip_ahead(infile, encoder_session.skip*bytes_per_frame)) { + flac__utils_printf(stderr, 1, "%s: ERROR during read while skipping samples\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + } + + data_bytes-= (unsigned int)encoder_session.skip*bytes_per_frame; /*@@@ WATCHOUT: 4GB limit */ + encoder_session.total_samples_to_encode= total_samples_in_input - encoder_session.skip; + if(encoder_session.until > 0) { + trim = total_samples_in_input - encoder_session.until; + FLAC__ASSERT(total_samples_in_input > 0); + FLAC__ASSERT(!options.common.sector_align); + data_bytes-= (unsigned int)trim*bytes_per_frame; + encoder_session.total_samples_to_encode-= trim; + } + if(options.common.sector_align) { + align_remainder= (unsigned int)(encoder_session.total_samples_to_encode % 588U); + if(options.common.is_last_file) + encoder_session.total_samples_to_encode+= (588U-align_remainder); /* will pad with zeroes */ + else + encoder_session.total_samples_to_encode-= align_remainder; /* will stop short and carry over to next file */ + } + + /* +54 for the size of the AIFF headers; this is just an estimate for the progress indicator and doesn't need to be exact */ + encoder_session.unencoded_size= encoder_session.total_samples_to_encode*bytes_per_frame+54; + + if(!EncoderSession_init_encoder(&encoder_session, options.common, channels, bps, sample_rate)) + return EncoderSession_finish_error(&encoder_session); + + /* first do any samples in the reservoir */ + if(options.common.sector_align && *options.common.align_reservoir_samples>0U) { + + if(!EncoderSession_process(&encoder_session, (const FLAC__int32 *const *)options.common.align_reservoir, *options.common.align_reservoir_samples)) { + print_error_with_state(&encoder_session, "ERROR during encoding"); + return EncoderSession_finish_error(&encoder_session); + } + } + + /* decrement the data_bytes counter if we need to align the file */ + if(options.common.sector_align) { + if(options.common.is_last_file) + *options.common.align_reservoir_samples= 0U; + else { + *options.common.align_reservoir_samples= align_remainder; + data_bytes-= (*options.common.align_reservoir_samples)*bytes_per_frame; + } + } + + /* now do from the file */ + while(data_bytes>0) { + size_t bytes_read= fread(ucbuffer_, 1U, min(data_bytes, CHUNK_OF_SAMPLES*bytes_per_frame), infile); + + if(bytes_read==0U) { + if(ferror(infile)) { + flac__utils_printf(stderr, 1, "%s: ERROR during read\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + else if(feof(infile)) { + flac__utils_printf(stderr, 1, "%s: WARNING: unexpected EOF; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned int)encoder_session.total_samples_to_encode, (unsigned int)encoder_session.samples_written); + data_bytes= 0; + } + } + else { + if(bytes_read % bytes_per_frame != 0U) { + flac__utils_printf(stderr, 1, "%s: ERROR: got partial sample\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + else { + unsigned int frames= bytes_read/bytes_per_frame; + format_input(input_, frames, true, false, channels, bps); + + if(!EncoderSession_process(&encoder_session, (const FLAC__int32 *const *)input_, frames)) { + print_error_with_state(&encoder_session, "ERROR during encoding"); + return EncoderSession_finish_error(&encoder_session); + } + else + data_bytes-= bytes_read; + } + } + } + + if(trim>0) { + FLAC__ASSERT(!options.common.sector_align); + if(!fskip_ahead(infile, trim*bytes_per_frame)) { + flac__utils_printf(stderr, 1, "%s: ERROR during read while skipping samples\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + } + + /* now read unaligned samples into reservoir or pad with zeroes if necessary */ + if(options.common.sector_align) { + if(options.common.is_last_file) { + unsigned int pad_frames= 588U-align_remainder; + + if(pad_frames<588U) { + unsigned int i; + + info_align_zero= pad_frames; + for(i= 0U; i>3)); + + if(!EncoderSession_process(&encoder_session, (const FLAC__int32 *const *)input_, pad_frames)) { + print_error_with_state(&encoder_session, "ERROR during encoding"); + return EncoderSession_finish_error(&encoder_session); + } + } + } + else { + if(*options.common.align_reservoir_samples > 0) { + size_t bytes_read= fread(ucbuffer_, 1U, (*options.common.align_reservoir_samples)*bytes_per_frame, infile); + + FLAC__ASSERT(CHUNK_OF_SAMPLES>=588U); + if(bytes_read==0U && ferror(infile)) { + flac__utils_printf(stderr, 1, "%s: ERROR during read\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + else if(bytes_read != (*options.common.align_reservoir_samples) * bytes_per_frame) { + flac__utils_printf(stderr, 1, "%s: WARNING: unexpected EOF; read %u bytes; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned int)bytes_read, (unsigned int)encoder_session.total_samples_to_encode, (unsigned int)encoder_session.samples_written); + } + else { + info_align_carry= *options.common.align_reservoir_samples; + format_input(options.common.align_reservoir, *options.common.align_reservoir_samples, true, false, channels, bps); + } + } + } + } + + if(pad==true) { + unsigned char tmp; + + if(fread(&tmp, 1U, 1U, infile)<1U) { + flac__utils_printf(stderr, 1, "%s: ERROR during read of SSND pad byte\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + } + + got_ssnd_chunk= true; + } + else { /* other chunk */ + if(!strncmp(chunk_id, "COMM", 4)) { + flac__utils_printf(stderr, 1, "%s: WARNING: skipping extra 'COMM' chunk\n", encoder_session.inbasefilename); + } + else if(!strncmp(chunk_id, "SSND", 4)) { + flac__utils_printf(stderr, 1, "%s: WARNING: skipping extra 'SSND' chunk\n", encoder_session.inbasefilename); + } + else { + flac__utils_printf(stderr, 1, "%s: WARNING: skipping unknown chunk '%s'\n", encoder_session.inbasefilename, chunk_id); + } + + /* chunk size */ + if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + else { + unsigned long skip= xx+(xx & 1U); + + FLAC__ASSERT(skip<=LONG_MAX); + if(!fskip_ahead(infile, skip)) { + fprintf(stderr, "%s: ERROR during read while skipping unknown chunk\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + } + } + } + + if(got_ssnd_chunk==false && sample_frames!=0U) { + flac__utils_printf(stderr, 1, "%s: ERROR: missing SSND chunk\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + + return EncoderSession_finish_ok(&encoder_session, info_align_carry, info_align_zero); +} + +int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, wav_encode_options_t options) +{ + EncoderSession encoder_session; + FLAC__bool is_unsigned_samples = false; + unsigned channels = 0, bps = 0, sample_rate = 0, data_bytes; + size_t bytes_per_wide_sample, bytes_read; + FLAC__uint16 x; + FLAC__uint32 xx; + FLAC__bool got_fmt_chunk = false, got_data_chunk = false; + unsigned align_remainder = 0; + int info_align_carry = -1, info_align_zero = -1; + + (void)infilesize; + (void)lookahead; + (void)lookahead_length; + + if(! + EncoderSession_construct( + &encoder_session, +#ifdef FLAC__HAS_OGG + options.common.use_ogg, +#else + /*use_ogg=*/false, +#endif + options.common.verify, + infile, + infilename, + outfilename + ) + ) + return 1; + + /* + * lookahead[] already has "RIFFxxxxWAVE", do sub-chunks + */ + while(!feof(infile)) { + if(!read_little_endian_uint32(infile, &xx, true, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + if(feof(infile)) + break; + if(xx == 0x20746d66 && !got_fmt_chunk) { /* "fmt " */ + unsigned block_align; + + /* fmt sub-chunk size */ + if(!read_little_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + if(xx < 16) { + flac__utils_printf(stderr, 1, "%s: ERROR: found non-standard 'fmt ' sub-chunk which has length = %u\n", encoder_session.inbasefilename, (unsigned)xx); + return EncoderSession_finish_error(&encoder_session); + } + else if(xx != 16 && xx != 18) { + flac__utils_printf(stderr, 1, "%s: WARNING: found non-standard 'fmt ' sub-chunk which has length = %u\n", encoder_session.inbasefilename, (unsigned)xx); + } + data_bytes = xx; + /* compression code */ + if(!read_little_endian_uint16(infile, &x, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + if(x != 1) { + flac__utils_printf(stderr, 1, "%s: ERROR: unsupported compression type %u\n", encoder_session.inbasefilename, (unsigned)x); + return EncoderSession_finish_error(&encoder_session); + } + /* number of channels */ + if(!read_little_endian_uint16(infile, &x, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + if(x == 0 || x > FLAC__MAX_CHANNELS) { + flac__utils_printf(stderr, 1, "%s: ERROR: unsupported number channels %u\n", encoder_session.inbasefilename, (unsigned)x); + return EncoderSession_finish_error(&encoder_session); + } + else if(options.common.sector_align && x != 2) { + flac__utils_printf(stderr, 1, "%s: ERROR: file has %u channels, must be 2 for --sector-align\n", encoder_session.inbasefilename, (unsigned)x); + return EncoderSession_finish_error(&encoder_session); + } + channels = x; + /* sample rate */ + if(!read_little_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + if(!FLAC__format_sample_rate_is_valid(xx)) { + flac__utils_printf(stderr, 1, "%s: ERROR: unsupported sample rate %u\n", encoder_session.inbasefilename, (unsigned)xx); + return EncoderSession_finish_error(&encoder_session); + } + else if(options.common.sector_align && xx != 44100) { + flac__utils_printf(stderr, 1, "%s: ERROR: file's sample rate is %u, must be 44100 for --sector-align\n", encoder_session.inbasefilename, (unsigned)xx); + return EncoderSession_finish_error(&encoder_session); + } + sample_rate = xx; + /* avg bytes per second (ignored) */ + if(!read_little_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + /* block align */ + if(!read_little_endian_uint16(infile, &x, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + block_align = x; + /* bits per sample */ + if(!read_little_endian_uint16(infile, &x, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + if(x != 8 && x != 16 && x != 24) { + flac__utils_printf(stderr, 1, "%s: ERROR: unsupported bits-per-sample %u\n", encoder_session.inbasefilename, (unsigned)x); + return EncoderSession_finish_error(&encoder_session); + } + else if(options.common.sector_align && x != 16) { + flac__utils_printf(stderr, 1, "%s: ERROR: file has %u bits per sample, must be 16 for --sector-align\n", encoder_session.inbasefilename, (unsigned)x); + return EncoderSession_finish_error(&encoder_session); + } + bps = x; + if(bps * channels != block_align * 8) { + flac__utils_printf(stderr, 1, "%s: ERROR: unsupported block alignment (%u), for bits-per-sample=%u, channels=%u\n", encoder_session.inbasefilename, block_align, bps, channels); + return EncoderSession_finish_error(&encoder_session); + } + is_unsigned_samples = (x == 8); + + /* skip any extra data in the fmt sub-chunk */ + data_bytes -= 16; + if(data_bytes > 0) { + unsigned left, need; + for(left = data_bytes; left > 0; ) { + need = min(left, CHUNK_OF_SAMPLES); + if(fread(ucbuffer_, 1U, need, infile) < need) { + flac__utils_printf(stderr, 1, "%s: ERROR during read while skipping samples\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + left -= need; + } + } + + /* + * now that we know the sample rate, canonicalize the + * --skip string to a number of samples: + */ + flac__utils_canonicalize_skip_until_specification(&options.common.skip_specification, sample_rate); + FLAC__ASSERT(options.common.skip_specification.value.samples >= 0); + encoder_session.skip = (FLAC__uint64)options.common.skip_specification.value.samples; + FLAC__ASSERT(!options.common.sector_align || encoder_session.skip == 0); + + got_fmt_chunk = true; + } + else if(xx == 0x61746164 && !got_data_chunk && got_fmt_chunk) { /* "data" */ + FLAC__uint64 total_samples_in_input, trim = 0; + FLAC__bool pad = false; + + /* data size */ + if(!read_little_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + data_bytes = xx; + pad = (data_bytes & 1U) ? true : false; + + bytes_per_wide_sample = channels * (bps >> 3); + + /* *options.common.align_reservoir_samples will be 0 unless --sector-align is used */ + FLAC__ASSERT(options.common.sector_align || *options.common.align_reservoir_samples == 0); + total_samples_in_input = data_bytes / bytes_per_wide_sample + *options.common.align_reservoir_samples; + + /* + * now that we know the input size, canonicalize the + * --until string to an absolute sample number: + */ + if(!canonicalize_until_specification(&options.common.until_specification, encoder_session.inbasefilename, sample_rate, encoder_session.skip, total_samples_in_input)) + return EncoderSession_finish_error(&encoder_session); + encoder_session.until = (FLAC__uint64)options.common.until_specification.value.samples; + FLAC__ASSERT(!options.common.sector_align || encoder_session.until == 0); + + if(encoder_session.skip > 0) { + if(!fskip_ahead(infile, encoder_session.skip * bytes_per_wide_sample)) { + flac__utils_printf(stderr, 1, "%s: ERROR during read while skipping samples\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + } + + data_bytes -= (unsigned)encoder_session.skip * bytes_per_wide_sample; /*@@@ WATCHOUT: 4GB limit */ + encoder_session.total_samples_to_encode = total_samples_in_input - encoder_session.skip; + if(encoder_session.until > 0) { + trim = total_samples_in_input - encoder_session.until; + FLAC__ASSERT(total_samples_in_input > 0); + FLAC__ASSERT(!options.common.sector_align); + data_bytes -= (unsigned int)trim * bytes_per_wide_sample; + encoder_session.total_samples_to_encode -= trim; + } + if(options.common.sector_align) { + align_remainder = (unsigned)(encoder_session.total_samples_to_encode % 588); + if(options.common.is_last_file) + encoder_session.total_samples_to_encode += (588-align_remainder); /* will pad with zeroes */ + else + encoder_session.total_samples_to_encode -= align_remainder; /* will stop short and carry over to next file */ + } + + /* +44 for the size of the WAV headers; this is just an estimate for the progress indicator and doesn't need to be exact */ + encoder_session.unencoded_size = encoder_session.total_samples_to_encode * bytes_per_wide_sample + 44; + + if(!EncoderSession_init_encoder(&encoder_session, options.common, channels, bps, sample_rate)) + return EncoderSession_finish_error(&encoder_session); + + /* + * first do any samples in the reservoir + */ + if(options.common.sector_align && *options.common.align_reservoir_samples > 0) { + if(!EncoderSession_process(&encoder_session, (const FLAC__int32 * const *)options.common.align_reservoir, *options.common.align_reservoir_samples)) { + print_error_with_state(&encoder_session, "ERROR during encoding"); + return EncoderSession_finish_error(&encoder_session); + } + } + + /* + * decrement the data_bytes counter if we need to align the file + */ + if(options.common.sector_align) { + if(options.common.is_last_file) { + *options.common.align_reservoir_samples = 0; + } + else { + *options.common.align_reservoir_samples = align_remainder; + data_bytes -= (*options.common.align_reservoir_samples) * bytes_per_wide_sample; + } + } + + /* + * now do from the file + */ + while(data_bytes > 0) { + bytes_read = fread(ucbuffer_, sizeof(unsigned char), min(data_bytes, CHUNK_OF_SAMPLES * bytes_per_wide_sample), infile); + if(bytes_read == 0) { + if(ferror(infile)) { + flac__utils_printf(stderr, 1, "%s: ERROR during read\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + else if(feof(infile)) { + flac__utils_printf(stderr, 1, "%s: WARNING: unexpected EOF; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned)encoder_session.total_samples_to_encode, (unsigned)encoder_session.samples_written); + data_bytes = 0; + } + } + else { + if(bytes_read % bytes_per_wide_sample != 0) { + flac__utils_printf(stderr, 1, "%s: ERROR: got partial sample\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + else { + unsigned wide_samples = bytes_read / bytes_per_wide_sample; + format_input(input_, wide_samples, false, is_unsigned_samples, channels, bps); + + if(!EncoderSession_process(&encoder_session, (const FLAC__int32 * const *)input_, wide_samples)) { + print_error_with_state(&encoder_session, "ERROR during encoding"); + return EncoderSession_finish_error(&encoder_session); + } + data_bytes -= bytes_read; + } + } + } + + if(trim > 0) { + FLAC__ASSERT(!options.common.sector_align); + if(!fskip_ahead(infile, trim * bytes_per_wide_sample)) { + flac__utils_printf(stderr, 1, "%s: ERROR during read while skipping samples\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + } + + /* + * now read unaligned samples into reservoir or pad with zeroes if necessary + */ + if(options.common.sector_align) { + if(options.common.is_last_file) { + unsigned wide_samples = 588 - align_remainder; + if(wide_samples < 588) { + unsigned channel; + + info_align_zero = wide_samples; + data_bytes = wide_samples * (bps >> 3); + for(channel = 0; channel < channels; channel++) + memset(input_[channel], 0, data_bytes); + + if(!EncoderSession_process(&encoder_session, (const FLAC__int32 * const *)input_, wide_samples)) { + print_error_with_state(&encoder_session, "ERROR during encoding"); + return EncoderSession_finish_error(&encoder_session); + } + } + } + else { + if(*options.common.align_reservoir_samples > 0) { + FLAC__ASSERT(CHUNK_OF_SAMPLES >= 588); + bytes_read = fread(ucbuffer_, sizeof(unsigned char), (*options.common.align_reservoir_samples) * bytes_per_wide_sample, infile); + if(bytes_read == 0 && ferror(infile)) { + flac__utils_printf(stderr, 1, "%s: ERROR during read\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + else if(bytes_read != (*options.common.align_reservoir_samples) * bytes_per_wide_sample) { + flac__utils_printf(stderr, 1, "%s: WARNING: unexpected EOF; read %u bytes; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned)bytes_read, (unsigned)encoder_session.total_samples_to_encode, (unsigned)encoder_session.samples_written); + data_bytes = 0; + } + else { + info_align_carry = *options.common.align_reservoir_samples; + format_input(options.common.align_reservoir, *options.common.align_reservoir_samples, false, is_unsigned_samples, channels, bps); + } + } + } + } + + if(pad == true) { + unsigned char tmp; + + if(fread(&tmp, 1U, 1U, infile) < 1U) { + flac__utils_printf(stderr, 1, "%s: ERROR during read of data pad byte\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + } + + got_data_chunk = true; + } + else { + if(xx == 0x20746d66 && got_fmt_chunk) { /* "fmt " */ + flac__utils_printf(stderr, 1, "%s: WARNING: skipping extra 'fmt ' sub-chunk\n", encoder_session.inbasefilename); + } + else if(xx == 0x61746164) { /* "data" */ + if(got_data_chunk) { + flac__utils_printf(stderr, 1, "%s: WARNING: skipping extra 'data' sub-chunk\n", encoder_session.inbasefilename); + } + else if(!got_fmt_chunk) { + flac__utils_printf(stderr, 1, "%s: ERROR: got 'data' sub-chunk before 'fmt' sub-chunk\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + else { + FLAC__ASSERT(0); + } + } + else { + flac__utils_printf(stderr, 1, "%s: WARNING: skipping unknown sub-chunk '%c%c%c%c'\n", encoder_session.inbasefilename, (char)(xx&255), (char)((xx>>8)&255), (char)((xx>>16)&255), (char)(xx>>24)); + } + /* sub-chunk size */ + if(!read_little_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + else { + unsigned long skip = xx+(xx & 1U); + + FLAC__ASSERT(skip<=LONG_MAX); + if(!fskip_ahead(infile, skip)) { + flac__utils_printf(stderr, 1, "%s: ERROR during read while skipping unsupported sub-chunk\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + } + } + } + + return EncoderSession_finish_ok(&encoder_session, info_align_carry, info_align_zero); +} + +int flac__encode_raw(FILE *infile, long infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, raw_encode_options_t options) +{ + EncoderSession encoder_session; + size_t bytes_read; + const size_t bytes_per_wide_sample = options.channels * (options.bps >> 3); + unsigned align_remainder = 0; + int info_align_carry = -1, info_align_zero = -1; + FLAC__uint64 total_samples_in_input = 0;; + + FLAC__ASSERT(!options.common.sector_align || options.channels == 2); + FLAC__ASSERT(!options.common.sector_align || options.bps == 16); + FLAC__ASSERT(!options.common.sector_align || options.sample_rate == 44100); + FLAC__ASSERT(!options.common.sector_align || infilesize >= 0); + FLAC__ASSERT(!options.common.replay_gain || options.channels <= 2); + FLAC__ASSERT(!options.common.replay_gain || grabbag__replaygain_is_valid_sample_frequency(options.sample_rate)); + + if(! + EncoderSession_construct( + &encoder_session, +#ifdef FLAC__HAS_OGG + options.common.use_ogg, +#else + /*use_ogg=*/false, +#endif + options.common.verify, + infile, + infilename, + outfilename + ) + ) + return 1; + + /* + * now that we know the sample rate, canonicalize the + * --skip string to a number of samples: + */ + flac__utils_canonicalize_skip_until_specification(&options.common.skip_specification, options.sample_rate); + FLAC__ASSERT(options.common.skip_specification.value.samples >= 0); + encoder_session.skip = (FLAC__uint64)options.common.skip_specification.value.samples; + FLAC__ASSERT(!options.common.sector_align || encoder_session.skip == 0); + + if(infilesize < 0) + total_samples_in_input = 0; + else { + /* *options.common.align_reservoir_samples will be 0 unless --sector-align is used */ + FLAC__ASSERT(options.common.sector_align || *options.common.align_reservoir_samples == 0); + total_samples_in_input = (unsigned)infilesize / bytes_per_wide_sample + *options.common.align_reservoir_samples; + } + + /* + * now that we know the input size, canonicalize the + * --until strings to a number of samples: + */ + if(!canonicalize_until_specification(&options.common.until_specification, encoder_session.inbasefilename, options.sample_rate, encoder_session.skip, total_samples_in_input)) + return EncoderSession_finish_error(&encoder_session); + encoder_session.until = (FLAC__uint64)options.common.until_specification.value.samples; + FLAC__ASSERT(!options.common.sector_align || encoder_session.until == 0); + + encoder_session.total_samples_to_encode = total_samples_in_input - encoder_session.skip; + if(encoder_session.until > 0) { + const FLAC__uint64 trim = total_samples_in_input - encoder_session.until; + FLAC__ASSERT(total_samples_in_input > 0); + FLAC__ASSERT(!options.common.sector_align); + encoder_session.total_samples_to_encode -= trim; + } + if(infilesize >= 0 && options.common.sector_align) { + FLAC__ASSERT(encoder_session.skip == 0); + align_remainder = (unsigned)(encoder_session.total_samples_to_encode % 588); + if(options.common.is_last_file) + encoder_session.total_samples_to_encode += (588-align_remainder); /* will pad with zeroes */ + else + encoder_session.total_samples_to_encode -= align_remainder; /* will stop short and carry over to next file */ + } + encoder_session.unencoded_size = encoder_session.total_samples_to_encode * bytes_per_wide_sample; + + if(encoder_session.total_samples_to_encode <= 0) + flac__utils_printf(stderr, 2, "(No runtime statistics possible; please wait for encoding to finish...)\n"); + + if(encoder_session.skip > 0) { + unsigned skip_bytes = bytes_per_wide_sample * (unsigned)encoder_session.skip; + if(skip_bytes > lookahead_length) { + skip_bytes -= lookahead_length; + lookahead_length = 0; + if(!fskip_ahead(infile, skip_bytes)) { + flac__utils_printf(stderr, 1, "%s: ERROR during read while skipping samples\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + } + else { + lookahead += skip_bytes; + lookahead_length -= skip_bytes; + } + } + + if(!EncoderSession_init_encoder(&encoder_session, options.common, options.channels, options.bps, options.sample_rate)) + return EncoderSession_finish_error(&encoder_session); + + /* + * first do any samples in the reservoir + */ + if(options.common.sector_align && *options.common.align_reservoir_samples > 0) { + if(!EncoderSession_process(&encoder_session, (const FLAC__int32 * const *)options.common.align_reservoir, *options.common.align_reservoir_samples)) { + print_error_with_state(&encoder_session, "ERROR during encoding"); + return EncoderSession_finish_error(&encoder_session); + } + } + + /* + * decrement infilesize if we need to align the file + */ + if(options.common.sector_align) { + FLAC__ASSERT(infilesize >= 0); + if(options.common.is_last_file) { + *options.common.align_reservoir_samples = 0; + } + else { + *options.common.align_reservoir_samples = align_remainder; + infilesize -= (long)((*options.common.align_reservoir_samples) * bytes_per_wide_sample); + FLAC__ASSERT(infilesize >= 0); + } + } + + /* + * now do from the file + */ + if(infilesize < 0) { + while(!feof(infile)) { + if(lookahead_length > 0) { + FLAC__ASSERT(lookahead_length < CHUNK_OF_SAMPLES * bytes_per_wide_sample); + memcpy(ucbuffer_, lookahead, lookahead_length); + bytes_read = fread(ucbuffer_+lookahead_length, sizeof(unsigned char), CHUNK_OF_SAMPLES * bytes_per_wide_sample - lookahead_length, infile) + lookahead_length; + if(ferror(infile)) { + flac__utils_printf(stderr, 1, "%s: ERROR during read\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + lookahead_length = 0; + } + else + bytes_read = fread(ucbuffer_, sizeof(unsigned char), CHUNK_OF_SAMPLES * bytes_per_wide_sample, infile); + + if(bytes_read == 0) { + if(ferror(infile)) { + flac__utils_printf(stderr, 1, "%s: ERROR during read\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + } + else if(bytes_read % bytes_per_wide_sample != 0) { + flac__utils_printf(stderr, 1, "%s: ERROR: got partial sample\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + else { + unsigned wide_samples = bytes_read / bytes_per_wide_sample; + format_input(input_, wide_samples, options.is_big_endian, options.is_unsigned_samples, options.channels, options.bps); + + if(!EncoderSession_process(&encoder_session, (const FLAC__int32 * const *)input_, wide_samples)) { + print_error_with_state(&encoder_session, "ERROR during encoding"); + return EncoderSession_finish_error(&encoder_session); + } + } + } + } + else { + const FLAC__uint64 max_input_bytes = encoder_session.total_samples_to_encode * bytes_per_wide_sample; + FLAC__uint64 total_input_bytes_read = 0; + while(total_input_bytes_read < max_input_bytes) { + { + size_t wanted = (CHUNK_OF_SAMPLES * bytes_per_wide_sample); + wanted = min(wanted, (size_t)(max_input_bytes - total_input_bytes_read)); + + if(lookahead_length > 0) { + FLAC__ASSERT(lookahead_length <= wanted); + memcpy(ucbuffer_, lookahead, lookahead_length); + wanted -= lookahead_length; + bytes_read = lookahead_length; + if(wanted > 0) { + bytes_read += fread(ucbuffer_+lookahead_length, sizeof(unsigned char), wanted, infile); + if(ferror(infile)) { + flac__utils_printf(stderr, 1, "%s: ERROR during read\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + } + lookahead_length = 0; + } + else + bytes_read = fread(ucbuffer_, sizeof(unsigned char), wanted, infile); + } + + if(bytes_read == 0) { + if(ferror(infile)) { + flac__utils_printf(stderr, 1, "%s: ERROR during read\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + else if(feof(infile)) { + flac__utils_printf(stderr, 1, "%s: WARNING: unexpected EOF; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned)encoder_session.total_samples_to_encode, (unsigned)encoder_session.samples_written); + total_input_bytes_read = max_input_bytes; + } + } + else { + if(bytes_read % bytes_per_wide_sample != 0) { + flac__utils_printf(stderr, 1, "%s: ERROR: got partial sample\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + else { + unsigned wide_samples = bytes_read / bytes_per_wide_sample; + format_input(input_, wide_samples, options.is_big_endian, options.is_unsigned_samples, options.channels, options.bps); + + if(!EncoderSession_process(&encoder_session, (const FLAC__int32 * const *)input_, wide_samples)) { + print_error_with_state(&encoder_session, "ERROR during encoding"); + return EncoderSession_finish_error(&encoder_session); + } + total_input_bytes_read += bytes_read; + } + } + } + } + + /* + * now read unaligned samples into reservoir or pad with zeroes if necessary + */ + if(options.common.sector_align) { + if(options.common.is_last_file) { + unsigned wide_samples = 588 - align_remainder; + if(wide_samples < 588) { + unsigned channel, data_bytes; + + info_align_zero = wide_samples; + data_bytes = wide_samples * (options.bps >> 3); + for(channel = 0; channel < options.channels; channel++) + memset(input_[channel], 0, data_bytes); + + if(!EncoderSession_process(&encoder_session, (const FLAC__int32 * const *)input_, wide_samples)) { + print_error_with_state(&encoder_session, "ERROR during encoding"); + return EncoderSession_finish_error(&encoder_session); + } + } + } + else { + if(*options.common.align_reservoir_samples > 0) { + FLAC__ASSERT(CHUNK_OF_SAMPLES >= 588); + bytes_read = fread(ucbuffer_, sizeof(unsigned char), (*options.common.align_reservoir_samples) * bytes_per_wide_sample, infile); + if(bytes_read == 0 && ferror(infile)) { + flac__utils_printf(stderr, 1, "%s: ERROR during read\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + else if(bytes_read != (*options.common.align_reservoir_samples) * bytes_per_wide_sample) { + flac__utils_printf(stderr, 1, "%s: WARNING: unexpected EOF; read %u bytes; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned)bytes_read, (unsigned)encoder_session.total_samples_to_encode, (unsigned)encoder_session.samples_written); + } + else { + info_align_carry = *options.common.align_reservoir_samples; + format_input(options.common.align_reservoir, *options.common.align_reservoir_samples, false, options.is_unsigned_samples, options.channels, options.bps); + } + } + } + } + + return EncoderSession_finish_ok(&encoder_session, info_align_carry, info_align_zero); +} + +FLAC__bool EncoderSession_construct(EncoderSession *e, FLAC__bool use_ogg, FLAC__bool verify, FILE *infile, const char *infilename, const char *outfilename) +{ + unsigned i; + FLAC__uint32 test = 1; + + /* + * initialize globals + */ + + is_big_endian_host_ = (*((FLAC__byte*)(&test)))? false : true; + + for(i = 0; i < FLAC__MAX_CHANNELS; i++) + input_[i] = &(in_[i][0]); + + + /* + * initialize instance + */ + +#ifdef FLAC__HAS_OGG + e->use_ogg = use_ogg; +#else + (void)use_ogg; +#endif + e->verify = verify; + + e->is_stdout = (0 == strcmp(outfilename, "-")); + + e->inbasefilename = grabbag__file_get_basename(infilename); + e->outfilename = outfilename; + + e->skip = 0; /* filled in later after the sample_rate is known */ + e->unencoded_size = 0; + e->total_samples_to_encode = 0; + e->bytes_written = 0; + e->samples_written = 0; + e->blocksize = 0; + e->stats_mask = 0; + + e->encoder.flac.stream = 0; + e->encoder.flac.file = 0; +#ifdef FLAC__HAS_OGG + e->encoder.ogg.stream = 0; + e->encoder.ogg.file = 0; +#endif + + e->fin = infile; + e->fout = 0; + e->seek_table_template = 0; + + if(e->is_stdout) { + e->fout = grabbag__file_get_binary_stdout(); + } + + if(0 == (e->seek_table_template = FLAC__metadata_object_new(FLAC__METADATA_TYPE_SEEKTABLE))) { + flac__utils_printf(stderr, 1, "%s: ERROR allocating memory for seek table\n", e->inbasefilename); + return false; + } + +#ifdef FLAC__HAS_OGG + if(e->use_ogg) { + if(e->is_stdout) { + e->encoder.ogg.stream = OggFLAC__stream_encoder_new(); + if(0 == e->encoder.ogg.stream) { + flac__utils_printf(stderr, 1, "%s: ERROR creating the encoder instance\n", e->inbasefilename); + EncoderSession_destroy(e); + return false; + } + } + else { + e->encoder.ogg.file = OggFLAC__file_encoder_new(); + if(0 == e->encoder.ogg.file) { + flac__utils_printf(stderr, 1, "%s: ERROR creating the encoder instance\n", e->inbasefilename); + EncoderSession_destroy(e); + return false; + } + } + } + else +#endif + if(e->is_stdout) { + e->encoder.flac.stream = FLAC__stream_encoder_new(); + if(0 == e->encoder.flac.stream) { + flac__utils_printf(stderr, 1, "%s: ERROR creating the encoder instance\n", e->inbasefilename); + EncoderSession_destroy(e); + return false; + } + } + else { + e->encoder.flac.file = FLAC__file_encoder_new(); + if(0 == e->encoder.flac.file) { + flac__utils_printf(stderr, 1, "%s: ERROR creating the encoder instance\n", e->inbasefilename); + EncoderSession_destroy(e); + return false; + } + } + + return true; +} + +void EncoderSession_destroy(EncoderSession *e) +{ + if(e->fin != stdin) + fclose(e->fin); + if(0 != e->fout && e->fout != stdout) + fclose(e->fout); + +#ifdef FLAC__HAS_OGG + if(e->use_ogg) { + if(e->is_stdout) { + if(0 != e->encoder.ogg.stream) { + OggFLAC__stream_encoder_delete(e->encoder.ogg.stream); + e->encoder.ogg.stream = 0; + } + } + else { + if(0 != e->encoder.ogg.file) { + OggFLAC__file_encoder_delete(e->encoder.ogg.file); + e->encoder.ogg.file = 0; + } + } + } + else +#endif + if(e->is_stdout) { + if(0 != e->encoder.flac.stream) { + FLAC__stream_encoder_delete(e->encoder.flac.stream); + e->encoder.flac.stream = 0; + } + } + else { + if(0 != e->encoder.flac.file) { + FLAC__file_encoder_delete(e->encoder.flac.file); + e->encoder.flac.file = 0; + } + } + + if(0 != e->seek_table_template) { + FLAC__metadata_object_delete(e->seek_table_template); + e->seek_table_template = 0; + } +} + +int EncoderSession_finish_ok(EncoderSession *e, int info_align_carry, int info_align_zero) +{ + FLAC__StreamEncoderState fse_state = FLAC__STREAM_ENCODER_OK; + int ret = 0; + +#ifdef FLAC__HAS_OGG + if(e->use_ogg) { + if(e->is_stdout) { + if(e->encoder.ogg.stream) { + fse_state = OggFLAC__stream_encoder_get_FLAC_stream_encoder_state(e->encoder.ogg.stream); + OggFLAC__stream_encoder_finish(e->encoder.ogg.stream); + } + } + else { + if(e->encoder.ogg.file) { + fse_state = OggFLAC__file_encoder_get_FLAC_stream_encoder_state(e->encoder.ogg.file); + OggFLAC__file_encoder_finish(e->encoder.ogg.file); + } + } + } + else +#endif + if(e->is_stdout) { + if(e->encoder.flac.stream) { + fse_state = FLAC__stream_encoder_get_state(e->encoder.flac.stream); + FLAC__stream_encoder_finish(e->encoder.flac.stream); + } + } + else { + if(e->encoder.flac.file) { + fse_state = FLAC__file_encoder_get_stream_encoder_state(e->encoder.flac.file); + FLAC__file_encoder_finish(e->encoder.flac.file); + } + } + + if(e->total_samples_to_encode > 0) { + print_stats(e); + flac__utils_printf(stderr, 2, "\n"); + } + + if(fse_state == FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA) { + print_verify_error(e); + ret = 1; + } + else { + if(info_align_carry >= 0) { + flac__utils_printf(stderr, 1, "%s: INFO: sector alignment causing %d samples to be carried over\n", e->inbasefilename, info_align_carry); + } + if(info_align_zero >= 0) { + flac__utils_printf(stderr, 1, "%s: INFO: sector alignment causing %d zero samples to be appended\n", e->inbasefilename, info_align_zero); + } + } + + EncoderSession_destroy(e); + + return ret; +} + +int EncoderSession_finish_error(EncoderSession *e) +{ + FLAC__StreamEncoderState fse_state; + + if(e->total_samples_to_encode > 0) + flac__utils_printf(stderr, 2, "\n"); + +#ifdef FLAC__HAS_OGG + if(e->use_ogg) { + if(e->is_stdout) { + fse_state = OggFLAC__stream_encoder_get_FLAC_stream_encoder_state(e->encoder.ogg.stream); + } + else { + fse_state = OggFLAC__file_encoder_get_FLAC_stream_encoder_state(e->encoder.ogg.file); + } + } + else +#endif + if(e->is_stdout) { + fse_state = FLAC__stream_encoder_get_state(e->encoder.flac.stream); + } + else { + fse_state = FLAC__file_encoder_get_stream_encoder_state(e->encoder.flac.file); + } + + if(fse_state == FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA) + print_verify_error(e); + else + unlink(e->outfilename); + + EncoderSession_destroy(e); + + return 1; +} + +FLAC__bool EncoderSession_init_encoder(EncoderSession *e, encode_options_t options, unsigned channels, unsigned bps, unsigned sample_rate) +{ + unsigned num_metadata; + FLAC__StreamMetadata padding, *cuesheet = 0; + FLAC__StreamMetadata *metadata[4]; + const FLAC__bool is_cdda = (channels == 1 || channels == 2) && (bps == 16) && (sample_rate == 44100); + + e->replay_gain = options.replay_gain; + e->channels = channels; + e->bits_per_sample = bps; + e->sample_rate = sample_rate; + + if(e->replay_gain) { + if(channels != 1 && channels != 2) { + flac__utils_printf(stderr, 1, "%s: ERROR, number of channels (%u) must be 1 or 2 for --replay-gain\n", e->inbasefilename, channels); + return false; + } + if(!grabbag__replaygain_is_valid_sample_frequency(sample_rate)) { + flac__utils_printf(stderr, 1, "%s: ERROR, invalid sample rate (%u) for --replay-gain\n", e->inbasefilename, sample_rate); + return false; + } + if(options.is_first_file) { + if(!grabbag__replaygain_init(sample_rate)) { + flac__utils_printf(stderr, 1, "%s: ERROR initializing ReplayGain stage\n", e->inbasefilename); + return false; + } + } + } + + if(channels != 2) + options.do_mid_side = options.loose_mid_side = false; + + if(!parse_cuesheet_(&cuesheet, options.cuesheet_filename, e->inbasefilename, is_cdda, e->total_samples_to_encode)) + return false; + + if(!convert_to_seek_table_template(options.requested_seek_points, options.num_requested_seek_points, options.cued_seekpoints? cuesheet : 0, e)) { + flac__utils_printf(stderr, 1, "%s: ERROR allocating memory for seek table\n", e->inbasefilename); + if(0 != cuesheet) + FLAC__metadata_object_delete(cuesheet); + return false; + } + + num_metadata = 0; + if(e->seek_table_template->data.seek_table.num_points > 0) { + e->seek_table_template->is_last = false; /* the encoder will set this for us */ + metadata[num_metadata++] = e->seek_table_template; + } + if(0 != cuesheet) + metadata[num_metadata++] = cuesheet; + metadata[num_metadata++] = options.vorbis_comment; + if(options.padding > 0) { + padding.is_last = false; /* the encoder will set this for us */ + padding.type = FLAC__METADATA_TYPE_PADDING; + padding.length = (unsigned)options.padding; + metadata[num_metadata++] = &padding; + } + + e->blocksize = options.blocksize; + e->stats_mask = (options.do_exhaustive_model_search || options.do_qlp_coeff_prec_search)? 0x0f : 0x3f; + +#ifdef FLAC__HAS_OGG + if(e->use_ogg) { + if(e->is_stdout) { + OggFLAC__stream_encoder_set_serial_number(e->encoder.ogg.stream, options.serial_number); + OggFLAC__stream_encoder_set_verify(e->encoder.ogg.stream, options.verify); + OggFLAC__stream_encoder_set_streamable_subset(e->encoder.ogg.stream, !options.lax); + OggFLAC__stream_encoder_set_do_mid_side_stereo(e->encoder.ogg.stream, options.do_mid_side); + OggFLAC__stream_encoder_set_loose_mid_side_stereo(e->encoder.ogg.stream, options.loose_mid_side); + OggFLAC__stream_encoder_set_channels(e->encoder.ogg.stream, channels); + OggFLAC__stream_encoder_set_bits_per_sample(e->encoder.ogg.stream, bps); + OggFLAC__stream_encoder_set_sample_rate(e->encoder.ogg.stream, sample_rate); + OggFLAC__stream_encoder_set_blocksize(e->encoder.ogg.stream, options.blocksize); + OggFLAC__stream_encoder_set_max_lpc_order(e->encoder.ogg.stream, options.max_lpc_order); + OggFLAC__stream_encoder_set_qlp_coeff_precision(e->encoder.ogg.stream, options.qlp_coeff_precision); + OggFLAC__stream_encoder_set_do_qlp_coeff_prec_search(e->encoder.ogg.stream, options.do_qlp_coeff_prec_search); + OggFLAC__stream_encoder_set_do_escape_coding(e->encoder.ogg.stream, options.do_escape_coding); + OggFLAC__stream_encoder_set_do_exhaustive_model_search(e->encoder.ogg.stream, options.do_exhaustive_model_search); + OggFLAC__stream_encoder_set_min_residual_partition_order(e->encoder.ogg.stream, options.min_residual_partition_order); + OggFLAC__stream_encoder_set_max_residual_partition_order(e->encoder.ogg.stream, options.max_residual_partition_order); + OggFLAC__stream_encoder_set_rice_parameter_search_dist(e->encoder.ogg.stream, options.rice_parameter_search_dist); + OggFLAC__stream_encoder_set_total_samples_estimate(e->encoder.ogg.stream, e->total_samples_to_encode); + OggFLAC__stream_encoder_set_metadata(e->encoder.ogg.stream, (num_metadata > 0)? metadata : 0, num_metadata); + OggFLAC__stream_encoder_set_write_callback(e->encoder.ogg.stream, ogg_stream_encoder_write_callback); + OggFLAC__stream_encoder_set_metadata_callback(e->encoder.ogg.stream, ogg_stream_encoder_metadata_callback); + OggFLAC__stream_encoder_set_client_data(e->encoder.ogg.stream, e); + + OggFLAC__stream_encoder_disable_constant_subframes(e->encoder.ogg.stream, options.debug.disable_constant_subframes); + OggFLAC__stream_encoder_disable_fixed_subframes(e->encoder.ogg.stream, options.debug.disable_fixed_subframes); + OggFLAC__stream_encoder_disable_verbatim_subframes(e->encoder.ogg.stream, options.debug.disable_verbatim_subframes); + + if(OggFLAC__stream_encoder_init(e->encoder.ogg.stream) != FLAC__STREAM_ENCODER_OK) { + print_error_with_state(e, "ERROR initializing encoder"); + if(0 != cuesheet) + FLAC__metadata_object_delete(cuesheet); + return false; + } + } + else { + OggFLAC__file_encoder_set_serial_number(e->encoder.ogg.file, options.serial_number); + OggFLAC__file_encoder_set_filename(e->encoder.ogg.file, e->outfilename); + OggFLAC__file_encoder_set_verify(e->encoder.ogg.file, options.verify); + OggFLAC__file_encoder_set_streamable_subset(e->encoder.ogg.file, !options.lax); + OggFLAC__file_encoder_set_do_mid_side_stereo(e->encoder.ogg.file, options.do_mid_side); + OggFLAC__file_encoder_set_loose_mid_side_stereo(e->encoder.ogg.file, options.loose_mid_side); + OggFLAC__file_encoder_set_channels(e->encoder.ogg.file, channels); + OggFLAC__file_encoder_set_bits_per_sample(e->encoder.ogg.file, bps); + OggFLAC__file_encoder_set_sample_rate(e->encoder.ogg.file, sample_rate); + OggFLAC__file_encoder_set_blocksize(e->encoder.ogg.file, options.blocksize); + OggFLAC__file_encoder_set_max_lpc_order(e->encoder.ogg.file, options.max_lpc_order); + OggFLAC__file_encoder_set_qlp_coeff_precision(e->encoder.ogg.file, options.qlp_coeff_precision); + OggFLAC__file_encoder_set_do_qlp_coeff_prec_search(e->encoder.ogg.file, options.do_qlp_coeff_prec_search); + OggFLAC__file_encoder_set_do_escape_coding(e->encoder.ogg.file, options.do_escape_coding); + OggFLAC__file_encoder_set_do_exhaustive_model_search(e->encoder.ogg.file, options.do_exhaustive_model_search); + OggFLAC__file_encoder_set_min_residual_partition_order(e->encoder.ogg.file, options.min_residual_partition_order); + OggFLAC__file_encoder_set_max_residual_partition_order(e->encoder.ogg.file, options.max_residual_partition_order); + OggFLAC__file_encoder_set_rice_parameter_search_dist(e->encoder.ogg.file, options.rice_parameter_search_dist); + OggFLAC__file_encoder_set_total_samples_estimate(e->encoder.ogg.file, e->total_samples_to_encode); + OggFLAC__file_encoder_set_metadata(e->encoder.ogg.file, (num_metadata > 0)? metadata : 0, num_metadata); + OggFLAC__file_encoder_set_progress_callback(e->encoder.ogg.file, ogg_file_encoder_progress_callback); + OggFLAC__file_encoder_set_client_data(e->encoder.ogg.file, e); + + OggFLAC__file_encoder_disable_constant_subframes(e->encoder.ogg.file, options.debug.disable_constant_subframes); + OggFLAC__file_encoder_disable_fixed_subframes(e->encoder.ogg.file, options.debug.disable_fixed_subframes); + OggFLAC__file_encoder_disable_verbatim_subframes(e->encoder.ogg.file, options.debug.disable_verbatim_subframes); + + if(OggFLAC__file_encoder_init(e->encoder.ogg.file) != OggFLAC__FILE_ENCODER_OK) { + print_error_with_state(e, "ERROR initializing encoder"); + if(0 != cuesheet) + FLAC__metadata_object_delete(cuesheet); + return false; + } + } + } + else +#endif + if(e->is_stdout) { + FLAC__stream_encoder_set_verify(e->encoder.flac.stream, options.verify); + FLAC__stream_encoder_set_streamable_subset(e->encoder.flac.stream, !options.lax); + FLAC__stream_encoder_set_do_mid_side_stereo(e->encoder.flac.stream, options.do_mid_side); + FLAC__stream_encoder_set_loose_mid_side_stereo(e->encoder.flac.stream, options.loose_mid_side); + FLAC__stream_encoder_set_channels(e->encoder.flac.stream, channels); + FLAC__stream_encoder_set_bits_per_sample(e->encoder.flac.stream, bps); + FLAC__stream_encoder_set_sample_rate(e->encoder.flac.stream, sample_rate); + FLAC__stream_encoder_set_blocksize(e->encoder.flac.stream, options.blocksize); + FLAC__stream_encoder_set_max_lpc_order(e->encoder.flac.stream, options.max_lpc_order); + FLAC__stream_encoder_set_qlp_coeff_precision(e->encoder.flac.stream, options.qlp_coeff_precision); + FLAC__stream_encoder_set_do_qlp_coeff_prec_search(e->encoder.flac.stream, options.do_qlp_coeff_prec_search); + FLAC__stream_encoder_set_do_escape_coding(e->encoder.flac.stream, options.do_escape_coding); + FLAC__stream_encoder_set_do_exhaustive_model_search(e->encoder.flac.stream, options.do_exhaustive_model_search); + FLAC__stream_encoder_set_min_residual_partition_order(e->encoder.flac.stream, options.min_residual_partition_order); + FLAC__stream_encoder_set_max_residual_partition_order(e->encoder.flac.stream, options.max_residual_partition_order); + FLAC__stream_encoder_set_rice_parameter_search_dist(e->encoder.flac.stream, options.rice_parameter_search_dist); + FLAC__stream_encoder_set_total_samples_estimate(e->encoder.flac.stream, e->total_samples_to_encode); + FLAC__stream_encoder_set_metadata(e->encoder.flac.stream, (num_metadata > 0)? metadata : 0, num_metadata); + FLAC__stream_encoder_set_write_callback(e->encoder.flac.stream, flac_stream_encoder_write_callback); + FLAC__stream_encoder_set_metadata_callback(e->encoder.flac.stream, flac_stream_encoder_metadata_callback); + FLAC__stream_encoder_set_client_data(e->encoder.flac.stream, e); + + FLAC__stream_encoder_disable_constant_subframes(e->encoder.flac.stream, options.debug.disable_constant_subframes); + FLAC__stream_encoder_disable_fixed_subframes(e->encoder.flac.stream, options.debug.disable_fixed_subframes); + FLAC__stream_encoder_disable_verbatim_subframes(e->encoder.flac.stream, options.debug.disable_verbatim_subframes); + + if(FLAC__stream_encoder_init(e->encoder.flac.stream) != FLAC__STREAM_ENCODER_OK) { + print_error_with_state(e, "ERROR initializing encoder"); + if(0 != cuesheet) + FLAC__metadata_object_delete(cuesheet); + return false; + } + } + else { + FLAC__file_encoder_set_filename(e->encoder.flac.file, e->outfilename); + FLAC__file_encoder_set_verify(e->encoder.flac.file, options.verify); + FLAC__file_encoder_set_streamable_subset(e->encoder.flac.file, !options.lax); + FLAC__file_encoder_set_do_mid_side_stereo(e->encoder.flac.file, options.do_mid_side); + FLAC__file_encoder_set_loose_mid_side_stereo(e->encoder.flac.file, options.loose_mid_side); + FLAC__file_encoder_set_channels(e->encoder.flac.file, channels); + FLAC__file_encoder_set_bits_per_sample(e->encoder.flac.file, bps); + FLAC__file_encoder_set_sample_rate(e->encoder.flac.file, sample_rate); + FLAC__file_encoder_set_blocksize(e->encoder.flac.file, options.blocksize); + FLAC__file_encoder_set_max_lpc_order(e->encoder.flac.file, options.max_lpc_order); + FLAC__file_encoder_set_qlp_coeff_precision(e->encoder.flac.file, options.qlp_coeff_precision); + FLAC__file_encoder_set_do_qlp_coeff_prec_search(e->encoder.flac.file, options.do_qlp_coeff_prec_search); + FLAC__file_encoder_set_do_escape_coding(e->encoder.flac.file, options.do_escape_coding); + FLAC__file_encoder_set_do_exhaustive_model_search(e->encoder.flac.file, options.do_exhaustive_model_search); + FLAC__file_encoder_set_min_residual_partition_order(e->encoder.flac.file, options.min_residual_partition_order); + FLAC__file_encoder_set_max_residual_partition_order(e->encoder.flac.file, options.max_residual_partition_order); + FLAC__file_encoder_set_rice_parameter_search_dist(e->encoder.flac.file, options.rice_parameter_search_dist); + FLAC__file_encoder_set_total_samples_estimate(e->encoder.flac.file, e->total_samples_to_encode); + FLAC__file_encoder_set_metadata(e->encoder.flac.file, (num_metadata > 0)? metadata : 0, num_metadata); + FLAC__file_encoder_set_progress_callback(e->encoder.flac.file, flac_file_encoder_progress_callback); + FLAC__file_encoder_set_client_data(e->encoder.flac.file, e); + + FLAC__file_encoder_disable_constant_subframes(e->encoder.flac.file, options.debug.disable_constant_subframes); + FLAC__file_encoder_disable_fixed_subframes(e->encoder.flac.file, options.debug.disable_fixed_subframes); + FLAC__file_encoder_disable_verbatim_subframes(e->encoder.flac.file, options.debug.disable_verbatim_subframes); + + if(FLAC__file_encoder_init(e->encoder.flac.file) != FLAC__FILE_ENCODER_OK) { + print_error_with_state(e, "ERROR initializing encoder"); + if(0 != cuesheet) + FLAC__metadata_object_delete(cuesheet); + return false; + } + } + + if(0 != cuesheet) + FLAC__metadata_object_delete(cuesheet); + + return true; +} + +FLAC__bool EncoderSession_process(EncoderSession *e, const FLAC__int32 * const buffer[], unsigned samples) +{ + if(e->replay_gain) { + if(!grabbag__replaygain_analyze(buffer, e->channels==2, e->bits_per_sample, samples)) { + flac__utils_printf(stderr, 1, "%s: WARNING, error while calculating ReplayGain\n", e->inbasefilename); + } + } + +#ifdef FLAC__HAS_OGG + if(e->use_ogg) { + if(e->is_stdout) { + return OggFLAC__stream_encoder_process(e->encoder.ogg.stream, buffer, samples); + } + else { + return OggFLAC__file_encoder_process(e->encoder.ogg.file, buffer, samples); + } + } + else +#endif + if(e->is_stdout) { + return FLAC__stream_encoder_process(e->encoder.flac.stream, buffer, samples); + } + else { + return FLAC__file_encoder_process(e->encoder.flac.file, buffer, samples); + } +} + +FLAC__bool convert_to_seek_table_template(const char *requested_seek_points, int num_requested_seek_points, FLAC__StreamMetadata *cuesheet, EncoderSession *e) +{ + const FLAC__bool only_placeholders = e->is_stdout; + FLAC__bool has_real_points; + + if(num_requested_seek_points == 0 && 0 == cuesheet) + return true; + + if(num_requested_seek_points < 0) { + requested_seek_points = "10s;"; + num_requested_seek_points = 1; + } + + if(num_requested_seek_points > 0) { + if(!grabbag__seektable_convert_specification_to_template(requested_seek_points, only_placeholders, e->total_samples_to_encode, e->sample_rate, e->seek_table_template, &has_real_points)) + return false; + } + + if(0 != cuesheet) { + unsigned i, j; + const FLAC__StreamMetadata_CueSheet *cs = &cuesheet->data.cue_sheet; + for(i = 0; i < cs->num_tracks; i++) { + const FLAC__StreamMetadata_CueSheet_Track *tr = cs->tracks+i; + for(j = 0; j < tr->num_indices; j++) { + if(!FLAC__metadata_object_seektable_template_append_point(e->seek_table_template, tr->offset + tr->indices[j].offset)) + return false; + has_real_points = true; + } + } + if(has_real_points) + if(!FLAC__metadata_object_seektable_template_sort(e->seek_table_template, /*compact=*/true)) + return false; + } + + if(has_real_points) { + if(e->is_stdout) { + flac__utils_printf(stderr, 1, "%s: WARNING, cannot write back seekpoints when encoding to stdout\n", e->inbasefilename); + } + } + + return true; +} + +FLAC__bool canonicalize_until_specification(utils__SkipUntilSpecification *spec, const char *inbasefilename, unsigned sample_rate, FLAC__uint64 skip, FLAC__uint64 total_samples_in_input) +{ + /* convert from mm:ss.sss to sample number if necessary */ + flac__utils_canonicalize_skip_until_specification(spec, sample_rate); + + /* special case: if "--until=-0", use the special value '0' to mean "end-of-stream" */ + if(spec->is_relative && spec->value.samples == 0) { + spec->is_relative = false; + return true; + } + + /* in any other case the total samples in the input must be known */ + if(total_samples_in_input == 0) { + flac__utils_printf(stderr, 1, "%s: ERROR, cannot use --until when input length is unknown\n", inbasefilename); + return false; + } + + FLAC__ASSERT(spec->value_is_samples); + + /* convert relative specifications to absolute */ + if(spec->is_relative) { + if(spec->value.samples <= 0) + spec->value.samples += (FLAC__int64)total_samples_in_input; + else + spec->value.samples += skip; + spec->is_relative = false; + } + + /* error check */ + if(spec->value.samples < 0) { + flac__utils_printf(stderr, 1, "%s: ERROR, --until value is before beginning of input\n", inbasefilename); + return false; + } + if((FLAC__uint64)spec->value.samples <= skip) { + flac__utils_printf(stderr, 1, "%s: ERROR, --until value is before --skip point\n", inbasefilename); + return false; + } + if((FLAC__uint64)spec->value.samples > total_samples_in_input) { + flac__utils_printf(stderr, 1, "%s: ERROR, --until value is after end of input\n", inbasefilename); + return false; + } + + return true; +} + +void format_input(FLAC__int32 *dest[], unsigned wide_samples, FLAC__bool is_big_endian, FLAC__bool is_unsigned_samples, unsigned channels, unsigned bps) +{ + unsigned wide_sample, sample, channel, byte; + + if(bps == 8) { + if(is_unsigned_samples) { + for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) + for(channel = 0; channel < channels; channel++, sample++) + dest[channel][wide_sample] = (FLAC__int32)ucbuffer_[sample] - 0x80; + } + else { + for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) + for(channel = 0; channel < channels; channel++, sample++) + dest[channel][wide_sample] = (FLAC__int32)scbuffer_[sample]; + } + } + else if(bps == 16) { + if(is_big_endian != is_big_endian_host_) { + unsigned char tmp; + const unsigned bytes = wide_samples * channels * (bps >> 3); + for(byte = 0; byte < bytes; byte += 2) { + tmp = ucbuffer_[byte]; + ucbuffer_[byte] = ucbuffer_[byte+1]; + ucbuffer_[byte+1] = tmp; + } + } + if(is_unsigned_samples) { + for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) + for(channel = 0; channel < channels; channel++, sample++) + dest[channel][wide_sample] = (FLAC__int32)usbuffer_[sample] - 0x8000; + } + else { + for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) + for(channel = 0; channel < channels; channel++, sample++) + dest[channel][wide_sample] = (FLAC__int32)ssbuffer_[sample]; + } + } + else if(bps == 24) { + if(!is_big_endian) { + unsigned char tmp; + const unsigned bytes = wide_samples * channels * (bps >> 3); + for(byte = 0; byte < bytes; byte += 3) { + tmp = ucbuffer_[byte]; + ucbuffer_[byte] = ucbuffer_[byte+2]; + ucbuffer_[byte+2] = tmp; + } + } + if(is_unsigned_samples) { + for(byte = sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) + for(channel = 0; channel < channels; channel++, sample++) { + dest[channel][wide_sample] = ucbuffer_[byte++]; dest[channel][wide_sample] <<= 8; + dest[channel][wide_sample] |= ucbuffer_[byte++]; dest[channel][wide_sample] <<= 8; + dest[channel][wide_sample] |= ucbuffer_[byte++]; + dest[channel][wide_sample] -= 0x800000; + } + } + else { + for(byte = sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) + for(channel = 0; channel < channels; channel++, sample++) { + dest[channel][wide_sample] = scbuffer_[byte++]; dest[channel][wide_sample] <<= 8; + dest[channel][wide_sample] |= ucbuffer_[byte++]; dest[channel][wide_sample] <<= 8; + dest[channel][wide_sample] |= ucbuffer_[byte++]; + } + } + } + else { + FLAC__ASSERT(0); + } +} + +#ifdef FLAC__HAS_OGG +FLAC__StreamEncoderWriteStatus ogg_stream_encoder_write_callback(const OggFLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data) +{ + EncoderSession *encoder_session = (EncoderSession*)client_data; + + (void)encoder; + + encoder_session->bytes_written += bytes; + /* + * With Ogg FLAC we don't get one write callback per frame and + * we don't have a good number for 'samples', so we estimate based + * on the frame number and the knowledge that all blocks (except + * the last) are the same size. + */ + (void)samples; + encoder_session->samples_written = (current_frame+1) * encoder_session->blocksize; + + if(encoder_session->total_samples_to_encode > 0 && !(current_frame & encoder_session->stats_mask)) + print_stats(encoder_session); + + if(flac__utils_fwrite(buffer, sizeof(FLAC__byte), bytes, encoder_session->fout) == bytes) + return FLAC__STREAM_ENCODER_WRITE_STATUS_OK; + else + return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR; +} + +void ogg_stream_encoder_metadata_callback(const OggFLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data) +{ + // do nothing, for compatibilty. soon we will be using the ogg file encoder anyway. + (void)encoder, (void)metadata, (void)client_data; +} + +void ogg_file_encoder_progress_callback(const OggFLAC__FileEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data) +{ + EncoderSession *encoder_session = (EncoderSession*)client_data; + + (void)encoder; + + /* + * With Ogg FLAC we don't get a value for 'samples_written', so we + * estimate based on the frames written and the knowledge that all + * blocks (except the last) are the same size. + */ + samples_written = frames_written * encoder_session->blocksize; + flac_file_encoder_progress_callback(0, bytes_written, samples_written, frames_written, total_frames_estimate, client_data); +} + +#endif + +FLAC__StreamEncoderWriteStatus flac_stream_encoder_write_callback(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data) +{ + EncoderSession *encoder_session = (EncoderSession*)client_data; + + (void)encoder; + + encoder_session->bytes_written += bytes; + encoder_session->samples_written += samples; + + if(samples && encoder_session->total_samples_to_encode > 0 && !(current_frame & encoder_session->stats_mask)) + print_stats(encoder_session); + + if(flac__utils_fwrite(buffer, sizeof(FLAC__byte), bytes, encoder_session->fout) == bytes) + return FLAC__STREAM_ENCODER_WRITE_STATUS_OK; + else + return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR; +} + +void flac_stream_encoder_metadata_callback(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data) +{ + /* + * Nothing to do; if we get here, we're decoding to stdout, in + * which case we can't seek backwards to write new metadata. + */ + (void)encoder, (void)metadata, (void)client_data; +} + +void flac_file_encoder_progress_callback(const FLAC__FileEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data) +{ + EncoderSession *encoder_session = (EncoderSession*)client_data; + + (void)encoder, (void)total_frames_estimate; + + encoder_session->bytes_written = bytes_written; + encoder_session->samples_written = samples_written; + + if(encoder_session->total_samples_to_encode > 0 && !((frames_written-1) & encoder_session->stats_mask)) + print_stats(encoder_session); +} + +FLAC__bool parse_cuesheet_(FLAC__StreamMetadata **cuesheet, const char *cuesheet_filename, const char *inbasefilename, FLAC__bool is_cdda, FLAC__uint64 lead_out_offset) +{ + FILE *f; + unsigned last_line_read; + const char *error_message; + + if(0 == cuesheet_filename) + return true; + + if(lead_out_offset == 0) { + flac__utils_printf(stderr, 1, "%s: ERROR cannot import cuesheet when the number of input samples to encode is unknown\n", inbasefilename); + return false; + } + + if(0 == (f = fopen(cuesheet_filename, "r"))) { + flac__utils_printf(stderr, 1, "%s: ERROR opening cuesheet \"%s\" for reading\n", inbasefilename, cuesheet_filename); + return false; + } + + *cuesheet = grabbag__cuesheet_parse(f, &error_message, &last_line_read, is_cdda, lead_out_offset); + + fclose(f); + + if(0 == *cuesheet) { + flac__utils_printf(stderr, 1, "%s: ERROR parsing cuesheet \"%s\" on line %u: %s\n", inbasefilename, cuesheet_filename, last_line_read, error_message); + return false; + } + + return true; +} + +void print_stats(const EncoderSession *encoder_session) +{ + const FLAC__uint64 samples_written = min(encoder_session->total_samples_to_encode, encoder_session->samples_written); +#if defined _MSC_VER || defined __MINGW32__ + /* with MSVC you have to spoon feed it the casting */ + const double progress = (double)(FLAC__int64)samples_written / (double)(FLAC__int64)encoder_session->total_samples_to_encode; + const double ratio = (double)(FLAC__int64)encoder_session->bytes_written / ((double)(FLAC__int64)encoder_session->unencoded_size * min(1.0, progress)); +#else + const double progress = (double)samples_written / (double)encoder_session->total_samples_to_encode; + const double ratio = (double)encoder_session->bytes_written / ((double)encoder_session->unencoded_size * min(1.0, progress)); +#endif + + + if(samples_written == encoder_session->total_samples_to_encode) { + flac__utils_printf(stderr, 2, "\r%s:%s wrote %u bytes, ratio=%0.3f", + encoder_session->inbasefilename, + encoder_session->verify? " Verify OK," : "", + (unsigned)encoder_session->bytes_written, + ratio + ); + } + else { + flac__utils_printf(stderr, 2, "\r%s: %u%% complete, ratio=%0.3f", encoder_session->inbasefilename, (unsigned)floor(progress * 100.0 + 0.5), ratio); + } +} + +void print_error_with_state(const EncoderSession *e, const char *message) +{ + const int ilen = strlen(e->inbasefilename) + 1; + const char *state_string; + + flac__utils_printf(stderr, 1, "\n%s: %s\n", e->inbasefilename, message); + +#ifdef FLAC__HAS_OGG + if(e->use_ogg) { + if(e->is_stdout) { + state_string = OggFLAC__stream_encoder_get_resolved_state_string(e->encoder.ogg.stream); + } + else { + state_string = OggFLAC__file_encoder_get_resolved_state_string(e->encoder.ogg.file); + } + } + else +#endif + if(e->is_stdout) { + state_string = FLAC__stream_encoder_get_resolved_state_string(e->encoder.flac.stream); + } + else { + state_string = FLAC__file_encoder_get_resolved_state_string(e->encoder.flac.file); + } + + flac__utils_printf(stderr, 1, "%*s state = %s\n", ilen, "", state_string); + + /* print out some more info for some errors: */ + if(0 == strcmp(state_string, FLAC__StreamEncoderStateString[FLAC__STREAM_ENCODER_NOT_STREAMABLE])) { + flac__utils_printf(stderr, 1, + "\n" + "The encoding parameters specified do not conform to the FLAC Subset and may not\n" + "be streamable or playable in hardware devices. Add --lax to the command-line\n" + "options to encode with these parameters.\n" + ); + } + else if( + 0 == strcmp(state_string, FLAC__FileEncoderStateString[FLAC__FILE_ENCODER_FATAL_ERROR_WHILE_WRITING]) +#ifdef FLAC__HAS_OGG + || 0 == strcmp(state_string, OggFLAC__FileEncoderStateString[OggFLAC__FILE_ENCODER_FATAL_ERROR_WHILE_WRITING]) +#endif + ) { + flac__utils_printf(stderr, 1, + "\n" + "An error occurred while writing; the most common cause is that the disk is full.\n" + ); + } + else if( + 0 == strcmp(state_string, FLAC__FileEncoderStateString[FLAC__FILE_ENCODER_ERROR_OPENING_FILE]) +#ifdef FLAC__HAS_OGG + || 0 == strcmp(state_string, OggFLAC__FileEncoderStateString[OggFLAC__FILE_ENCODER_ERROR_OPENING_FILE]) +#endif + ) { + flac__utils_printf(stderr, 1, + "\n" + "An error occurred opening the output file; it is likely that the output\n" + "directory does not exist or is not writable, the output file already exists and\n" + "is not writable, or the disk is full.\n" + ); + } +} + +void print_verify_error(EncoderSession *e) +{ + FLAC__uint64 absolute_sample; + unsigned frame_number; + unsigned channel; + unsigned sample; + FLAC__int32 expected; + FLAC__int32 got; + +#ifdef FLAC__HAS_OGG + if(e->use_ogg) { + if(e->is_stdout) { + OggFLAC__stream_encoder_get_verify_decoder_error_stats(e->encoder.ogg.stream, &absolute_sample, &frame_number, &channel, &sample, &expected, &got); + } + else { + OggFLAC__file_encoder_get_verify_decoder_error_stats(e->encoder.ogg.file, &absolute_sample, &frame_number, &channel, &sample, &expected, &got); + } + } + else +#endif + if(e->is_stdout) { + FLAC__stream_encoder_get_verify_decoder_error_stats(e->encoder.flac.stream, &absolute_sample, &frame_number, &channel, &sample, &expected, &got); + } + else { + FLAC__file_encoder_get_verify_decoder_error_stats(e->encoder.flac.file, &absolute_sample, &frame_number, &channel, &sample, &expected, &got); + } + + flac__utils_printf(stderr, 1, "%s: ERROR: mismatch in decoded data, verify FAILED!\n", e->inbasefilename); + flac__utils_printf(stderr, 1, " Absolute sample=%u, frame=%u, channel=%u, sample=%u, expected %d, got %d\n", (unsigned)absolute_sample, frame_number, channel, sample, expected, got); + flac__utils_printf(stderr, 1, " In all known cases, verify errors are caused by hardware problems,\n"); + flac__utils_printf(stderr, 1, " usually overclocking or bad RAM. Delete %s\n", e->inbasefilename); + flac__utils_printf(stderr, 1, " and repeat the flac command exactly as before. If it does not give a\n"); + flac__utils_printf(stderr, 1, " verify error in the exact same place each time you try it, then there is\n"); + flac__utils_printf(stderr, 1, " a problem with your hardware. If it does, keep the bad FLAC file and\n"); + flac__utils_printf(stderr, 1, " submit a bug report to:\n"); + flac__utils_printf(stderr, 1, " http://sourceforge.net/bugs/?func=addbug&group_id=13478\n"); + flac__utils_printf(stderr, 1, " Make sure to include an email contact in the comment and/or use the\n"); + flac__utils_printf(stderr, 1, " \"Monitor\" feature to monitor the bug status.\n"); + flac__utils_printf(stderr, 1, "Verify FAILED! Do not trust %s\n", e->outfilename); +} + +FLAC__bool read_little_endian_uint16(FILE *f, FLAC__uint16 *val, FLAC__bool eof_ok, const char *fn) +{ + size_t bytes_read = fread(val, 1, 2, f); + + if(bytes_read == 0) { + if(!eof_ok) { + flac__utils_printf(stderr, 1, "%s: ERROR: unexpected EOF\n", fn); + return false; + } + else + return true; + } + else if(bytes_read < 2) { + flac__utils_printf(stderr, 1, "%s: ERROR: unexpected EOF\n", fn); + return false; + } + else { + if(is_big_endian_host_) { + FLAC__byte tmp, *b = (FLAC__byte*)val; + tmp = b[1]; b[1] = b[0]; b[0] = tmp; + } + return true; + } +} + +FLAC__bool read_little_endian_uint32(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn) +{ + size_t bytes_read = fread(val, 1, 4, f); + + if(bytes_read == 0) { + if(!eof_ok) { + flac__utils_printf(stderr, 1, "%s: ERROR: unexpected EOF\n", fn); + return false; + } + else + return true; + } + else if(bytes_read < 4) { + flac__utils_printf(stderr, 1, "%s: ERROR: unexpected EOF\n", fn); + return false; + } + else { + if(is_big_endian_host_) { + FLAC__byte tmp, *b = (FLAC__byte*)val; + tmp = b[3]; b[3] = b[0]; b[0] = tmp; + tmp = b[2]; b[2] = b[1]; b[1] = tmp; + } + return true; + } +} + +FLAC__bool read_big_endian_uint16(FILE *f, FLAC__uint16 *val, FLAC__bool eof_ok, const char *fn) +{ + unsigned char buf[4]; + size_t bytes_read= fread(buf, 1, 2, f); + + if(bytes_read==0U && eof_ok) + return true; + else if(bytes_read<2U) { + flac__utils_printf(stderr, 1, "%s: ERROR: unexpected EOF\n", fn); + return false; + } + + /* this is independent of host endianness */ + *val= (FLAC__uint16)(buf[0])<<8 | buf[1]; + + return true; +} + +FLAC__bool read_big_endian_uint32(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn) +{ + unsigned char buf[4]; + size_t bytes_read= fread(buf, 1, 4, f); + + if(bytes_read==0U && eof_ok) + return true; + else if(bytes_read<4U) { + flac__utils_printf(stderr, 1, "%s: ERROR: unexpected EOF\n", fn); + return false; + } + + /* this is independent of host endianness */ + *val= (FLAC__uint32)(buf[0])<<24 | (FLAC__uint32)(buf[1])<<16 | + (FLAC__uint32)(buf[2])<<8 | buf[3]; + + return true; +} + +FLAC__bool read_sane_extended(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn) + /* Read an IEEE 754 80-bit (aka SANE) extended floating point value from 'f', + * convert it into an integral value and store in 'val'. Return false if only + * between 1 and 9 bytes remain in 'f', if 0 bytes remain in 'f' and 'eof_ok' is + * false, or if the value is negative, between zero and one, or too large to be + * represented by 'val'; return true otherwise. + */ +{ + unsigned int i; + unsigned char buf[10]; + size_t bytes_read= fread(buf, 1U, 10U, f); + FLAC__int16 e= ((FLAC__uint16)(buf[0])<<8 | (FLAC__uint16)(buf[1]))-0x3FFF; + FLAC__int16 shift= 63-e; + FLAC__uint64 p= 0U; + + if(bytes_read==0U && eof_ok) + return true; + else if(bytes_read<10U) { + flac__utils_printf(stderr, 1, "%s: ERROR: unexpected EOF\n", fn); + return false; + } + else if((buf[0]>>7)==1U || e<0 || e>63) { + flac__utils_printf(stderr, 1, "%s: ERROR: invalid floating-point value\n", fn); + return false; + } + + for(i= 0U; i<8U; ++i) + p|= (FLAC__uint64)(buf[i+2])<<(56U-i*8); + *val= (FLAC__uint32)((p>>shift)+(p>>(shift-1) & 0x1)); + + return true; +} + +FLAC__bool fskip_ahead(FILE *f, FLAC__uint64 offset) +{ + static unsigned char dump[8192]; + + while(offset > 0) { + long need = (long)min(offset, LONG_MAX); + if(fseek(f, need, SEEK_CUR) < 0) { + need = (long)min(offset, sizeof(dump)); + if(fread(dump, need, 1, f) < 1) + return false; + } + offset -= need; + } + return true; +} diff --git a/Libraries/FLAC/flac-src/src/flac/encode.h b/Libraries/FLAC/flac-src/src/flac/encode.h new file mode 100644 index 000000000..9dd0300ee --- /dev/null +++ b/Libraries/FLAC/flac-src/src/flac/encode.h @@ -0,0 +1,90 @@ +/* flac - Command-line FLAC encoder/decoder + * Copyright (C) 2000,2001,2002,2003,2004,2005 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef flac__encode_h +#define flac__encode_h + +#include "FLAC/metadata.h" +#include "utils.h" + +#ifdef HAVE_CONFIG_H +#include +#endif + +typedef struct { + utils__SkipUntilSpecification skip_specification; + utils__SkipUntilSpecification until_specification; + FLAC__bool verify; +#ifdef FLAC__HAS_OGG + FLAC__bool use_ogg; + long serial_number; +#endif + FLAC__bool lax; + FLAC__bool do_mid_side; + FLAC__bool loose_mid_side; + FLAC__bool do_exhaustive_model_search; + FLAC__bool do_escape_coding; + FLAC__bool do_qlp_coeff_prec_search; + unsigned min_residual_partition_order; + unsigned max_residual_partition_order; + unsigned rice_parameter_search_dist; + unsigned max_lpc_order; + unsigned blocksize; + unsigned qlp_coeff_precision; + int padding; + char *requested_seek_points; + int num_requested_seek_points; + const char *cuesheet_filename; + FLAC__bool cued_seekpoints; + + /* options related to --replay-gain and --sector-align */ + FLAC__bool is_first_file; + FLAC__bool is_last_file; + FLAC__int32 **align_reservoir; + unsigned *align_reservoir_samples; + FLAC__bool replay_gain; + FLAC__bool sector_align; + + FLAC__StreamMetadata *vorbis_comment; + + struct { + FLAC__bool disable_constant_subframes; + FLAC__bool disable_fixed_subframes; + FLAC__bool disable_verbatim_subframes; + } debug; +} encode_options_t; + +typedef struct { + encode_options_t common; +} wav_encode_options_t; + +typedef struct { + encode_options_t common; + + FLAC__bool is_big_endian; + FLAC__bool is_unsigned_samples; + unsigned channels; + unsigned bps; + unsigned sample_rate; +} raw_encode_options_t; + +int flac__encode_aif(FILE *infile, long infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, wav_encode_options_t options); +int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, wav_encode_options_t options); +int flac__encode_raw(FILE *infile, long infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, raw_encode_options_t options); + +#endif diff --git a/Libraries/FLAC/flac-src/src/flac/flac.dsp b/Libraries/FLAC/flac-src/src/flac/flac.dsp new file mode 100644 index 000000000..6a3aa09f9 --- /dev/null +++ b/Libraries/FLAC/flac-src/src/flac/flac.dsp @@ -0,0 +1,148 @@ +# Microsoft Developer Studio Project File - Name="flac" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=flac - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "flac.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "flac.mak" CFG="flac - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "flac - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "flac - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "flac - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\..\obj\release\bin" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "..\..\include" /D "NDEBUG" /D "FLAC__NO_DLL" /D "FLAC__HAS_OGG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FD /c +# SUBTRACT CPP /YX /Yc /Yu +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 ..\..\obj\release\lib\grabbag_static.lib ..\..\obj\release\lib\libOggFLAC_static.lib ..\..\obj\release\lib\libFLAC_static.lib ..\..\obj\release\lib\replaygain_analysis_static.lib ..\..\obj\release\lib\replaygain_synthesis_static.lib ..\..\obj\release\lib\getopt_static.lib ..\..\obj\release\lib\utf8_static.lib ..\..\obj\release\lib\ogg_static.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "flac - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\..\obj\debug\bin" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "." /I "..\..\include" /D "_DEBUG" /D "FLAC__NO_DLL" /D "FLAC__HAS_OGG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c +# SUBTRACT CPP /YX /Yc /Yu +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 ..\..\obj\debug\lib\grabbag_static.lib ..\..\obj\debug\lib\libOggFLAC_static.lib ..\..\obj\debug\lib\libFLAC_static.lib ..\..\obj\debug\lib\replaygain_analysis_static.lib ..\..\obj\debug\lib\replaygain_synthesis_static.lib ..\..\obj\debug\lib\getopt_static.lib ..\..\obj\debug\lib\utf8_static.lib ..\..\obj\release\lib\ogg_static.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "flac - Win32 Release" +# Name "flac - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\analyze.c +# End Source File +# Begin Source File + +SOURCE=.\decode.c +# End Source File +# Begin Source File + +SOURCE=.\encode.c +# End Source File +# Begin Source File + +SOURCE=.\main.c +# End Source File +# Begin Source File + +SOURCE=.\local_string_utils.c +# End Source File +# Begin Source File + +SOURCE=.\utils.c +# End Source File +# Begin Source File + +SOURCE=.\vorbiscomment.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\analyze.h +# End Source File +# Begin Source File + +SOURCE=.\decode.h +# End Source File +# Begin Source File + +SOURCE=.\encode.h +# End Source File +# Begin Source File + +SOURCE=.\local_string_utils.h +# End Source File +# Begin Source File + +SOURCE=.\utils.h +# End Source File +# Begin Source File + +SOURCE=.\vorbiscomment.h +# End Source File +# End Group +# End Target +# End Project diff --git a/Libraries/FLAC/flac-src/src/flac/local_string_utils.c b/Libraries/FLAC/flac-src/src/flac/local_string_utils.c new file mode 100644 index 000000000..9b0d49f10 --- /dev/null +++ b/Libraries/FLAC/flac-src/src/flac/local_string_utils.c @@ -0,0 +1,104 @@ +/* flac - Command-line FLAC encoder/decoder + */ + +#include + +#include "utils.h" + +/* $OpenBSD: strlcpy.c,v 1.8 2003/06/17 21:56:24 millert Exp $ + * + * Copyright (c) 1998 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + * Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +size_t +flac__strlcpy(char *dst, const char *src, size_t siz) +{ + register char *d = dst; + register const char *s = src; + register size_t n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0 && --n != 0) { + do { + if ((*d++ = *s++) == 0) + break; + } while (--n != 0); + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + + return(s - src - 1); /* count does not include NUL */ +} + +/* $OpenBSD: strlcat.c,v 1.11 2003/06/17 21:56:24 millert Exp $ + * + * Copyright (c) 1998 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + * Appends src to string dst of size siz (unlike strncat, siz is the + * full size of dst, not space left). At most siz-1 characters + * will be copied. Always NUL terminates (unless siz <= strlen(dst)). + * Returns strlen(src) + MIN(siz, strlen(initial dst)). + * If retval >= siz, truncation occurred. + */ +size_t +flac__strlcat(char *dst, const char *src, size_t siz) +{ + register char *d = dst; + register const char *s = src; + register size_t n = siz; + size_t dlen; + + /* Find the end of dst and adjust bytes left but don't go past end */ + while (n-- != 0 && *d != '\0') + d++; + dlen = d - dst; + n = siz - dlen; + + if (n == 0) + return(dlen + strlen(s)); + while (*s != '\0') { + if (n != 1) { + *d++ = *s; + n--; + } + s++; + } + *d = '\0'; + + return(dlen + (s - src)); /* count does not include NUL */ +} diff --git a/Libraries/FLAC/flac-src/src/flac/local_string_utils.h b/Libraries/FLAC/flac-src/src/flac/local_string_utils.h new file mode 100644 index 000000000..208e3f855 --- /dev/null +++ b/Libraries/FLAC/flac-src/src/flac/local_string_utils.h @@ -0,0 +1,27 @@ +/* flac - Command-line FLAC encoder/decoder + * Copyright (C) 2002,2003,2004,2005 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef flac__local_string_utils_h +#define flac__local_string_utils_h + +#include /* for size_t */ + +size_t flac__strlcpy(char *dst, const char *src, size_t siz); +size_t flac__strlcat(char *dst, const char *src, size_t siz); + +#endif diff --git a/Libraries/FLAC/flac-src/src/flac/main.c b/Libraries/FLAC/flac-src/src/flac/main.c new file mode 100644 index 000000000..b27940d52 --- /dev/null +++ b/Libraries/FLAC/flac-src/src/flac/main.c @@ -0,0 +1,1827 @@ +/* flac - Command-line FLAC encoder/decoder + * Copyright (C) 2000,2001,2002,2003,2004,2005 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +#if !defined _MSC_VER && !defined __MINGW32__ +/* unlink is in stdio.h in VC++ */ +#include /* for unlink() */ +#else +#define strcasecmp stricmp +#endif +#include "FLAC/all.h" +#include "share/grabbag.h" +#include "analyze.h" +#include "decode.h" +#include "encode.h" +#include "local_string_utils.h" /* for flac__strlcat() and flac__strlcpy() */ +#include "utils.h" +#include "vorbiscomment.h" + +#if 0 +/*[JEC] was:#if HAVE_GETOPT_LONG*/ +/*[JEC] see flac/include/share/getopt.h as to why the change */ +# include +#else +# include "share/getopt.h" +#endif + +typedef enum { RAW, WAV, AIF } FileFormat; + +static int do_it(); + +static FLAC__bool init_options(); +static int parse_options(int argc, char *argv[]); +static int parse_option(int short_option, const char *long_option, const char *option_argument); +static void free_options(); + +static int usage_error(const char *message, ...); +static void short_usage(); +static void show_version(); +static void show_help(); +static void show_explain(); +static void format_mistake(const char *infilename, const char *wrong, const char *right); + +static int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_last_file); +static int decode_file(const char *infilename); + +static const char *get_encoded_outfilename(const char *infilename); +static const char *get_decoded_outfilename(const char *infilename); +static const char *get_outfilename(const char *infilename, const char *suffix); + +static void die(const char *message); +static char *local_strdup(const char *source); + + +/* + * share__getopt format struct; note that for long options with no + * short option equivalent we just set the 'val' field to 0. + */ +static struct share__option long_options_[] = { + /* + * general options + */ + { "help" , share__no_argument, 0, 'h' }, + { "explain" , share__no_argument, 0, 'H' }, + { "version" , share__no_argument, 0, 'v' }, + { "decode" , share__no_argument, 0, 'd' }, + { "analyze" , share__no_argument, 0, 'a' }, + { "test" , share__no_argument, 0, 't' }, + { "stdout" , share__no_argument, 0, 'c' }, + { "silent" , share__no_argument, 0, 's' }, + { "totally-silent" , share__no_argument, 0, 0 }, + { "force" , share__no_argument, 0, 'f' }, + { "delete-input-file", share__no_argument, 0, 0 }, + { "output-prefix" , share__required_argument, 0, 0 }, + { "output-name" , share__required_argument, 0, 'o' }, + { "skip" , share__required_argument, 0, 0 }, + { "until" , share__required_argument, 0, 0 }, + + /* + * decoding options + */ + { "decode-through-errors", share__no_argument, 0, 'F' }, + { "cue" , share__required_argument, 0, 0 }, + { "apply-replaygain-which-is-not-lossless", share__optional_argument, 0, 0 }, /* undocumented */ + + /* + * encoding options + */ + { "cuesheet" , share__required_argument, 0, 0 }, + { "no-cued-seekpoints" , share__no_argument, 0, 0 }, + { "tag" , share__required_argument, 0, 'T' }, + { "compression-level-0" , share__no_argument, 0, '0' }, + { "compression-level-1" , share__no_argument, 0, '1' }, + { "compression-level-2" , share__no_argument, 0, '2' }, + { "compression-level-3" , share__no_argument, 0, '3' }, + { "compression-level-4" , share__no_argument, 0, '4' }, + { "compression-level-5" , share__no_argument, 0, '5' }, + { "compression-level-6" , share__no_argument, 0, '6' }, + { "compression-level-7" , share__no_argument, 0, '7' }, + { "compression-level-8" , share__no_argument, 0, '8' }, + { "compression-level-9" , share__no_argument, 0, '9' }, + { "best" , share__no_argument, 0, '8' }, + { "fast" , share__no_argument, 0, '0' }, + { "super-secret-totally-impractical-compression-level", share__no_argument, 0, 0 }, + { "verify" , share__no_argument, 0, 'V' }, + { "force-aiff-format" , share__no_argument, 0, 0 }, + { "force-raw-format" , share__no_argument, 0, 0 }, + { "lax" , share__no_argument, 0, 0 }, + { "replay-gain" , share__no_argument, 0, 0 }, + { "sector-align" , share__no_argument, 0, 0 }, + { "seekpoint" , share__required_argument, 0, 'S' }, + { "padding" , share__required_argument, 0, 'P' }, +#ifdef FLAC__HAS_OGG + { "ogg" , share__no_argument, 0, 0 }, + { "serial-number" , share__required_argument, 0, 0 }, +#endif + { "blocksize" , share__required_argument, 0, 'b' }, + { "exhaustive-model-search" , share__no_argument, 0, 'e' }, + { "max-lpc-order" , share__required_argument, 0, 'l' }, + { "mid-side" , share__no_argument, 0, 'm' }, + { "adaptive-mid-side" , share__no_argument, 0, 'M' }, + { "qlp-coeff-precision-search", share__no_argument, 0, 'p' }, + { "qlp-coeff-precision" , share__required_argument, 0, 'q' }, + { "rice-partition-order" , share__required_argument, 0, 'r' }, + { "endian" , share__required_argument, 0, 0 }, + { "channels" , share__required_argument, 0, 0 }, + { "bps" , share__required_argument, 0, 0 }, + { "sample-rate" , share__required_argument, 0, 0 }, + { "sign" , share__required_argument, 0, 0 }, + { "input-size" , share__required_argument, 0, 0 }, + + /* + * analysis options + */ + { "residual-gnuplot", share__no_argument, 0, 0 }, + { "residual-text", share__no_argument, 0, 0 }, + + /* + * negatives + */ + { "no-decode-through-errors" , share__no_argument, 0, 0 }, + { "no-silent" , share__no_argument, 0, 0 }, + { "no-force" , share__no_argument, 0, 0 }, + { "no-seektable" , share__no_argument, 0, 0 }, + { "no-delete-input-file" , share__no_argument, 0, 0 }, + { "no-replay-gain" , share__no_argument, 0, 0 }, + { "no-sector-align" , share__no_argument, 0, 0 }, + { "no-lax" , share__no_argument, 0, 0 }, +#ifdef FLAC__HAS_OGG + { "no-ogg" , share__no_argument, 0, 0 }, +#endif + { "no-exhaustive-model-search", share__no_argument, 0, 0 }, + { "no-mid-side" , share__no_argument, 0, 0 }, + { "no-adaptive-mid-side" , share__no_argument, 0, 0 }, + { "no-qlp-coeff-prec-search" , share__no_argument, 0, 0 }, + { "no-padding" , share__no_argument, 0, 0 }, + { "no-verify" , share__no_argument, 0, 0 }, + { "no-residual-gnuplot" , share__no_argument, 0, 0 }, + { "no-residual-text" , share__no_argument, 0, 0 }, + /* + * undocumented debugging options for the test suite + */ + { "disable-constant-subframes", share__no_argument, 0, 0 }, + { "disable-fixed-subframes" , share__no_argument, 0, 0 }, + { "disable-verbatim-subframes", share__no_argument, 0, 0 }, + + {0, 0, 0, 0} +}; + + +/* + * global to hold command-line option values + */ + +static struct { + FLAC__bool show_help; + FLAC__bool show_explain; + FLAC__bool show_version; + FLAC__bool mode_decode; + FLAC__bool verify; + FLAC__bool force_file_overwrite; + FLAC__bool continue_through_decode_errors; + replaygain_synthesis_spec_t replaygain_synthesis_spec; + FLAC__bool lax; + FLAC__bool test_only; + FLAC__bool analyze; + FLAC__bool use_ogg; + FLAC__bool has_serial_number; /* true iff --serial-number was used */ + long serial_number; /* this is the Ogg serial number and is unused for native FLAC */ + FLAC__bool do_mid_side; + FLAC__bool loose_mid_side; + FLAC__bool do_exhaustive_model_search; + FLAC__bool do_escape_coding; + FLAC__bool do_qlp_coeff_prec_search; + FLAC__bool force_to_stdout; + FLAC__bool force_aiff_format; + FLAC__bool force_raw_format; + FLAC__bool delete_input; + FLAC__bool replay_gain; + FLAC__bool sector_align; + const char *cmdline_forced_outfilename; + const char *output_prefix; + analysis_options aopts; + int padding; + unsigned max_lpc_order; + unsigned qlp_coeff_precision; + const char *skip_specification; + const char *until_specification; + const char *cue_specification; + int format_is_big_endian; + int format_is_unsigned_samples; + int format_channels; + int format_bps; + int format_sample_rate; + long format_input_size; + int blocksize; + int min_residual_partition_order; + int max_residual_partition_order; + int rice_parameter_search_dist; + char requested_seek_points[50000]; /* bad MAGIC NUMBER but buffer overflow is checked */ + int num_requested_seek_points; /* -1 => no -S options were given, 0 => -S- was given */ + const char *cuesheet_filename; + FLAC__bool cued_seekpoints; + + unsigned num_files; + char **filenames; + + FLAC__StreamMetadata *vorbis_comment; + + struct { + FLAC__bool disable_constant_subframes; + FLAC__bool disable_fixed_subframes; + FLAC__bool disable_verbatim_subframes; + } debug; +} option_values; + + +/* + * miscellaneous globals + */ + +static FLAC__int32 align_reservoir_0[588], align_reservoir_1[588]; /* for carrying over samples from --sector-align */ +static FLAC__int32 *align_reservoir[2] = { align_reservoir_0, align_reservoir_1 }; +static unsigned align_reservoir_samples = 0; /* 0 .. 587 */ + + +int main(int argc, char *argv[]) +{ + int retval = 0; + + setlocale(LC_ALL, ""); + if(!init_options()) { + flac__utils_printf(stderr, 1, "ERROR: allocating memory\n"); + retval = 1; + } + else { + if((retval = parse_options(argc, argv)) == 0) + retval = do_it(); + } + + free_options(); + + return retval; +} + +int do_it() +{ + int retval = 0; + + if(option_values.show_version) { + show_version(); + return 0; + } + else if(option_values.show_explain) { + show_explain(); + return 0; + } + else if(option_values.show_help) { + show_help(); + return 0; + } + else { + if(option_values.num_files == 0) { + if(flac__utils_verbosity_ >= 1) + short_usage(); + return 0; + } + + /* + * tweak options; validate the values + */ + if(!option_values.mode_decode) { + if(option_values.blocksize < 0) { + if(option_values.max_lpc_order == 0) + option_values.blocksize = 1152; + else + option_values.blocksize = 4608; + } + if(option_values.max_residual_partition_order < 0) { + if(option_values.blocksize <= 1152) + option_values.max_residual_partition_order = 2; + else if(option_values.blocksize <= 2304) + option_values.max_residual_partition_order = 3; + else if(option_values.blocksize <= 4608) + option_values.max_residual_partition_order = 3; + else + option_values.max_residual_partition_order = 4; + option_values.min_residual_partition_order = option_values.max_residual_partition_order; + } + if(option_values.rice_parameter_search_dist < 0) { + option_values.rice_parameter_search_dist = 0; + } + if(0 != option_values.cue_specification) + return usage_error("ERROR: --cue is not allowed in test mode\n"); + } + else { + if(option_values.test_only) { + if(0 != option_values.skip_specification) + return usage_error("ERROR: --skip is not allowed in test mode\n"); + if(0 != option_values.until_specification) + return usage_error("ERROR: --until is not allowed in test mode\n"); + if(0 != option_values.cue_specification) + return usage_error("ERROR: --cue is not allowed in test mode\n"); + } + } + + if(0 != option_values.cue_specification && (0 != option_values.skip_specification || 0 != option_values.until_specification)) + return usage_error("ERROR: --cue may not be combined with --skip or --until\n"); + + FLAC__ASSERT(option_values.blocksize >= 0 || option_values.mode_decode); + + if(option_values.format_channels >= 0) { + if(option_values.format_channels == 0 || (unsigned)option_values.format_channels > FLAC__MAX_CHANNELS) + return usage_error("ERROR: invalid number of channels '%u', must be > 0 and <= %u\n", option_values.format_channels, FLAC__MAX_CHANNELS); + } + if(option_values.format_bps >= 0) { + if(option_values.format_bps != 8 && option_values.format_bps != 16 && option_values.format_bps != 24) + return usage_error("ERROR: invalid bits per sample '%u' (must be 8/16/24)\n", option_values.format_bps); + } + if(option_values.format_sample_rate >= 0) { + if(!FLAC__format_sample_rate_is_valid(option_values.format_sample_rate)) + return usage_error("ERROR: invalid sample rate '%u', must be > 0 and <= %u\n", option_values.format_sample_rate, FLAC__MAX_SAMPLE_RATE); + } + if(option_values.force_raw_format && option_values.force_aiff_format) + return usage_error("ERROR: only one of --force-raw-format and --force-aiff-format allowed\n"); + if(option_values.mode_decode) { + if(!option_values.force_raw_format) { + if(option_values.format_is_big_endian >= 0) + return usage_error("ERROR: --endian only allowed with --force-raw-format\n"); + if(option_values.format_is_unsigned_samples >= 0) + return usage_error("ERROR: --sign only allowed with --force-raw-format\n"); + } + if(option_values.format_channels >= 0) + return usage_error("ERROR: --channels not allowed with --decode\n"); + if(option_values.format_bps >= 0) + return usage_error("ERROR: --bps not allowed with --decode\n"); + if(option_values.format_sample_rate >= 0) + return usage_error("ERROR: --sample-rate not allowed with --decode\n"); + } + if(!option_values.mode_decode && ((unsigned)option_values.blocksize < FLAC__MIN_BLOCK_SIZE || (unsigned)option_values.blocksize > FLAC__MAX_BLOCK_SIZE)) { + return usage_error("ERROR: invalid blocksize '%u', must be >= %u and <= %u\n", (unsigned)option_values.blocksize, FLAC__MIN_BLOCK_SIZE, FLAC__MAX_BLOCK_SIZE); + } + if(option_values.qlp_coeff_precision > 0 && option_values.qlp_coeff_precision < FLAC__MIN_QLP_COEFF_PRECISION) { + return usage_error("ERROR: invalid value '%u' for qlp coeff precision, must be 0 or >= %u\n", option_values.qlp_coeff_precision, FLAC__MIN_QLP_COEFF_PRECISION); + } + + if(option_values.sector_align) { + if(option_values.mode_decode) + return usage_error("ERROR: --sector-align only allowed for encoding\n"); + if(0 != option_values.skip_specification) + return usage_error("ERROR: --sector-align not allowed with --skip\n"); + if(0 != option_values.until_specification) + return usage_error("ERROR: --sector-align not allowed with --until\n"); + if(0 != option_values.cue_specification) + return usage_error("ERROR: --sector-align not allowed with --cue\n"); + if(option_values.format_channels >= 0 && option_values.format_channels != 2) + return usage_error("ERROR: --sector-align can only be done with stereo input\n"); + if(option_values.format_bps >= 0 && option_values.format_bps != 16) + return usage_error("ERROR: --sector-align can only be done with 16-bit samples\n"); + if(option_values.format_sample_rate >= 0 && option_values.format_sample_rate != 44100) + return usage_error("ERROR: --sector-align can only be done with a sample rate of 44100\n"); + } + if(option_values.replay_gain) { + if(option_values.force_to_stdout) + return usage_error("ERROR: --replay-gain not allowed with -c/--stdout\n"); + if(option_values.mode_decode) + return usage_error("ERROR: --replay-gain only allowed for encoding\n"); + if(option_values.format_channels > 2) + return usage_error("ERROR: --replay-gain can only be done with mono/stereo input\n"); + if(option_values.format_sample_rate >= 0 && !grabbag__replaygain_is_valid_sample_frequency(option_values.format_sample_rate)) + return usage_error("ERROR: invalid sample rate used with --replay-gain\n"); + /* + * We want to reserve padding space for the ReplayGain + * tags that we will set later, to avoid rewriting the + * whole file. + */ + if(option_values.padding < 0) { + flac__utils_printf(stderr, 1, "NOTE: --replay-gain may leave a small PADDING block even with --no-padding\n"); + option_values.padding = GRABBAG__REPLAYGAIN_MAX_TAG_SPACE_REQUIRED; + } + else { + option_values.padding += GRABBAG__REPLAYGAIN_MAX_TAG_SPACE_REQUIRED; + } + } + if(option_values.num_files > 1 && option_values.cmdline_forced_outfilename) { + return usage_error("ERROR: -o/--output-name cannot be used with multiple files\n"); + } + if(option_values.cmdline_forced_outfilename && option_values.output_prefix) { + return usage_error("ERROR: --output-prefix conflicts with -o/--output-name\n"); + } + if(!option_values.mode_decode && 0 != option_values.cuesheet_filename && option_values.num_files > 1) { + return usage_error("ERROR: --cuesheet cannot be used when encoding multiple files\n"); + } + } + + flac__utils_printf(stderr, 2, "\n"); + flac__utils_printf(stderr, 2, "flac %s, Copyright (C) 2000,2001,2002,2003,2004,2005 Josh Coalson\n", FLAC__VERSION_STRING); + flac__utils_printf(stderr, 2, "flac comes with ABSOLUTELY NO WARRANTY. This is free software, and you are\n"); + flac__utils_printf(stderr, 2, "welcome to redistribute it under certain conditions. Type `flac' for details.\n\n"); + + if(!option_values.mode_decode) { + char padopt[16]; + if(option_values.padding < 0) + strcpy(padopt, "-"); + else + sprintf(padopt, " %d", option_values.padding); + flac__utils_printf(stderr, 2, + "options:%s%s%s%s -P%s -b %u%s -l %u%s%s%s -q %u -r %u,%u%s\n", + option_values.delete_input?" --delete-input-file":"", + option_values.sector_align?" --sector-align":"", + option_values.use_ogg?" --ogg":"", + option_values.lax?" --lax":"", + padopt, + (unsigned)option_values.blocksize, + option_values.loose_mid_side?" -M":option_values.do_mid_side?" -m":"", + option_values.max_lpc_order, + option_values.do_exhaustive_model_search?" -e":"", + option_values.do_escape_coding?" -E":"", + option_values.do_qlp_coeff_prec_search?" -p":"", + option_values.qlp_coeff_precision, + (unsigned)option_values.min_residual_partition_order, + (unsigned)option_values.max_residual_partition_order, + option_values.verify? " -V":"" + ); + } + + if(option_values.mode_decode) { + FLAC__bool first = true; + + if(option_values.num_files == 0) { + retval = decode_file("-"); + } + else { + unsigned i; + if(option_values.num_files > 1) + option_values.cmdline_forced_outfilename = 0; + for(i = 0, retval = 0; i < option_values.num_files; i++) { + if(0 == strcmp(option_values.filenames[i], "-") && !first) + continue; + retval |= decode_file(option_values.filenames[i]); + first = false; + } + } + } + else { /* encode */ + FLAC__bool first = true; + + if(option_values.num_files == 0) { + retval = encode_file("-", first, true); + } + else { + unsigned i; + if(option_values.num_files > 1) + option_values.cmdline_forced_outfilename = 0; + for(i = 0, retval = 0; i < option_values.num_files; i++) { + if(0 == strcmp(option_values.filenames[i], "-") && !first) + continue; + retval |= encode_file(option_values.filenames[i], first, i == (option_values.num_files-1)); + first = false; + } + if(option_values.replay_gain && retval == 0) { + float album_gain, album_peak; + grabbag__replaygain_get_album(&album_gain, &album_peak); + for(i = 0; i < option_values.num_files; i++) { + const char *error, *outfilename = get_encoded_outfilename(option_values.filenames[i]); + if(0 == outfilename) { + flac__utils_printf(stderr, 1, "ERROR: filename too long: %s", option_values.filenames[i]); + return 1; + } + if(0 == strcmp(option_values.filenames[i], "-")) { + FLAC__ASSERT(0); + /* double protection */ + flac__utils_printf(stderr, 1, "internal error\n"); + return 2; + } + if(0 != (error = grabbag__replaygain_store_to_file_album(outfilename, album_gain, album_peak, /*preserve_modtime=*/true))) { + flac__utils_printf(stderr, 1, "%s: ERROR writing ReplayGain album tags\n", outfilename); + retval = 1; + } + } + } + } + } + + return retval; +} + +FLAC__bool init_options() +{ + option_values.show_help = false; + option_values.show_explain = false; + option_values.mode_decode = false; + option_values.verify = false; + option_values.force_file_overwrite = false; + option_values.continue_through_decode_errors = false; + option_values.replaygain_synthesis_spec.apply = false; + option_values.replaygain_synthesis_spec.use_album_gain = true; + option_values.replaygain_synthesis_spec.limiter = RGSS_LIMIT__HARD; + option_values.replaygain_synthesis_spec.noise_shaping = NOISE_SHAPING_LOW; + option_values.replaygain_synthesis_spec.preamp = 0.0; + option_values.lax = false; + option_values.test_only = false; + option_values.analyze = false; + option_values.use_ogg = false; + option_values.has_serial_number = false; + option_values.serial_number = 0; + option_values.do_mid_side = true; + option_values.loose_mid_side = false; + option_values.do_exhaustive_model_search = false; + option_values.do_escape_coding = false; + option_values.do_qlp_coeff_prec_search = false; + option_values.force_to_stdout = false; + option_values.force_aiff_format = false; + option_values.force_raw_format = false; + option_values.delete_input = false; + option_values.replay_gain = false; + option_values.sector_align = false; + option_values.cmdline_forced_outfilename = 0; + option_values.output_prefix = 0; + option_values.aopts.do_residual_text = false; + option_values.aopts.do_residual_gnuplot = false; + option_values.padding = 4096; + option_values.max_lpc_order = 8; + option_values.qlp_coeff_precision = 0; + option_values.skip_specification = 0; + option_values.until_specification = 0; + option_values.cue_specification = 0; + option_values.format_is_big_endian = -1; + option_values.format_is_unsigned_samples = -1; + option_values.format_channels = -1; + option_values.format_bps = -1; + option_values.format_sample_rate = -1; + option_values.format_input_size = -1; + option_values.blocksize = -1; + option_values.min_residual_partition_order = -1; + option_values.max_residual_partition_order = -1; + option_values.rice_parameter_search_dist = -1; + option_values.requested_seek_points[0] = '\0'; + option_values.num_requested_seek_points = -1; + option_values.cuesheet_filename = 0; + option_values.cued_seekpoints = true; + + option_values.num_files = 0; + option_values.filenames = 0; + + if(0 == (option_values.vorbis_comment = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT))) + return false; + + option_values.debug.disable_constant_subframes = false; + option_values.debug.disable_fixed_subframes = false; + option_values.debug.disable_verbatim_subframes = false; + + return true; +} + +int parse_options(int argc, char *argv[]) +{ + int short_option; + int option_index = 1; + FLAC__bool had_error = false; + const char *short_opts = "0123456789ab:cdefFhHl:mMo:pP:q:r:sS:tT:vV"; + + while ((short_option = share__getopt_long(argc, argv, short_opts, long_options_, &option_index)) != -1) { + switch (short_option) { + case 0: /* long option with no equivalent short option */ + had_error |= (parse_option(short_option, long_options_[option_index].name, share__optarg) != 0); + break; + case '?': + case ':': + had_error = true; + break; + default: /* short option */ + had_error |= (parse_option(short_option, 0, share__optarg) != 0); + break; + } + } + + if(had_error) { + return 1; + } + + FLAC__ASSERT(share__optind <= argc); + + option_values.num_files = argc - share__optind; + + if(option_values.num_files > 0) { + unsigned i = 0; + if(0 == (option_values.filenames = (char**)malloc(sizeof(char*) * option_values.num_files))) + die("out of memory allocating space for file names list"); + while(share__optind < argc) + option_values.filenames[i++] = local_strdup(argv[share__optind++]); + } + + return 0; +} + +int parse_option(int short_option, const char *long_option, const char *option_argument) +{ + char *p; + + if(short_option == 0) { + FLAC__ASSERT(0 != long_option); + if(0 == strcmp(long_option, "totally-silent")) { + flac__utils_verbosity_ = 0; + } + else if(0 == strcmp(long_option, "delete-input-file")) { + option_values.delete_input = true; + } + else if(0 == strcmp(long_option, "output-prefix")) { + FLAC__ASSERT(0 != option_argument); + option_values.output_prefix = option_argument; + } + else if(0 == strcmp(long_option, "skip")) { + FLAC__ASSERT(0 != option_argument); + option_values.skip_specification = option_argument; + } + else if(0 == strcmp(long_option, "until")) { + FLAC__ASSERT(0 != option_argument); + option_values.until_specification = option_argument; + } + else if(0 == strcmp(long_option, "input-size")) { + FLAC__ASSERT(0 != option_argument); + option_values.format_input_size = atol(option_argument); + } + else if(0 == strcmp(long_option, "cue")) { + FLAC__ASSERT(0 != option_argument); + option_values.cue_specification = option_argument; + } + else if(0 == strcmp(long_option, "apply-replaygain-which-is-not-lossless")) { + option_values.replaygain_synthesis_spec.apply = true; + if (0 != option_argument) { + char *p; + option_values.replaygain_synthesis_spec.limiter = RGSS_LIMIT__NONE; + option_values.replaygain_synthesis_spec.noise_shaping = NOISE_SHAPING_NONE; + option_values.replaygain_synthesis_spec.preamp = strtod(option_argument, &p); + for ( ; *p; p++) { + if (*p == 'a') + option_values.replaygain_synthesis_spec.use_album_gain = true; + else if (*p == 't') + option_values.replaygain_synthesis_spec.use_album_gain = false; + else if (*p == 'l') + option_values.replaygain_synthesis_spec.limiter = RGSS_LIMIT__PEAK; + else if (*p == 'L') + option_values.replaygain_synthesis_spec.limiter = RGSS_LIMIT__HARD; + else if (*p == 'n' && p[1] >= '0' && p[1] <= '3') { + option_values.replaygain_synthesis_spec.noise_shaping = p[1] - '0'; + p++; + } + else + return usage_error("ERROR: bad specification string \"%s\" for --%s\n", option_argument, long_option); + } + } + } + else if(0 == strcmp(long_option, "cuesheet")) { + FLAC__ASSERT(0 != option_argument); + option_values.cuesheet_filename = option_argument; + } + else if(0 == strcmp(long_option, "no-cued-seekpoints")) { + option_values.cued_seekpoints = false; + } + else if(0 == strcmp(long_option, "super-secret-totally-impractical-compression-level")) { + option_values.lax = true; + option_values.do_exhaustive_model_search = true; + option_values.do_escape_coding = true; + option_values.do_mid_side = true; + option_values.loose_mid_side = false; + option_values.do_qlp_coeff_prec_search = true; + option_values.min_residual_partition_order = 0; + option_values.max_residual_partition_order = 16; + option_values.rice_parameter_search_dist = 0; + option_values.max_lpc_order = 32; + } + else if(0 == strcmp(long_option, "force-aiff-format")) { + option_values.force_aiff_format = true; + } + else if(0 == strcmp(long_option, "force-raw-format")) { + option_values.force_raw_format = true; + } + else if(0 == strcmp(long_option, "lax")) { + option_values.lax = true; + } + else if(0 == strcmp(long_option, "replay-gain")) { + option_values.replay_gain = true; + } + else if(0 == strcmp(long_option, "sector-align")) { + option_values.sector_align = true; + } +#ifdef FLAC__HAS_OGG + else if(0 == strcmp(long_option, "ogg")) { + option_values.use_ogg = true; + } + else if(0 == strcmp(long_option, "serial-number")) { + option_values.has_serial_number = true; + option_values.serial_number = atol(option_argument); + } +#endif + else if(0 == strcmp(long_option, "endian")) { + FLAC__ASSERT(0 != option_argument); + if(0 == strncmp(option_argument, "big", strlen(option_argument))) + option_values.format_is_big_endian = true; + else if(0 == strncmp(option_argument, "little", strlen(option_argument))) + option_values.format_is_big_endian = false; + else + return usage_error("ERROR: argument to --endian must be \"big\" or \"little\"\n"); + } + else if(0 == strcmp(long_option, "channels")) { + FLAC__ASSERT(0 != option_argument); + option_values.format_channels = atoi(option_argument); + } + else if(0 == strcmp(long_option, "bps")) { + FLAC__ASSERT(0 != option_argument); + option_values.format_bps = atoi(option_argument); + } + else if(0 == strcmp(long_option, "sample-rate")) { + FLAC__ASSERT(0 != option_argument); + option_values.format_sample_rate = atoi(option_argument); + } + else if(0 == strcmp(long_option, "sign")) { + FLAC__ASSERT(0 != option_argument); + if(0 == strncmp(option_argument, "signed", strlen(option_argument))) + option_values.format_is_unsigned_samples = false; + else if(0 == strncmp(option_argument, "unsigned", strlen(option_argument))) + option_values.format_is_unsigned_samples = true; + else + return usage_error("ERROR: argument to --sign must be \"signed\" or \"unsigned\"\n"); + } + else if(0 == strcmp(long_option, "residual-gnuplot")) { + option_values.aopts.do_residual_gnuplot = true; + } + else if(0 == strcmp(long_option, "residual-text")) { + option_values.aopts.do_residual_text = true; + } + /* + * negatives + */ + else if(0 == strcmp(long_option, "no-decode-through-errors")) { + option_values.continue_through_decode_errors = false; + } + else if(0 == strcmp(long_option, "no-silent")) { + flac__utils_verbosity_ = 2; + } + else if(0 == strcmp(long_option, "no-force")) { + option_values.force_file_overwrite = false; + } + else if(0 == strcmp(long_option, "no-seektable")) { + option_values.num_requested_seek_points = 0; + option_values.requested_seek_points[0] = '\0'; + } + else if(0 == strcmp(long_option, "no-delete-input-file")) { + option_values.delete_input = false; + } + else if(0 == strcmp(long_option, "no-replay-gain")) { + option_values.replay_gain = false; + } + else if(0 == strcmp(long_option, "no-sector-align")) { + option_values.sector_align = false; + } + else if(0 == strcmp(long_option, "no-lax")) { + option_values.lax = false; + } +#ifdef FLAC__HAS_OGG + else if(0 == strcmp(long_option, "no-ogg")) { + option_values.use_ogg = false; + } +#endif + else if(0 == strcmp(long_option, "no-exhaustive-model-search")) { + option_values.do_exhaustive_model_search = false; + } + else if(0 == strcmp(long_option, "no-mid-side")) { + option_values.do_mid_side = option_values.loose_mid_side = false; + } + else if(0 == strcmp(long_option, "no-adaptive-mid-side")) { + option_values.loose_mid_side = option_values.do_mid_side = false; + } + else if(0 == strcmp(long_option, "no-qlp-coeff-prec-search")) { + option_values.do_qlp_coeff_prec_search = false; + } + else if(0 == strcmp(long_option, "no-padding")) { + option_values.padding = -1; + } + else if(0 == strcmp(long_option, "no-verify")) { + option_values.verify = false; + } + else if(0 == strcmp(long_option, "no-residual-gnuplot")) { + option_values.aopts.do_residual_gnuplot = false; + } + else if(0 == strcmp(long_option, "no-residual-text")) { + option_values.aopts.do_residual_text = false; + } + else if(0 == strcmp(long_option, "disable-constant-subframes")) { + option_values.debug.disable_constant_subframes = true; + } + else if(0 == strcmp(long_option, "disable-fixed-subframes")) { + option_values.debug.disable_fixed_subframes = true; + } + else if(0 == strcmp(long_option, "disable-verbatim-subframes")) { + option_values.debug.disable_verbatim_subframes = true; + } + } + else { + const char *violation; + switch(short_option) { + case 'h': + option_values.show_help = true; + break; + case 'H': + option_values.show_explain = true; + break; + case 'v': + option_values.show_version = true; + break; + case 'd': + option_values.mode_decode = true; + break; + case 'a': + option_values.mode_decode = true; + option_values.analyze = true; + break; + case 't': + option_values.mode_decode = true; + option_values.test_only = true; + break; + case 'c': + option_values.force_to_stdout = true; + break; + case 's': + flac__utils_verbosity_ = 1; + break; + case 'f': + option_values.force_file_overwrite = true; + break; + case 'o': + FLAC__ASSERT(0 != option_argument); + option_values.cmdline_forced_outfilename = option_argument; + break; + case 'F': + option_values.continue_through_decode_errors = true; + break; + case 'T': + FLAC__ASSERT(0 != option_argument); + if(!flac__vorbiscomment_add(option_values.vorbis_comment, option_argument, &violation)) + return usage_error("ERROR: (-T/--tag) %s\n", violation); + break; + case '0': + option_values.do_exhaustive_model_search = false; + option_values.do_escape_coding = false; + option_values.do_mid_side = false; + option_values.loose_mid_side = false; + option_values.qlp_coeff_precision = 0; + option_values.min_residual_partition_order = option_values.max_residual_partition_order = 2; + option_values.rice_parameter_search_dist = 0; + option_values.max_lpc_order = 0; + break; + case '1': + option_values.do_exhaustive_model_search = false; + option_values.do_escape_coding = false; + option_values.do_mid_side = true; + option_values.loose_mid_side = true; + option_values.qlp_coeff_precision = 0; + option_values.min_residual_partition_order = option_values.max_residual_partition_order = 2; + option_values.rice_parameter_search_dist = 0; + option_values.max_lpc_order = 0; + break; + case '2': + option_values.do_exhaustive_model_search = false; + option_values.do_escape_coding = false; + option_values.do_mid_side = true; + option_values.loose_mid_side = false; + option_values.qlp_coeff_precision = 0; + option_values.min_residual_partition_order = 0; + option_values.max_residual_partition_order = 3; + option_values.rice_parameter_search_dist = 0; + option_values.max_lpc_order = 0; + break; + case '3': + option_values.do_exhaustive_model_search = false; + option_values.do_escape_coding = false; + option_values.do_mid_side = false; + option_values.loose_mid_side = false; + option_values.qlp_coeff_precision = 0; + option_values.min_residual_partition_order = option_values.max_residual_partition_order = 3; + option_values.rice_parameter_search_dist = 0; + option_values.max_lpc_order = 6; + break; + case '4': + option_values.do_exhaustive_model_search = false; + option_values.do_escape_coding = false; + option_values.do_mid_side = true; + option_values.loose_mid_side = true; + option_values.qlp_coeff_precision = 0; + option_values.min_residual_partition_order = option_values.max_residual_partition_order = 3; + option_values.rice_parameter_search_dist = 0; + option_values.max_lpc_order = 8; + break; + case '5': + option_values.do_exhaustive_model_search = false; + option_values.do_escape_coding = false; + option_values.do_mid_side = true; + option_values.loose_mid_side = false; + option_values.qlp_coeff_precision = 0; + option_values.min_residual_partition_order = option_values.max_residual_partition_order = 3; + option_values.rice_parameter_search_dist = 0; + option_values.max_lpc_order = 8; + break; + case '6': + option_values.do_exhaustive_model_search = false; + option_values.do_escape_coding = false; + option_values.do_mid_side = true; + option_values.loose_mid_side = false; + option_values.qlp_coeff_precision = 0; + option_values.min_residual_partition_order = 0; + option_values.max_residual_partition_order = 4; + option_values.rice_parameter_search_dist = 0; + option_values.max_lpc_order = 8; + break; + case '7': + option_values.do_exhaustive_model_search = true; + option_values.do_escape_coding = false; + option_values.do_mid_side = true; + option_values.loose_mid_side = false; + option_values.qlp_coeff_precision = 0; + option_values.min_residual_partition_order = 0; + option_values.max_residual_partition_order = 6; + option_values.rice_parameter_search_dist = 0; + option_values.max_lpc_order = 8; + break; + case '8': + option_values.do_exhaustive_model_search = true; + option_values.do_escape_coding = false; + option_values.do_mid_side = true; + option_values.loose_mid_side = false; + option_values.qlp_coeff_precision = 0; + option_values.min_residual_partition_order = 0; + option_values.max_residual_partition_order = 6; + option_values.rice_parameter_search_dist = 0; + option_values.max_lpc_order = 12; + break; + case '9': + return usage_error("ERROR: compression level '9' is reserved\n"); + case 'V': + option_values.verify = true; + break; + case 'S': + FLAC__ASSERT(0 != option_argument); + if(option_values.num_requested_seek_points < 0) + option_values.num_requested_seek_points = 0; + option_values.num_requested_seek_points++; + if(strlen(option_values.requested_seek_points)+strlen(option_argument)+2 >= sizeof(option_values.requested_seek_points)) { + return usage_error("ERROR: too many seekpoints requested\n"); + } + else { + strcat(option_values.requested_seek_points, option_argument); + strcat(option_values.requested_seek_points, ";"); + } + break; + case 'P': + FLAC__ASSERT(0 != option_argument); + option_values.padding = atoi(option_argument); + if(option_values.padding < 0) + return usage_error("ERROR: argument to -P must be >= 0\n"); + break; + case 'b': + FLAC__ASSERT(0 != option_argument); + option_values.blocksize = atoi(option_argument); + break; + case 'e': + option_values.do_exhaustive_model_search = true; + break; + case 'E': + option_values.do_escape_coding = true; + break; + case 'l': + FLAC__ASSERT(0 != option_argument); + option_values.max_lpc_order = atoi(option_argument); + break; + case 'm': + option_values.do_mid_side = true; + option_values.loose_mid_side = false; + break; + case 'M': + option_values.loose_mid_side = option_values.do_mid_side = true; + break; + case 'p': + option_values.do_qlp_coeff_prec_search = true; + break; + case 'q': + FLAC__ASSERT(0 != option_argument); + option_values.qlp_coeff_precision = atoi(option_argument); + break; + case 'r': + FLAC__ASSERT(0 != option_argument); + p = strchr(option_argument, ','); + if(0 == p) { + option_values.min_residual_partition_order = 0; + option_values.max_residual_partition_order = atoi(option_argument); + } + else { + option_values.min_residual_partition_order = atoi(option_argument); + option_values.max_residual_partition_order = atoi(++p); + } + break; + case 'R': + FLAC__ASSERT(0 != option_argument); + option_values.rice_parameter_search_dist = atoi(option_argument); + break; + default: + FLAC__ASSERT(0); + } + } + + return 0; +} + +void free_options() +{ + unsigned i; + if(0 != option_values.filenames) { + for(i = 0; i < option_values.num_files; i++) { + if(0 != option_values.filenames[i]) + free(option_values.filenames[i]); + } + free(option_values.filenames); + } + if(0 != option_values.vorbis_comment) + FLAC__metadata_object_delete(option_values.vorbis_comment); +} + +int usage_error(const char *message, ...) +{ + if(flac__utils_verbosity_ >= 1) { + va_list args; + + FLAC__ASSERT(0 != message); + + va_start(args, message); + + (void) vfprintf(stderr, message, args); + + va_end(args); + + printf("Type \"flac\" for a usage summary or \"flac --help\" for all options\n"); + } + + return 1; +} + +void show_version() +{ + printf("flac %s\n", FLAC__VERSION_STRING); +} + +static void usage_header() +{ + printf("===============================================================================\n"); + printf("flac - Command-line FLAC encoder/decoder version %s\n", FLAC__VERSION_STRING); + printf("Copyright (C) 2000,2001,2002,2003,2004,2005 Josh Coalson\n"); + printf("\n"); + printf("This program is free software; you can redistribute it and/or\n"); + printf("modify it under the terms of the GNU General Public License\n"); + printf("as published by the Free Software Foundation; either version 2\n"); + printf("of the License, or (at your option) any later version.\n"); + printf("\n"); + printf("This program is distributed in the hope that it will be useful,\n"); + printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n"); + printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"); + printf("GNU General Public License for more details.\n"); + printf("\n"); + printf("You should have received a copy of the GNU General Public License\n"); + printf("along with this program; if not, write to the Free Software\n"); + printf("Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n"); + printf("===============================================================================\n"); +} + +static void usage_summary() +{ + printf("Usage:\n"); + printf("\n"); + printf(" Encoding: flac [] [] [INPUTFILE [...]]\n"); + printf(" Decoding: flac -d [] [] [FLACFILE [...]]\n"); + printf(" Testing: flac -t [] [FLACFILE [...]]\n"); + printf("Analyzing: flac -a [] [] [FLACFILE [...]]\n"); + printf("\n"); +} + +void short_usage() +{ + usage_header(); + printf("\n"); + printf("This is the short help; for all options use 'flac --help'; for even more\n"); + printf("instructions use 'flac --explain'\n"); + printf("\n"); + printf("To encode:\n"); + printf(" flac [-#] [INPUTFILE [...]]\n"); + printf("\n"); + printf(" -# is -0 (fastest compression) to -8 (highest compression); -5 is the default\n"); + printf("\n"); + printf("To decode:\n"); + printf(" flac -d [INPUTFILE [...]]\n"); + printf("\n"); + printf("To test:\n"); + printf(" flac -t [INPUTFILE [...]]\n"); +} + +void show_help() +{ + usage_header(); + usage_summary(); + printf("general options:\n"); + printf(" -v, --version Show the flac version number\n"); + printf(" -h, --help Show this screen\n"); + printf(" -H, --explain Show detailed explanation of usage and options\n"); + printf(" -d, --decode Decode (the default behavior is to encode)\n"); + printf(" -t, --test Same as -d except no decoded file is written\n"); + printf(" -a, --analyze Same as -d except an analysis file is written\n"); + printf(" -c, --stdout Write output to stdout\n"); + printf(" -s, --silent Do not write runtime encode/decode statistics\n"); + printf(" --totally-silent Do not print anything, including errors\n"); + printf(" -f, --force Force overwriting of output files\n"); + printf(" -o, --output-name=FILENAME Force the output file name\n"); + printf(" --output-prefix=STRING Prepend STRING to output names\n"); + printf(" --delete-input-file Deletes after a successful encode/decode\n"); + printf(" --skip={#|mm:ss.ss} Skip the given initial samples for each input\n"); + printf(" --until={#|[+|-]mm:ss.ss} Stop at the given sample for each input file\n"); +#ifdef FLAC__HAS_OGG + printf(" --ogg Use Ogg as transport layer\n"); + printf(" --serial-number Serial number to use for the FLAC stream\n"); +#endif + printf("analysis options:\n"); + printf(" --residual-text Include residual signal in text output\n"); + printf(" --residual-gnuplot Generate gnuplot files of residual distribution\n"); + printf("decoding options:\n"); + printf(" -F, --decode-through-errors Continue decoding through stream errors\n"); + printf(" --cue=[#.#][-[#.#]] Set the beginning and ending cuepoints to decode\n"); + printf("encoding options:\n"); + printf(" -V, --verify Verify a correct encoding\n"); + printf(" --lax Allow encoder to generate non-Subset files\n"); + printf(" --sector-align Align multiple files on sector boundaries\n"); + printf(" --replay-gain Calculate ReplayGain & store in Vorbis comments\n"); + printf(" --cuesheet=FILENAME Import cuesheet and store in CUESHEET block\n"); + printf(" -T, --tag=FIELD=VALUE Add a Vorbis comment; may appear multiple times\n"); + printf(" -S, --seekpoint={#|X|#x|#s} Add seek point(s)\n"); + printf(" -P, --padding=# Write a PADDING block of length #\n"); + printf(" -0, --compression-level-0, --fast Synonymous with -l 0 -b 1152 -r 2,2\n"); + printf(" -1, --compression-level-1 Synonymous with -l 0 -b 1152 -M -r 2,2\n"); + printf(" -2, --compression-level-2 Synonymous with -l 0 -b 1152 -m -r 3\n"); + printf(" -3, --compression-level-3 Synonymous with -l 6 -b 4608 -r 3,3\n"); + printf(" -4, --compression-level-4 Synonymous with -l 8 -b 4608 -M -r 3,3\n"); + printf(" -5, --compression-level-5 Synonymous with -l 8 -b 4608 -m -r 3,3\n"); + printf(" -6, --compression-level-6 Synonymous with -l 8 -b 4608 -m -r 4\n"); + printf(" -7, --compression-level-7 Synonymous with -l 8 -b 4608 -m -e -r 6\n"); + printf(" -8, --compression-level-8, --best Synonymous with -l 12 -b 4608 -m -e -r 6\n"); + printf(" -b, --blocksize=# Specify blocksize in samples\n"); + printf(" -m, --mid-side Try mid-side coding for each frame\n"); + printf(" -M, --adaptive-mid-side Adaptive mid-side coding for all frames\n"); + printf(" -e, --exhaustive-model-search Do exhaustive model search (expensive!)\n"); + printf(" -l, --max-lpc-order=# Max LPC order; 0 => only fixed predictors\n"); + printf(" -p, --qlp-coeff-precision-search Exhaustively search LP coeff quantization\n"); + printf(" -q, --qlp-coeff-precision=# Specify precision in bits\n"); + printf(" -r, --rice-partition-order=[#,]# Set [min,]max residual partition order\n"); + printf("format options:\n"); + printf(" --endian={big|little} Set byte order for samples\n"); + printf(" --channels=# Number of channels\n"); + printf(" --bps=# Number of bits per sample\n"); + printf(" --sample-rate=# Sample rate in Hz\n"); + printf(" --sign={signed|unsigned} Sign of samples\n"); + printf(" --input-size=# Size of the raw input in bytes\n"); + printf(" --force-aiff-format Force decoding to AIFF format\n"); + printf(" --force-raw-format Treat input or output as raw samples\n"); + printf("negative options:\n"); + printf(" --no-adaptive-mid-side\n"); + printf(" --no-decode-through-errors\n"); + printf(" --no-delete-input-file\n"); + printf(" --no-exhaustive-model-search\n"); + printf(" --no-lax\n"); + printf(" --no-mid-side\n"); +#ifdef FLAC__HAS_OGG + printf(" --no-ogg\n"); +#endif + printf(" --no-padding\n"); + printf(" --no-qlp-coeff-prec-search\n"); + printf(" --no-replay-gain\n"); + printf(" --no-residual-gnuplot\n"); + printf(" --no-residual-text\n"); + printf(" --no-sector-align\n"); + printf(" --no-seektable\n"); + printf(" --no-silent\n"); + printf(" --no-force\n"); + printf(" --no-verify\n"); +} + +void show_explain() +{ + usage_header(); + usage_summary(); + printf("For encoding:\n"); + printf(" The input file(s) may be a PCM RIFF WAVE file, AIFF file, or raw samples.\n"); + printf(" The output file(s) will be in native FLAC or Ogg FLAC format\n"); + printf("For decoding, the reverse is true.\n"); + printf("\n"); + printf("A single INPUTFILE may be - for stdin. No INPUTFILE implies stdin. Use of\n"); + printf("stdin implies -c (write to stdout). Normally you should use:\n"); + printf(" flac [options] -o outfilename or flac -d [options] -o outfilename\n"); + printf("instead of:\n"); + printf(" flac [options] > outfilename or flac -d [options] > outfilename\n"); + printf("since the former allows flac to seek backwards to write the STREAMINFO or\n"); + printf("WAVE/AIFF header contents when necessary.\n"); + printf("\n"); + printf("flac checks for the presence of a AIFF/WAVE header to decide whether or not to\n"); + printf("treat an input file as AIFF/WAVE format or raw samples. If any input file is\n"); + printf("raw you must specify the format options {-fb|fl} -fc -fp and -fs, which will\n"); + printf("apply to all raw files. You can force AIFF/WAVE files to be treated as raw\n"); + printf("files using -fr.\n"); + printf("\n"); + printf("general options:\n"); + printf(" -v, --version Show the flac version number\n"); + printf(" -h, --help Show basic usage a list of all options\n"); + printf(" -H, --explain Show this screen\n"); + printf(" -d, --decode Decode (the default behavior is to encode)\n"); + printf(" -t, --test Same as -d except no decoded file is written\n"); + printf(" -a, --analyze Same as -d except an analysis file is written\n"); + printf(" -c, --stdout Write output to stdout\n"); + printf(" -s, --silent Do not write runtime encode/decode statistics\n"); + printf(" --totally-silent Do not print anything of any kind, including\n"); + printf(" warnings or errors. The exit code will be the\n"); + printf(" only way to determine successful completion.\n"); + printf(" -f, --force Force overwriting of output files\n"); + printf(" -o, --output-name=FILENAME Force the output file name; usually flac just\n"); + printf(" changes the extension. May only be used when\n"); + printf(" encoding a single file. May not be used in\n"); + printf(" conjunction with --output-prefix.\n"); + printf(" --output-prefix=STRING Prefix each output file name with the given\n"); + printf(" STRING. This can be useful for encoding or\n"); + printf(" decoding files to a different directory. Make\n"); + printf(" sure if your STRING is a path name that it ends\n"); + printf(" with a '/' slash.\n"); + printf(" --delete-input-file Automatically delete the input file after a\n"); + printf(" successful encode or decode. If there was an\n"); + printf(" error (including a verify error) the input file\n"); + printf(" is left intact.\n"); + printf(" --skip={#|mm:ss.ss} Skip the first # samples of each input file; can\n"); + printf(" be used both for encoding and decoding. The\n"); + printf(" alternative form mm:ss.ss can be used to specify\n"); + printf(" minutes, seconds, and fractions of a second.\n"); + printf(" --until={#|[+|-]mm:ss.ss} Stop at the given sample number for each input\n"); + printf(" file. The given sample number is not included\n"); + printf(" in the decoded output. The alternative form\n"); + printf(" mm:ss.ss can be used to specify minutes,\n"); + printf(" seconds, and fractions of a second. If a `+'\n"); + printf(" sign is at the beginning, the --until point is\n"); + printf(" relative to the --skip point. If a `-' sign is\n"); + printf(" at the beginning, the --until point is relative\n"); + printf(" to end of the audio.\n"); +#ifdef FLAC__HAS_OGG + printf(" --ogg When encoding, generate Ogg FLAC output instead\n"); + printf(" of native FLAC. Ogg FLAC streams are FLAC\n"); + printf(" streams wrapped in an Ogg transport layer. The\n"); + printf(" resulting file should have an '.ogg' extension\n"); + printf(" and will still be decodable by flac. When\n"); + printf(" decoding, force the input to be treated as\n"); + printf(" Ogg FLAC. This is useful when piping input\n"); + printf(" from stdin or when the filename does not end in\n"); + printf(" '.ogg'.\n"); + printf(" --serial-number Serial number to use for the FLAC stream. When\n"); + printf(" encoding and no serial number is given, flac\n"); + printf(" uses '0'. When decoding and no number is\n"); + printf(" given, flac uses the serial number of the first\n"); + printf(" page.\n"); +#endif + printf("analysis options:\n"); + printf(" --residual-text Include residual signal in text output. This\n"); + printf(" will make the file very big, much larger than\n"); + printf(" even the decoded file.\n"); + printf(" --residual-gnuplot Generate gnuplot files of residual distribution\n"); + printf(" of each subframe\n"); + printf("decoding options:\n"); + printf(" -F, --decode-through-errors By default flac stops decoding with an error\n"); + printf(" and removes the partially decoded file if it\n"); + printf(" encounters a bitstream error. With -F, errors\n"); + printf(" are still printed but flac will continue\n"); + printf(" decoding to completion. Note that errors may\n"); + printf(" cause the decoded audio to be missing some\n"); + printf(" samples or have silent sections.\n"); + printf(" --cue=[#.#][-[#.#]] Set the beginning and ending cuepoints to\n"); + printf(" decode. The optional first #.# is the track and\n"); + printf(" index point at which decoding will start; the\n"); + printf(" default is the beginning of the stream. The\n"); + printf(" optional second #.# is the track and index point\n"); + printf(" at which decoding will end; the default is the\n"); + printf(" end of the stream. If the cuepoint does not\n"); + printf(" exist, the closest one before it (for the start\n"); + printf(" point) or after it (for the end point) will be\n"); + printf(" used. The cuepoints are merely translated into\n"); + printf(" sample numbers then used as --skip and --until.\n"); + printf("encoding options:\n"); + printf(" -V, --verify Verify a correct encoding by decoding the\n"); + printf(" output in parallel and comparing to the\n"); + printf(" original\n"); + printf(" --lax Allow encoder to generate non-Subset files\n"); + printf(" --sector-align Align encoding of multiple CD format WAVE files\n"); + printf(" on sector boundaries.\n"); + printf(" --replay-gain Calculate ReplayGain values and store in Vorbis\n"); + printf(" comments. Title gains/peaks will be computed\n"); + printf(" for each file, and an album gain/peak will be\n"); + printf(" computed for all files. All input files must\n"); + printf(" have the same resolution, sample rate, and\n"); + printf(" number of channels. The sample rate must be\n"); + printf(" one of 8, 11.025, 12, 16, 22.05, 24, 32, 44.1,\n"); + printf(" or 48 kHz. NOTE: this option may also leave a\n"); + printf(" few extra bytes in the PADDING block.\n"); + printf(" --cuesheet=FILENAME Import the given cuesheet file and store it in\n"); + printf(" a CUESHEET metadata block. This option may only\n"); + printf(" be used when encoding a single file. A\n"); + printf(" seekpoint will be added for each index point in\n"); + printf(" the cuesheet to the SEEKTABLE unless\n"); + printf(" --no-cued-seekpoints is specified.\n"); + printf(" -T, --tag=FIELD=VALUE Add a Vorbis comment. Make sure to quote the\n"); + printf(" comment if necessary. This option may appear\n"); + printf(" more than once to add several comments. NOTE:\n"); + printf(" all tags will be added to all encoded files.\n"); + printf(" -S, --seekpoint={#|X|#x|#s} Include a point or points in a SEEKTABLE\n"); + printf(" # : a specific sample number for a seek point\n"); + printf(" X : a placeholder point (always goes at the end of the SEEKTABLE)\n"); + printf(" #x : # evenly spaced seekpoints, the first being at sample 0\n"); + printf(" #s : a seekpoint every # seconds; # does not have to be a whole number\n"); + printf(" You may use many -S options; the resulting SEEKTABLE will be the unique-\n"); + printf(" ified union of all such values.\n"); + printf(" With no -S options, flac defaults to '-S 10s'. Use -S- for no SEEKTABLE.\n"); + printf(" Note: -S #x and -S #s will not work if the encoder can't determine the\n"); + printf(" input size before starting.\n"); + printf(" Note: if you use -S # and # is >= samples in the input, there will be\n"); + printf(" either no seek point entered (if the input size is determinable\n"); + printf(" before encoding starts) or a placeholder point (if input size is not\n"); + printf(" determinable)\n"); + printf(" -P, --padding=# Tell the encoder to write a PADDING metadata\n"); + printf(" block of the given length (in bytes) after the\n"); + printf(" STREAMINFO block. This is useful if you plan\n"); + printf(" to tag the file later with an APPLICATION\n"); + printf(" block; instead of having to rewrite the entire\n"); + printf(" file later just to insert your block, you can\n"); + printf(" write directly over the PADDING block. Note\n"); + printf(" that the total length of the PADDING block will\n"); + printf(" be 4 bytes longer than the length given because\n"); + printf(" of the 4 metadata block header bytes. You can\n"); + printf(" force no PADDING block at all to be written with\n"); + printf(" --no-padding. The encoder writes a PADDING\n"); + printf(" block of 4096 bytes by default.\n"); + printf(" -b, --blocksize=# Specify the blocksize in samples; the default is\n"); + printf(" 1152 for -l 0, else 4608; must be one of 192,\n"); + printf(" 576, 1152, 2304, 4608, 256, 512, 1024, 2048,\n"); + printf(" 4096, 8192, 16384, or 32768 (unless --lax is\n"); + printf(" used)\n"); + printf(" -0, --compression-level-0, --fast Synonymous with -l 0 -b 1152 -r 2,2\n"); + printf(" -1, --compression-level-1 Synonymous with -l 0 -b 1152 -M -r 2,2\n"); + printf(" -2, --compression-level-2 Synonymous with -l 0 -b 1152 -m -r 3\n"); + printf(" -3, --compression-level-3 Synonymous with -l 6 -b 4608 -r 3,3\n"); + printf(" -4, --compression-level-4 Synonymous with -l 8 -b 4608 -M -r 3,3\n"); + printf(" -5, --compression-level-5 Synonymous with -l 8 -b 4608 -m -r 3,3\n"); + printf(" -5 is the default setting\n"); + printf(" -6, --compression-level-6 Synonymous with -l 8 -b 4608 -m -r 4\n"); + printf(" -7, --compression-level-7 Synonymous with -l 8 -b 4608 -m -e -r 6\n"); + printf(" -8, --compression-level-8, --best Synonymous with -l 12 -b 4608 -m -e -r 6\n"); + printf(" -m, --mid-side Try mid-side coding for each frame\n"); + printf(" (stereo only)\n"); + printf(" -M, --adaptive-mid-side Adaptive mid-side coding for all frames\n"); + printf(" (stereo only)\n"); + printf(" -e, --exhaustive-model-search Do exhaustive model search (expensive!)\n"); + printf(" -l, --max-lpc-order=# Max LPC order; 0 => only fixed predictors\n"); + printf(" -p, --qlp-coeff-precision-search Do exhaustive search of LP coefficient\n"); + printf(" quantization (expensive!); overrides -q;\n"); + printf(" does nothing if using -l 0\n"); + printf(" -q, --qlp-coeff-precision=# Specify precision in bits of quantized\n"); + printf(" linear-predictor coefficients; 0 => let\n"); + printf(" encoder decide (the minimun is %u, the\n", FLAC__MIN_QLP_COEFF_PRECISION); + printf(" default is -q 0)\n"); + printf(" -r, --rice-partition-order=[#,]# Set [min,]max residual partition order\n"); + printf(" (# is 0..16; min defaults to 0; the\n"); + printf(" default is -r 0; above 4 doesn't usually\n"); + printf(" help much)\n"); + printf("format options:\n"); + printf(" --endian={big|little} Set byte order for samples\n"); + printf(" --channels=# Number of channels\n"); + printf(" --bps=# Number of bits per sample\n"); + printf(" --sample-rate=# Sample rate in Hz\n"); + printf(" --sign={signed|unsigned} Sign of samples (the default is signed)\n"); + printf(" --input-size=# Size of the raw input in bytes. If you are\n"); + printf(" encoding raw samples from stdin, you must set\n"); + printf(" this option in order to be able to use --skip,\n"); + printf(" --until, --cue-sheet, or other options that need\n"); + printf(" to know the size of the input beforehand. If\n"); + printf(" the size given is greater than what is found in\n"); + printf(" the input stream, the encoder will complain\n"); + printf(" about an unexpected end-of-file. If the size\n"); + printf(" given is less, samples will be truncated.\n"); + printf(" --force-aiff-format Force the decoder to output AIFF format. This\n"); + printf(" option is not needed if the output filename (as\n"); + printf(" set by -o) ends with .aif or .aiff; this option\n"); + printf(" has no effect when encoding since input AIFF is\n"); + printf(" auto-detected.\n"); + printf(" --force-raw-format Force input (when encoding) or output (when\n"); + printf(" decoding) to be treated as raw samples\n"); + printf("negative options:\n"); + printf(" --no-adaptive-mid-side\n"); + printf(" --no-decode-through-errors\n"); + printf(" --no-delete-input-file\n"); + printf(" --no-exhaustive-model-search\n"); + printf(" --no-lax\n"); + printf(" --no-mid-side\n"); +#ifdef FLAC__HAS_OGG + printf(" --no-ogg\n"); +#endif + printf(" --no-padding\n"); + printf(" --no-qlp-coeff-prec-search\n"); + printf(" --no-residual-gnuplot\n"); + printf(" --no-residual-text\n"); + printf(" --no-sector-align\n"); + printf(" --no-seektable\n"); + printf(" --no-silent\n"); + printf(" --no-force\n"); + printf(" --no-verify\n"); +} + +void format_mistake(const char *infilename, const char *wrong, const char *right) +{ + flac__utils_printf(stderr, 1, "WARNING: %s is not a %s file; treating as a %s file\n", infilename, wrong, right); +} + +int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_last_file) +{ + FILE *encode_infile; + FLAC__byte lookahead[12]; + unsigned lookahead_length = 0; + FileFormat fmt= RAW; + int retval; + long infilesize; + encode_options_t common_options; + const char *outfilename = get_encoded_outfilename(infilename); + + if(0 == outfilename) { + flac__utils_printf(stderr, 1, "ERROR: filename too long: %s", infilename); + return 1; + } + + /* + * Error if output file already exists (and -f not used). + * Use grabbag__file_get_filesize() as a cheap way to check. + */ + if(!option_values.test_only && !option_values.force_file_overwrite && grabbag__file_get_filesize(outfilename) != (off_t)(-1)) { + flac__utils_printf(stderr, 1, "ERROR: output file %s already exists, use -f to override\n", outfilename); + return 1; + } + + if(0 == strcmp(infilename, "-")) { + infilesize = -1; + encode_infile = grabbag__file_get_binary_stdin(); + } + else { + infilesize = grabbag__file_get_filesize(infilename); + if(0 == (encode_infile = fopen(infilename, "rb"))) { + flac__utils_printf(stderr, 1, "ERROR: can't open input file %s\n", infilename); + return 1; + } + } + + if(!option_values.force_raw_format) { + /* first set format based on name */ + if(strlen(infilename) >= 4 && 0 == strcasecmp(infilename+(strlen(infilename)-4), ".wav")) + fmt= WAV; + else if(strlen(infilename) >= 4 && 0 == strcasecmp(infilename+(strlen(infilename)-4), ".aif")) + fmt= AIF; + else if(strlen(infilename) >= 5 && 0 == strcasecmp(infilename+(strlen(infilename)-5), ".aiff")) + fmt= AIF; + + /* attempt to guess the file type based on the first 12 bytes */ + if((lookahead_length = fread(lookahead, 1, 12, encode_infile)) < 12) { + if(fmt != RAW) + format_mistake(infilename, fmt == AIF ? "AIFF" : "WAVE", "raw"); + fmt= RAW; + } + else { + if(!strncmp((const char *)lookahead, "RIFF", 4) && !strncmp((const char *)lookahead+8, "WAVE", 4)) + fmt= WAV; + else if(!strncmp((const char *)lookahead, "FORM", 4) && !strncmp((const char *)lookahead+8, "AIFF", 4)) + fmt= AIF; + else { + if(fmt != RAW) + format_mistake(infilename, fmt == AIF ? "AIFF" : "WAVE", "raw"); + fmt= RAW; + } + } + } + + if(option_values.format_input_size >= 0) { + if (fmt != RAW || infilesize >= 0) { + flac__utils_printf(stderr, 1, "ERROR: can only use --input-size when encoding raw samples from stdin\n"); + return 1; + } + else { + infilesize = option_values.format_input_size; + } + } + + if(option_values.sector_align && fmt == RAW && infilesize < 0) { + flac__utils_printf(stderr, 1, "ERROR: can't --sector-align when the input size is unknown\n"); + return 1; + } + + if(fmt == RAW) { + if(option_values.format_is_big_endian < 0 || option_values.format_is_unsigned_samples < 0 || option_values.format_channels < 0 || option_values.format_bps < 0 || option_values.format_sample_rate < 0) + return usage_error("ERROR: for encoding a raw file you must specify a value for --endian, --sign, --channels, --bps, and --sample-rate\n"); + } + + if(encode_infile == stdin || option_values.force_to_stdout) { + if(option_values.replay_gain) + return usage_error("ERROR: --replay-gain cannot be used when encoding to stdout\n"); + } + + if(!flac__utils_parse_skip_until_specification(option_values.skip_specification, &common_options.skip_specification) || common_options.skip_specification.is_relative) + return usage_error("ERROR: invalid value for --skip\n"); + + if(!flac__utils_parse_skip_until_specification(option_values.until_specification, &common_options.until_specification)) /*@@@ more checks: no + without --skip, no - unless known total_samples_to_{en,de}code */ + return usage_error("ERROR: invalid value for --until\n"); + /* if there is no "--until" we want to default to "--until=-0" */ + if(0 == option_values.until_specification) + common_options.until_specification.is_relative = true; + + common_options.verify = option_values.verify; +#ifdef FLAC__HAS_OGG + common_options.use_ogg = option_values.use_ogg; + /* set a random serial number if one has not yet been specified */ + if(!option_values.has_serial_number) { + srand(time(0)); + option_values.serial_number = rand(); + option_values.has_serial_number = true; + } + common_options.serial_number = option_values.serial_number++; +#endif + common_options.lax = option_values.lax; + common_options.do_mid_side = option_values.do_mid_side; + common_options.loose_mid_side = option_values.loose_mid_side; + common_options.do_exhaustive_model_search = option_values.do_exhaustive_model_search; + common_options.do_escape_coding = option_values.do_escape_coding; + common_options.do_qlp_coeff_prec_search = option_values.do_qlp_coeff_prec_search; + common_options.min_residual_partition_order = option_values.min_residual_partition_order; + common_options.max_residual_partition_order = option_values.max_residual_partition_order; + common_options.rice_parameter_search_dist = option_values.rice_parameter_search_dist; + common_options.max_lpc_order = option_values.max_lpc_order; + common_options.blocksize = (unsigned)option_values.blocksize; + common_options.qlp_coeff_precision = option_values.qlp_coeff_precision; + common_options.padding = option_values.padding; + common_options.requested_seek_points = option_values.requested_seek_points; + common_options.num_requested_seek_points = option_values.num_requested_seek_points; + common_options.cuesheet_filename = option_values.cuesheet_filename; + common_options.cued_seekpoints = option_values.cued_seekpoints; + common_options.is_first_file = is_first_file; + common_options.is_last_file = is_last_file; + common_options.align_reservoir = align_reservoir; + common_options.align_reservoir_samples = &align_reservoir_samples; + common_options.replay_gain = option_values.replay_gain; + common_options.sector_align = option_values.sector_align; + common_options.vorbis_comment = option_values.vorbis_comment; + common_options.debug.disable_constant_subframes = option_values.debug.disable_constant_subframes; + common_options.debug.disable_fixed_subframes = option_values.debug.disable_fixed_subframes; + common_options.debug.disable_verbatim_subframes = option_values.debug.disable_verbatim_subframes; + + if(fmt == RAW) { + raw_encode_options_t options; + + options.common = common_options; + options.is_big_endian = option_values.format_is_big_endian; + options.is_unsigned_samples = option_values.format_is_unsigned_samples; + options.channels = option_values.format_channels; + options.bps = option_values.format_bps; + options.sample_rate = option_values.format_sample_rate; + + retval = flac__encode_raw(encode_infile, infilesize, infilename, outfilename, lookahead, lookahead_length, options); + } + else { + wav_encode_options_t options; + + options.common = common_options; + + if(fmt == AIF) + retval = flac__encode_aif(encode_infile, infilesize, infilename, outfilename, lookahead, lookahead_length, options); + else + retval = flac__encode_wav(encode_infile, infilesize, infilename, outfilename, lookahead, lookahead_length, options); + } + + if(retval == 0 && strcmp(infilename, "-")) { + if(strcmp(outfilename, "-")) { + if(option_values.replay_gain) { + float title_gain, title_peak; + const char *error; + grabbag__replaygain_get_title(&title_gain, &title_peak); + if(0 != (error = grabbag__replaygain_store_to_file_title(outfilename, title_gain, title_peak, /*preserve_modtime=*/true))) { + flac__utils_printf(stderr, 1, "%s: ERROR writing ReplayGain title tags\n", outfilename); + } + } + grabbag__file_copy_metadata(infilename, outfilename); + } + if(option_values.delete_input) + unlink(infilename); + } + + return retval; +} + +int decode_file(const char *infilename) +{ + int retval; + FLAC__bool treat_as_ogg = false; + decode_options_t common_options; + const char *outfilename = get_decoded_outfilename(infilename); + + if(0 == outfilename) { + flac__utils_printf(stderr, 1, "ERROR: filename too long: %s", infilename); + return 1; + } + + /* + * Error if output file already exists (and -f not used). + * Use grabbag__file_get_filesize() as a cheap way to check. + */ + if(!option_values.test_only && !option_values.force_file_overwrite && grabbag__file_get_filesize(outfilename) != (off_t)(-1)) { + flac__utils_printf(stderr, 1, "ERROR: output file %s already exists, use -f to override\n", outfilename); + return 1; + } + + if(!option_values.test_only && !option_values.analyze) { + if(option_values.force_raw_format && (option_values.format_is_big_endian < 0 || option_values.format_is_unsigned_samples < 0)) + return usage_error("ERROR: for decoding to a raw file you must specify a value for --endian and --sign\n"); + } + + if(option_values.use_ogg) + treat_as_ogg = true; + else if(strlen(infilename) >= 4 && 0 == strcasecmp(infilename+(strlen(infilename)-4), ".ogg")) + treat_as_ogg = true; + else + treat_as_ogg = false; + +#ifndef FLAC__HAS_OGG + if(treat_as_ogg) { + flac__utils_printf(stderr, 1, "%s: Ogg support has not been built into this copy of flac\n", infilename); + return 1; + } +#endif + + if(!flac__utils_parse_skip_until_specification(option_values.skip_specification, &common_options.skip_specification) || common_options.skip_specification.is_relative) + return usage_error("ERROR: invalid value for --skip\n"); + + if(!flac__utils_parse_skip_until_specification(option_values.until_specification, &common_options.until_specification)) /*@@@ more checks: no + without --skip, no - unless known total_samples_to_{en,de}code */ + return usage_error("ERROR: invalid value for --until\n"); + /* if there is no "--until" we want to default to "--until=-0" */ + if(0 == option_values.until_specification) + common_options.until_specification.is_relative = true; + + if(option_values.cue_specification) { + if(!flac__utils_parse_cue_specification(option_values.cue_specification, &common_options.cue_specification)) + return usage_error("ERROR: invalid value for --cue\n"); + common_options.has_cue_specification = true; + } + else + common_options.has_cue_specification = false; + + common_options.continue_through_decode_errors = option_values.continue_through_decode_errors; + common_options.replaygain_synthesis_spec = option_values.replaygain_synthesis_spec; +#ifdef FLAC__HAS_OGG + common_options.is_ogg = treat_as_ogg; + common_options.use_first_serial_number = !option_values.has_serial_number; + common_options.serial_number = option_values.serial_number; +#endif + + if(!option_values.force_raw_format) { + wav_decode_options_t options; + + options.common = common_options; + + if( + option_values.force_aiff_format || + (strlen(outfilename) >= 4 && 0 == strcasecmp(outfilename+(strlen(outfilename)-4), ".aif")) || + (strlen(outfilename) >= 5 && 0 == strcasecmp(outfilename+(strlen(outfilename)-5), ".aiff")) + ) + retval = flac__decode_aiff(infilename, option_values.test_only? 0 : outfilename, option_values.analyze, option_values.aopts, options); + else + retval = flac__decode_wav(infilename, option_values.test_only? 0 : outfilename, option_values.analyze, option_values.aopts, options); + } + else { + raw_decode_options_t options; + + options.common = common_options; + options.is_big_endian = option_values.format_is_big_endian; + options.is_unsigned_samples = option_values.format_is_unsigned_samples; + + retval = flac__decode_raw(infilename, option_values.test_only? 0 : outfilename, option_values.analyze, option_values.aopts, options); + } + + if(retval == 0 && strcmp(infilename, "-")) { + if(strcmp(outfilename, "-")) + grabbag__file_copy_metadata(infilename, outfilename); + if(option_values.delete_input && !option_values.test_only && !option_values.analyze) + unlink(infilename); + } + + return retval; +} + +const char *get_encoded_outfilename(const char *infilename) +{ + const char *suffix = (option_values.use_ogg? ".ogg" : ".flac"); + return get_outfilename(infilename, suffix); +} + +const char *get_decoded_outfilename(const char *infilename) +{ + const char *suffix; + if(option_values.analyze) { + suffix = ".ana"; + } + else if(option_values.force_raw_format) { + suffix = ".raw"; + } + else if(option_values.force_aiff_format) { + suffix = ".aiff"; + } + else { + suffix = ".wav"; + } + return get_outfilename(infilename, suffix); +} + +const char *get_outfilename(const char *infilename, const char *suffix) +{ + if(0 == option_values.cmdline_forced_outfilename) { + static char buffer[4096]; /* @@@ bad MAGIC NUMBER */ + + if(0 == strcmp(infilename, "-") || option_values.force_to_stdout) { + strcpy(buffer, "-"); + } + else { + char *p; + if (flac__strlcpy(buffer, option_values.output_prefix? option_values.output_prefix : "", sizeof buffer) >= sizeof buffer) + return 0; + if (flac__strlcat(buffer, infilename, sizeof buffer) >= sizeof buffer) + return 0; + if(0 == (p = strrchr(buffer, '.'))) { + if (flac__strlcat(buffer, suffix, sizeof buffer) >= sizeof buffer) + return 0; + } + else { + if(0 == strcmp(p, suffix)) { + *p = '\0'; + if (flac__strlcat(buffer, "_new", sizeof buffer) >= sizeof buffer) + return 0; + } + else { + *p = '\0'; + } + if (flac__strlcat(buffer, suffix, sizeof buffer) >= sizeof buffer) + return 0; + } + } + return buffer; + } + else + return option_values.cmdline_forced_outfilename; +} + +void die(const char *message) +{ + FLAC__ASSERT(0 != message); + flac__utils_printf(stderr, 1, "ERROR: %s\n", message); + exit(1); +} + +char *local_strdup(const char *source) +{ + char *ret; + FLAC__ASSERT(0 != source); + if(0 == (ret = strdup(source))) + die("out of memory during strdup()"); + return ret; +} diff --git a/Libraries/FLAC/flac-src/src/flac/utils.c b/Libraries/FLAC/flac-src/src/flac/utils.c new file mode 100644 index 000000000..abfb32632 --- /dev/null +++ b/Libraries/FLAC/flac-src/src/flac/utils.c @@ -0,0 +1,271 @@ +/* flac - Command-line FLAC encoder/decoder + * Copyright (C) 2002,2003,2004,2005 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#if HAVE_CONFIG_H +# include +#endif + +#include "utils.h" +#include "FLAC/assert.h" +#include +#include +#include +#include + +int flac__utils_verbosity_ = 2; + +static FLAC__bool local__parse_uint64_(const char *s, FLAC__uint64 *value) +{ + FLAC__uint64 ret = 0; + char c; + + if(*s == '\0') + return false; + + while('\0' != (c = *s++)) + if(c >= '0' && c <= '9') + ret = ret * 10 + (c - '0'); + else + return false; + + *value = ret; + return true; +} + +static FLAC__bool local__parse_timecode_(const char *s, double *value) +{ + double ret; + unsigned i; + char c; + + /* parse [0-9][0-9]*: */ + c = *s++; + if(c >= '0' && c <= '9') + i = (c - '0'); + else + return false; + while(':' != (c = *s++)) { + if(c >= '0' && c <= '9') + i = i * 10 + (c - '0'); + else + return false; + } + ret = (double)i * 60.; + + /* parse [0-9]*[.]?[0-9]* i.e. a sign-less rational number */ + if(strspn(s, "1234567890.") != strlen(s)) + return false; + { + const char *p = strchr(s, '.'); + if(p && 0 != strchr(++p, '.')) + return false; + } + ret += atof(s); + + *value = ret; + return true; +} + +static FLAC__bool local__parse_cue_(const char *s, const char *end, unsigned *track, unsigned *index) +{ + FLAC__bool got_track = false, got_index = false; + unsigned t = 0, i = 0; + char c; + + while(end? s < end : *s != '\0') { + c = *s++; + if(c >= '0' && c <= '9') { + t = t * 10 + (c - '0'); + got_track = true; + } + else if(c == '.') + break; + else + return false; + } + while(end? s < end : *s != '\0') { + c = *s++; + if(c >= '0' && c <= '9') { + i = i * 10 + (c - '0'); + got_index = true; + } + else + return false; + } + *track = t; + *index = i; + return got_track && got_index; +} + +/* + * @@@ this only works with sorted cuesheets (the spec strongly recommends but + * does not require sorted cuesheets). but if it's not sorted, picking a + * nearest cue point has no significance. + */ +static FLAC__uint64 local__find_closest_cue_(const FLAC__StreamMetadata_CueSheet *cuesheet, unsigned track, unsigned index, FLAC__uint64 total_samples, FLAC__bool look_forward) +{ + int t, i; + if(look_forward) { + for(t = 0; t < (int)cuesheet->num_tracks; t++) + for(i = 0; i < (int)cuesheet->tracks[t].num_indices; i++) + if(cuesheet->tracks[t].number > track || (cuesheet->tracks[t].number == track && cuesheet->tracks[t].indices[i].number >= index)) + return cuesheet->tracks[t].offset + cuesheet->tracks[t].indices[i].offset; + return total_samples; + } + else { + for(t = (int)cuesheet->num_tracks - 1; t >= 0; t--) + for(i = (int)cuesheet->tracks[t].num_indices - 1; i >= 0; i--) + if(cuesheet->tracks[t].number < track || (cuesheet->tracks[t].number == track && cuesheet->tracks[t].indices[i].number <= index)) + return cuesheet->tracks[t].offset + cuesheet->tracks[t].indices[i].offset; + return 0; + } +} + +void flac__utils_printf(FILE *stream, int level, const char *format, ...) +{ + if(flac__utils_verbosity_ >= level) { + va_list args; + + FLAC__ASSERT(0 != format); + + va_start(args, format); + + (void) vfprintf(stream, format, args); + + va_end(args); + } +} + +#ifdef FLAC__VALGRIND_TESTING +size_t flac__utils_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) +{ + size_t ret = fwrite(ptr, size, nmemb, stream); + if(!ferror(stream)) + fflush(stream); + return ret; +} +#endif + +FLAC__bool flac__utils_parse_skip_until_specification(const char *s, utils__SkipUntilSpecification *spec) +{ + FLAC__uint64 val; + FLAC__bool is_negative = false; + + FLAC__ASSERT(0 != spec); + + spec->is_relative = false; + spec->value_is_samples = true; + spec->value.samples = 0; + + if(0 != s) { + if(s[0] == '-') { + is_negative = true; + spec->is_relative = true; + s++; + } + else if(s[0] == '+') { + spec->is_relative = true; + s++; + } + + if(local__parse_uint64_(s, &val)) { + spec->value_is_samples = true; + spec->value.samples = (FLAC__int64)val; + if(is_negative) + spec->value.samples = -(spec->value.samples); + } + else { + double d; + if(!local__parse_timecode_(s, &d)) + return false; + spec->value_is_samples = false; + spec->value.seconds = d; + if(is_negative) + spec->value.seconds = -(spec->value.seconds); + } + } + + return true; +} + +void flac__utils_canonicalize_skip_until_specification(utils__SkipUntilSpecification *spec, unsigned sample_rate) +{ + FLAC__ASSERT(0 != spec); + if(!spec->value_is_samples) { + spec->value.samples = (FLAC__int64)(spec->value.seconds * (double)sample_rate); + spec->value_is_samples = true; + } +} + +FLAC__bool flac__utils_parse_cue_specification(const char *s, utils__CueSpecification *spec) +{ + const char *start = s, *end = 0; + + FLAC__ASSERT(0 != spec); + + spec->has_start_point = spec->has_end_point = false; + + s = strchr(s, '-'); + + if(0 != s) { + if(s == start) + start = 0; + end = s+1; + if(*end == '\0') + end = 0; + } + + if(start) { + if(!local__parse_cue_(start, s, &spec->start_track, &spec->start_index)) + return false; + spec->has_start_point = true; + } + + if(end) { + if(!local__parse_cue_(end, 0, &spec->end_track, &spec->end_index)) + return false; + spec->has_end_point = true; + } + + return true; +} + +void flac__utils_canonicalize_cue_specification(const utils__CueSpecification *cue_spec, const FLAC__StreamMetadata_CueSheet *cuesheet, FLAC__uint64 total_samples, utils__SkipUntilSpecification *skip_spec, utils__SkipUntilSpecification *until_spec) +{ + FLAC__ASSERT(0 != cue_spec); + FLAC__ASSERT(0 != cuesheet); + FLAC__ASSERT(0 != total_samples); + FLAC__ASSERT(0 != skip_spec); + FLAC__ASSERT(0 != until_spec); + + skip_spec->is_relative = false; + skip_spec->value_is_samples = true; + + until_spec->is_relative = false; + until_spec->value_is_samples = true; + + if(cue_spec->has_start_point) + skip_spec->value.samples = local__find_closest_cue_(cuesheet, cue_spec->start_track, cue_spec->start_index, total_samples, /*look_forward=*/false); + else + skip_spec->value.samples = 0; + + if(cue_spec->has_end_point) + until_spec->value.samples = local__find_closest_cue_(cuesheet, cue_spec->end_track, cue_spec->end_index, total_samples, /*look_forward=*/true); + else + until_spec->value.samples = total_samples; +} diff --git a/Libraries/FLAC/flac-src/src/flac/utils.h b/Libraries/FLAC/flac-src/src/flac/utils.h new file mode 100644 index 000000000..def058502 --- /dev/null +++ b/Libraries/FLAC/flac-src/src/flac/utils.h @@ -0,0 +1,56 @@ +/* flac - Command-line FLAC encoder/decoder + * Copyright (C) 2002,2003,2004,2005 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef flac__utils_h +#define flac__utils_h + +#include "FLAC/ordinals.h" +#include "FLAC/format.h" /* for FLAC__StreamMetadata_CueSheet */ +#include /* for FILE */ + +typedef struct { + FLAC__bool is_relative; /* i.e. specification string started with + or - */ + FLAC__bool value_is_samples; + union { + double seconds; + FLAC__int64 samples; + } value; +} utils__SkipUntilSpecification; + +typedef struct { + FLAC__bool has_start_point, has_end_point; + unsigned start_track, start_index; + unsigned end_track, end_index; +} utils__CueSpecification; + +#ifdef FLAC__VALGRIND_TESTING +size_t flac__utils_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); +#else +#define flac__utils_fwrite fwrite +#endif + +extern int flac__utils_verbosity_; +void flac__utils_printf(FILE *stream, int level, const char *format, ...); + +FLAC__bool flac__utils_parse_skip_until_specification(const char *s, utils__SkipUntilSpecification *spec); +void flac__utils_canonicalize_skip_until_specification(utils__SkipUntilSpecification *spec, unsigned sample_rate); + +FLAC__bool flac__utils_parse_cue_specification(const char *s, utils__CueSpecification *spec); +void flac__utils_canonicalize_cue_specification(const utils__CueSpecification *cue_spec, const FLAC__StreamMetadata_CueSheet *cuesheet, FLAC__uint64 total_samples, utils__SkipUntilSpecification *skip_spec, utils__SkipUntilSpecification *until_spec); + +#endif diff --git a/Libraries/FLAC/flac-src/src/flac/vorbiscomment.c b/Libraries/FLAC/flac-src/src/flac/vorbiscomment.c new file mode 100644 index 000000000..b2025ce46 --- /dev/null +++ b/Libraries/FLAC/flac-src/src/flac/vorbiscomment.c @@ -0,0 +1,177 @@ +/* flac - Command-line FLAC encoder/decoder + * Copyright (C) 2002,2003,2004,2005 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#if HAVE_CONFIG_H +# include +#endif + +#include "vorbiscomment.h" +#include "FLAC/assert.h" +#include "FLAC/metadata.h" +#include "share/utf8.h" +#include +#include +#include +#include + + +/* + * This struct and the following 4 static functions are copied from + * ../metaflac/main.c. Maybe someday there will be a convenience + * library for Vorbis comment parsing. + */ +typedef struct { + char *field; /* the whole field as passed on the command line, i.e. "NAME=VALUE" */ + char *field_name; + /* according to the vorbis spec, field values can contain \0 so simple C strings are not enough here */ + unsigned field_value_length; + char *field_value; +} Argument_VcField; + +static void die(const char *message) +{ + FLAC__ASSERT(0 != message); + fprintf(stderr, "ERROR: %s\n", message); + exit(1); +} + +static char *local_strdup(const char *source) +{ + char *ret; + FLAC__ASSERT(0 != source); + if(0 == (ret = strdup(source))) + die("out of memory during strdup()"); + return ret; +} + +static FLAC__bool parse_vorbis_comment_field(const char *field_ref, char **field, char **name, char **value, unsigned *length, const char **violation) +{ + static const char * const violations[] = { + "field name contains invalid character", + "field contains no '=' character" + }; + + char *p, *q, *s; + + if(0 != field) + *field = local_strdup(field_ref); + + s = local_strdup(field_ref); + + if(0 == (p = strchr(s, '='))) { + free(s); + *violation = violations[1]; + return false; + } + *p++ = '\0'; + + for(q = s; *q; q++) { + if(*q < 0x20 || *q > 0x7d || *q == 0x3d) { + free(s); + *violation = violations[0]; + return false; + } + } + + *name = local_strdup(s); + *value = local_strdup(p); + *length = strlen(p); + + free(s); + return true; +} + +/* slight modification: no 'filename' arg, and errors are passed back in 'violation' instead of printed to stderr */ +static FLAC__bool set_vc_field(FLAC__StreamMetadata *block, const Argument_VcField *field, FLAC__bool *needs_write, FLAC__bool raw, const char **violation) +{ + FLAC__StreamMetadata_VorbisComment_Entry entry; + char *converted; + FLAC__bool needs_free = false; + + FLAC__ASSERT(0 != block); + FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT); + FLAC__ASSERT(0 != field); + FLAC__ASSERT(0 != needs_write); + + if(raw) { + entry.entry = (FLAC__byte *)field->field; + } + else if(utf8_encode(field->field, &converted) >= 0) { + entry.entry = (FLAC__byte *)converted; + needs_free = true; + } + else { + *violation = "couldn't convert comment to UTF-8"; + return false; + } + + entry.length = strlen((const char *)entry.entry); + + if(!FLAC__metadata_object_vorbiscomment_append_comment(block, entry, /*copy=*/true)) { + if(needs_free) + free(converted); + *violation = "memory allocation failure"; + return false; + } + else { + *needs_write = true; + if(needs_free) + free(converted); + return true; + } +} + +/* + * The rest of the code is novel + */ + +static void free_field(Argument_VcField *obj) +{ + if(0 != obj->field) + free(obj->field); + if(0 != obj->field_name) + free(obj->field_name); + if(0 != obj->field_value) + free(obj->field_value); +} + +FLAC__bool flac__vorbiscomment_add(FLAC__StreamMetadata *block, const char *comment, const char **violation) +{ + Argument_VcField parsed; + FLAC__bool dummy; + + FLAC__ASSERT(0 != block); + FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT); + FLAC__ASSERT(0 != comment); + + memset(&parsed, 0, sizeof(parsed)); + + if(!parse_vorbis_comment_field(comment, &(parsed.field), &(parsed.field_name), &(parsed.field_value), &(parsed.field_value_length), violation)) { + free_field(&parsed); + return false; + } + + if(!set_vc_field(block, &parsed, &dummy, /*raw=*/false, violation)) { + free_field(&parsed); + return false; + } + else { + free_field(&parsed); + return true; + } +} diff --git a/Libraries/FLAC/flac-src/src/flac/vorbiscomment.h b/Libraries/FLAC/flac-src/src/flac/vorbiscomment.h new file mode 100644 index 000000000..be2bddcff --- /dev/null +++ b/Libraries/FLAC/flac-src/src/flac/vorbiscomment.h @@ -0,0 +1,26 @@ +/* flac - Command-line FLAC encoder/decoder + * Copyright (C) 2002,2003,2004,2005 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef flac__vorbiscomment_h +#define flac__vorbiscomment_h + +#include "FLAC/metadata.h" + +FLAC__bool flac__vorbiscomment_add(FLAC__StreamMetadata *block, const char *comment, const char **violation); + +#endif