mirror of
https://github.com/claunia/cuetools.net.git
synced 2025-12-16 18:14:25 +00:00
initial checkin
This commit is contained in:
22
flac/src/share/Makefile.am
Normal file
22
flac/src/share/Makefile.am
Normal file
@@ -0,0 +1,22 @@
|
||||
# FLAC - Free Lossless Audio Codec
|
||||
# Copyright (C) 2002,2003,2004,2005,2006,2007,2008 Josh Coalson
|
||||
#
|
||||
# This file is part the FLAC project. FLAC is comprised of several
|
||||
# components distributed under difference licenses. The codec libraries
|
||||
# are distributed under Xiph.Org's BSD-like license (see the file
|
||||
# COPYING.Xiph in this distribution). All other programs, libraries, and
|
||||
# plugins are distributed under the GPL (see COPYING.GPL). The documentation
|
||||
# is distributed under the Gnu FDL (see COPYING.FDL). Each file in the
|
||||
# FLAC distribution contains at the top the terms under which it may be
|
||||
# distributed.
|
||||
#
|
||||
# Since this particular file is relevant to all components of FLAC,
|
||||
# it may be distributed under the Xiph.Org license, which is the least
|
||||
# restrictive of those mentioned above. See the file COPYING.Xiph in this
|
||||
# distribution.
|
||||
|
||||
SUBDIRS = getopt replaygain_analysis replaygain_synthesis grabbag utf8
|
||||
|
||||
EXTRA_DIST = \
|
||||
Makefile.lite \
|
||||
README
|
||||
53
flac/src/share/Makefile.lite
Normal file
53
flac/src/share/Makefile.lite
Normal file
@@ -0,0 +1,53 @@
|
||||
# FLAC - Free Lossless Audio Codec
|
||||
# Copyright (C) 2001,2002,2003,2004,2005,2006,2007,2008 Josh Coalson
|
||||
#
|
||||
# This file is part the FLAC project. FLAC is comprised of several
|
||||
# components distributed under difference licenses. The codec libraries
|
||||
# are distributed under Xiph.Org's BSD-like license (see the file
|
||||
# COPYING.Xiph in this distribution). All other programs, libraries, and
|
||||
# plugins are distributed under the GPL (see COPYING.GPL). The documentation
|
||||
# is distributed under the Gnu FDL (see COPYING.FDL). Each file in the
|
||||
# FLAC distribution contains at the top the terms under which it may be
|
||||
# distributed.
|
||||
#
|
||||
# Since this particular file is relevant to all components of FLAC,
|
||||
# it may be distributed under the Xiph.Org license, which is the least
|
||||
# restrictive of those mentioned above. See the file COPYING.Xiph in this
|
||||
# distribution.
|
||||
|
||||
.PHONY: all getopt grabbag replaygain_analysis replaygain_synthesis utf8
|
||||
all: getopt grabbag replaygain_analysis replaygain_synthesis utf8
|
||||
|
||||
DEFAULT_CONFIG = release
|
||||
|
||||
CONFIG = $(DEFAULT_CONFIG)
|
||||
|
||||
debug : CONFIG = debug
|
||||
valgrind: CONFIG = valgrind
|
||||
release : CONFIG = release
|
||||
|
||||
debug : all
|
||||
valgrind: all
|
||||
release : all
|
||||
|
||||
getopt:
|
||||
(cd $@ ; $(MAKE) -f Makefile.lite $(CONFIG))
|
||||
|
||||
grabbag:
|
||||
(cd $@ ; $(MAKE) -f Makefile.lite $(CONFIG))
|
||||
|
||||
replaygain_analysis:
|
||||
(cd $@ ; $(MAKE) -f Makefile.lite $(CONFIG))
|
||||
|
||||
replaygain_synthesis:
|
||||
(cd $@ ; $(MAKE) -f Makefile.lite $(CONFIG))
|
||||
|
||||
utf8:
|
||||
(cd $@ ; $(MAKE) -f Makefile.lite $(CONFIG))
|
||||
|
||||
clean:
|
||||
-(cd getopt ; $(MAKE) -f Makefile.lite clean)
|
||||
-(cd grabbag ; $(MAKE) -f Makefile.lite clean)
|
||||
-(cd replaygain_analysis ; $(MAKE) -f Makefile.lite clean)
|
||||
-(cd replaygain_synthesis ; $(MAKE) -f Makefile.lite clean)
|
||||
-(cd utf8 ; $(MAKE) -f Makefile.lite clean)
|
||||
5
flac/src/share/README
Normal file
5
flac/src/share/README
Normal file
@@ -0,0 +1,5 @@
|
||||
This directory contains several convenience libraries used by the rest of the
|
||||
tools and plugins. Two of them (getopt and utf8) are shamelessly copied from
|
||||
vorbistools, one for manipulating UTF-8 strings (GPL) and one for implementing
|
||||
getopt (LGPL). libFLAC does not link to either; the only FLAC tools that do
|
||||
are GPL'ed.
|
||||
20
flac/src/share/getopt/Makefile.am
Normal file
20
flac/src/share/getopt/Makefile.am
Normal file
@@ -0,0 +1,20 @@
|
||||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/include/share
|
||||
|
||||
noinst_LIBRARIES = libgetopt.a
|
||||
|
||||
libgetopt_a_SOURCES = getopt.c getopt1.c
|
||||
|
||||
EXTRA_DIST = \
|
||||
Makefile.lite \
|
||||
getopt_static.dsp \
|
||||
getopt_static.vcproj
|
||||
|
||||
debug:
|
||||
$(MAKE) all CFLAGS="@DEBUG@"
|
||||
|
||||
profile:
|
||||
$(MAKE) all CFLAGS="@PROFILE@"
|
||||
16
flac/src/share/getopt/Makefile.lite
Normal file
16
flac/src/share/getopt/Makefile.lite
Normal file
@@ -0,0 +1,16 @@
|
||||
#
|
||||
# GNU makefile
|
||||
#
|
||||
|
||||
topdir = ../../..
|
||||
|
||||
LIB_NAME = libgetopt
|
||||
INCLUDES = -I$(topdir)/include -I$(topdir)/include/share
|
||||
|
||||
SRCS_C = \
|
||||
getopt.c \
|
||||
getopt1.c
|
||||
|
||||
include $(topdir)/build/lib.mk
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
1065
flac/src/share/getopt/getopt.c
Normal file
1065
flac/src/share/getopt/getopt.c
Normal file
File diff suppressed because it is too large
Load Diff
204
flac/src/share/getopt/getopt1.c
Normal file
204
flac/src/share/getopt/getopt1.c
Normal file
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
NOTE:
|
||||
I cannot get the vanilla getopt code to work (i.e. compile only what
|
||||
is needed and not duplicate symbols found in the standard library)
|
||||
on all the platforms that FLAC supports. In particular the gating
|
||||
of code with the ELIDE_CODE #define is not accurate enough on systems
|
||||
that are POSIX but not glibc. If someone has a patch that works on
|
||||
GNU/Linux, Darwin, AND Solaris please submit it on the project page:
|
||||
http://sourceforge.net/projects/flac
|
||||
|
||||
In the meantime I have munged the global symbols and removed gates
|
||||
around code, while at the same time trying to touch the original as
|
||||
little as possible.
|
||||
*/
|
||||
/* getopt_long and getopt_long_only entry points for GNU getopt.
|
||||
Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98
|
||||
Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "share/getopt.h"
|
||||
/*[JEC] was:#include "getopt.h"*/
|
||||
|
||||
#if !defined __STDC__ || !__STDC__
|
||||
/* This is a separate conditional since some stdc systems
|
||||
reject `defined (const)'. */
|
||||
#ifndef const
|
||||
#define const
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* Comment out all this code if we are using the GNU C Library, and are not
|
||||
actually compiling the library itself. This code is part of the GNU C
|
||||
Library, but also included in many other GNU distributions. Compiling
|
||||
and linking in this code is a waste when using the GNU C library
|
||||
(especially if it is a shared library). Rather than having every GNU
|
||||
program understand `configure --with-gnu-libc' and omit the object files,
|
||||
it is simpler to just do this in the source for each such file. */
|
||||
|
||||
#define GETOPT_INTERFACE_VERSION 2
|
||||
#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
|
||||
#include <gnu-versions.h>
|
||||
#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
|
||||
#define ELIDE_CODE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
/*[JEC] was:#ifndef ELIDE_CODE*/
|
||||
|
||||
|
||||
/* This needs to come after some library #include
|
||||
to get __GNU_LIBRARY__ defined. */
|
||||
#ifdef __GNU_LIBRARY__
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
int
|
||||
share__getopt_long (argc, argv, options, long_options, opt_index)
|
||||
int argc;
|
||||
char *const *argv;
|
||||
const char *options;
|
||||
const struct share__option *long_options;
|
||||
int *opt_index;
|
||||
{
|
||||
return share___getopt_internal (argc, argv, options, long_options, opt_index, 0);
|
||||
}
|
||||
|
||||
/* Like share__getopt_long, but '-' as well as '--' can indicate a long option.
|
||||
If an option that starts with '-' (not '--') doesn't match a long option,
|
||||
but does match a short option, it is parsed as a short option
|
||||
instead. */
|
||||
|
||||
int
|
||||
share__getopt_long_only (argc, argv, options, long_options, opt_index)
|
||||
int argc;
|
||||
char *const *argv;
|
||||
const char *options;
|
||||
const struct share__option *long_options;
|
||||
int *opt_index;
|
||||
{
|
||||
return share___getopt_internal (argc, argv, options, long_options, opt_index, 1);
|
||||
}
|
||||
|
||||
|
||||
#endif /* Not ELIDE_CODE. */
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int
|
||||
main (argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int c;
|
||||
int digit_optind = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
int this_option_optind = share__optind ? share__optind : 1;
|
||||
int option_index = 0;
|
||||
static struct share__option long_options[] =
|
||||
{
|
||||
{"add", 1, 0, 0},
|
||||
{"append", 0, 0, 0},
|
||||
{"delete", 1, 0, 0},
|
||||
{"verbose", 0, 0, 0},
|
||||
{"create", 0, 0, 0},
|
||||
{"file", 1, 0, 0},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
c = share__getopt_long (argc, argv, "abc:d:0123456789",
|
||||
long_options, &option_index);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 0:
|
||||
printf ("option %s", long_options[option_index].name);
|
||||
if (share__optarg)
|
||||
printf (" with arg %s", share__optarg);
|
||||
printf ("\n");
|
||||
break;
|
||||
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
if (digit_optind != 0 && digit_optind != this_option_optind)
|
||||
printf ("digits occur in two different argv-elements.\n");
|
||||
digit_optind = this_option_optind;
|
||||
printf ("option %c\n", c);
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
printf ("option a\n");
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
printf ("option b\n");
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
printf ("option c with value `%s'\n", share__optarg);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
printf ("option d with value `%s'\n", share__optarg);
|
||||
break;
|
||||
|
||||
case '?':
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("?? getopt returned character code 0%o ??\n", c);
|
||||
}
|
||||
}
|
||||
|
||||
if (share__optind < argc)
|
||||
{
|
||||
printf ("non-option ARGV-elements: ");
|
||||
while (share__optind < argc)
|
||||
printf ("%s ", argv[share__optind++]);
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
exit (0);
|
||||
}
|
||||
|
||||
#endif /* TEST */
|
||||
112
flac/src/share/getopt/getopt_static.dsp
Normal file
112
flac/src/share/getopt/getopt_static.dsp
Normal file
@@ -0,0 +1,112 @@
|
||||
# Microsoft Developer Studio Project File - Name="getopt_static" - Package Owner=<4>
|
||||
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
|
||||
|
||||
# TARGTYPE "Win32 (x86) Static Library" 0x0104
|
||||
|
||||
|
||||
|
||||
CFG=getopt_static - 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 "getopt_static.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 "getopt_static.mak" CFG="getopt_static - Win32 Debug"
|
||||
|
||||
!MESSAGE
|
||||
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
|
||||
!MESSAGE
|
||||
|
||||
!MESSAGE "getopt_static - Win32 Release" (based on "Win32 (x86) Static Library")
|
||||
|
||||
!MESSAGE "getopt_static - Win32 Debug" (based on "Win32 (x86) Static Library")
|
||||
|
||||
!MESSAGE
|
||||
|
||||
|
||||
|
||||
# Begin Project
|
||||
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
|
||||
# PROP Scc_ProjName "getopt"
|
||||
|
||||
# PROP Scc_LocalPath "..\..\.."
|
||||
|
||||
CPP=cl.exe
|
||||
|
||||
RSC=rc.exe
|
||||
|
||||
|
||||
|
||||
!IF "$(CFG)" == "getopt_static - 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\lib"
|
||||
|
||||
# PROP Intermediate_Dir "Release_static"
|
||||
|
||||
# PROP Target_Dir ""
|
||||
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /I ".\include" /I "..\..\..\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
|
||||
BSC32=bscmake.exe
|
||||
|
||||
# ADD BASE BSC32 /nologo
|
||||
|
||||
# ADD BSC32 /nologo
|
||||
|
||||
LIB32=link.exe -lib
|
||||
|
||||
# ADD BASE LIB32 /nologo
|
||||
|
||||
# ADD LIB32 /nologo /nodefaultlib
|
||||
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "getopt_static - Win32 Debug"
|
||||
|
||||
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
|
||||
322
flac/src/share/getopt/getopt_static.vcproj
Normal file
322
flac/src/share/getopt/getopt_static.vcproj
Normal file
@@ -0,0 +1,322 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8,00"
|
||||
Name="getopt_static"
|
||||
ProjectGUID="{4cefbc80-c215-11db-8314-0800200c9a66}"
|
||||
RootNamespace="getopt_static"
|
||||
Keyword="Win32Proj"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
<Platform
|
||||
Name="x64"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="..\..\..\obj\debug\lib"
|
||||
IntermediateDirectory="Debug_static"
|
||||
ConfigurationType="4"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=".\include;..\..\..\include"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;FLAC__NO_DLL;DEBUG"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="4"
|
||||
CompileAs="0"
|
||||
DisableSpecificWarnings="4267;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="..\..\..\obj\debug\lib\$(ProjectName).lib"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="..\..\..\obj\release\lib"
|
||||
IntermediateDirectory="Release_static"
|
||||
ConfigurationType="4"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
EnableIntrinsicFunctions="true"
|
||||
FavorSizeOrSpeed="1"
|
||||
OmitFramePointers="true"
|
||||
WholeProgramOptimization="true"
|
||||
AdditionalIncludeDirectories=".\include;..\..\..\include"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;FLAC__NO_DLL"
|
||||
RuntimeLibrary="0"
|
||||
BufferSecurityCheck="false"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"
|
||||
DisableSpecificWarnings="4267;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="..\..\..\obj\release\lib\$(ProjectName).lib"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug|x64"
|
||||
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TargetEnvironment="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=".\include;..\..\..\include"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;FLAC__NO_DLL;DEBUG"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"
|
||||
DisableSpecificWarnings="4267;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="..\..\..\obj\debug\lib\$(ProjectName).lib"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|x64"
|
||||
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TargetEnvironment="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
EnableIntrinsicFunctions="true"
|
||||
FavorSizeOrSpeed="1"
|
||||
OmitFramePointers="true"
|
||||
WholeProgramOptimization="true"
|
||||
AdditionalIncludeDirectories=".\include;..\..\..\include"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;FLAC__NO_DLL"
|
||||
RuntimeLibrary="0"
|
||||
BufferSecurityCheck="false"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"
|
||||
DisableSpecificWarnings="4267;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="..\..\..\obj\release\lib\$(ProjectName).lib"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\getopt.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\getopt1.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Public Header Files"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\..\include\share\getopt.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
25
flac/src/share/grabbag/Makefile.am
Normal file
25
flac/src/share/grabbag/Makefile.am
Normal file
@@ -0,0 +1,25 @@
|
||||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/include
|
||||
|
||||
noinst_LTLIBRARIES = libgrabbag.la
|
||||
|
||||
libgrabbag_la_SOURCES = \
|
||||
cuesheet.c \
|
||||
file.c \
|
||||
picture.c \
|
||||
replaygain.c \
|
||||
seektable.c
|
||||
|
||||
EXTRA_DIST = \
|
||||
Makefile.lite \
|
||||
grabbag_static.dsp \
|
||||
grabbag_static.vcproj
|
||||
|
||||
debug:
|
||||
$(MAKE) all CFLAGS="@DEBUG@"
|
||||
|
||||
profile:
|
||||
$(MAKE) all CFLAGS="@PROFILE@"
|
||||
19
flac/src/share/grabbag/Makefile.lite
Normal file
19
flac/src/share/grabbag/Makefile.lite
Normal file
@@ -0,0 +1,19 @@
|
||||
#
|
||||
# GNU makefile
|
||||
#
|
||||
|
||||
topdir = ../../..
|
||||
|
||||
LIB_NAME = libgrabbag
|
||||
INCLUDES = -I$(topdir)/include
|
||||
|
||||
SRCS_C = \
|
||||
cuesheet.c \
|
||||
file.c \
|
||||
picture.c \
|
||||
replaygain.c \
|
||||
seektable.c
|
||||
|
||||
include $(topdir)/build/lib.mk
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
611
flac/src/share/grabbag/cuesheet.c
Normal file
611
flac/src/share/grabbag/cuesheet.c
Normal file
@@ -0,0 +1,611 @@
|
||||
/* grabbag - Convenience lib for various routines common to several tools
|
||||
* Copyright (C) 2002,2003,2004,2005,2006,2007,2008 Josh Coalson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "share/grabbag.h"
|
||||
#include "FLAC/assert.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
unsigned grabbag__cuesheet_msf_to_frame(unsigned minutes, unsigned seconds, unsigned frames)
|
||||
{
|
||||
return ((minutes * 60) + seconds) * 75 + frames;
|
||||
}
|
||||
|
||||
void grabbag__cuesheet_frame_to_msf(unsigned frame, unsigned *minutes, unsigned *seconds, unsigned *frames)
|
||||
{
|
||||
*frames = frame % 75;
|
||||
frame /= 75;
|
||||
*seconds = frame % 60;
|
||||
frame /= 60;
|
||||
*minutes = frame;
|
||||
}
|
||||
|
||||
/* since we only care about values >= 0 or error, returns < 0 for any illegal string, else value */
|
||||
static int local__parse_int_(const char *s)
|
||||
{
|
||||
int ret = 0;
|
||||
char c;
|
||||
|
||||
if(*s == '\0')
|
||||
return -1;
|
||||
|
||||
while('\0' != (c = *s++))
|
||||
if(c >= '0' && c <= '9')
|
||||
ret = ret * 10 + (c - '0');
|
||||
else
|
||||
return -1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* since we only care about values >= 0 or error, returns < 0 for any illegal string, else value */
|
||||
static FLAC__int64 local__parse_int64_(const char *s)
|
||||
{
|
||||
FLAC__int64 ret = 0;
|
||||
char c;
|
||||
|
||||
if(*s == '\0')
|
||||
return -1;
|
||||
|
||||
while('\0' != (c = *s++))
|
||||
if(c >= '0' && c <= '9')
|
||||
ret = ret * 10 + (c - '0');
|
||||
else
|
||||
return -1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* accept '[0-9]+:[0-9][0-9]?:[0-9][0-9]?', but max second of 59 and max frame of 74, e.g. 0:0:0, 123:45:67
|
||||
* return sample number or <0 for error
|
||||
*/
|
||||
static FLAC__int64 local__parse_msf_(const char *s)
|
||||
{
|
||||
FLAC__int64 ret, field;
|
||||
char c;
|
||||
|
||||
c = *s++;
|
||||
if(c >= '0' && c <= '9')
|
||||
field = (c - '0');
|
||||
else
|
||||
return -1;
|
||||
while(':' != (c = *s++)) {
|
||||
if(c >= '0' && c <= '9')
|
||||
field = field * 10 + (c - '0');
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = field * 60 * 44100;
|
||||
|
||||
c = *s++;
|
||||
if(c >= '0' && c <= '9')
|
||||
field = (c - '0');
|
||||
else
|
||||
return -1;
|
||||
if(':' != (c = *s++)) {
|
||||
if(c >= '0' && c <= '9') {
|
||||
field = field * 10 + (c - '0');
|
||||
c = *s++;
|
||||
if(c != ':')
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(field >= 60)
|
||||
return -1;
|
||||
|
||||
ret += field * 44100;
|
||||
|
||||
c = *s++;
|
||||
if(c >= '0' && c <= '9')
|
||||
field = (c - '0');
|
||||
else
|
||||
return -1;
|
||||
if('\0' != (c = *s++)) {
|
||||
if(c >= '0' && c <= '9') {
|
||||
field = field * 10 + (c - '0');
|
||||
c = *s++;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(c != '\0')
|
||||
return -1;
|
||||
|
||||
if(field >= 75)
|
||||
return -1;
|
||||
|
||||
ret += field * (44100 / 75);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char *local__get_field_(char **s, FLAC__bool allow_quotes)
|
||||
{
|
||||
FLAC__bool has_quote = false;
|
||||
char *p;
|
||||
|
||||
FLAC__ASSERT(0 != s);
|
||||
|
||||
if(0 == *s)
|
||||
return 0;
|
||||
|
||||
/* skip leading whitespace */
|
||||
while(**s && 0 != strchr(" \t\r\n", **s))
|
||||
(*s)++;
|
||||
|
||||
if(**s == 0) {
|
||||
*s = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(allow_quotes && (**s == '"')) {
|
||||
has_quote = true;
|
||||
(*s)++;
|
||||
if(**s == 0) {
|
||||
*s = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
p = *s;
|
||||
|
||||
if(has_quote) {
|
||||
*s = strchr(*s, '\"');
|
||||
/* if there is no matching end quote, it's an error */
|
||||
if(0 == *s)
|
||||
p = *s = 0;
|
||||
else {
|
||||
**s = '\0';
|
||||
(*s)++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
while(**s && 0 == strchr(" \t\r\n", **s))
|
||||
(*s)++;
|
||||
if(**s) {
|
||||
**s = '\0';
|
||||
(*s)++;
|
||||
}
|
||||
else
|
||||
*s = 0;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static FLAC__bool local__cuesheet_parse_(FILE *file, const char **error_message, unsigned *last_line_read, FLAC__StreamMetadata *cuesheet, FLAC__bool is_cdda, FLAC__uint64 lead_out_offset)
|
||||
{
|
||||
#if defined _MSC_VER || defined __MINGW32__ || defined __EMX__
|
||||
#define FLAC__STRCASECMP stricmp
|
||||
#else
|
||||
#define FLAC__STRCASECMP strcasecmp
|
||||
#endif
|
||||
char buffer[4096], *line, *field;
|
||||
unsigned forced_leadout_track_num = 0;
|
||||
FLAC__uint64 forced_leadout_track_offset = 0;
|
||||
int in_track_num = -1, in_index_num = -1;
|
||||
FLAC__bool disc_has_catalog = false, track_has_flags = false, track_has_isrc = false, has_forced_leadout = false;
|
||||
FLAC__StreamMetadata_CueSheet *cs = &cuesheet->data.cue_sheet;
|
||||
|
||||
cs->lead_in = is_cdda? 2 * 44100 /* The default lead-in size for CD-DA */ : 0;
|
||||
cs->is_cd = is_cdda;
|
||||
|
||||
while(0 != fgets(buffer, sizeof(buffer), file)) {
|
||||
(*last_line_read)++;
|
||||
line = buffer;
|
||||
|
||||
{
|
||||
size_t linelen = strlen(line);
|
||||
if((linelen == sizeof(buffer)-1) && line[linelen-1] != '\n') {
|
||||
*error_message = "line too long";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(0 != (field = local__get_field_(&line, /*allow_quotes=*/false))) {
|
||||
if(0 == FLAC__STRCASECMP(field, "CATALOG")) {
|
||||
if(disc_has_catalog) {
|
||||
*error_message = "found multiple CATALOG commands";
|
||||
return false;
|
||||
}
|
||||
if(0 == (field = local__get_field_(&line, /*allow_quotes=*/true))) {
|
||||
*error_message = "CATALOG is missing catalog number";
|
||||
return false;
|
||||
}
|
||||
if(strlen(field) >= sizeof(cs->media_catalog_number)) {
|
||||
*error_message = "CATALOG number is too long";
|
||||
return false;
|
||||
}
|
||||
if(is_cdda && (strlen(field) != 13 || strspn(field, "0123456789") != 13)) {
|
||||
*error_message = "CD-DA CATALOG number must be 13 decimal digits";
|
||||
return false;
|
||||
}
|
||||
strcpy(cs->media_catalog_number, field);
|
||||
disc_has_catalog = true;
|
||||
}
|
||||
else if(0 == FLAC__STRCASECMP(field, "FLAGS")) {
|
||||
if(track_has_flags) {
|
||||
*error_message = "found multiple FLAGS commands";
|
||||
return false;
|
||||
}
|
||||
if(in_track_num < 0 || in_index_num >= 0) {
|
||||
*error_message = "FLAGS command must come after TRACK but before INDEX";
|
||||
return false;
|
||||
}
|
||||
while(0 != (field = local__get_field_(&line, /*allow_quotes=*/false))) {
|
||||
if(0 == FLAC__STRCASECMP(field, "PRE"))
|
||||
cs->tracks[cs->num_tracks-1].pre_emphasis = 1;
|
||||
}
|
||||
track_has_flags = true;
|
||||
}
|
||||
else if(0 == FLAC__STRCASECMP(field, "INDEX")) {
|
||||
FLAC__int64 xx;
|
||||
FLAC__StreamMetadata_CueSheet_Track *track = &cs->tracks[cs->num_tracks-1];
|
||||
if(in_track_num < 0) {
|
||||
*error_message = "found INDEX before any TRACK";
|
||||
return false;
|
||||
}
|
||||
if(0 == (field = local__get_field_(&line, /*allow_quotes=*/false))) {
|
||||
*error_message = "INDEX is missing index number";
|
||||
return false;
|
||||
}
|
||||
in_index_num = local__parse_int_(field);
|
||||
if(in_index_num < 0) {
|
||||
*error_message = "INDEX has invalid index number";
|
||||
return false;
|
||||
}
|
||||
FLAC__ASSERT(cs->num_tracks > 0);
|
||||
if(track->num_indices == 0) {
|
||||
/* it's the first index point of the track */
|
||||
if(in_index_num > 1) {
|
||||
*error_message = "first INDEX number of a TRACK must be 0 or 1";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(in_index_num != track->indices[track->num_indices-1].number + 1) {
|
||||
*error_message = "INDEX numbers must be sequential";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(is_cdda && in_index_num > 99) {
|
||||
*error_message = "CD-DA INDEX number must be between 0 and 99, inclusive";
|
||||
return false;
|
||||
}
|
||||
/*@@@ search for duplicate track number? */
|
||||
if(0 == (field = local__get_field_(&line, /*allow_quotes=*/false))) {
|
||||
*error_message = "INDEX is missing an offset after the index number";
|
||||
return false;
|
||||
}
|
||||
xx = local__parse_msf_(field);
|
||||
if(xx < 0) {
|
||||
if(is_cdda) {
|
||||
*error_message = "illegal INDEX offset (not of the form MM:SS:FF)";
|
||||
return false;
|
||||
}
|
||||
xx = local__parse_int64_(field);
|
||||
if(xx < 0) {
|
||||
*error_message = "illegal INDEX offset";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(is_cdda && cs->num_tracks == 1 && cs->tracks[0].num_indices == 0 && xx != 0) {
|
||||
*error_message = "first INDEX of first TRACK must have an offset of 00:00:00";
|
||||
return false;
|
||||
}
|
||||
if(is_cdda && track->num_indices > 0 && (FLAC__uint64)xx <= track->indices[track->num_indices-1].offset) {
|
||||
*error_message = "CD-DA INDEX offsets must increase in time";
|
||||
return false;
|
||||
}
|
||||
/* fill in track offset if it's the first index of the track */
|
||||
if(track->num_indices == 0)
|
||||
track->offset = (FLAC__uint64)xx;
|
||||
if(is_cdda && cs->num_tracks > 1) {
|
||||
const FLAC__StreamMetadata_CueSheet_Track *prev = &cs->tracks[cs->num_tracks-2];
|
||||
if((FLAC__uint64)xx <= prev->offset + prev->indices[prev->num_indices-1].offset) {
|
||||
*error_message = "CD-DA INDEX offsets must increase in time";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(!FLAC__metadata_object_cuesheet_track_insert_blank_index(cuesheet, cs->num_tracks-1, track->num_indices)) {
|
||||
*error_message = "memory allocation error";
|
||||
return false;
|
||||
}
|
||||
track->indices[track->num_indices-1].offset = (FLAC__uint64)xx - track->offset;
|
||||
track->indices[track->num_indices-1].number = in_index_num;
|
||||
}
|
||||
else if(0 == FLAC__STRCASECMP(field, "ISRC")) {
|
||||
char *l, *r;
|
||||
if(track_has_isrc) {
|
||||
*error_message = "found multiple ISRC commands";
|
||||
return false;
|
||||
}
|
||||
if(in_track_num < 0 || in_index_num >= 0) {
|
||||
*error_message = "ISRC command must come after TRACK but before INDEX";
|
||||
return false;
|
||||
}
|
||||
if(0 == (field = local__get_field_(&line, /*allow_quotes=*/false))) {
|
||||
*error_message = "ISRC is missing ISRC number";
|
||||
return false;
|
||||
}
|
||||
/* strip out dashes */
|
||||
for(l = r = field; *r; r++) {
|
||||
if(*r != '-')
|
||||
*l++ = *r;
|
||||
}
|
||||
*l = '\0';
|
||||
if(strlen(field) != 12 || strspn(field, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") < 5 || strspn(field+5, "1234567890") != 7) {
|
||||
*error_message = "invalid ISRC number";
|
||||
return false;
|
||||
}
|
||||
strcpy(cs->tracks[cs->num_tracks-1].isrc, field);
|
||||
track_has_isrc = true;
|
||||
}
|
||||
else if(0 == FLAC__STRCASECMP(field, "TRACK")) {
|
||||
if(cs->num_tracks > 0) {
|
||||
const FLAC__StreamMetadata_CueSheet_Track *prev = &cs->tracks[cs->num_tracks-1];
|
||||
if(
|
||||
prev->num_indices == 0 ||
|
||||
(
|
||||
is_cdda &&
|
||||
(
|
||||
(prev->num_indices == 1 && prev->indices[0].number != 1) ||
|
||||
(prev->num_indices == 2 && prev->indices[0].number != 1 && prev->indices[1].number != 1)
|
||||
)
|
||||
)
|
||||
) {
|
||||
*error_message = is_cdda?
|
||||
"previous TRACK must specify at least one INDEX 01" :
|
||||
"previous TRACK must specify at least one INDEX";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(0 == (field = local__get_field_(&line, /*allow_quotes=*/false))) {
|
||||
*error_message = "TRACK is missing track number";
|
||||
return false;
|
||||
}
|
||||
in_track_num = local__parse_int_(field);
|
||||
if(in_track_num < 0) {
|
||||
*error_message = "TRACK has invalid track number";
|
||||
return false;
|
||||
}
|
||||
if(in_track_num == 0) {
|
||||
*error_message = "TRACK number must be greater than 0";
|
||||
return false;
|
||||
}
|
||||
if(is_cdda) {
|
||||
if(in_track_num > 99) {
|
||||
*error_message = "CD-DA TRACK number must be between 1 and 99, inclusive";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(in_track_num == 255) {
|
||||
*error_message = "TRACK number 255 is reserved for the lead-out";
|
||||
return false;
|
||||
}
|
||||
else if(in_track_num > 255) {
|
||||
*error_message = "TRACK number must be between 1 and 254, inclusive";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(is_cdda && cs->num_tracks > 0 && in_track_num != cs->tracks[cs->num_tracks-1].number + 1) {
|
||||
*error_message = "CD-DA TRACK numbers must be sequential";
|
||||
return false;
|
||||
}
|
||||
/*@@@ search for duplicate track number? */
|
||||
if(0 == (field = local__get_field_(&line, /*allow_quotes=*/false))) {
|
||||
*error_message = "TRACK is missing a track type after the track number";
|
||||
return false;
|
||||
}
|
||||
if(!FLAC__metadata_object_cuesheet_insert_blank_track(cuesheet, cs->num_tracks)) {
|
||||
*error_message = "memory allocation error";
|
||||
return false;
|
||||
}
|
||||
cs->tracks[cs->num_tracks-1].number = in_track_num;
|
||||
cs->tracks[cs->num_tracks-1].type = (0 == FLAC__STRCASECMP(field, "AUDIO"))? 0 : 1; /*@@@ should we be more strict with the value here? */
|
||||
in_index_num = -1;
|
||||
track_has_flags = false;
|
||||
track_has_isrc = false;
|
||||
}
|
||||
else if(0 == FLAC__STRCASECMP(field, "REM")) {
|
||||
if(0 != (field = local__get_field_(&line, /*allow_quotes=*/false))) {
|
||||
if(0 == strcmp(field, "FLAC__lead-in")) {
|
||||
FLAC__int64 xx;
|
||||
if(0 == (field = local__get_field_(&line, /*allow_quotes=*/false))) {
|
||||
*error_message = "FLAC__lead-in is missing offset";
|
||||
return false;
|
||||
}
|
||||
xx = local__parse_int64_(field);
|
||||
if(xx < 0) {
|
||||
*error_message = "illegal FLAC__lead-in offset";
|
||||
return false;
|
||||
}
|
||||
if(is_cdda && xx % 588 != 0) {
|
||||
*error_message = "illegal CD-DA FLAC__lead-in offset, must be even multiple of 588 samples";
|
||||
return false;
|
||||
}
|
||||
cs->lead_in = (FLAC__uint64)xx;
|
||||
}
|
||||
else if(0 == strcmp(field, "FLAC__lead-out")) {
|
||||
int track_num;
|
||||
FLAC__int64 offset;
|
||||
if(has_forced_leadout) {
|
||||
*error_message = "multiple FLAC__lead-out commands";
|
||||
return false;
|
||||
}
|
||||
if(0 == (field = local__get_field_(&line, /*allow_quotes=*/false))) {
|
||||
*error_message = "FLAC__lead-out is missing track number";
|
||||
return false;
|
||||
}
|
||||
track_num = local__parse_int_(field);
|
||||
if(track_num < 0) {
|
||||
*error_message = "illegal FLAC__lead-out track number";
|
||||
return false;
|
||||
}
|
||||
forced_leadout_track_num = (unsigned)track_num;
|
||||
/*@@@ search for duplicate track number? */
|
||||
if(0 == (field = local__get_field_(&line, /*allow_quotes=*/false))) {
|
||||
*error_message = "FLAC__lead-out is missing offset";
|
||||
return false;
|
||||
}
|
||||
offset = local__parse_int64_(field);
|
||||
if(offset < 0) {
|
||||
*error_message = "illegal FLAC__lead-out offset";
|
||||
return false;
|
||||
}
|
||||
forced_leadout_track_offset = (FLAC__uint64)offset;
|
||||
if(forced_leadout_track_offset != lead_out_offset) {
|
||||
*error_message = "FLAC__lead-out offset does not match end-of-stream offset";
|
||||
return false;
|
||||
}
|
||||
has_forced_leadout = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(cs->num_tracks == 0) {
|
||||
*error_message = "there must be at least one TRACK command";
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
const FLAC__StreamMetadata_CueSheet_Track *prev = &cs->tracks[cs->num_tracks-1];
|
||||
if(
|
||||
prev->num_indices == 0 ||
|
||||
(
|
||||
is_cdda &&
|
||||
(
|
||||
(prev->num_indices == 1 && prev->indices[0].number != 1) ||
|
||||
(prev->num_indices == 2 && prev->indices[0].number != 1 && prev->indices[1].number != 1)
|
||||
)
|
||||
)
|
||||
) {
|
||||
*error_message = is_cdda?
|
||||
"previous TRACK must specify at least one INDEX 01" :
|
||||
"previous TRACK must specify at least one INDEX";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(!has_forced_leadout) {
|
||||
forced_leadout_track_num = is_cdda? 170 : 255;
|
||||
forced_leadout_track_offset = lead_out_offset;
|
||||
}
|
||||
if(!FLAC__metadata_object_cuesheet_insert_blank_track(cuesheet, cs->num_tracks)) {
|
||||
*error_message = "memory allocation error";
|
||||
return false;
|
||||
}
|
||||
cs->tracks[cs->num_tracks-1].number = forced_leadout_track_num;
|
||||
cs->tracks[cs->num_tracks-1].offset = forced_leadout_track_offset;
|
||||
|
||||
if(!feof(file)) {
|
||||
*error_message = "read error";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
#undef FLAC__STRCASECMP
|
||||
}
|
||||
|
||||
FLAC__StreamMetadata *grabbag__cuesheet_parse(FILE *file, const char **error_message, unsigned *last_line_read, FLAC__bool is_cdda, FLAC__uint64 lead_out_offset)
|
||||
{
|
||||
FLAC__StreamMetadata *cuesheet;
|
||||
|
||||
FLAC__ASSERT(0 != file);
|
||||
FLAC__ASSERT(0 != error_message);
|
||||
FLAC__ASSERT(0 != last_line_read);
|
||||
|
||||
*last_line_read = 0;
|
||||
cuesheet = FLAC__metadata_object_new(FLAC__METADATA_TYPE_CUESHEET);
|
||||
|
||||
if(0 == cuesheet) {
|
||||
*error_message = "memory allocation error";
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!local__cuesheet_parse_(file, error_message, last_line_read, cuesheet, is_cdda, lead_out_offset)) {
|
||||
FLAC__metadata_object_delete(cuesheet);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return cuesheet;
|
||||
}
|
||||
|
||||
void grabbag__cuesheet_emit(FILE *file, const FLAC__StreamMetadata *cuesheet, const char *file_reference)
|
||||
{
|
||||
const FLAC__StreamMetadata_CueSheet *cs;
|
||||
unsigned track_num, index_num;
|
||||
|
||||
FLAC__ASSERT(0 != file);
|
||||
FLAC__ASSERT(0 != cuesheet);
|
||||
FLAC__ASSERT(cuesheet->type == FLAC__METADATA_TYPE_CUESHEET);
|
||||
|
||||
cs = &cuesheet->data.cue_sheet;
|
||||
|
||||
if(*(cs->media_catalog_number))
|
||||
fprintf(file, "CATALOG %s\n", cs->media_catalog_number);
|
||||
fprintf(file, "FILE %s\n", file_reference);
|
||||
|
||||
for(track_num = 0; track_num < cs->num_tracks-1; track_num++) {
|
||||
const FLAC__StreamMetadata_CueSheet_Track *track = cs->tracks + track_num;
|
||||
|
||||
fprintf(file, " TRACK %02u %s\n", (unsigned)track->number, track->type == 0? "AUDIO" : "DATA");
|
||||
|
||||
if(track->pre_emphasis)
|
||||
fprintf(file, " FLAGS PRE\n");
|
||||
if(*(track->isrc))
|
||||
fprintf(file, " ISRC %s\n", track->isrc);
|
||||
|
||||
for(index_num = 0; index_num < track->num_indices; index_num++) {
|
||||
const FLAC__StreamMetadata_CueSheet_Index *index = track->indices + index_num;
|
||||
|
||||
fprintf(file, " INDEX %02u ", (unsigned)index->number);
|
||||
if(cs->is_cd) {
|
||||
const unsigned logical_frame = (unsigned)((track->offset + index->offset) / (44100 / 75));
|
||||
unsigned m, s, f;
|
||||
grabbag__cuesheet_frame_to_msf(logical_frame, &m, &s, &f);
|
||||
fprintf(file, "%02u:%02u:%02u\n", m, s, f);
|
||||
}
|
||||
else
|
||||
#ifdef _MSC_VER
|
||||
fprintf(file, "%I64u\n", track->offset + index->offset);
|
||||
#else
|
||||
fprintf(file, "%llu\n", (unsigned long long)(track->offset + index->offset));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
fprintf(file, "REM FLAC__lead-in %I64u\n", cs->lead_in);
|
||||
fprintf(file, "REM FLAC__lead-out %u %I64u\n", (unsigned)cs->tracks[track_num].number, cs->tracks[track_num].offset);
|
||||
#else
|
||||
fprintf(file, "REM FLAC__lead-in %llu\n", (unsigned long long)cs->lead_in);
|
||||
fprintf(file, "REM FLAC__lead-out %u %llu\n", (unsigned)cs->tracks[track_num].number, (unsigned long long)cs->tracks[track_num].offset);
|
||||
#endif
|
||||
}
|
||||
192
flac/src/share/grabbag/file.c
Normal file
192
flac/src/share/grabbag/file.c
Normal file
@@ -0,0 +1,192 @@
|
||||
/* grabbag - Convenience lib for various routines common to several tools
|
||||
* Copyright (C) 2002,2003,2004,2005,2006,2007,2008 Josh Coalson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#if defined _MSC_VER || defined __MINGW32__
|
||||
#include <sys/utime.h> /* for utime() */
|
||||
#include <io.h> /* for chmod(), _setmode(), unlink() */
|
||||
#include <fcntl.h> /* for _O_BINARY */
|
||||
#else
|
||||
#include <sys/types.h> /* some flavors of BSD (like OS X) require this to get time_t */
|
||||
#include <utime.h> /* for utime() */
|
||||
#endif
|
||||
#if defined __CYGWIN__ || defined __EMX__
|
||||
#include <io.h> /* for setmode(), O_BINARY */
|
||||
#include <fcntl.h> /* for _O_BINARY */
|
||||
#endif
|
||||
#include <sys/stat.h> /* for stat(), maybe chmod() */
|
||||
#if defined _WIN32 && !defined __CYGWIN__
|
||||
#else
|
||||
#include <unistd.h> /* for unlink() */
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h> /* for strrchr() */
|
||||
#if defined _WIN32 && !defined __CYGWIN__
|
||||
// for GetFileInformationByHandle() etc
|
||||
#include <windows.h>
|
||||
#include <winbase.h>
|
||||
#endif
|
||||
#include "share/grabbag.h"
|
||||
|
||||
|
||||
void grabbag__file_copy_metadata(const char *srcpath, const char *destpath)
|
||||
{
|
||||
struct stat srcstat;
|
||||
struct utimbuf srctime;
|
||||
|
||||
if(0 == stat(srcpath, &srcstat)) {
|
||||
srctime.actime = srcstat.st_atime;
|
||||
srctime.modtime = srcstat.st_mtime;
|
||||
(void)chmod(destpath, srcstat.st_mode);
|
||||
(void)utime(destpath, &srctime);
|
||||
}
|
||||
}
|
||||
|
||||
off_t grabbag__file_get_filesize(const char *srcpath)
|
||||
{
|
||||
struct stat srcstat;
|
||||
|
||||
if(0 == stat(srcpath, &srcstat))
|
||||
return srcstat.st_size;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char *grabbag__file_get_basename(const char *srcpath)
|
||||
{
|
||||
const char *p;
|
||||
|
||||
p = strrchr(srcpath, '/');
|
||||
if(0 == p) {
|
||||
p = strrchr(srcpath, '\\');
|
||||
if(0 == p)
|
||||
return srcpath;
|
||||
}
|
||||
return ++p;
|
||||
}
|
||||
|
||||
FLAC__bool grabbag__file_change_stats(const char *filename, FLAC__bool read_only)
|
||||
{
|
||||
struct stat stats;
|
||||
|
||||
if(0 == stat(filename, &stats)) {
|
||||
#if !defined _MSC_VER && !defined __MINGW32__
|
||||
if(read_only) {
|
||||
stats.st_mode &= ~S_IWUSR;
|
||||
stats.st_mode &= ~S_IWGRP;
|
||||
stats.st_mode &= ~S_IWOTH;
|
||||
}
|
||||
else {
|
||||
stats.st_mode |= S_IWUSR;
|
||||
}
|
||||
#else
|
||||
if(read_only)
|
||||
stats.st_mode &= ~S_IWRITE;
|
||||
else
|
||||
stats.st_mode |= S_IWRITE;
|
||||
#endif
|
||||
if(0 != chmod(filename, stats.st_mode))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC__bool grabbag__file_are_same(const char *f1, const char *f2)
|
||||
{
|
||||
#if defined _MSC_VER || defined __MINGW32__
|
||||
/* see
|
||||
* http://www.hydrogenaudio.org/forums/index.php?showtopic=49439&pid=444300&st=0
|
||||
* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/getfileinformationbyhandle.asp
|
||||
* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/by_handle_file_information_str.asp
|
||||
* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/createfile.asp
|
||||
* apparently both the files have to be open at the same time for the comparison to work
|
||||
*/
|
||||
FLAC__bool same = false;
|
||||
BY_HANDLE_FILE_INFORMATION info1, info2;
|
||||
HANDLE h1, h2;
|
||||
BOOL ok = 1;
|
||||
h1 = CreateFile(f1, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
h2 = CreateFile(f2, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if(h1 == INVALID_HANDLE_VALUE || h2 == INVALID_HANDLE_VALUE)
|
||||
ok = 0;
|
||||
ok &= GetFileInformationByHandle(h1, &info1);
|
||||
ok &= GetFileInformationByHandle(h2, &info2);
|
||||
if(ok)
|
||||
same =
|
||||
info1.dwVolumeSerialNumber == info2.dwVolumeSerialNumber &&
|
||||
info1.nFileIndexHigh == info2.nFileIndexHigh &&
|
||||
info1.nFileIndexLow == info2.nFileIndexLow
|
||||
;
|
||||
if(h1 != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(h1);
|
||||
if(h2 != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(h2);
|
||||
return same;
|
||||
#else
|
||||
struct stat s1, s2;
|
||||
return f1 && f2 && stat(f1, &s1) == 0 && stat(f2, &s2) == 0 && s1.st_ino == s2.st_ino && s1.st_dev == s2.st_dev;
|
||||
#endif
|
||||
}
|
||||
|
||||
FLAC__bool grabbag__file_remove_file(const char *filename)
|
||||
{
|
||||
return grabbag__file_change_stats(filename, /*read_only=*/false) && 0 == unlink(filename);
|
||||
}
|
||||
|
||||
FILE *grabbag__file_get_binary_stdin(void)
|
||||
{
|
||||
/* if something breaks here it is probably due to the presence or
|
||||
* absence of an underscore before the identifiers 'setmode',
|
||||
* 'fileno', and/or 'O_BINARY'; check your system header files.
|
||||
*/
|
||||
#if defined _MSC_VER || defined __MINGW32__
|
||||
_setmode(_fileno(stdin), _O_BINARY);
|
||||
#elif defined __CYGWIN__
|
||||
/* almost certainly not needed for any modern Cygwin, but let's be safe... */
|
||||
setmode(_fileno(stdin), _O_BINARY);
|
||||
#elif defined __EMX__
|
||||
setmode(fileno(stdin), O_BINARY);
|
||||
#endif
|
||||
|
||||
return stdin;
|
||||
}
|
||||
|
||||
FILE *grabbag__file_get_binary_stdout(void)
|
||||
{
|
||||
/* if something breaks here it is probably due to the presence or
|
||||
* absence of an underscore before the identifiers 'setmode',
|
||||
* 'fileno', and/or 'O_BINARY'; check your system header files.
|
||||
*/
|
||||
#if defined _MSC_VER || defined __MINGW32__
|
||||
_setmode(_fileno(stdout), _O_BINARY);
|
||||
#elif defined __CYGWIN__
|
||||
/* almost certainly not needed for any modern Cygwin, but let's be safe... */
|
||||
setmode(_fileno(stdout), _O_BINARY);
|
||||
#elif defined __EMX__
|
||||
setmode(fileno(stdout), O_BINARY);
|
||||
#endif
|
||||
|
||||
return stdout;
|
||||
}
|
||||
144
flac/src/share/grabbag/grabbag_static.dsp
Normal file
144
flac/src/share/grabbag/grabbag_static.dsp
Normal file
@@ -0,0 +1,144 @@
|
||||
# Microsoft Developer Studio Project File - Name="grabbag_static" - Package Owner=<4>
|
||||
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
|
||||
|
||||
# TARGTYPE "Win32 (x86) Static Library" 0x0104
|
||||
|
||||
|
||||
|
||||
CFG=grabbag_static - 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 "grabbag_static.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 "grabbag_static.mak" CFG="grabbag_static - Win32 Debug"
|
||||
|
||||
!MESSAGE
|
||||
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
|
||||
!MESSAGE
|
||||
|
||||
!MESSAGE "grabbag_static - Win32 Release" (based on "Win32 (x86) Static Library")
|
||||
|
||||
!MESSAGE "grabbag_static - Win32 Debug" (based on "Win32 (x86) Static Library")
|
||||
|
||||
!MESSAGE
|
||||
|
||||
|
||||
|
||||
# Begin Project
|
||||
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
|
||||
# PROP Scc_ProjName "grabbag"
|
||||
|
||||
# PROP Scc_LocalPath "..\..\.."
|
||||
|
||||
CPP=cl.exe
|
||||
|
||||
RSC=rc.exe
|
||||
|
||||
|
||||
|
||||
!IF "$(CFG)" == "grabbag_static - 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\lib"
|
||||
|
||||
# PROP Intermediate_Dir "Release_static"
|
||||
|
||||
# PROP Target_Dir ""
|
||||
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /Op /I ".\include" /I "..\..\..\include" /D "FLAC__NO_DLL" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
|
||||
BSC32=bscmake.exe
|
||||
|
||||
# ADD BASE BSC32 /nologo
|
||||
|
||||
# ADD BSC32 /nologo
|
||||
|
||||
LIB32=link.exe -lib
|
||||
|
||||
# ADD BASE LIB32 /nologo
|
||||
|
||||
# ADD LIB32 /nologo /nodefaultlib
|
||||
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "grabbag_static - 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\lib"
|
||||
|
||||
# PROP Intermediate_Dir "Debug_static"
|
||||
|
||||
# PROP Target_Dir ""
|
||||
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
|
||||
|
||||
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I ".\include" /I "..\..\..\include" /D "FLAC__NO_DLL" /D "WIN32" /D "_DEBUG" /D "DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
|
||||
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
|
||||
BSC32=bscmake.exe
|
||||
|
||||
# ADD BASE BSC32 /nologo
|
||||
|
||||
# ADD BSC32 /nologo
|
||||
|
||||
358
flac/src/share/grabbag/grabbag_static.vcproj
Normal file
358
flac/src/share/grabbag/grabbag_static.vcproj
Normal file
@@ -0,0 +1,358 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8,00"
|
||||
Name="grabbag_static"
|
||||
ProjectGUID="{4cefbc81-c215-11db-8314-0800200c9a66}"
|
||||
RootNamespace="grabbag_static"
|
||||
Keyword="Win32Proj"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
<Platform
|
||||
Name="x64"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="..\..\..\obj\debug\lib"
|
||||
IntermediateDirectory="Debug_static"
|
||||
ConfigurationType="4"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=".\include;..\..\..\include"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;FLAC__NO_DLL;DEBUG"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="4"
|
||||
CompileAs="0"
|
||||
DisableSpecificWarnings="4267;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="..\..\..\obj\debug\lib\$(ProjectName).lib"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="..\..\..\obj\release\lib"
|
||||
IntermediateDirectory="Release_static"
|
||||
ConfigurationType="4"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
EnableIntrinsicFunctions="true"
|
||||
FavorSizeOrSpeed="1"
|
||||
OmitFramePointers="true"
|
||||
WholeProgramOptimization="true"
|
||||
AdditionalIncludeDirectories=".\include;..\..\..\include"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;FLAC__NO_DLL"
|
||||
RuntimeLibrary="0"
|
||||
BufferSecurityCheck="false"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"
|
||||
DisableSpecificWarnings="4267;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="..\..\..\obj\release\lib\$(ProjectName).lib"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug|x64"
|
||||
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TargetEnvironment="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=".\include;..\..\..\include"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;FLAC__NO_DLL;DEBUG"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"
|
||||
DisableSpecificWarnings="4267;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="..\..\..\obj\debug\lib\$(ProjectName).lib"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|x64"
|
||||
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TargetEnvironment="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
EnableIntrinsicFunctions="true"
|
||||
FavorSizeOrSpeed="1"
|
||||
OmitFramePointers="true"
|
||||
WholeProgramOptimization="true"
|
||||
AdditionalIncludeDirectories=".\include;..\..\..\include"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;FLAC__NO_DLL"
|
||||
RuntimeLibrary="0"
|
||||
BufferSecurityCheck="false"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"
|
||||
DisableSpecificWarnings="4267;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="..\..\..\obj\release\lib\$(ProjectName).lib"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\cuesheet.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\file.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\picture.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\replaygain.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\seektable.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Public Header Files"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\..\include\share\grabbag.h"
|
||||
>
|
||||
</File>
|
||||
<Filter
|
||||
Name="grabbag"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\..\include\share\grabbag\cuesheet.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\include\share\grabbag\file.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\include\share\grabbag\picture.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\include\share\grabbag\replaygain.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\include\share\grabbag\seektable.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
407
flac/src/share/grabbag/picture.c
Normal file
407
flac/src/share/grabbag/picture.c
Normal file
@@ -0,0 +1,407 @@
|
||||
/* grabbag - Convenience lib for various routines common to several tools
|
||||
* Copyright (C) 2006,2007,2008 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 <config.h>
|
||||
#endif
|
||||
|
||||
#include "share/alloc.h"
|
||||
#include "share/grabbag.h"
|
||||
#include "FLAC/assert.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* slightly different that strndup(): this always copies 'size' bytes starting from s into a NUL-terminated string. */
|
||||
static char *local__strndup_(const char *s, size_t size)
|
||||
{
|
||||
char *x = (char*)safe_malloc_add_2op_(size, /*+*/1);
|
||||
if(x) {
|
||||
memcpy(x, s, size);
|
||||
x[size] = '\0';
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
static FLAC__bool local__parse_type_(const char *s, size_t len, FLAC__StreamMetadata_Picture *picture)
|
||||
{
|
||||
size_t i;
|
||||
FLAC__uint32 val = 0;
|
||||
|
||||
picture->type = FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER;
|
||||
|
||||
if(len == 0)
|
||||
return true; /* empty string implies default to 'front cover' */
|
||||
|
||||
for(i = 0; i < len; i++) {
|
||||
if(s[i] >= '0' && s[i] <= '9')
|
||||
val = 10*val + (FLAC__uint32)(s[i] - '0');
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
if(i == len)
|
||||
picture->type = val;
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static FLAC__bool local__parse_resolution_(const char *s, size_t len, FLAC__StreamMetadata_Picture *picture)
|
||||
{
|
||||
int state = 0;
|
||||
size_t i;
|
||||
FLAC__uint32 val = 0;
|
||||
|
||||
picture->width = picture->height = picture->depth = picture->colors = 0;
|
||||
|
||||
if(len == 0)
|
||||
return true; /* empty string implies client wants to get info from the file itself */
|
||||
|
||||
for(i = 0; i < len; i++) {
|
||||
if(s[i] == 'x') {
|
||||
if(state == 0)
|
||||
picture->width = val;
|
||||
else if(state == 1)
|
||||
picture->height = val;
|
||||
else
|
||||
return false;
|
||||
state++;
|
||||
val = 0;
|
||||
}
|
||||
else if(s[i] == '/') {
|
||||
if(state == 2)
|
||||
picture->depth = val;
|
||||
else
|
||||
return false;
|
||||
state++;
|
||||
val = 0;
|
||||
}
|
||||
else if(s[i] >= '0' && s[i] <= '9')
|
||||
val = 10*val + (FLAC__uint32)(s[i] - '0');
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
if(state < 2)
|
||||
return false;
|
||||
else if(state == 2)
|
||||
picture->depth = val;
|
||||
else if(state == 3)
|
||||
picture->colors = val;
|
||||
else
|
||||
return false;
|
||||
if(picture->depth < 32 && 1u<<picture->depth < picture->colors)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static FLAC__bool local__extract_mime_type_(FLAC__StreamMetadata *obj)
|
||||
{
|
||||
if(obj->data.picture.data_length >= 8 && 0 == memcmp(obj->data.picture.data, "\x89PNG\x0d\x0a\x1a\x0a", 8))
|
||||
return FLAC__metadata_object_picture_set_mime_type(obj, "image/png", /*copy=*/true);
|
||||
else if(obj->data.picture.data_length >= 6 && (0 == memcmp(obj->data.picture.data, "GIF87a", 6) || 0 == memcmp(obj->data.picture.data, "GIF89a", 6)))
|
||||
return FLAC__metadata_object_picture_set_mime_type(obj, "image/gif", /*copy=*/true);
|
||||
else if(obj->data.picture.data_length >= 2 && 0 == memcmp(obj->data.picture.data, "\xff\xd8", 2))
|
||||
return FLAC__metadata_object_picture_set_mime_type(obj, "image/jpeg", /*copy=*/true);
|
||||
return false;
|
||||
}
|
||||
|
||||
static FLAC__bool local__extract_resolution_color_info_(FLAC__StreamMetadata_Picture *picture)
|
||||
{
|
||||
const FLAC__byte *data = picture->data;
|
||||
FLAC__uint32 len = picture->data_length;
|
||||
|
||||
if(0 == strcmp(picture->mime_type, "image/png")) {
|
||||
/* c.f. http://www.w3.org/TR/PNG/ */
|
||||
FLAC__bool need_palette = false; /* if IHDR has color_type=3, we need to also read the PLTE chunk to get the #colors */
|
||||
if(len < 8 || memcmp(data, "\x89PNG\x0d\x0a\x1a\x0a", 8))
|
||||
return false;
|
||||
/* try to find IHDR chunk */
|
||||
data += 8;
|
||||
len -= 8;
|
||||
while(len > 12) { /* every PNG chunk must be at least 12 bytes long */
|
||||
const FLAC__uint32 clen = (FLAC__uint32)data[0] << 24 | (FLAC__uint32)data[1] << 16 | (FLAC__uint32)data[2] << 8 | (FLAC__uint32)data[3];
|
||||
if(0 == memcmp(data+4, "IHDR", 4) && clen == 13) {
|
||||
unsigned color_type = data[17];
|
||||
picture->width = (FLAC__uint32)data[8] << 24 | (FLAC__uint32)data[9] << 16 | (FLAC__uint32)data[10] << 8 | (FLAC__uint32)data[11];
|
||||
picture->height = (FLAC__uint32)data[12] << 24 | (FLAC__uint32)data[13] << 16 | (FLAC__uint32)data[14] << 8 | (FLAC__uint32)data[15];
|
||||
if(color_type == 3) {
|
||||
/* even though the bit depth for color_type==3 can be 1,2,4,or 8,
|
||||
* the spec in 11.2.2 of http://www.w3.org/TR/PNG/ says that the
|
||||
* sample depth is always 8
|
||||
*/
|
||||
picture->depth = 8 * 3u;
|
||||
need_palette = true;
|
||||
data += 12 + clen;
|
||||
len -= 12 + clen;
|
||||
}
|
||||
else {
|
||||
if(color_type == 0) /* greyscale, 1 sample per pixel */
|
||||
picture->depth = (FLAC__uint32)data[16];
|
||||
if(color_type == 2) /* truecolor, 3 samples per pixel */
|
||||
picture->depth = (FLAC__uint32)data[16] * 3u;
|
||||
if(color_type == 4) /* greyscale+alpha, 2 samples per pixel */
|
||||
picture->depth = (FLAC__uint32)data[16] * 2u;
|
||||
if(color_type == 6) /* truecolor+alpha, 4 samples per pixel */
|
||||
picture->depth = (FLAC__uint32)data[16] * 4u;
|
||||
picture->colors = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if(need_palette && 0 == memcmp(data+4, "PLTE", 4)) {
|
||||
picture->colors = clen / 3u;
|
||||
return true;
|
||||
}
|
||||
else if(clen + 12 > len)
|
||||
return false;
|
||||
else {
|
||||
data += 12 + clen;
|
||||
len -= 12 + clen;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(0 == strcmp(picture->mime_type, "image/jpeg")) {
|
||||
/* c.f. http://www.w3.org/Graphics/JPEG/itu-t81.pdf and Q22 of http://www.faqs.org/faqs/jpeg-faq/part1/ */
|
||||
if(len < 2 || memcmp(data, "\xff\xd8", 2))
|
||||
return false;
|
||||
data += 2;
|
||||
len -= 2;
|
||||
while(1) {
|
||||
/* look for sync FF byte */
|
||||
for( ; len > 0; data++, len--) {
|
||||
if(*data == 0xff)
|
||||
break;
|
||||
}
|
||||
if(len == 0)
|
||||
return false;
|
||||
/* eat any extra pad FF bytes before marker */
|
||||
for( ; len > 0; data++, len--) {
|
||||
if(*data != 0xff)
|
||||
break;
|
||||
}
|
||||
if(len == 0)
|
||||
return false;
|
||||
/* if we hit SOS or EOI, bail */
|
||||
if(*data == 0xda || *data == 0xd9)
|
||||
return false;
|
||||
/* looking for some SOFn */
|
||||
else if(memchr("\xc0\xc1\xc2\xc3\xc5\xc6\xc7\xc9\xca\xcb\xcd\xce\xcf", *data, 13)) {
|
||||
data++; len--; /* skip marker byte */
|
||||
if(len < 2)
|
||||
return false;
|
||||
else {
|
||||
const FLAC__uint32 clen = (FLAC__uint32)data[0] << 8 | (FLAC__uint32)data[1];
|
||||
if(clen < 8 || len < clen)
|
||||
return false;
|
||||
picture->width = (FLAC__uint32)data[5] << 8 | (FLAC__uint32)data[6];
|
||||
picture->height = (FLAC__uint32)data[3] << 8 | (FLAC__uint32)data[4];
|
||||
picture->depth = (FLAC__uint32)data[2] * (FLAC__uint32)data[7];
|
||||
picture->colors = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
/* else skip it */
|
||||
else {
|
||||
data++; len--; /* skip marker byte */
|
||||
if(len < 2)
|
||||
return false;
|
||||
else {
|
||||
const FLAC__uint32 clen = (FLAC__uint32)data[0] << 8 | (FLAC__uint32)data[1];
|
||||
if(clen < 2 || len < clen)
|
||||
return false;
|
||||
data += clen;
|
||||
len -= clen;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(0 == strcmp(picture->mime_type, "image/gif")) {
|
||||
/* c.f. http://www.w3.org/Graphics/GIF/spec-gif89a.txt */
|
||||
if(len < 14)
|
||||
return false;
|
||||
if(memcmp(data, "GIF87a", 6) && memcmp(data, "GIF89a", 6))
|
||||
return false;
|
||||
#if 0
|
||||
/* according to the GIF spec, even if the GCTF is 0, the low 3 bits should still tell the total # colors used */
|
||||
if(data[10] & 0x80 == 0)
|
||||
return false;
|
||||
#endif
|
||||
picture->width = (FLAC__uint32)data[6] | ((FLAC__uint32)data[7] << 8);
|
||||
picture->height = (FLAC__uint32)data[8] | ((FLAC__uint32)data[9] << 8);
|
||||
#if 0
|
||||
/* this value doesn't seem to be reliable... */
|
||||
picture->depth = (((FLAC__uint32)(data[10] & 0x70) >> 4) + 1) * 3u;
|
||||
#else
|
||||
/* ...just pessimistically assume it's 24-bit color without scanning all the color tables */
|
||||
picture->depth = 8u * 3u;
|
||||
#endif
|
||||
picture->colors = 1u << ((FLAC__uint32)(data[10] & 0x07) + 1u);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
FLAC__StreamMetadata *grabbag__picture_parse_specification(const char *spec, const char **error_message)
|
||||
{
|
||||
FLAC__StreamMetadata *obj;
|
||||
int state = 0;
|
||||
static const char *error_messages[] = {
|
||||
"memory allocation error",
|
||||
"invalid picture specification",
|
||||
"invalid picture specification: can't parse resolution/color part",
|
||||
"unable to extract resolution and color info from URL, user must set explicitly",
|
||||
"unable to extract resolution and color info from file, user must set explicitly",
|
||||
"error opening picture file",
|
||||
"error reading picture file",
|
||||
"invalid picture type",
|
||||
"unable to guess MIME type from file, user must set explicitly",
|
||||
"type 1 icon must be a 32x32 pixel PNG"
|
||||
};
|
||||
|
||||
FLAC__ASSERT(0 != spec);
|
||||
FLAC__ASSERT(0 != error_message);
|
||||
|
||||
/* double protection */
|
||||
if(0 == spec)
|
||||
return 0;
|
||||
if(0 == error_message)
|
||||
return 0;
|
||||
|
||||
*error_message = 0;
|
||||
|
||||
if(0 == (obj = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PICTURE)))
|
||||
*error_message = error_messages[0];
|
||||
|
||||
if(strchr(spec, '|')) { /* full format */
|
||||
const char *p;
|
||||
char *q;
|
||||
for(p = spec; *error_message==0 && *p; ) {
|
||||
if(*p == '|') {
|
||||
switch(state) {
|
||||
case 0: /* type */
|
||||
if(!local__parse_type_(spec, p-spec, &obj->data.picture))
|
||||
*error_message = error_messages[7];
|
||||
break;
|
||||
case 1: /* mime type */
|
||||
if(p-spec) { /* if blank, we'll try to guess later from the picture data */
|
||||
if(0 == (q = local__strndup_(spec, p-spec)))
|
||||
*error_message = error_messages[0];
|
||||
else if(!FLAC__metadata_object_picture_set_mime_type(obj, q, /*copy=*/false))
|
||||
*error_message = error_messages[0];
|
||||
}
|
||||
break;
|
||||
case 2: /* description */
|
||||
if(0 == (q = local__strndup_(spec, p-spec)))
|
||||
*error_message = error_messages[0];
|
||||
else if(!FLAC__metadata_object_picture_set_description(obj, (FLAC__byte*)q, /*copy=*/false))
|
||||
*error_message = error_messages[0];
|
||||
break;
|
||||
case 3: /* resolution/color (e.g. [300x300x16[/1234]] */
|
||||
if(!local__parse_resolution_(spec, p-spec, &obj->data.picture))
|
||||
*error_message = error_messages[2];
|
||||
break;
|
||||
default:
|
||||
*error_message = error_messages[1];
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
spec = p;
|
||||
state++;
|
||||
}
|
||||
else
|
||||
p++;
|
||||
}
|
||||
}
|
||||
else { /* simple format, filename only, everything else guessed */
|
||||
if(!local__parse_type_("", 0, &obj->data.picture)) /* use default picture type */
|
||||
*error_message = error_messages[7];
|
||||
/* leave MIME type to be filled in later */
|
||||
/* leave description empty */
|
||||
/* leave the rest to be filled in later: */
|
||||
else if(!local__parse_resolution_("", 0, &obj->data.picture))
|
||||
*error_message = error_messages[2];
|
||||
else
|
||||
state = 4;
|
||||
}
|
||||
|
||||
/* parse filename, read file, try to extract resolution/color info if needed */
|
||||
if(*error_message == 0) {
|
||||
if(state != 4)
|
||||
*error_message = error_messages[1];
|
||||
else { /* 'spec' points to filename/URL */
|
||||
if(0 == strcmp(obj->data.picture.mime_type, "-->")) { /* magic MIME type means URL */
|
||||
if(!FLAC__metadata_object_picture_set_data(obj, (FLAC__byte*)spec, strlen(spec), /*copy=*/true))
|
||||
*error_message = error_messages[0];
|
||||
else if(obj->data.picture.width == 0 || obj->data.picture.height == 0 || obj->data.picture.depth == 0)
|
||||
*error_message = error_messages[3];
|
||||
}
|
||||
else { /* regular picture file */
|
||||
const off_t size = grabbag__file_get_filesize(spec);
|
||||
if(size < 0)
|
||||
*error_message = error_messages[5];
|
||||
else {
|
||||
FLAC__byte *buffer = (FLAC__byte*)safe_malloc_(size);
|
||||
if(0 == buffer)
|
||||
*error_message = error_messages[0];
|
||||
else {
|
||||
FILE *f = fopen(spec, "rb");
|
||||
if(0 == f)
|
||||
*error_message = error_messages[5];
|
||||
else {
|
||||
if(fread(buffer, 1, size, f) != (size_t)size)
|
||||
*error_message = error_messages[6];
|
||||
fclose(f);
|
||||
if(0 == *error_message) {
|
||||
if(!FLAC__metadata_object_picture_set_data(obj, buffer, size, /*copy=*/false))
|
||||
*error_message = error_messages[6];
|
||||
/* try to extract MIME type if user left it blank */
|
||||
else if(*obj->data.picture.mime_type == '\0' && !local__extract_mime_type_(obj))
|
||||
*error_message = error_messages[8];
|
||||
/* try to extract resolution/color info if user left it blank */
|
||||
else if((obj->data.picture.width == 0 || obj->data.picture.height == 0 || obj->data.picture.depth == 0) && !local__extract_resolution_color_info_(&obj->data.picture))
|
||||
*error_message = error_messages[4];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(*error_message == 0) {
|
||||
if(
|
||||
obj->data.picture.type == FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON_STANDARD &&
|
||||
(
|
||||
(strcmp(obj->data.picture.mime_type, "image/png") && strcmp(obj->data.picture.mime_type, "-->")) ||
|
||||
obj->data.picture.width != 32 ||
|
||||
obj->data.picture.height != 32
|
||||
)
|
||||
)
|
||||
*error_message = error_messages[9];
|
||||
}
|
||||
|
||||
if(*error_message && obj) {
|
||||
FLAC__metadata_object_delete(obj);
|
||||
obj = 0;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
668
flac/src/share/grabbag/replaygain.c
Normal file
668
flac/src/share/grabbag/replaygain.c
Normal file
@@ -0,0 +1,668 @@
|
||||
/* grabbag - Convenience lib for various routines common to several tools
|
||||
* Copyright (C) 2002,2003,2004,2005,2006,2007,2008 Josh Coalson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "share/grabbag.h"
|
||||
#include "share/replaygain_analysis.h"
|
||||
#include "FLAC/assert.h"
|
||||
#include "FLAC/metadata.h"
|
||||
#include "FLAC/stream_decoder.h"
|
||||
#include <locale.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#if defined _MSC_VER || defined __MINGW32__
|
||||
#include <io.h> /* for chmod() */
|
||||
#endif
|
||||
#include <sys/stat.h> /* for stat(), maybe chmod() */
|
||||
|
||||
#ifdef local_min
|
||||
#undef local_min
|
||||
#endif
|
||||
#define local_min(a,b) ((a)<(b)?(a):(b))
|
||||
|
||||
#ifdef local_max
|
||||
#undef local_max
|
||||
#endif
|
||||
#define local_max(a,b) ((a)>(b)?(a):(b))
|
||||
|
||||
static const char *reference_format_ = "%s=%2.1f dB";
|
||||
static const char *gain_format_ = "%s=%+2.2f dB";
|
||||
static const char *peak_format_ = "%s=%1.8f";
|
||||
|
||||
static double album_peak_, title_peak_;
|
||||
|
||||
const unsigned GRABBAG__REPLAYGAIN_MAX_TAG_SPACE_REQUIRED = 190;
|
||||
/*
|
||||
FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN/8 + 29 + 1 + 8 +
|
||||
FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN/8 + 21 + 1 + 10 +
|
||||
FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN/8 + 21 + 1 + 12 +
|
||||
FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN/8 + 21 + 1 + 10 +
|
||||
FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN/8 + 21 + 1 + 12
|
||||
*/
|
||||
|
||||
const FLAC__byte * const GRABBAG__REPLAYGAIN_TAG_REFERENCE_LOUDNESS = (const FLAC__byte * const)"REPLAYGAIN_REFERENCE_LOUDNESS";
|
||||
const FLAC__byte * const GRABBAG__REPLAYGAIN_TAG_TITLE_GAIN = (const FLAC__byte * const)"REPLAYGAIN_TRACK_GAIN";
|
||||
const FLAC__byte * const GRABBAG__REPLAYGAIN_TAG_TITLE_PEAK = (const FLAC__byte * const)"REPLAYGAIN_TRACK_PEAK";
|
||||
const FLAC__byte * const GRABBAG__REPLAYGAIN_TAG_ALBUM_GAIN = (const FLAC__byte * const)"REPLAYGAIN_ALBUM_GAIN";
|
||||
const FLAC__byte * const GRABBAG__REPLAYGAIN_TAG_ALBUM_PEAK = (const FLAC__byte * const)"REPLAYGAIN_ALBUM_PEAK";
|
||||
|
||||
|
||||
static FLAC__bool get_file_stats_(const char *filename, struct stat *stats)
|
||||
{
|
||||
FLAC__ASSERT(0 != filename);
|
||||
FLAC__ASSERT(0 != stats);
|
||||
return (0 == stat(filename, stats));
|
||||
}
|
||||
|
||||
static void set_file_stats_(const char *filename, struct stat *stats)
|
||||
{
|
||||
FLAC__ASSERT(0 != filename);
|
||||
FLAC__ASSERT(0 != stats);
|
||||
|
||||
(void)chmod(filename, stats->st_mode);
|
||||
}
|
||||
|
||||
static FLAC__bool append_tag_(FLAC__StreamMetadata *block, const char *format, const FLAC__byte *name, float value)
|
||||
{
|
||||
char buffer[256];
|
||||
char *saved_locale;
|
||||
FLAC__StreamMetadata_VorbisComment_Entry entry;
|
||||
|
||||
FLAC__ASSERT(0 != block);
|
||||
FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
|
||||
FLAC__ASSERT(0 != format);
|
||||
FLAC__ASSERT(0 != name);
|
||||
|
||||
buffer[sizeof(buffer)-1] = '\0';
|
||||
/*
|
||||
* We need to save the old locale and switch to "C" because the locale
|
||||
* influences the formatting of %f and we want it a certain way.
|
||||
*/
|
||||
saved_locale = strdup(setlocale(LC_ALL, 0));
|
||||
if (0 == saved_locale)
|
||||
return false;
|
||||
setlocale(LC_ALL, "C");
|
||||
#if defined _MSC_VER || defined __MINGW32__
|
||||
_snprintf(buffer, sizeof(buffer)-1, format, name, value);
|
||||
#else
|
||||
snprintf(buffer, sizeof(buffer)-1, format, name, value);
|
||||
#endif
|
||||
setlocale(LC_ALL, saved_locale);
|
||||
free(saved_locale);
|
||||
|
||||
entry.entry = (FLAC__byte *)buffer;
|
||||
entry.length = strlen(buffer);
|
||||
|
||||
return FLAC__metadata_object_vorbiscomment_append_comment(block, entry, /*copy=*/true);
|
||||
}
|
||||
|
||||
FLAC__bool grabbag__replaygain_is_valid_sample_frequency(unsigned sample_frequency)
|
||||
{
|
||||
static const unsigned valid_sample_rates[] = {
|
||||
8000,
|
||||
11025,
|
||||
12000,
|
||||
16000,
|
||||
22050,
|
||||
24000,
|
||||
32000,
|
||||
44100,
|
||||
48000
|
||||
};
|
||||
static const unsigned n_valid_sample_rates = sizeof(valid_sample_rates) / sizeof(valid_sample_rates[0]);
|
||||
|
||||
unsigned i;
|
||||
|
||||
for(i = 0; i < n_valid_sample_rates; i++)
|
||||
if(sample_frequency == valid_sample_rates[i])
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
FLAC__bool grabbag__replaygain_init(unsigned sample_frequency)
|
||||
{
|
||||
title_peak_ = album_peak_ = 0.0;
|
||||
return InitGainAnalysis((long)sample_frequency) == INIT_GAIN_ANALYSIS_OK;
|
||||
}
|
||||
|
||||
FLAC__bool grabbag__replaygain_analyze(const FLAC__int32 * const input[], FLAC__bool is_stereo, unsigned bps, unsigned samples)
|
||||
{
|
||||
/* using a small buffer improves data locality; we'd like it to fit easily in the dcache */
|
||||
static Float_t lbuffer[2048], rbuffer[2048];
|
||||
static const unsigned nbuffer = sizeof(lbuffer) / sizeof(lbuffer[0]);
|
||||
FLAC__int32 block_peak = 0, s;
|
||||
unsigned i, j;
|
||||
|
||||
FLAC__ASSERT(bps >= 4 && bps <= FLAC__REFERENCE_CODEC_MAX_BITS_PER_SAMPLE);
|
||||
FLAC__ASSERT(FLAC__MIN_BITS_PER_SAMPLE == 4);
|
||||
/*
|
||||
* We use abs() on a FLAC__int32 which is undefined for the most negative value.
|
||||
* If the reference codec ever handles 32bps we will have to write a special
|
||||
* case here.
|
||||
*/
|
||||
FLAC__ASSERT(FLAC__REFERENCE_CODEC_MAX_BITS_PER_SAMPLE < 32);
|
||||
|
||||
if(bps == 16) {
|
||||
if(is_stereo) {
|
||||
j = 0;
|
||||
while(samples > 0) {
|
||||
const unsigned n = local_min(samples, nbuffer);
|
||||
for(i = 0; i < n; i++, j++) {
|
||||
s = input[0][j];
|
||||
lbuffer[i] = (Float_t)s;
|
||||
s = abs(s);
|
||||
block_peak = local_max(block_peak, s);
|
||||
|
||||
s = input[1][j];
|
||||
rbuffer[i] = (Float_t)s;
|
||||
s = abs(s);
|
||||
block_peak = local_max(block_peak, s);
|
||||
}
|
||||
samples -= n;
|
||||
if(AnalyzeSamples(lbuffer, rbuffer, n, 2) != GAIN_ANALYSIS_OK)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
j = 0;
|
||||
while(samples > 0) {
|
||||
const unsigned n = local_min(samples, nbuffer);
|
||||
for(i = 0; i < n; i++, j++) {
|
||||
s = input[0][j];
|
||||
lbuffer[i] = (Float_t)s;
|
||||
s = abs(s);
|
||||
block_peak = local_max(block_peak, s);
|
||||
}
|
||||
samples -= n;
|
||||
if(AnalyzeSamples(lbuffer, 0, n, 1) != GAIN_ANALYSIS_OK)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else { /* bps must be < 32 according to above assertion */
|
||||
const double scale = (
|
||||
(bps > 16)?
|
||||
(double)1. / (double)(1u << (bps - 16)) :
|
||||
(double)(1u << (16 - bps))
|
||||
);
|
||||
|
||||
if(is_stereo) {
|
||||
j = 0;
|
||||
while(samples > 0) {
|
||||
const unsigned n = local_min(samples, nbuffer);
|
||||
for(i = 0; i < n; i++, j++) {
|
||||
s = input[0][j];
|
||||
lbuffer[i] = (Float_t)(scale * (double)s);
|
||||
s = abs(s);
|
||||
block_peak = local_max(block_peak, s);
|
||||
|
||||
s = input[1][j];
|
||||
rbuffer[i] = (Float_t)(scale * (double)s);
|
||||
s = abs(s);
|
||||
block_peak = local_max(block_peak, s);
|
||||
}
|
||||
samples -= n;
|
||||
if(AnalyzeSamples(lbuffer, rbuffer, n, 2) != GAIN_ANALYSIS_OK)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
j = 0;
|
||||
while(samples > 0) {
|
||||
const unsigned n = local_min(samples, nbuffer);
|
||||
for(i = 0; i < n; i++, j++) {
|
||||
s = input[0][j];
|
||||
lbuffer[i] = (Float_t)(scale * (double)s);
|
||||
s = abs(s);
|
||||
block_peak = local_max(block_peak, s);
|
||||
}
|
||||
samples -= n;
|
||||
if(AnalyzeSamples(lbuffer, 0, n, 1) != GAIN_ANALYSIS_OK)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const double peak_scale = (double)(1u << (bps - 1));
|
||||
double peak = (double)block_peak / peak_scale;
|
||||
if(peak > title_peak_)
|
||||
title_peak_ = peak;
|
||||
if(peak > album_peak_)
|
||||
album_peak_ = peak;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void grabbag__replaygain_get_album(float *gain, float *peak)
|
||||
{
|
||||
*gain = (float)GetAlbumGain();
|
||||
*peak = (float)album_peak_;
|
||||
album_peak_ = 0.0;
|
||||
}
|
||||
|
||||
void grabbag__replaygain_get_title(float *gain, float *peak)
|
||||
{
|
||||
*gain = (float)GetTitleGain();
|
||||
*peak = (float)title_peak_;
|
||||
title_peak_ = 0.0;
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
unsigned channels;
|
||||
unsigned bits_per_sample;
|
||||
unsigned sample_rate;
|
||||
FLAC__bool error;
|
||||
} DecoderInstance;
|
||||
|
||||
static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
|
||||
{
|
||||
DecoderInstance *instance = (DecoderInstance*)client_data;
|
||||
const unsigned bits_per_sample = frame->header.bits_per_sample;
|
||||
const unsigned channels = frame->header.channels;
|
||||
const unsigned sample_rate = frame->header.sample_rate;
|
||||
const unsigned samples = frame->header.blocksize;
|
||||
|
||||
(void)decoder;
|
||||
|
||||
if(
|
||||
!instance->error &&
|
||||
(channels == 2 || channels == 1) &&
|
||||
bits_per_sample == instance->bits_per_sample &&
|
||||
channels == instance->channels &&
|
||||
sample_rate == instance->sample_rate
|
||||
) {
|
||||
instance->error = !grabbag__replaygain_analyze(buffer, channels==2, bits_per_sample, samples);
|
||||
}
|
||||
else {
|
||||
instance->error = true;
|
||||
}
|
||||
|
||||
if(!instance->error)
|
||||
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
|
||||
else
|
||||
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
|
||||
}
|
||||
|
||||
static void metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
|
||||
{
|
||||
DecoderInstance *instance = (DecoderInstance*)client_data;
|
||||
|
||||
(void)decoder;
|
||||
|
||||
if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
|
||||
instance->bits_per_sample = metadata->data.stream_info.bits_per_sample;
|
||||
instance->channels = metadata->data.stream_info.channels;
|
||||
instance->sample_rate = metadata->data.stream_info.sample_rate;
|
||||
|
||||
if(instance->channels != 1 && instance->channels != 2) {
|
||||
instance->error = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if(!grabbag__replaygain_is_valid_sample_frequency(instance->sample_rate)) {
|
||||
instance->error = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
|
||||
{
|
||||
DecoderInstance *instance = (DecoderInstance*)client_data;
|
||||
|
||||
(void)decoder, (void)status;
|
||||
|
||||
instance->error = true;
|
||||
}
|
||||
|
||||
const char *grabbag__replaygain_analyze_file(const char *filename, float *title_gain, float *title_peak)
|
||||
{
|
||||
DecoderInstance instance;
|
||||
FLAC__StreamDecoder *decoder = FLAC__stream_decoder_new();
|
||||
|
||||
if(0 == decoder)
|
||||
return "memory allocation error";
|
||||
|
||||
instance.error = false;
|
||||
|
||||
/* It does these three by default but lets be explicit: */
|
||||
FLAC__stream_decoder_set_md5_checking(decoder, false);
|
||||
FLAC__stream_decoder_set_metadata_ignore_all(decoder);
|
||||
FLAC__stream_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_STREAMINFO);
|
||||
|
||||
if(FLAC__stream_decoder_init_file(decoder, filename, write_callback_, metadata_callback_, error_callback_, &instance) != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
|
||||
FLAC__stream_decoder_delete(decoder);
|
||||
return "initializing decoder";
|
||||
}
|
||||
|
||||
if(!FLAC__stream_decoder_process_until_end_of_stream(decoder) || instance.error) {
|
||||
FLAC__stream_decoder_delete(decoder);
|
||||
return "decoding file";
|
||||
}
|
||||
|
||||
FLAC__stream_decoder_delete(decoder);
|
||||
|
||||
grabbag__replaygain_get_title(title_gain, title_peak);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *grabbag__replaygain_store_to_vorbiscomment(FLAC__StreamMetadata *block, float album_gain, float album_peak, float title_gain, float title_peak)
|
||||
{
|
||||
const char *error;
|
||||
|
||||
if(0 != (error = grabbag__replaygain_store_to_vorbiscomment_reference(block)))
|
||||
return error;
|
||||
|
||||
if(0 != (error = grabbag__replaygain_store_to_vorbiscomment_title(block, title_gain, title_peak)))
|
||||
return error;
|
||||
|
||||
if(0 != (error = grabbag__replaygain_store_to_vorbiscomment_album(block, album_gain, album_peak)))
|
||||
return error;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *grabbag__replaygain_store_to_vorbiscomment_reference(FLAC__StreamMetadata *block)
|
||||
{
|
||||
FLAC__ASSERT(0 != block);
|
||||
FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
|
||||
|
||||
if(FLAC__metadata_object_vorbiscomment_remove_entries_matching(block, (const char *)GRABBAG__REPLAYGAIN_TAG_REFERENCE_LOUDNESS) < 0)
|
||||
return "memory allocation error";
|
||||
|
||||
if(!append_tag_(block, reference_format_, GRABBAG__REPLAYGAIN_TAG_REFERENCE_LOUDNESS, ReplayGainReferenceLoudness))
|
||||
return "memory allocation error";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *grabbag__replaygain_store_to_vorbiscomment_album(FLAC__StreamMetadata *block, float album_gain, float album_peak)
|
||||
{
|
||||
FLAC__ASSERT(0 != block);
|
||||
FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
|
||||
|
||||
if(
|
||||
FLAC__metadata_object_vorbiscomment_remove_entries_matching(block, (const char *)GRABBAG__REPLAYGAIN_TAG_ALBUM_GAIN) < 0 ||
|
||||
FLAC__metadata_object_vorbiscomment_remove_entries_matching(block, (const char *)GRABBAG__REPLAYGAIN_TAG_ALBUM_PEAK) < 0
|
||||
)
|
||||
return "memory allocation error";
|
||||
|
||||
if(
|
||||
!append_tag_(block, gain_format_, GRABBAG__REPLAYGAIN_TAG_ALBUM_GAIN, album_gain) ||
|
||||
!append_tag_(block, peak_format_, GRABBAG__REPLAYGAIN_TAG_ALBUM_PEAK, album_peak)
|
||||
)
|
||||
return "memory allocation error";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *grabbag__replaygain_store_to_vorbiscomment_title(FLAC__StreamMetadata *block, float title_gain, float title_peak)
|
||||
{
|
||||
FLAC__ASSERT(0 != block);
|
||||
FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
|
||||
|
||||
if(
|
||||
FLAC__metadata_object_vorbiscomment_remove_entries_matching(block, (const char *)GRABBAG__REPLAYGAIN_TAG_TITLE_GAIN) < 0 ||
|
||||
FLAC__metadata_object_vorbiscomment_remove_entries_matching(block, (const char *)GRABBAG__REPLAYGAIN_TAG_TITLE_PEAK) < 0
|
||||
)
|
||||
return "memory allocation error";
|
||||
|
||||
if(
|
||||
!append_tag_(block, gain_format_, GRABBAG__REPLAYGAIN_TAG_TITLE_GAIN, title_gain) ||
|
||||
!append_tag_(block, peak_format_, GRABBAG__REPLAYGAIN_TAG_TITLE_PEAK, title_peak)
|
||||
)
|
||||
return "memory allocation error";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *store_to_file_pre_(const char *filename, FLAC__Metadata_Chain **chain, FLAC__StreamMetadata **block)
|
||||
{
|
||||
FLAC__Metadata_Iterator *iterator;
|
||||
const char *error;
|
||||
FLAC__bool found_vc_block = false;
|
||||
|
||||
if(0 == (*chain = FLAC__metadata_chain_new()))
|
||||
return "memory allocation error";
|
||||
|
||||
if(!FLAC__metadata_chain_read(*chain, filename)) {
|
||||
error = FLAC__Metadata_ChainStatusString[FLAC__metadata_chain_status(*chain)];
|
||||
FLAC__metadata_chain_delete(*chain);
|
||||
return error;
|
||||
}
|
||||
|
||||
if(0 == (iterator = FLAC__metadata_iterator_new())) {
|
||||
FLAC__metadata_chain_delete(*chain);
|
||||
return "memory allocation error";
|
||||
}
|
||||
|
||||
FLAC__metadata_iterator_init(iterator, *chain);
|
||||
|
||||
do {
|
||||
*block = FLAC__metadata_iterator_get_block(iterator);
|
||||
if((*block)->type == FLAC__METADATA_TYPE_VORBIS_COMMENT)
|
||||
found_vc_block = true;
|
||||
} while(!found_vc_block && FLAC__metadata_iterator_next(iterator));
|
||||
|
||||
if(!found_vc_block) {
|
||||
/* create a new block */
|
||||
*block = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT);
|
||||
if(0 == *block) {
|
||||
FLAC__metadata_chain_delete(*chain);
|
||||
FLAC__metadata_iterator_delete(iterator);
|
||||
return "memory allocation error";
|
||||
}
|
||||
while(FLAC__metadata_iterator_next(iterator))
|
||||
;
|
||||
if(!FLAC__metadata_iterator_insert_block_after(iterator, *block)) {
|
||||
error = FLAC__Metadata_ChainStatusString[FLAC__metadata_chain_status(*chain)];
|
||||
FLAC__metadata_chain_delete(*chain);
|
||||
FLAC__metadata_iterator_delete(iterator);
|
||||
return error;
|
||||
}
|
||||
/* iterator is left pointing to new block */
|
||||
FLAC__ASSERT(FLAC__metadata_iterator_get_block(iterator) == *block);
|
||||
}
|
||||
|
||||
FLAC__metadata_iterator_delete(iterator);
|
||||
|
||||
FLAC__ASSERT(0 != *block);
|
||||
FLAC__ASSERT((*block)->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *store_to_file_post_(const char *filename, FLAC__Metadata_Chain *chain, FLAC__bool preserve_modtime)
|
||||
{
|
||||
struct stat stats;
|
||||
const FLAC__bool have_stats = get_file_stats_(filename, &stats);
|
||||
|
||||
(void)grabbag__file_change_stats(filename, /*read_only=*/false);
|
||||
|
||||
FLAC__metadata_chain_sort_padding(chain);
|
||||
if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, preserve_modtime)) {
|
||||
FLAC__metadata_chain_delete(chain);
|
||||
return FLAC__Metadata_ChainStatusString[FLAC__metadata_chain_status(chain)];
|
||||
}
|
||||
|
||||
FLAC__metadata_chain_delete(chain);
|
||||
|
||||
if(have_stats)
|
||||
set_file_stats_(filename, &stats);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *grabbag__replaygain_store_to_file(const char *filename, float album_gain, float album_peak, float title_gain, float title_peak, FLAC__bool preserve_modtime)
|
||||
{
|
||||
FLAC__Metadata_Chain *chain;
|
||||
FLAC__StreamMetadata *block;
|
||||
const char *error;
|
||||
|
||||
if(0 != (error = store_to_file_pre_(filename, &chain, &block)))
|
||||
return error;
|
||||
|
||||
if(0 != (error = grabbag__replaygain_store_to_vorbiscomment(block, album_gain, album_peak, title_gain, title_peak))) {
|
||||
FLAC__metadata_chain_delete(chain);
|
||||
return error;
|
||||
}
|
||||
|
||||
if(0 != (error = store_to_file_post_(filename, chain, preserve_modtime)))
|
||||
return error;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *grabbag__replaygain_store_to_file_reference(const char *filename, FLAC__bool preserve_modtime)
|
||||
{
|
||||
FLAC__Metadata_Chain *chain;
|
||||
FLAC__StreamMetadata *block;
|
||||
const char *error;
|
||||
|
||||
if(0 != (error = store_to_file_pre_(filename, &chain, &block)))
|
||||
return error;
|
||||
|
||||
if(0 != (error = grabbag__replaygain_store_to_vorbiscomment_reference(block))) {
|
||||
FLAC__metadata_chain_delete(chain);
|
||||
return error;
|
||||
}
|
||||
|
||||
if(0 != (error = store_to_file_post_(filename, chain, preserve_modtime)))
|
||||
return error;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *grabbag__replaygain_store_to_file_album(const char *filename, float album_gain, float album_peak, FLAC__bool preserve_modtime)
|
||||
{
|
||||
FLAC__Metadata_Chain *chain;
|
||||
FLAC__StreamMetadata *block;
|
||||
const char *error;
|
||||
|
||||
if(0 != (error = store_to_file_pre_(filename, &chain, &block)))
|
||||
return error;
|
||||
|
||||
if(0 != (error = grabbag__replaygain_store_to_vorbiscomment_album(block, album_gain, album_peak))) {
|
||||
FLAC__metadata_chain_delete(chain);
|
||||
return error;
|
||||
}
|
||||
|
||||
if(0 != (error = store_to_file_post_(filename, chain, preserve_modtime)))
|
||||
return error;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *grabbag__replaygain_store_to_file_title(const char *filename, float title_gain, float title_peak, FLAC__bool preserve_modtime)
|
||||
{
|
||||
FLAC__Metadata_Chain *chain;
|
||||
FLAC__StreamMetadata *block;
|
||||
const char *error;
|
||||
|
||||
if(0 != (error = store_to_file_pre_(filename, &chain, &block)))
|
||||
return error;
|
||||
|
||||
if(0 != (error = grabbag__replaygain_store_to_vorbiscomment_title(block, title_gain, title_peak))) {
|
||||
FLAC__metadata_chain_delete(chain);
|
||||
return error;
|
||||
}
|
||||
|
||||
if(0 != (error = store_to_file_post_(filename, chain, preserve_modtime)))
|
||||
return error;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static FLAC__bool parse_double_(const FLAC__StreamMetadata_VorbisComment_Entry *entry, double *val)
|
||||
{
|
||||
char s[32], *end;
|
||||
const char *p, *q;
|
||||
double v;
|
||||
|
||||
FLAC__ASSERT(0 != entry);
|
||||
FLAC__ASSERT(0 != val);
|
||||
|
||||
p = (const char *)entry->entry;
|
||||
q = strchr(p, '=');
|
||||
if(0 == q)
|
||||
return false;
|
||||
q++;
|
||||
memset(s, 0, sizeof(s)-1);
|
||||
strncpy(s, q, local_min(sizeof(s)-1, entry->length - (q-p)));
|
||||
|
||||
v = strtod(s, &end);
|
||||
if(end == s)
|
||||
return false;
|
||||
|
||||
*val = v;
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC__bool grabbag__replaygain_load_from_vorbiscomment(const FLAC__StreamMetadata *block, FLAC__bool album_mode, FLAC__bool strict, double *reference, double *gain, double *peak)
|
||||
{
|
||||
int reference_offset, gain_offset, peak_offset;
|
||||
|
||||
FLAC__ASSERT(0 != block);
|
||||
FLAC__ASSERT(0 != reference);
|
||||
FLAC__ASSERT(0 != gain);
|
||||
FLAC__ASSERT(0 != peak);
|
||||
FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
|
||||
|
||||
/* Default to current level until overridden by a detected tag; this
|
||||
* will always be true until we change replaygain_analysis.c
|
||||
*/
|
||||
*reference = ReplayGainReferenceLoudness;
|
||||
|
||||
if(0 <= (reference_offset = FLAC__metadata_object_vorbiscomment_find_entry_from(block, /*offset=*/0, (const char *)GRABBAG__REPLAYGAIN_TAG_REFERENCE_LOUDNESS)))
|
||||
(void)parse_double_(block->data.vorbis_comment.comments + reference_offset, reference);
|
||||
|
||||
if(0 > (gain_offset = FLAC__metadata_object_vorbiscomment_find_entry_from(block, /*offset=*/0, (const char *)(album_mode? GRABBAG__REPLAYGAIN_TAG_ALBUM_GAIN : GRABBAG__REPLAYGAIN_TAG_TITLE_GAIN))))
|
||||
return !strict && grabbag__replaygain_load_from_vorbiscomment(block, !album_mode, /*strict=*/true, reference, gain, peak);
|
||||
if(0 > (peak_offset = FLAC__metadata_object_vorbiscomment_find_entry_from(block, /*offset=*/0, (const char *)(album_mode? GRABBAG__REPLAYGAIN_TAG_ALBUM_PEAK : GRABBAG__REPLAYGAIN_TAG_TITLE_PEAK))))
|
||||
return !strict && grabbag__replaygain_load_from_vorbiscomment(block, !album_mode, /*strict=*/true, reference, gain, peak);
|
||||
|
||||
if(!parse_double_(block->data.vorbis_comment.comments + gain_offset, gain))
|
||||
return !strict && grabbag__replaygain_load_from_vorbiscomment(block, !album_mode, /*strict=*/true, reference, gain, peak);
|
||||
if(!parse_double_(block->data.vorbis_comment.comments + peak_offset, peak))
|
||||
return !strict && grabbag__replaygain_load_from_vorbiscomment(block, !album_mode, /*strict=*/true, reference, gain, peak);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
double grabbag__replaygain_compute_scale_factor(double peak, double gain, double preamp, FLAC__bool prevent_clipping)
|
||||
{
|
||||
double scale;
|
||||
FLAC__ASSERT(peak >= 0.0);
|
||||
gain += preamp;
|
||||
scale = (float) pow(10.0, gain * 0.05);
|
||||
if(prevent_clipping && peak > 0.0) {
|
||||
const double max_scale = (float)(1.0 / peak);
|
||||
if(scale > max_scale)
|
||||
scale = max_scale;
|
||||
}
|
||||
return scale;
|
||||
}
|
||||
132
flac/src/share/grabbag/seektable.c
Normal file
132
flac/src/share/grabbag/seektable.c
Normal file
@@ -0,0 +1,132 @@
|
||||
/* grabbag - Convenience lib for various routines common to several tools
|
||||
* Copyright (C) 2002,2003,2004,2005,2006,2007,2008 Josh Coalson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "share/grabbag.h"
|
||||
#include "FLAC/assert.h"
|
||||
#include <stdlib.h> /* for atoi() */
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
/* There's no strtoll() in MSVC6 so we just write a specialized one */
|
||||
static FLAC__int64 local__strtoll(const char *src, char **endptr)
|
||||
{
|
||||
FLAC__bool neg = false;
|
||||
FLAC__int64 ret = 0;
|
||||
int c;
|
||||
FLAC__ASSERT(0 != src);
|
||||
if(*src == '-') {
|
||||
neg = true;
|
||||
src++;
|
||||
}
|
||||
while(0 != (c = *src)) {
|
||||
c -= '0';
|
||||
if(c >= 0 && c <= 9)
|
||||
ret = (ret * 10) + c;
|
||||
else
|
||||
break;
|
||||
src++;
|
||||
}
|
||||
if(endptr)
|
||||
*endptr = (char*)src;
|
||||
return neg? -ret : ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
FLAC__bool grabbag__seektable_convert_specification_to_template(const char *spec, FLAC__bool only_explicit_placeholders, FLAC__uint64 total_samples_to_encode, unsigned sample_rate, FLAC__StreamMetadata *seektable_template, FLAC__bool *spec_has_real_points)
|
||||
{
|
||||
unsigned i;
|
||||
const char *pt;
|
||||
|
||||
FLAC__ASSERT(0 != spec);
|
||||
FLAC__ASSERT(0 != seektable_template);
|
||||
FLAC__ASSERT(seektable_template->type = FLAC__METADATA_TYPE_SEEKTABLE);
|
||||
|
||||
if(0 != spec_has_real_points)
|
||||
*spec_has_real_points = false;
|
||||
|
||||
for(pt = spec, i = 0; pt && *pt; i++) {
|
||||
const char *q = strchr(pt, ';');
|
||||
FLAC__ASSERT(0 != q);
|
||||
|
||||
if(q > pt) {
|
||||
if(0 == strncmp(pt, "X;", 2)) { /* -S X */
|
||||
if(!FLAC__metadata_object_seektable_template_append_placeholders(seektable_template, 1))
|
||||
return false;
|
||||
}
|
||||
else if(q[-1] == 'x') { /* -S #x */
|
||||
if(total_samples_to_encode > 0) { /* we can only do these if we know the number of samples to encode up front */
|
||||
if(0 != spec_has_real_points)
|
||||
*spec_has_real_points = true;
|
||||
if(!only_explicit_placeholders) {
|
||||
const int n = (unsigned)atoi(pt);
|
||||
if(n > 0)
|
||||
if(!FLAC__metadata_object_seektable_template_append_spaced_points(seektable_template, (unsigned)n, total_samples_to_encode))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(q[-1] == 's') { /* -S #s */
|
||||
if(total_samples_to_encode > 0) { /* we can only do these if we know the number of samples to encode up front */
|
||||
FLAC__ASSERT(sample_rate > 0);
|
||||
if(0 != spec_has_real_points)
|
||||
*spec_has_real_points = true;
|
||||
if(!only_explicit_placeholders) {
|
||||
const double sec = atof(pt);
|
||||
if(sec > 0.0) {
|
||||
unsigned samples = (unsigned)(sec * (double)sample_rate);
|
||||
if(samples > 0) {
|
||||
/* +1 for the initial point at sample 0 */
|
||||
if(!FLAC__metadata_object_seektable_template_append_spaced_points_by_samples(seektable_template, samples, total_samples_to_encode))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else { /* -S # */
|
||||
if(0 != spec_has_real_points)
|
||||
*spec_has_real_points = true;
|
||||
if(!only_explicit_placeholders) {
|
||||
char *endptr;
|
||||
#ifdef _MSC_VER
|
||||
const FLAC__int64 n = local__strtoll(pt, &endptr);
|
||||
#else
|
||||
const FLAC__int64 n = (FLAC__int64)strtoll(pt, &endptr, 10);
|
||||
#endif
|
||||
if(
|
||||
(n > 0 || (endptr > pt && *endptr == ';')) && /* is a valid number (extra check needed for "0") */
|
||||
(total_samples_to_encode == 0 || (FLAC__uint64)n < total_samples_to_encode) /* number is not >= the known total_samples_to_encode */
|
||||
)
|
||||
if(!FLAC__metadata_object_seektable_template_append_point(seektable_template, (FLAC__uint64)n))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pt = ++q;
|
||||
}
|
||||
|
||||
if(!FLAC__metadata_object_seektable_template_sort(seektable_template, /*compact=*/true))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
20
flac/src/share/replaygain_analysis/Makefile.am
Normal file
20
flac/src/share/replaygain_analysis/Makefile.am
Normal file
@@ -0,0 +1,20 @@
|
||||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/include/share
|
||||
|
||||
noinst_LTLIBRARIES = libreplaygain_analysis.la
|
||||
|
||||
libreplaygain_analysis_la_SOURCES = replaygain_analysis.c
|
||||
|
||||
EXTRA_DIST = \
|
||||
Makefile.lite \
|
||||
replaygain_analysis_static.dsp \
|
||||
replaygain_analysis_static.vcproj
|
||||
|
||||
debug:
|
||||
$(MAKE) all CFLAGS="@DEBUG@"
|
||||
|
||||
profile:
|
||||
$(MAKE) all CFLAGS="@PROFILE@"
|
||||
15
flac/src/share/replaygain_analysis/Makefile.lite
Normal file
15
flac/src/share/replaygain_analysis/Makefile.lite
Normal file
@@ -0,0 +1,15 @@
|
||||
#
|
||||
# GNU makefile
|
||||
#
|
||||
|
||||
topdir = ../../..
|
||||
|
||||
LIB_NAME = libreplaygain_analysis
|
||||
INCLUDES = -I$(topdir)/include/share
|
||||
|
||||
SRCS_C = \
|
||||
replaygain_analysis.c
|
||||
|
||||
include $(topdir)/build/lib.mk
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
430
flac/src/share/replaygain_analysis/replaygain_analysis.c
Normal file
430
flac/src/share/replaygain_analysis/replaygain_analysis.c
Normal file
@@ -0,0 +1,430 @@
|
||||
/*
|
||||
* ReplayGainAnalysis - analyzes input samples and give the recommended dB change
|
||||
* Copyright (C) 2001 David Robinson and Glen Sawyer
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* concept and filter values by David Robinson (David@Robinson.org)
|
||||
* -- blame him if you think the idea is flawed
|
||||
* original coding by Glen Sawyer (glensawyer@hotmail.com)
|
||||
* -- blame him if you think this runs too slowly, or the coding is otherwise flawed
|
||||
*
|
||||
* lots of code improvements by Frank Klemm ( http://www.uni-jena.de/~pfk/mpp/ )
|
||||
* -- credit him for all the _good_ programming ;)
|
||||
*
|
||||
* minor cosmetic tweaks to integrate with FLAC by Josh Coalson
|
||||
*
|
||||
*
|
||||
* For an explanation of the concepts and the basic algorithms involved, go to:
|
||||
* http://www.replaygain.org/
|
||||
*/
|
||||
|
||||
/*
|
||||
* Here's the deal. Call
|
||||
*
|
||||
* InitGainAnalysis ( long samplefreq );
|
||||
*
|
||||
* to initialize everything. Call
|
||||
*
|
||||
* AnalyzeSamples ( const Float_t* left_samples,
|
||||
* const Float_t* right_samples,
|
||||
* size_t num_samples,
|
||||
* int num_channels );
|
||||
*
|
||||
* as many times as you want, with as many or as few samples as you want.
|
||||
* If mono, pass the sample buffer in through left_samples, leave
|
||||
* right_samples NULL, and make sure num_channels = 1.
|
||||
*
|
||||
* GetTitleGain()
|
||||
*
|
||||
* will return the recommended dB level change for all samples analyzed
|
||||
* SINCE THE LAST TIME you called GetTitleGain() OR InitGainAnalysis().
|
||||
*
|
||||
* GetAlbumGain()
|
||||
*
|
||||
* will return the recommended dB level change for all samples analyzed
|
||||
* since InitGainAnalysis() was called and finalized with GetTitleGain().
|
||||
*
|
||||
* Pseudo-code to process an album:
|
||||
*
|
||||
* Float_t l_samples [4096];
|
||||
* Float_t r_samples [4096];
|
||||
* size_t num_samples;
|
||||
* unsigned int num_songs;
|
||||
* unsigned int i;
|
||||
*
|
||||
* InitGainAnalysis ( 44100 );
|
||||
* for ( i = 1; i <= num_songs; i++ ) {
|
||||
* while ( ( num_samples = getSongSamples ( song[i], left_samples, right_samples ) ) > 0 )
|
||||
* AnalyzeSamples ( left_samples, right_samples, num_samples, 2 );
|
||||
* fprintf ("Recommended dB change for song %2d: %+6.2f dB\n", i, GetTitleGain() );
|
||||
* }
|
||||
* fprintf ("Recommended dB change for whole album: %+6.2f dB\n", GetAlbumGain() );
|
||||
*/
|
||||
|
||||
/*
|
||||
* So here's the main source of potential code confusion:
|
||||
*
|
||||
* The filters applied to the incoming samples are IIR filters,
|
||||
* meaning they rely on up to <filter order> number of previous samples
|
||||
* AND up to <filter order> number of previous filtered samples.
|
||||
*
|
||||
* I set up the AnalyzeSamples routine to minimize memory usage and interface
|
||||
* complexity. The speed isn't compromised too much (I don't think), but the
|
||||
* internal complexity is higher than it should be for such a relatively
|
||||
* simple routine.
|
||||
*
|
||||
* Optimization/clarity suggestions are welcome.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "replaygain_analysis.h"
|
||||
|
||||
Float_t ReplayGainReferenceLoudness = 89.0; /* in dB SPL */
|
||||
|
||||
typedef unsigned short Uint16_t;
|
||||
typedef signed short Int16_t;
|
||||
typedef unsigned int Uint32_t;
|
||||
typedef signed int Int32_t;
|
||||
|
||||
#define YULE_ORDER 10
|
||||
#define BUTTER_ORDER 2
|
||||
#define RMS_PERCENTILE 0.95 /* percentile which is louder than the proposed level */
|
||||
#define MAX_SAMP_FREQ 48000. /* maximum allowed sample frequency [Hz] */
|
||||
#define RMS_WINDOW_TIME 0.050 /* Time slice size [s] */
|
||||
#define STEPS_per_dB 100. /* Table entries per dB */
|
||||
#define MAX_dB 120. /* Table entries for 0...MAX_dB (normal max. values are 70...80 dB) */
|
||||
|
||||
#define MAX_ORDER (BUTTER_ORDER > YULE_ORDER ? BUTTER_ORDER : YULE_ORDER)
|
||||
/* [JEC] the following was originally #defined as:
|
||||
* (size_t) (MAX_SAMP_FREQ * RMS_WINDOW_TIME)
|
||||
* but that seemed to fail to take into account the ceil() part of the
|
||||
* sampleWindow calculation in ResetSampleFrequency(), and was causing
|
||||
* buffer overflows for 48kHz analysis, hence the +1.
|
||||
*/
|
||||
#ifndef __sun
|
||||
#define MAX_SAMPLES_PER_WINDOW (size_t) (MAX_SAMP_FREQ * RMS_WINDOW_TIME + 1.) /* max. Samples per Time slice */
|
||||
#else
|
||||
/* [JEC] Solaris Forte compiler doesn't like float calc in array indices */
|
||||
#define MAX_SAMPLES_PER_WINDOW (size_t) (2401)
|
||||
#endif
|
||||
#define PINK_REF 64.82 /* 298640883795 */ /* calibration value */
|
||||
|
||||
static Float_t linprebuf [MAX_ORDER * 2];
|
||||
static Float_t* linpre; /* left input samples, with pre-buffer */
|
||||
static Float_t lstepbuf [MAX_SAMPLES_PER_WINDOW + MAX_ORDER];
|
||||
static Float_t* lstep; /* left "first step" (i.e. post first filter) samples */
|
||||
static Float_t loutbuf [MAX_SAMPLES_PER_WINDOW + MAX_ORDER];
|
||||
static Float_t* lout; /* left "out" (i.e. post second filter) samples */
|
||||
static Float_t rinprebuf [MAX_ORDER * 2];
|
||||
static Float_t* rinpre; /* right input samples ... */
|
||||
static Float_t rstepbuf [MAX_SAMPLES_PER_WINDOW + MAX_ORDER];
|
||||
static Float_t* rstep;
|
||||
static Float_t routbuf [MAX_SAMPLES_PER_WINDOW + MAX_ORDER];
|
||||
static Float_t* rout;
|
||||
static unsigned int sampleWindow; /* number of samples required to reach number of milliseconds required for RMS window */
|
||||
static unsigned long totsamp;
|
||||
static double lsum;
|
||||
static double rsum;
|
||||
static int freqindex;
|
||||
#ifndef __sun
|
||||
static Uint32_t A [(size_t)(STEPS_per_dB * MAX_dB)];
|
||||
static Uint32_t B [(size_t)(STEPS_per_dB * MAX_dB)];
|
||||
#else
|
||||
/* [JEC] Solaris Forte compiler doesn't like float calc in array indices */
|
||||
static Uint32_t A [12000];
|
||||
static Uint32_t B [12000];
|
||||
#endif
|
||||
|
||||
/* for each filter:
|
||||
[0] 48 kHz, [1] 44.1 kHz, [2] 32 kHz, [3] 24 kHz, [4] 22050 Hz, [5] 16 kHz, [6] 12 kHz, [7] is 11025 Hz, [8] 8 kHz */
|
||||
|
||||
#ifdef WIN32
|
||||
#pragma warning ( disable : 4305 )
|
||||
#endif
|
||||
|
||||
static const Float_t AYule [9] [11] = {
|
||||
{ 1., -3.84664617118067, 7.81501653005538,-11.34170355132042, 13.05504219327545,-12.28759895145294, 9.48293806319790, -5.87257861775999, 2.75465861874613, -0.86984376593551, 0.13919314567432 },
|
||||
{ 1., -3.47845948550071, 6.36317777566148, -8.54751527471874, 9.47693607801280, -8.81498681370155, 6.85401540936998, -4.39470996079559, 2.19611684890774, -0.75104302451432, 0.13149317958808 },
|
||||
{ 1., -2.37898834973084, 2.84868151156327, -2.64577170229825, 2.23697657451713, -1.67148153367602, 1.00595954808547, -0.45953458054983, 0.16378164858596, -0.05032077717131, 0.02347897407020 },
|
||||
{ 1., -1.61273165137247, 1.07977492259970, -0.25656257754070, -0.16276719120440, -0.22638893773906, 0.39120800788284, -0.22138138954925, 0.04500235387352, 0.02005851806501, 0.00302439095741 },
|
||||
{ 1., -1.49858979367799, 0.87350271418188, 0.12205022308084, -0.80774944671438, 0.47854794562326, -0.12453458140019, -0.04067510197014, 0.08333755284107, -0.04237348025746, 0.02977207319925 },
|
||||
{ 1., -0.62820619233671, 0.29661783706366, -0.37256372942400, 0.00213767857124, -0.42029820170918, 0.22199650564824, 0.00613424350682, 0.06747620744683, 0.05784820375801, 0.03222754072173 },
|
||||
{ 1., -1.04800335126349, 0.29156311971249, -0.26806001042947, 0.00819999645858, 0.45054734505008, -0.33032403314006, 0.06739368333110, -0.04784254229033, 0.01639907836189, 0.01807364323573 },
|
||||
{ 1., -0.51035327095184, -0.31863563325245, -0.20256413484477, 0.14728154134330, 0.38952639978999, -0.23313271880868, -0.05246019024463, -0.02505961724053, 0.02442357316099, 0.01818801111503 },
|
||||
{ 1., -0.25049871956020, -0.43193942311114, -0.03424681017675, -0.04678328784242, 0.26408300200955, 0.15113130533216, -0.17556493366449, -0.18823009262115, 0.05477720428674, 0.04704409688120 }
|
||||
};
|
||||
|
||||
static const Float_t BYule [9] [11] = {
|
||||
{ 0.03857599435200, -0.02160367184185, -0.00123395316851, -0.00009291677959, -0.01655260341619, 0.02161526843274, -0.02074045215285, 0.00594298065125, 0.00306428023191, 0.00012025322027, 0.00288463683916 },
|
||||
{ 0.05418656406430, -0.02911007808948, -0.00848709379851, -0.00851165645469, -0.00834990904936, 0.02245293253339, -0.02596338512915, 0.01624864962975, -0.00240879051584, 0.00674613682247, -0.00187763777362 },
|
||||
{ 0.15457299681924, -0.09331049056315, -0.06247880153653, 0.02163541888798, -0.05588393329856, 0.04781476674921, 0.00222312597743, 0.03174092540049, -0.01390589421898, 0.00651420667831, -0.00881362733839 },
|
||||
{ 0.30296907319327, -0.22613988682123, -0.08587323730772, 0.03282930172664, -0.00915702933434, -0.02364141202522, -0.00584456039913, 0.06276101321749, -0.00000828086748, 0.00205861885564, -0.02950134983287 },
|
||||
{ 0.33642304856132, -0.25572241425570, -0.11828570177555, 0.11921148675203, -0.07834489609479, -0.00469977914380, -0.00589500224440, 0.05724228140351, 0.00832043980773, -0.01635381384540, -0.01760176568150 },
|
||||
{ 0.44915256608450, -0.14351757464547, -0.22784394429749, -0.01419140100551, 0.04078262797139, -0.12398163381748, 0.04097565135648, 0.10478503600251, -0.01863887810927, -0.03193428438915, 0.00541907748707 },
|
||||
{ 0.56619470757641, -0.75464456939302, 0.16242137742230, 0.16744243493672, -0.18901604199609, 0.30931782841830, -0.27562961986224, 0.00647310677246, 0.08647503780351, -0.03788984554840, -0.00588215443421 },
|
||||
{ 0.58100494960553, -0.53174909058578, -0.14289799034253, 0.17520704835522, 0.02377945217615, 0.15558449135573, -0.25344790059353, 0.01628462406333, 0.06920467763959, -0.03721611395801, -0.00749618797172 },
|
||||
{ 0.53648789255105, -0.42163034350696, -0.00275953611929, 0.04267842219415, -0.10214864179676, 0.14590772289388, -0.02459864859345, -0.11202315195388, -0.04060034127000, 0.04788665548180, -0.02217936801134 }
|
||||
};
|
||||
|
||||
static const Float_t AButter [9] [3] = {
|
||||
{ 1., -1.97223372919527, 0.97261396931306 },
|
||||
{ 1., -1.96977855582618, 0.97022847566350 },
|
||||
{ 1., -1.95835380975398, 0.95920349965459 },
|
||||
{ 1., -1.95002759149878, 0.95124613669835 },
|
||||
{ 1., -1.94561023566527, 0.94705070426118 },
|
||||
{ 1., -1.92783286977036, 0.93034775234268 },
|
||||
{ 1., -1.91858953033784, 0.92177618768381 },
|
||||
{ 1., -1.91542108074780, 0.91885558323625 },
|
||||
{ 1., -1.88903307939452, 0.89487434461664 }
|
||||
};
|
||||
|
||||
static const Float_t BButter [9] [3] = {
|
||||
{ 0.98621192462708, -1.97242384925416, 0.98621192462708 },
|
||||
{ 0.98500175787242, -1.97000351574484, 0.98500175787242 },
|
||||
{ 0.97938932735214, -1.95877865470428, 0.97938932735214 },
|
||||
{ 0.97531843204928, -1.95063686409857, 0.97531843204928 },
|
||||
{ 0.97316523498161, -1.94633046996323, 0.97316523498161 },
|
||||
{ 0.96454515552826, -1.92909031105652, 0.96454515552826 },
|
||||
{ 0.96009142950541, -1.92018285901082, 0.96009142950541 },
|
||||
{ 0.95856916599601, -1.91713833199203, 0.95856916599601 },
|
||||
{ 0.94597685600279, -1.89195371200558, 0.94597685600279 }
|
||||
};
|
||||
|
||||
#ifdef WIN32
|
||||
#pragma warning ( default : 4305 )
|
||||
#endif
|
||||
|
||||
/* When calling this procedure, make sure that ip[-order] and op[-order] point to real data! */
|
||||
|
||||
static void
|
||||
filter ( const Float_t* input, Float_t* output, size_t nSamples, const Float_t* a, const Float_t* b, size_t order )
|
||||
{
|
||||
double y;
|
||||
size_t i;
|
||||
size_t k;
|
||||
|
||||
for ( i = 0; i < nSamples; i++ ) {
|
||||
y = input[i] * b[0];
|
||||
for ( k = 1; k <= order; k++ )
|
||||
y += input[i-k] * b[k] - output[i-k] * a[k];
|
||||
output[i] = (Float_t)y;
|
||||
}
|
||||
}
|
||||
|
||||
/* returns a INIT_GAIN_ANALYSIS_OK if successful, INIT_GAIN_ANALYSIS_ERROR if not */
|
||||
|
||||
int
|
||||
ResetSampleFrequency ( long samplefreq ) {
|
||||
int i;
|
||||
|
||||
/* zero out initial values */
|
||||
for ( i = 0; i < MAX_ORDER; i++ )
|
||||
linprebuf[i] = lstepbuf[i] = loutbuf[i] = rinprebuf[i] = rstepbuf[i] = routbuf[i] = 0.;
|
||||
|
||||
switch ( (int)(samplefreq) ) {
|
||||
case 48000: freqindex = 0; break;
|
||||
case 44100: freqindex = 1; break;
|
||||
case 32000: freqindex = 2; break;
|
||||
case 24000: freqindex = 3; break;
|
||||
case 22050: freqindex = 4; break;
|
||||
case 16000: freqindex = 5; break;
|
||||
case 12000: freqindex = 6; break;
|
||||
case 11025: freqindex = 7; break;
|
||||
case 8000: freqindex = 8; break;
|
||||
default: return INIT_GAIN_ANALYSIS_ERROR;
|
||||
}
|
||||
|
||||
sampleWindow = (int) ceil (samplefreq * RMS_WINDOW_TIME);
|
||||
|
||||
lsum = 0.;
|
||||
rsum = 0.;
|
||||
totsamp = 0;
|
||||
|
||||
memset ( A, 0, sizeof(A) );
|
||||
|
||||
return INIT_GAIN_ANALYSIS_OK;
|
||||
}
|
||||
|
||||
int
|
||||
InitGainAnalysis ( long samplefreq )
|
||||
{
|
||||
if (ResetSampleFrequency(samplefreq) != INIT_GAIN_ANALYSIS_OK) {
|
||||
return INIT_GAIN_ANALYSIS_ERROR;
|
||||
}
|
||||
|
||||
linpre = linprebuf + MAX_ORDER;
|
||||
rinpre = rinprebuf + MAX_ORDER;
|
||||
lstep = lstepbuf + MAX_ORDER;
|
||||
rstep = rstepbuf + MAX_ORDER;
|
||||
lout = loutbuf + MAX_ORDER;
|
||||
rout = routbuf + MAX_ORDER;
|
||||
|
||||
memset ( B, 0, sizeof(B) );
|
||||
|
||||
return INIT_GAIN_ANALYSIS_OK;
|
||||
}
|
||||
|
||||
/* returns GAIN_ANALYSIS_OK if successful, GAIN_ANALYSIS_ERROR if not */
|
||||
|
||||
int
|
||||
AnalyzeSamples ( const Float_t* left_samples, const Float_t* right_samples, size_t num_samples, int num_channels )
|
||||
{
|
||||
const Float_t* curleft;
|
||||
const Float_t* curright;
|
||||
long batchsamples;
|
||||
long cursamples;
|
||||
long cursamplepos;
|
||||
int i;
|
||||
|
||||
if ( num_samples == 0 )
|
||||
return GAIN_ANALYSIS_OK;
|
||||
|
||||
cursamplepos = 0;
|
||||
batchsamples = num_samples;
|
||||
|
||||
switch ( num_channels) {
|
||||
case 1: right_samples = left_samples;
|
||||
case 2: break;
|
||||
default: return GAIN_ANALYSIS_ERROR;
|
||||
}
|
||||
|
||||
if ( num_samples < MAX_ORDER ) {
|
||||
memcpy ( linprebuf + MAX_ORDER, left_samples , num_samples * sizeof(Float_t) );
|
||||
memcpy ( rinprebuf + MAX_ORDER, right_samples, num_samples * sizeof(Float_t) );
|
||||
}
|
||||
else {
|
||||
memcpy ( linprebuf + MAX_ORDER, left_samples, MAX_ORDER * sizeof(Float_t) );
|
||||
memcpy ( rinprebuf + MAX_ORDER, right_samples, MAX_ORDER * sizeof(Float_t) );
|
||||
}
|
||||
|
||||
while ( batchsamples > 0 ) {
|
||||
cursamples = batchsamples > (long)(sampleWindow-totsamp) ? (long)(sampleWindow - totsamp) : batchsamples;
|
||||
if ( cursamplepos < MAX_ORDER ) {
|
||||
curleft = linpre+cursamplepos;
|
||||
curright = rinpre+cursamplepos;
|
||||
if (cursamples > MAX_ORDER - cursamplepos )
|
||||
cursamples = MAX_ORDER - cursamplepos;
|
||||
}
|
||||
else {
|
||||
curleft = left_samples + cursamplepos;
|
||||
curright = right_samples + cursamplepos;
|
||||
}
|
||||
|
||||
filter ( curleft , lstep + totsamp, cursamples, AYule[freqindex], BYule[freqindex], YULE_ORDER );
|
||||
filter ( curright, rstep + totsamp, cursamples, AYule[freqindex], BYule[freqindex], YULE_ORDER );
|
||||
|
||||
filter ( lstep + totsamp, lout + totsamp, cursamples, AButter[freqindex], BButter[freqindex], BUTTER_ORDER );
|
||||
filter ( rstep + totsamp, rout + totsamp, cursamples, AButter[freqindex], BButter[freqindex], BUTTER_ORDER );
|
||||
|
||||
for ( i = 0; i < cursamples; i++ ) { /* Get the squared values */
|
||||
lsum += lout [totsamp+i] * lout [totsamp+i];
|
||||
rsum += rout [totsamp+i] * rout [totsamp+i];
|
||||
}
|
||||
|
||||
batchsamples -= cursamples;
|
||||
cursamplepos += cursamples;
|
||||
totsamp += cursamples;
|
||||
if ( totsamp == sampleWindow ) { /* Get the Root Mean Square (RMS) for this set of samples */
|
||||
double val = STEPS_per_dB * 10. * log10 ( (lsum+rsum) / totsamp * 0.5 + 1.e-37 );
|
||||
int ival = (int) val;
|
||||
if ( ival < 0 ) ival = 0;
|
||||
if ( ival >= (int)(sizeof(A)/sizeof(*A)) ) ival = (int)(sizeof(A)/sizeof(*A)) - 1;
|
||||
A [ival]++;
|
||||
lsum = rsum = 0.;
|
||||
memmove ( loutbuf , loutbuf + totsamp, MAX_ORDER * sizeof(Float_t) );
|
||||
memmove ( routbuf , routbuf + totsamp, MAX_ORDER * sizeof(Float_t) );
|
||||
memmove ( lstepbuf, lstepbuf + totsamp, MAX_ORDER * sizeof(Float_t) );
|
||||
memmove ( rstepbuf, rstepbuf + totsamp, MAX_ORDER * sizeof(Float_t) );
|
||||
totsamp = 0;
|
||||
}
|
||||
if ( totsamp > sampleWindow ) /* somehow I really screwed up: Error in programming! Contact author about totsamp > sampleWindow */
|
||||
return GAIN_ANALYSIS_ERROR;
|
||||
}
|
||||
if ( num_samples < MAX_ORDER ) {
|
||||
memmove ( linprebuf, linprebuf + num_samples, (MAX_ORDER-num_samples) * sizeof(Float_t) );
|
||||
memmove ( rinprebuf, rinprebuf + num_samples, (MAX_ORDER-num_samples) * sizeof(Float_t) );
|
||||
memcpy ( linprebuf + MAX_ORDER - num_samples, left_samples, num_samples * sizeof(Float_t) );
|
||||
memcpy ( rinprebuf + MAX_ORDER - num_samples, right_samples, num_samples * sizeof(Float_t) );
|
||||
}
|
||||
else {
|
||||
memcpy ( linprebuf, left_samples + num_samples - MAX_ORDER, MAX_ORDER * sizeof(Float_t) );
|
||||
memcpy ( rinprebuf, right_samples + num_samples - MAX_ORDER, MAX_ORDER * sizeof(Float_t) );
|
||||
}
|
||||
|
||||
return GAIN_ANALYSIS_OK;
|
||||
}
|
||||
|
||||
|
||||
static Float_t
|
||||
analyzeResult ( Uint32_t* Array, size_t len )
|
||||
{
|
||||
Uint32_t elems;
|
||||
Int32_t upper;
|
||||
size_t i;
|
||||
|
||||
elems = 0;
|
||||
for ( i = 0; i < len; i++ )
|
||||
elems += Array[i];
|
||||
if ( elems == 0 )
|
||||
return GAIN_NOT_ENOUGH_SAMPLES;
|
||||
|
||||
upper = (Int32_t) ceil (elems * (1. - RMS_PERCENTILE));
|
||||
for ( i = len; i-- > 0; ) {
|
||||
if ( (upper -= Array[i]) <= 0 )
|
||||
break;
|
||||
}
|
||||
|
||||
return (Float_t) ((Float_t)PINK_REF - (Float_t)i / (Float_t)STEPS_per_dB);
|
||||
}
|
||||
|
||||
|
||||
Float_t
|
||||
GetTitleGain ( void )
|
||||
{
|
||||
Float_t retval;
|
||||
unsigned int i;
|
||||
|
||||
retval = analyzeResult ( A, sizeof(A)/sizeof(*A) );
|
||||
|
||||
for ( i = 0; i < sizeof(A)/sizeof(*A); i++ ) {
|
||||
B[i] += A[i];
|
||||
A[i] = 0;
|
||||
}
|
||||
|
||||
for ( i = 0; i < MAX_ORDER; i++ )
|
||||
linprebuf[i] = lstepbuf[i] = loutbuf[i] = rinprebuf[i] = rstepbuf[i] = routbuf[i] = 0.f;
|
||||
|
||||
totsamp = 0;
|
||||
lsum = rsum = 0.;
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
Float_t
|
||||
GetAlbumGain ( void )
|
||||
{
|
||||
return analyzeResult ( B, sizeof(B)/sizeof(*B) );
|
||||
}
|
||||
|
||||
/* end of replaygain_analysis.c */
|
||||
@@ -0,0 +1,108 @@
|
||||
# Microsoft Developer Studio Project File - Name="replaygain_analysis_static" - Package Owner=<4>
|
||||
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
|
||||
|
||||
# TARGTYPE "Win32 (x86) Static Library" 0x0104
|
||||
|
||||
|
||||
|
||||
CFG=replaygain_analysis_static - 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 "replaygain_analysis_static.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 "replaygain_analysis_static.mak" CFG="replaygain_analysis_static - Win32 Debug"
|
||||
|
||||
!MESSAGE
|
||||
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
|
||||
!MESSAGE
|
||||
|
||||
!MESSAGE "replaygain_analysis_static - Win32 Release" (based on "Win32 (x86) Static Library")
|
||||
|
||||
!MESSAGE "replaygain_analysis_static - Win32 Debug" (based on "Win32 (x86) Static Library")
|
||||
|
||||
!MESSAGE
|
||||
|
||||
|
||||
|
||||
# Begin Project
|
||||
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
|
||||
# PROP Scc_ProjName "replaygain_analysis"
|
||||
|
||||
# PROP Scc_LocalPath "..\..\.."
|
||||
|
||||
CPP=cl.exe
|
||||
|
||||
RSC=rc.exe
|
||||
|
||||
|
||||
|
||||
!IF "$(CFG)" == "replaygain_analysis_static - 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\lib"
|
||||
|
||||
# PROP Intermediate_Dir "Release_static"
|
||||
|
||||
# PROP Target_Dir ""
|
||||
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /Op /I ".\include" /I "..\..\..\include\share" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
|
||||
BSC32=bscmake.exe
|
||||
|
||||
# ADD BASE BSC32 /nologo
|
||||
|
||||
# ADD BSC32 /nologo
|
||||
|
||||
LIB32=link.exe -lib
|
||||
|
||||
# ADD BASE LIB32 /nologo
|
||||
|
||||
# ADD LIB32 /nologo /nodefaultlib
|
||||
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "replaygain_analysis_static - Win32 Debug"
|
||||
|
||||
@@ -0,0 +1,318 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8,00"
|
||||
Name="replaygain_analysis_static"
|
||||
ProjectGUID="{4cefbc89-c215-11db-8314-0800200c9a66}"
|
||||
RootNamespace="replaygain_analysis_static"
|
||||
Keyword="Win32Proj"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
<Platform
|
||||
Name="x64"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="..\..\..\obj\debug\lib"
|
||||
IntermediateDirectory="Debug_static"
|
||||
ConfigurationType="4"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=".\include;..\..\..\include\share"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;FLAC__NO_DLL;DEBUG"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="4"
|
||||
CompileAs="0"
|
||||
DisableSpecificWarnings="4267;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="..\..\..\obj\debug\lib\$(ProjectName).lib"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="..\..\..\obj\release\lib"
|
||||
IntermediateDirectory="Release_static"
|
||||
ConfigurationType="4"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
EnableIntrinsicFunctions="true"
|
||||
FavorSizeOrSpeed="1"
|
||||
OmitFramePointers="true"
|
||||
WholeProgramOptimization="true"
|
||||
AdditionalIncludeDirectories=".\include;..\..\..\include\share"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;FLAC__NO_DLL"
|
||||
RuntimeLibrary="0"
|
||||
BufferSecurityCheck="false"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"
|
||||
DisableSpecificWarnings="4267;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="..\..\..\obj\release\lib\$(ProjectName).lib"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug|x64"
|
||||
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TargetEnvironment="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=".\include;..\..\..\include\share"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;FLAC__NO_DLL;DEBUG"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"
|
||||
DisableSpecificWarnings="4267;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="..\..\..\obj\debug\lib\$(ProjectName).lib"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|x64"
|
||||
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TargetEnvironment="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
EnableIntrinsicFunctions="true"
|
||||
FavorSizeOrSpeed="1"
|
||||
OmitFramePointers="true"
|
||||
WholeProgramOptimization="true"
|
||||
AdditionalIncludeDirectories=".\include;..\..\..\include\share"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;FLAC__NO_DLL"
|
||||
RuntimeLibrary="0"
|
||||
BufferSecurityCheck="false"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"
|
||||
DisableSpecificWarnings="4267;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="..\..\..\obj\release\lib\$(ProjectName).lib"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Public Header Files"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\..\include\share\replaygain_analysis.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\replaygain_analysis.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
22
flac/src/share/replaygain_synthesis/Makefile.am
Normal file
22
flac/src/share/replaygain_synthesis/Makefile.am
Normal file
@@ -0,0 +1,22 @@
|
||||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
|
||||
SUBDIRS = include .
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/include/share
|
||||
|
||||
noinst_LTLIBRARIES = libreplaygain_synthesis.la
|
||||
|
||||
libreplaygain_synthesis_la_SOURCES = replaygain_synthesis.c
|
||||
|
||||
EXTRA_DIST = \
|
||||
Makefile.lite \
|
||||
replaygain_synthesis_static.dsp \
|
||||
replaygain_synthesis_static.vcproj
|
||||
|
||||
debug:
|
||||
$(MAKE) all CFLAGS="@DEBUG@"
|
||||
|
||||
profile:
|
||||
$(MAKE) all CFLAGS="@PROFILE@"
|
||||
15
flac/src/share/replaygain_synthesis/Makefile.lite
Normal file
15
flac/src/share/replaygain_synthesis/Makefile.lite
Normal file
@@ -0,0 +1,15 @@
|
||||
#
|
||||
# GNU makefile
|
||||
#
|
||||
|
||||
topdir = ../../..
|
||||
|
||||
LIB_NAME = libreplaygain_synthesis
|
||||
INCLUDES = -I./include -I$(topdir)/include -I$(topdir)/include/share
|
||||
|
||||
SRCS_C = \
|
||||
replaygain_synthesis.c
|
||||
|
||||
include $(topdir)/build/lib.mk
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
18
flac/src/share/replaygain_synthesis/include/Makefile.am
Normal file
18
flac/src/share/replaygain_synthesis/include/Makefile.am
Normal file
@@ -0,0 +1,18 @@
|
||||
# replaygain_synthesis - Routines for applying ReplayGain to a signal
|
||||
# Copyright (C) 2002,2003,2004,2005,2006,2007,2008 Josh Coalson
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
#
|
||||
# This library 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
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
SUBDIRS = private
|
||||
@@ -0,0 +1,19 @@
|
||||
# replaygain_synthesis - Routines for applying ReplayGain to a signal
|
||||
# Copyright (C) 2002,2003,2004,2005,2006,2007,2008 Josh Coalson
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
#
|
||||
# This library 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
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
noinst_HEADERS = \
|
||||
fast_float_math_hack.h
|
||||
@@ -0,0 +1,39 @@
|
||||
# ifdef __ICL /* only Intel C compiler has fmath ??? */
|
||||
|
||||
#include <mathf.h>
|
||||
|
||||
/* Nearest integer, absolute value, etc. */
|
||||
|
||||
#define ceil ceilf
|
||||
#define fabs fabsf
|
||||
#define floor floorf
|
||||
#define fmod fmodf
|
||||
#define rint rintf
|
||||
#define hypot hypotf
|
||||
|
||||
/* Power functions */
|
||||
|
||||
#define pow powf
|
||||
#define sqrt sqrtf
|
||||
|
||||
/* Exponential and logarithmic functions */
|
||||
|
||||
#define exp expf
|
||||
#define log logf
|
||||
#define log10 log10f
|
||||
|
||||
/* Trigonometric functions */
|
||||
|
||||
#define acos acosf
|
||||
#define asin asinf
|
||||
#define atan atanf
|
||||
#define cos cosf
|
||||
#define sin sinf
|
||||
#define tan tanf
|
||||
|
||||
/* Hyperbolic functions */
|
||||
#define cosh coshf
|
||||
#define sinh sinhf
|
||||
#define tanh tanhf
|
||||
|
||||
# endif
|
||||
467
flac/src/share/replaygain_synthesis/replaygain_synthesis.c
Normal file
467
flac/src/share/replaygain_synthesis/replaygain_synthesis.c
Normal file
@@ -0,0 +1,467 @@
|
||||
/* replaygain_synthesis - Routines for applying ReplayGain to a signal
|
||||
* Copyright (C) 2002,2003,2004,2005,2006,2007,2008 Josh Coalson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
/*
|
||||
* This is an aggregation of pieces of code from John Edwards' WaveGain
|
||||
* program. Mostly cosmetic changes were made; otherwise, the dithering
|
||||
* code is almost untouched and the gain processing was converted from
|
||||
* processing a whole file to processing chunks of samples.
|
||||
*
|
||||
* The original copyright notices for WaveGain's dither.c and wavegain.c
|
||||
* appear below:
|
||||
*/
|
||||
/*
|
||||
* (c) 2002 John Edwards
|
||||
* mostly lifted from work by Frank Klemm
|
||||
* random functions for dithering.
|
||||
*/
|
||||
/*
|
||||
* Copyright (C) 2002 John Edwards
|
||||
* Additional code by Magnus Holmgren and Gian-Carlo Pascutto
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h> /* for memset() */
|
||||
#include <math.h>
|
||||
#include "private/fast_float_math_hack.h"
|
||||
#include "replaygain_synthesis.h"
|
||||
#include "FLAC/assert.h"
|
||||
|
||||
#ifndef FLaC__INLINE
|
||||
#define FLaC__INLINE
|
||||
#endif
|
||||
|
||||
/* adjust for compilers that can't understand using LL suffix for int64_t literals */
|
||||
#ifdef _MSC_VER
|
||||
#define FLAC__I64L(x) x
|
||||
#else
|
||||
#define FLAC__I64L(x) x##LL
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* the following is based on parts of dither.c
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* This is a simple random number generator with good quality for audio purposes.
|
||||
* It consists of two polycounters with opposite rotation direction and different
|
||||
* periods. The periods are coprime, so the total period is the product of both.
|
||||
*
|
||||
* -------------------------------------------------------------------------------------------------
|
||||
* +-> |31:30:29:28:27:26:25:24:23:22:21:20:19:18:17:16:15:14:13:12:11:10: 9: 8: 7: 6: 5: 4: 3: 2: 1: 0|
|
||||
* | -------------------------------------------------------------------------------------------------
|
||||
* | | | | | | |
|
||||
* | +--+--+--+-XOR-+--------+
|
||||
* | |
|
||||
* +--------------------------------------------------------------------------------------+
|
||||
*
|
||||
* -------------------------------------------------------------------------------------------------
|
||||
* |31:30:29:28:27:26:25:24:23:22:21:20:19:18:17:16:15:14:13:12:11:10: 9: 8: 7: 6: 5: 4: 3: 2: 1: 0| <-+
|
||||
* ------------------------------------------------------------------------------------------------- |
|
||||
* | | | | |
|
||||
* +--+----XOR----+--+ |
|
||||
* | |
|
||||
* +----------------------------------------------------------------------------------------+
|
||||
*
|
||||
*
|
||||
* The first has an period of 3*5*17*257*65537, the second of 7*47*73*178481,
|
||||
* which gives a period of 18.410.713.077.675.721.215. The result is the
|
||||
* XORed values of both generators.
|
||||
*/
|
||||
|
||||
static unsigned int random_int_(void)
|
||||
{
|
||||
static const unsigned char parity_[256] = {
|
||||
0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,
|
||||
1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,
|
||||
1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,
|
||||
0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,
|
||||
1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,
|
||||
0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,
|
||||
0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,
|
||||
1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0
|
||||
};
|
||||
static unsigned int r1_ = 1;
|
||||
static unsigned int r2_ = 1;
|
||||
|
||||
unsigned int t1, t2, t3, t4;
|
||||
|
||||
/* Parity calculation is done via table lookup, this is also available
|
||||
* on CPUs without parity, can be implemented in C and avoid unpredictable
|
||||
* jumps and slow rotate through the carry flag operations.
|
||||
*/
|
||||
t3 = t1 = r1_; t4 = t2 = r2_;
|
||||
t1 &= 0xF5; t2 >>= 25;
|
||||
t1 = parity_[t1]; t2 &= 0x63;
|
||||
t1 <<= 31; t2 = parity_[t2];
|
||||
|
||||
return (r1_ = (t3 >> 1) | t1 ) ^ (r2_ = (t4 + t4) | t2 );
|
||||
}
|
||||
|
||||
/* gives a equal distributed random number */
|
||||
/* between -2^31*mult and +2^31*mult */
|
||||
static double random_equi_(double mult)
|
||||
{
|
||||
return mult * (int) random_int_();
|
||||
}
|
||||
|
||||
/* gives a triangular distributed random number */
|
||||
/* between -2^32*mult and +2^32*mult */
|
||||
static double random_triangular_(double mult)
|
||||
{
|
||||
return mult * ( (double) (int) random_int_() + (double) (int) random_int_() );
|
||||
}
|
||||
|
||||
|
||||
static const float F44_0 [16 + 32] = {
|
||||
(float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0,
|
||||
(float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0,
|
||||
|
||||
(float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0,
|
||||
(float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0,
|
||||
|
||||
(float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0,
|
||||
(float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0
|
||||
};
|
||||
|
||||
|
||||
static const float F44_1 [16 + 32] = { /* SNR(w) = 4.843163 dB, SNR = -3.192134 dB */
|
||||
(float) 0.85018292704024355931, (float) 0.29089597350995344721, (float)-0.05021866022121039450, (float)-0.23545456294599161833,
|
||||
(float)-0.58362726442227032096, (float)-0.67038978965193036429, (float)-0.38566861572833459221, (float)-0.15218663390367969967,
|
||||
(float)-0.02577543084864530676, (float) 0.14119295297688728127, (float) 0.22398848581628781612, (float) 0.15401727203382084116,
|
||||
(float) 0.05216161232906000929, (float)-0.00282237820999675451, (float)-0.03042794608323867363, (float)-0.03109780942998826024,
|
||||
|
||||
(float) 0.85018292704024355931, (float) 0.29089597350995344721, (float)-0.05021866022121039450, (float)-0.23545456294599161833,
|
||||
(float)-0.58362726442227032096, (float)-0.67038978965193036429, (float)-0.38566861572833459221, (float)-0.15218663390367969967,
|
||||
(float)-0.02577543084864530676, (float) 0.14119295297688728127, (float) 0.22398848581628781612, (float) 0.15401727203382084116,
|
||||
(float) 0.05216161232906000929, (float)-0.00282237820999675451, (float)-0.03042794608323867363, (float)-0.03109780942998826024,
|
||||
|
||||
(float) 0.85018292704024355931, (float) 0.29089597350995344721, (float)-0.05021866022121039450, (float)-0.23545456294599161833,
|
||||
(float)-0.58362726442227032096, (float)-0.67038978965193036429, (float)-0.38566861572833459221, (float)-0.15218663390367969967,
|
||||
(float)-0.02577543084864530676, (float) 0.14119295297688728127, (float) 0.22398848581628781612, (float) 0.15401727203382084116,
|
||||
(float) 0.05216161232906000929, (float)-0.00282237820999675451, (float)-0.03042794608323867363, (float)-0.03109780942998826024,
|
||||
};
|
||||
|
||||
|
||||
static const float F44_2 [16 + 32] = { /* SNR(w) = 10.060213 dB, SNR = -12.766730 dB */
|
||||
(float) 1.78827593892108555290, (float) 0.95508210637394326553, (float)-0.18447626783899924429, (float)-0.44198126506275016437,
|
||||
(float)-0.88404052492547413497, (float)-1.42218907262407452967, (float)-1.02037566838362314995, (float)-0.34861755756425577264,
|
||||
(float)-0.11490230170431934434, (float) 0.12498899339968611803, (float) 0.38065885268563131927, (float) 0.31883491321310506562,
|
||||
(float) 0.10486838686563442765, (float)-0.03105361685110374845, (float)-0.06450524884075370758, (float)-0.02939198261121969816,
|
||||
|
||||
(float) 1.78827593892108555290, (float) 0.95508210637394326553, (float)-0.18447626783899924429, (float)-0.44198126506275016437,
|
||||
(float)-0.88404052492547413497, (float)-1.42218907262407452967, (float)-1.02037566838362314995, (float)-0.34861755756425577264,
|
||||
(float)-0.11490230170431934434, (float) 0.12498899339968611803, (float) 0.38065885268563131927, (float) 0.31883491321310506562,
|
||||
(float) 0.10486838686563442765, (float)-0.03105361685110374845, (float)-0.06450524884075370758, (float)-0.02939198261121969816,
|
||||
|
||||
(float) 1.78827593892108555290, (float) 0.95508210637394326553, (float)-0.18447626783899924429, (float)-0.44198126506275016437,
|
||||
(float)-0.88404052492547413497, (float)-1.42218907262407452967, (float)-1.02037566838362314995, (float)-0.34861755756425577264,
|
||||
(float)-0.11490230170431934434, (float) 0.12498899339968611803, (float) 0.38065885268563131927, (float) 0.31883491321310506562,
|
||||
(float) 0.10486838686563442765, (float)-0.03105361685110374845, (float)-0.06450524884075370758, (float)-0.02939198261121969816,
|
||||
};
|
||||
|
||||
|
||||
static const float F44_3 [16 + 32] = { /* SNR(w) = 15.382598 dB, SNR = -29.402334 dB */
|
||||
(float) 2.89072132015058161445, (float) 2.68932810943698754106, (float) 0.21083359339410251227, (float)-0.98385073324997617515,
|
||||
(float)-1.11047823227097316719, (float)-2.18954076314139673147, (float)-2.36498032881953056225, (float)-0.95484132880101140785,
|
||||
(float)-0.23924057925542965158, (float)-0.13865235703915925642, (float) 0.43587843191057992846, (float) 0.65903257226026665927,
|
||||
(float) 0.24361815372443152787, (float)-0.00235974960154720097, (float) 0.01844166574603346289, (float) 0.01722945988740875099,
|
||||
|
||||
(float) 2.89072132015058161445, (float) 2.68932810943698754106, (float) 0.21083359339410251227, (float)-0.98385073324997617515,
|
||||
(float)-1.11047823227097316719, (float)-2.18954076314139673147, (float)-2.36498032881953056225, (float)-0.95484132880101140785,
|
||||
(float)-0.23924057925542965158, (float)-0.13865235703915925642, (float) 0.43587843191057992846, (float) 0.65903257226026665927,
|
||||
(float) 0.24361815372443152787, (float)-0.00235974960154720097, (float) 0.01844166574603346289, (float) 0.01722945988740875099,
|
||||
|
||||
(float) 2.89072132015058161445, (float) 2.68932810943698754106, (float) 0.21083359339410251227, (float)-0.98385073324997617515,
|
||||
(float)-1.11047823227097316719, (float)-2.18954076314139673147, (float)-2.36498032881953056225, (float)-0.95484132880101140785,
|
||||
(float)-0.23924057925542965158, (float)-0.13865235703915925642, (float) 0.43587843191057992846, (float) 0.65903257226026665927,
|
||||
(float) 0.24361815372443152787, (float)-0.00235974960154720097, (float) 0.01844166574603346289, (float) 0.01722945988740875099
|
||||
};
|
||||
|
||||
|
||||
static double scalar16_(const float* x, const float* y)
|
||||
{
|
||||
return
|
||||
x[ 0]*y[ 0] + x[ 1]*y[ 1] + x[ 2]*y[ 2] + x[ 3]*y[ 3] +
|
||||
x[ 4]*y[ 4] + x[ 5]*y[ 5] + x[ 6]*y[ 6] + x[ 7]*y[ 7] +
|
||||
x[ 8]*y[ 8] + x[ 9]*y[ 9] + x[10]*y[10] + x[11]*y[11] +
|
||||
x[12]*y[12] + x[13]*y[13] + x[14]*y[14] + x[15]*y[15];
|
||||
}
|
||||
|
||||
|
||||
void FLAC__replaygain_synthesis__init_dither_context(DitherContext *d, int bits, int shapingtype)
|
||||
{
|
||||
static unsigned char default_dither [] = { 92, 92, 88, 84, 81, 78, 74, 67, 0, 0 };
|
||||
static const float* F [] = { F44_0, F44_1, F44_2, F44_3 };
|
||||
|
||||
int index;
|
||||
|
||||
if (shapingtype < 0) shapingtype = 0;
|
||||
if (shapingtype > 3) shapingtype = 3;
|
||||
d->ShapingType = (NoiseShaping)shapingtype;
|
||||
index = bits - 11 - shapingtype;
|
||||
if (index < 0) index = 0;
|
||||
if (index > 9) index = 9;
|
||||
|
||||
memset ( d->ErrorHistory , 0, sizeof (d->ErrorHistory ) );
|
||||
memset ( d->DitherHistory, 0, sizeof (d->DitherHistory) );
|
||||
|
||||
d->FilterCoeff = F [shapingtype];
|
||||
d->Mask = ((FLAC__uint64)-1) << (32 - bits);
|
||||
d->Add = 0.5 * ((1L << (32 - bits)) - 1);
|
||||
d->Dither = 0.01f*default_dither[index] / (((FLAC__int64)1) << bits);
|
||||
d->LastHistoryIndex = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* the following is based on parts of wavegain.c
|
||||
*/
|
||||
|
||||
static FLaC__INLINE FLAC__int64 dither_output_(DitherContext *d, FLAC__bool do_dithering, int shapingtype, int i, double Sum, int k)
|
||||
{
|
||||
union {
|
||||
double d;
|
||||
FLAC__int64 i;
|
||||
} doubletmp;
|
||||
double Sum2;
|
||||
FLAC__int64 val;
|
||||
|
||||
#define ROUND64(x) ( doubletmp.d = (x) + d->Add + (FLAC__int64)FLAC__I64L(0x001FFFFD80000000), doubletmp.i - (FLAC__int64)FLAC__I64L(0x433FFFFD80000000) )
|
||||
|
||||
if(do_dithering) {
|
||||
if(shapingtype == 0) {
|
||||
double tmp = random_equi_(d->Dither);
|
||||
Sum2 = tmp - d->LastRandomNumber [k];
|
||||
d->LastRandomNumber [k] = (int)tmp;
|
||||
Sum2 = Sum += Sum2;
|
||||
val = ROUND64(Sum2) & d->Mask;
|
||||
}
|
||||
else {
|
||||
Sum2 = random_triangular_(d->Dither) - scalar16_(d->DitherHistory[k], d->FilterCoeff + i);
|
||||
Sum += d->DitherHistory [k] [(-1-i)&15] = (float)Sum2;
|
||||
Sum2 = Sum + scalar16_(d->ErrorHistory [k], d->FilterCoeff + i);
|
||||
val = ROUND64(Sum2) & d->Mask;
|
||||
d->ErrorHistory [k] [(-1-i)&15] = (float)(Sum - val);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
else
|
||||
return ROUND64(Sum);
|
||||
|
||||
#undef ROUND64
|
||||
}
|
||||
|
||||
#if 0
|
||||
float peak = 0.f,
|
||||
new_peak,
|
||||
factor_clip
|
||||
double scale,
|
||||
dB;
|
||||
|
||||
...
|
||||
|
||||
peak is in the range -32768.0 .. 32767.0
|
||||
|
||||
/* calculate factors for ReplayGain and ClippingPrevention */
|
||||
*track_gain = GetTitleGain() + settings->man_gain;
|
||||
scale = (float) pow(10., *track_gain * 0.05);
|
||||
if(settings->clip_prev) {
|
||||
factor_clip = (float) (32767./( peak + 1));
|
||||
if(scale < factor_clip)
|
||||
factor_clip = 1.f;
|
||||
else
|
||||
factor_clip /= scale;
|
||||
scale *= factor_clip;
|
||||
}
|
||||
new_peak = (float) peak * scale;
|
||||
|
||||
dB = 20. * log10(scale);
|
||||
*track_gain = (float) dB;
|
||||
|
||||
const double scale = pow(10., (double)gain * 0.05);
|
||||
#endif
|
||||
|
||||
|
||||
size_t FLAC__replaygain_synthesis__apply_gain(FLAC__byte *data_out, FLAC__bool little_endian_data_out, FLAC__bool unsigned_data_out, const FLAC__int32 * const input[], unsigned wide_samples, unsigned channels, const unsigned source_bps, const unsigned target_bps, const double scale, const FLAC__bool hard_limit, FLAC__bool do_dithering, DitherContext *dither_context)
|
||||
{
|
||||
static const FLAC__int32 conv_factors_[33] = {
|
||||
-1, /* 0 bits-per-sample (not supported) */
|
||||
-1, /* 1 bits-per-sample (not supported) */
|
||||
-1, /* 2 bits-per-sample (not supported) */
|
||||
-1, /* 3 bits-per-sample (not supported) */
|
||||
268435456, /* 4 bits-per-sample */
|
||||
134217728, /* 5 bits-per-sample */
|
||||
67108864, /* 6 bits-per-sample */
|
||||
33554432, /* 7 bits-per-sample */
|
||||
16777216, /* 8 bits-per-sample */
|
||||
8388608, /* 9 bits-per-sample */
|
||||
4194304, /* 10 bits-per-sample */
|
||||
2097152, /* 11 bits-per-sample */
|
||||
1048576, /* 12 bits-per-sample */
|
||||
524288, /* 13 bits-per-sample */
|
||||
262144, /* 14 bits-per-sample */
|
||||
131072, /* 15 bits-per-sample */
|
||||
65536, /* 16 bits-per-sample */
|
||||
32768, /* 17 bits-per-sample */
|
||||
16384, /* 18 bits-per-sample */
|
||||
8192, /* 19 bits-per-sample */
|
||||
4096, /* 20 bits-per-sample */
|
||||
2048, /* 21 bits-per-sample */
|
||||
1024, /* 22 bits-per-sample */
|
||||
512, /* 23 bits-per-sample */
|
||||
256, /* 24 bits-per-sample */
|
||||
128, /* 25 bits-per-sample */
|
||||
64, /* 26 bits-per-sample */
|
||||
32, /* 27 bits-per-sample */
|
||||
16, /* 28 bits-per-sample */
|
||||
8, /* 29 bits-per-sample */
|
||||
4, /* 30 bits-per-sample */
|
||||
2, /* 31 bits-per-sample */
|
||||
1 /* 32 bits-per-sample */
|
||||
};
|
||||
static const FLAC__int64 hard_clip_factors_[33] = {
|
||||
0, /* 0 bits-per-sample (not supported) */
|
||||
0, /* 1 bits-per-sample (not supported) */
|
||||
0, /* 2 bits-per-sample (not supported) */
|
||||
0, /* 3 bits-per-sample (not supported) */
|
||||
-8, /* 4 bits-per-sample */
|
||||
-16, /* 5 bits-per-sample */
|
||||
-32, /* 6 bits-per-sample */
|
||||
-64, /* 7 bits-per-sample */
|
||||
-128, /* 8 bits-per-sample */
|
||||
-256, /* 9 bits-per-sample */
|
||||
-512, /* 10 bits-per-sample */
|
||||
-1024, /* 11 bits-per-sample */
|
||||
-2048, /* 12 bits-per-sample */
|
||||
-4096, /* 13 bits-per-sample */
|
||||
-8192, /* 14 bits-per-sample */
|
||||
-16384, /* 15 bits-per-sample */
|
||||
-32768, /* 16 bits-per-sample */
|
||||
-65536, /* 17 bits-per-sample */
|
||||
-131072, /* 18 bits-per-sample */
|
||||
-262144, /* 19 bits-per-sample */
|
||||
-524288, /* 20 bits-per-sample */
|
||||
-1048576, /* 21 bits-per-sample */
|
||||
-2097152, /* 22 bits-per-sample */
|
||||
-4194304, /* 23 bits-per-sample */
|
||||
-8388608, /* 24 bits-per-sample */
|
||||
-16777216, /* 25 bits-per-sample */
|
||||
-33554432, /* 26 bits-per-sample */
|
||||
-67108864, /* 27 bits-per-sample */
|
||||
-134217728, /* 28 bits-per-sample */
|
||||
-268435456, /* 29 bits-per-sample */
|
||||
-536870912, /* 30 bits-per-sample */
|
||||
-1073741824, /* 31 bits-per-sample */
|
||||
(FLAC__int64)(-1073741824) * 2 /* 32 bits-per-sample */
|
||||
};
|
||||
const FLAC__int32 conv_factor = conv_factors_[target_bps];
|
||||
const FLAC__int64 hard_clip_factor = hard_clip_factors_[target_bps];
|
||||
/*
|
||||
* The integer input coming in has a varying range based on the
|
||||
* source_bps. We want to normalize it to [-1.0, 1.0) so instead
|
||||
* of doing two multiplies on each sample, we just multiple
|
||||
* 'scale' by 1/(2^(source_bps-1))
|
||||
*/
|
||||
const double multi_scale = scale / (double)(1u << (source_bps-1));
|
||||
|
||||
FLAC__byte * const start = data_out;
|
||||
unsigned i, channel;
|
||||
const FLAC__int32 *input_;
|
||||
double sample;
|
||||
const unsigned bytes_per_sample = target_bps / 8;
|
||||
const unsigned last_history_index = dither_context->LastHistoryIndex;
|
||||
NoiseShaping noise_shaping = dither_context->ShapingType;
|
||||
FLAC__int64 val64;
|
||||
FLAC__int32 val32;
|
||||
FLAC__int32 uval32;
|
||||
const FLAC__uint32 twiggle = 1u << (target_bps - 1);
|
||||
|
||||
FLAC__ASSERT(channels > 0 && channels <= FLAC_SHARE__MAX_SUPPORTED_CHANNELS);
|
||||
FLAC__ASSERT(source_bps >= 4);
|
||||
FLAC__ASSERT(target_bps >= 4);
|
||||
FLAC__ASSERT(source_bps <= 32);
|
||||
FLAC__ASSERT(target_bps < 32);
|
||||
FLAC__ASSERT((target_bps & 7) == 0);
|
||||
|
||||
for(channel = 0; channel < channels; channel++) {
|
||||
const unsigned incr = bytes_per_sample * channels;
|
||||
data_out = start + bytes_per_sample * channel;
|
||||
input_ = input[channel];
|
||||
for(i = 0; i < wide_samples; i++, data_out += incr) {
|
||||
sample = (double)input_[i] * multi_scale;
|
||||
|
||||
if(hard_limit) {
|
||||
/* hard 6dB limiting */
|
||||
if(sample < -0.5)
|
||||
sample = tanh((sample + 0.5) / (1-0.5)) * (1-0.5) - 0.5;
|
||||
else if(sample > 0.5)
|
||||
sample = tanh((sample - 0.5) / (1-0.5)) * (1-0.5) + 0.5;
|
||||
}
|
||||
sample *= 2147483647.f;
|
||||
|
||||
val64 = dither_output_(dither_context, do_dithering, noise_shaping, (i + last_history_index) % 32, sample, channel) / conv_factor;
|
||||
|
||||
val32 = (FLAC__int32)val64;
|
||||
if(val64 >= -hard_clip_factor)
|
||||
val32 = (FLAC__int32)(-(hard_clip_factor+1));
|
||||
else if(val64 < hard_clip_factor)
|
||||
val32 = (FLAC__int32)hard_clip_factor;
|
||||
|
||||
uval32 = (FLAC__uint32)val32;
|
||||
if (unsigned_data_out)
|
||||
uval32 ^= twiggle;
|
||||
|
||||
if (little_endian_data_out) {
|
||||
switch(target_bps) {
|
||||
case 24:
|
||||
data_out[2] = (FLAC__byte)(uval32 >> 16);
|
||||
/* fall through */
|
||||
case 16:
|
||||
data_out[1] = (FLAC__byte)(uval32 >> 8);
|
||||
/* fall through */
|
||||
case 8:
|
||||
data_out[0] = (FLAC__byte)uval32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch(target_bps) {
|
||||
case 24:
|
||||
data_out[0] = (FLAC__byte)(uval32 >> 16);
|
||||
data_out[1] = (FLAC__byte)(uval32 >> 8);
|
||||
data_out[2] = (FLAC__byte)uval32;
|
||||
break;
|
||||
case 16:
|
||||
data_out[0] = (FLAC__byte)(uval32 >> 8);
|
||||
data_out[1] = (FLAC__byte)uval32;
|
||||
break;
|
||||
case 8:
|
||||
data_out[0] = (FLAC__byte)uval32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dither_context->LastHistoryIndex = (last_history_index + wide_samples) % 32;
|
||||
|
||||
return wide_samples * channels * (target_bps/8);
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
# Microsoft Developer Studio Project File - Name="replaygain_synthesis_static" - Package Owner=<4>
|
||||
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
|
||||
|
||||
# TARGTYPE "Win32 (x86) Static Library" 0x0104
|
||||
|
||||
|
||||
|
||||
CFG=replaygain_synthesis_static - 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 "replaygain_synthesis_static.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 "replaygain_synthesis_static.mak" CFG="replaygain_synthesis_static - Win32 Debug"
|
||||
|
||||
!MESSAGE
|
||||
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
|
||||
!MESSAGE
|
||||
|
||||
!MESSAGE "replaygain_synthesis_static - Win32 Release" (based on "Win32 (x86) Static Library")
|
||||
|
||||
!MESSAGE "replaygain_synthesis_static - Win32 Debug" (based on "Win32 (x86) Static Library")
|
||||
|
||||
!MESSAGE
|
||||
|
||||
|
||||
|
||||
# Begin Project
|
||||
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
|
||||
# PROP Scc_ProjName "replaygain_synthesis"
|
||||
|
||||
# PROP Scc_LocalPath "..\..\.."
|
||||
|
||||
CPP=cl.exe
|
||||
|
||||
RSC=rc.exe
|
||||
|
||||
|
||||
|
||||
!IF "$(CFG)" == "replaygain_synthesis_static - 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\lib"
|
||||
|
||||
# PROP Intermediate_Dir "Release_static"
|
||||
|
||||
# PROP Target_Dir ""
|
||||
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /Op /I ".\include" /I "..\..\..\include" /I "..\..\..\include\share" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
|
||||
BSC32=bscmake.exe
|
||||
|
||||
# ADD BASE BSC32 /nologo
|
||||
|
||||
# ADD BSC32 /nologo
|
||||
|
||||
LIB32=link.exe -lib
|
||||
|
||||
# ADD BASE LIB32 /nologo
|
||||
|
||||
# ADD LIB32 /nologo /nodefaultlib
|
||||
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "replaygain_synthesis_static - Win32 Debug"
|
||||
|
||||
@@ -0,0 +1,322 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8,00"
|
||||
Name="replaygain_synthesis_static"
|
||||
ProjectGUID="{4cefbc8a-c215-11db-8314-0800200c9a66}"
|
||||
RootNamespace="replaygain_synthesis_static"
|
||||
Keyword="Win32Proj"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
<Platform
|
||||
Name="x64"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="..\..\..\obj\debug\lib"
|
||||
IntermediateDirectory="Debug_static"
|
||||
ConfigurationType="4"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=".\include;..\..\..\include;..\..\..\include\share"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;FLAC__NO_DLL;DEBUG"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="4"
|
||||
CompileAs="0"
|
||||
DisableSpecificWarnings="4267;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="..\..\..\obj\debug\lib\$(ProjectName).lib"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="..\..\..\obj\release\lib"
|
||||
IntermediateDirectory="Release_static"
|
||||
ConfigurationType="4"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
EnableIntrinsicFunctions="true"
|
||||
FavorSizeOrSpeed="1"
|
||||
OmitFramePointers="true"
|
||||
WholeProgramOptimization="true"
|
||||
AdditionalIncludeDirectories=".\include;..\..\..\include;..\..\..\include\share"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;FLAC__NO_DLL"
|
||||
RuntimeLibrary="0"
|
||||
BufferSecurityCheck="false"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"
|
||||
DisableSpecificWarnings="4267;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="..\..\..\obj\release\lib\$(ProjectName).lib"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug|x64"
|
||||
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TargetEnvironment="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=".\include;..\..\..\include;..\..\..\include\share"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;FLAC__NO_DLL;DEBUG"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"
|
||||
DisableSpecificWarnings="4267;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="..\..\..\obj\debug\lib\$(ProjectName).lib"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|x64"
|
||||
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TargetEnvironment="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
EnableIntrinsicFunctions="true"
|
||||
FavorSizeOrSpeed="1"
|
||||
OmitFramePointers="true"
|
||||
WholeProgramOptimization="true"
|
||||
AdditionalIncludeDirectories=".\include;..\..\..\include;..\..\..\include\share"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;FLAC__NO_DLL"
|
||||
RuntimeLibrary="0"
|
||||
BufferSecurityCheck="false"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"
|
||||
DisableSpecificWarnings="4267;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="..\..\..\obj\release\lib\$(ProjectName).lib"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\include\private\fast_float_math_hack.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Public Header Files"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\..\include\share\replaygain_synthesis.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\replaygain_synthesis.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
25
flac/src/share/utf8/Makefile.am
Normal file
25
flac/src/share/utf8/Makefile.am
Normal file
@@ -0,0 +1,25 @@
|
||||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/include/share
|
||||
|
||||
noinst_LTLIBRARIES = libutf8.la
|
||||
|
||||
libutf8_la_SOURCES = charset.c charset.h iconvert.c utf8.c
|
||||
|
||||
EXTRA_DIST = \
|
||||
Makefile.lite \
|
||||
charmaps.h \
|
||||
makemap.c \
|
||||
charset_test.c \
|
||||
charsetmap.h \
|
||||
iconvert.h \
|
||||
utf8_static.dsp \
|
||||
utf8_static.vcproj
|
||||
|
||||
debug:
|
||||
$(MAKE) all CFLAGS="@DEBUG@"
|
||||
|
||||
profile:
|
||||
$(MAKE) all CFLAGS="@PROFILE@"
|
||||
17
flac/src/share/utf8/Makefile.lite
Normal file
17
flac/src/share/utf8/Makefile.lite
Normal file
@@ -0,0 +1,17 @@
|
||||
#
|
||||
# GNU makefile
|
||||
#
|
||||
|
||||
topdir = ../../..
|
||||
|
||||
LIB_NAME = libutf8
|
||||
INCLUDES = -I$(topdir)/include -I$(topdir)/include/share
|
||||
|
||||
SRCS_C = \
|
||||
charset.c \
|
||||
iconvert.c \
|
||||
utf8.c
|
||||
|
||||
include $(topdir)/build/lib.mk
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
57
flac/src/share/utf8/charmaps.h
Normal file
57
flac/src/share/utf8/charmaps.h
Normal file
@@ -0,0 +1,57 @@
|
||||
|
||||
/*
|
||||
* If you need to generate more maps, use makemap.c on a system
|
||||
* with a decent iconv.
|
||||
*/
|
||||
|
||||
static const unsigned short mapping_iso_8859_2[256] = {
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
|
||||
0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
|
||||
0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
|
||||
0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
|
||||
0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
|
||||
0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
|
||||
0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
|
||||
0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
|
||||
0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
|
||||
0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
|
||||
0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
|
||||
0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
|
||||
0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
|
||||
0x00a0, 0x0104, 0x02d8, 0x0141, 0x00a4, 0x013d, 0x015a, 0x00a7,
|
||||
0x00a8, 0x0160, 0x015e, 0x0164, 0x0179, 0x00ad, 0x017d, 0x017b,
|
||||
0x00b0, 0x0105, 0x02db, 0x0142, 0x00b4, 0x013e, 0x015b, 0x02c7,
|
||||
0x00b8, 0x0161, 0x015f, 0x0165, 0x017a, 0x02dd, 0x017e, 0x017c,
|
||||
0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7,
|
||||
0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e,
|
||||
0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7,
|
||||
0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df,
|
||||
0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7,
|
||||
0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f,
|
||||
0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7,
|
||||
0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9
|
||||
};
|
||||
|
||||
static struct {
|
||||
const char *name;
|
||||
const unsigned short *map;
|
||||
struct charset *charset;
|
||||
} maps[] = {
|
||||
{ "ISO-8859-2", mapping_iso_8859_2, 0 },
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
|
||||
static const struct {
|
||||
const char *bad;
|
||||
const char *good;
|
||||
} names[] = {
|
||||
{ "ANSI_X3.4-1968", "us-ascii" },
|
||||
{ 0, 0 }
|
||||
};
|
||||
532
flac/src/share/utf8/charset.c
Normal file
532
flac/src/share/utf8/charset.c
Normal file
@@ -0,0 +1,532 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Edmund Grimley Evans <edmundo@rano.org>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* See the corresponding header file for a description of the functions
|
||||
* that this file provides.
|
||||
*
|
||||
* This was first written for Ogg Vorbis but could be of general use.
|
||||
*
|
||||
* The only deliberate assumption about data sizes is that a short has
|
||||
* at least 16 bits, but this code has only been tested on systems with
|
||||
* 8-bit char, 16-bit short and 32-bit int.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_ICONV /* should be ifdef USE_CHARSET_CONVERT */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "share/alloc.h"
|
||||
#include "charset.h"
|
||||
|
||||
#include "charmaps.h"
|
||||
|
||||
/*
|
||||
* This is like the standard strcasecmp, but it does not depend
|
||||
* on the locale. Locale-dependent functions can be dangerous:
|
||||
* we once had a bug involving strcasecmp("iso", "ISO") in a
|
||||
* Turkish locale!
|
||||
*
|
||||
* (I'm not really sure what the official standard says
|
||||
* about the sign of strcasecmp("Z", "["), but usually
|
||||
* we're only interested in whether it's zero.)
|
||||
*/
|
||||
|
||||
static int ascii_strcasecmp(const char *s1, const char *s2)
|
||||
{
|
||||
char c1, c2;
|
||||
|
||||
for (;; s1++, s2++) {
|
||||
if (!*s1 || !*s1)
|
||||
break;
|
||||
if (*s1 == *s2)
|
||||
continue;
|
||||
c1 = *s1;
|
||||
if ('a' <= c1 && c1 <= 'z')
|
||||
c1 += 'A' - 'a';
|
||||
c2 = *s2;
|
||||
if ('a' <= c2 && c2 <= 'z')
|
||||
c2 += 'A' - 'a';
|
||||
if (c1 != c2)
|
||||
break;
|
||||
}
|
||||
return (unsigned char)*s1 - (unsigned char)*s2;
|
||||
}
|
||||
|
||||
/*
|
||||
* UTF-8 equivalents of the C library's wctomb() and mbtowc().
|
||||
*/
|
||||
|
||||
int utf8_mbtowc(int *pwc, const char *s, size_t n)
|
||||
{
|
||||
unsigned char c;
|
||||
int wc, i, k;
|
||||
|
||||
if (!n || !s)
|
||||
return 0;
|
||||
|
||||
c = *s;
|
||||
if (c < 0x80) {
|
||||
if (pwc)
|
||||
*pwc = c;
|
||||
return c ? 1 : 0;
|
||||
}
|
||||
else if (c < 0xc2)
|
||||
return -1;
|
||||
else if (c < 0xe0) {
|
||||
if (n >= 2 && (s[1] & 0xc0) == 0x80) {
|
||||
if (pwc)
|
||||
*pwc = ((c & 0x1f) << 6) | (s[1] & 0x3f);
|
||||
return 2;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
else if (c < 0xf0)
|
||||
k = 3;
|
||||
else if (c < 0xf8)
|
||||
k = 4;
|
||||
else if (c < 0xfc)
|
||||
k = 5;
|
||||
else if (c < 0xfe)
|
||||
k = 6;
|
||||
else
|
||||
return -1;
|
||||
|
||||
if (n < (size_t)k)
|
||||
return -1;
|
||||
wc = *s++ & ((1 << (7 - k)) - 1);
|
||||
for (i = 1; i < k; i++) {
|
||||
if ((*s & 0xc0) != 0x80)
|
||||
return -1;
|
||||
wc = (wc << 6) | (*s++ & 0x3f);
|
||||
}
|
||||
if (wc < (1 << (5 * k - 4)))
|
||||
return -1;
|
||||
if (pwc)
|
||||
*pwc = wc;
|
||||
return k;
|
||||
}
|
||||
|
||||
int utf8_wctomb(char *s, int wc1)
|
||||
{
|
||||
unsigned int wc = wc1;
|
||||
|
||||
if (!s)
|
||||
return 0;
|
||||
if (wc < (1u << 7)) {
|
||||
*s++ = wc;
|
||||
return 1;
|
||||
}
|
||||
else if (wc < (1u << 11)) {
|
||||
*s++ = 0xc0 | (wc >> 6);
|
||||
*s++ = 0x80 | (wc & 0x3f);
|
||||
return 2;
|
||||
}
|
||||
else if (wc < (1u << 16)) {
|
||||
*s++ = 0xe0 | (wc >> 12);
|
||||
*s++ = 0x80 | ((wc >> 6) & 0x3f);
|
||||
*s++ = 0x80 | (wc & 0x3f);
|
||||
return 3;
|
||||
}
|
||||
else if (wc < (1u << 21)) {
|
||||
*s++ = 0xf0 | (wc >> 18);
|
||||
*s++ = 0x80 | ((wc >> 12) & 0x3f);
|
||||
*s++ = 0x80 | ((wc >> 6) & 0x3f);
|
||||
*s++ = 0x80 | (wc & 0x3f);
|
||||
return 4;
|
||||
}
|
||||
else if (wc < (1u << 26)) {
|
||||
*s++ = 0xf8 | (wc >> 24);
|
||||
*s++ = 0x80 | ((wc >> 18) & 0x3f);
|
||||
*s++ = 0x80 | ((wc >> 12) & 0x3f);
|
||||
*s++ = 0x80 | ((wc >> 6) & 0x3f);
|
||||
*s++ = 0x80 | (wc & 0x3f);
|
||||
return 5;
|
||||
}
|
||||
else if (wc < (1u << 31)) {
|
||||
*s++ = 0xfc | (wc >> 30);
|
||||
*s++ = 0x80 | ((wc >> 24) & 0x3f);
|
||||
*s++ = 0x80 | ((wc >> 18) & 0x3f);
|
||||
*s++ = 0x80 | ((wc >> 12) & 0x3f);
|
||||
*s++ = 0x80 | ((wc >> 6) & 0x3f);
|
||||
*s++ = 0x80 | (wc & 0x3f);
|
||||
return 6;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The charset "object" and methods.
|
||||
*/
|
||||
|
||||
struct charset {
|
||||
int max;
|
||||
int (*mbtowc)(void *table, int *pwc, const char *s, size_t n);
|
||||
int (*wctomb)(void *table, char *s, int wc);
|
||||
void *map;
|
||||
};
|
||||
|
||||
int charset_mbtowc(struct charset *charset, int *pwc, const char *s, size_t n)
|
||||
{
|
||||
return (*charset->mbtowc)(charset->map, pwc, s, n);
|
||||
}
|
||||
|
||||
int charset_wctomb(struct charset *charset, char *s, int wc)
|
||||
{
|
||||
return (*charset->wctomb)(charset->map, s, wc);
|
||||
}
|
||||
|
||||
int charset_max(struct charset *charset)
|
||||
{
|
||||
return charset->max;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implementation of UTF-8.
|
||||
*/
|
||||
|
||||
static int mbtowc_utf8(void *map, int *pwc, const char *s, size_t n)
|
||||
{
|
||||
(void)map;
|
||||
return utf8_mbtowc(pwc, s, n);
|
||||
}
|
||||
|
||||
static int wctomb_utf8(void *map, char *s, int wc)
|
||||
{
|
||||
(void)map;
|
||||
return utf8_wctomb(s, wc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Implementation of US-ASCII.
|
||||
* Probably on most architectures this compiles to less than 256 bytes
|
||||
* of code, so we can save space by not having a table for this one.
|
||||
*/
|
||||
|
||||
static int mbtowc_ascii(void *map, int *pwc, const char *s, size_t n)
|
||||
{
|
||||
int wc;
|
||||
|
||||
(void)map;
|
||||
if (!n || !s)
|
||||
return 0;
|
||||
wc = (unsigned char)*s;
|
||||
if (wc & ~0x7f)
|
||||
return -1;
|
||||
if (pwc)
|
||||
*pwc = wc;
|
||||
return wc ? 1 : 0;
|
||||
}
|
||||
|
||||
static int wctomb_ascii(void *map, char *s, int wc)
|
||||
{
|
||||
(void)map;
|
||||
if (!s)
|
||||
return 0;
|
||||
if (wc & ~0x7f)
|
||||
return -1;
|
||||
*s = wc;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implementation of ISO-8859-1.
|
||||
* Probably on most architectures this compiles to less than 256 bytes
|
||||
* of code, so we can save space by not having a table for this one.
|
||||
*/
|
||||
|
||||
static int mbtowc_iso1(void *map, int *pwc, const char *s, size_t n)
|
||||
{
|
||||
int wc;
|
||||
|
||||
(void)map;
|
||||
if (!n || !s)
|
||||
return 0;
|
||||
wc = (unsigned char)*s;
|
||||
if (wc & ~0xff)
|
||||
return -1;
|
||||
if (pwc)
|
||||
*pwc = wc;
|
||||
return wc ? 1 : 0;
|
||||
}
|
||||
|
||||
static int wctomb_iso1(void *map, char *s, int wc)
|
||||
{
|
||||
(void)map;
|
||||
if (!s)
|
||||
return 0;
|
||||
if (wc & ~0xff)
|
||||
return -1;
|
||||
*s = wc;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implementation of any 8-bit charset.
|
||||
*/
|
||||
|
||||
struct map {
|
||||
const unsigned short *from;
|
||||
struct inverse_map *to;
|
||||
};
|
||||
|
||||
static int mbtowc_8bit(void *map1, int *pwc, const char *s, size_t n)
|
||||
{
|
||||
struct map *map = map1;
|
||||
unsigned short wc;
|
||||
|
||||
if (!n || !s)
|
||||
return 0;
|
||||
wc = map->from[(unsigned char)*s];
|
||||
if (wc == 0xffff)
|
||||
return -1;
|
||||
if (pwc)
|
||||
*pwc = (int)wc;
|
||||
return wc ? 1 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* For the inverse map we use a hash table, which has the advantages
|
||||
* of small constant memory requirement and simple memory allocation,
|
||||
* but the disadvantage of slow conversion in the worst case.
|
||||
* If you need real-time performance while letting a potentially
|
||||
* malicious user define their own map, then the method used in
|
||||
* linux/drivers/char/consolemap.c would be more appropriate.
|
||||
*/
|
||||
|
||||
struct inverse_map {
|
||||
unsigned char first[256];
|
||||
unsigned char next[256];
|
||||
};
|
||||
|
||||
/*
|
||||
* The simple hash is good enough for this application.
|
||||
* Use the alternative trivial hashes for testing.
|
||||
*/
|
||||
#define HASH(i) ((i) & 0xff)
|
||||
/* #define HASH(i) 0 */
|
||||
/* #define HASH(i) 99 */
|
||||
|
||||
static struct inverse_map *make_inverse_map(const unsigned short *from)
|
||||
{
|
||||
struct inverse_map *to;
|
||||
char used[256];
|
||||
int i, j, k;
|
||||
|
||||
to = (struct inverse_map *)malloc(sizeof(struct inverse_map));
|
||||
if (!to)
|
||||
return 0;
|
||||
for (i = 0; i < 256; i++)
|
||||
to->first[i] = to->next[i] = used[i] = 0;
|
||||
for (i = 255; i >= 0; i--)
|
||||
if (from[i] != 0xffff) {
|
||||
k = HASH(from[i]);
|
||||
to->next[i] = to->first[k];
|
||||
to->first[k] = i;
|
||||
used[k] = 1;
|
||||
}
|
||||
|
||||
/* Point the empty buckets at an empty list. */
|
||||
for (i = 0; i < 256; i++)
|
||||
if (!to->next[i])
|
||||
break;
|
||||
if (i < 256)
|
||||
for (j = 0; j < 256; j++)
|
||||
if (!used[j])
|
||||
to->first[j] = i;
|
||||
|
||||
return to;
|
||||
}
|
||||
|
||||
int wctomb_8bit(void *map1, char *s, int wc1)
|
||||
{
|
||||
struct map *map = map1;
|
||||
unsigned short wc = wc1;
|
||||
int i;
|
||||
|
||||
if (!s)
|
||||
return 0;
|
||||
|
||||
if (wc1 & ~0xffff)
|
||||
return -1;
|
||||
|
||||
if (1) /* Change 1 to 0 to test the case where malloc fails. */
|
||||
if (!map->to)
|
||||
map->to = make_inverse_map(map->from);
|
||||
|
||||
if (map->to) {
|
||||
/* Use the inverse map. */
|
||||
i = map->to->first[HASH(wc)];
|
||||
for (;;) {
|
||||
if (map->from[i] == wc) {
|
||||
*s = i;
|
||||
return 1;
|
||||
}
|
||||
if (!(i = map->to->next[i]))
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* We don't have an inverse map, so do a linear search. */
|
||||
for (i = 0; i < 256; i++)
|
||||
if (map->from[i] == wc) {
|
||||
*s = i;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The "constructor" charset_find().
|
||||
*/
|
||||
|
||||
struct charset charset_utf8 = {
|
||||
6,
|
||||
&mbtowc_utf8,
|
||||
&wctomb_utf8,
|
||||
0
|
||||
};
|
||||
|
||||
struct charset charset_iso1 = {
|
||||
1,
|
||||
&mbtowc_iso1,
|
||||
&wctomb_iso1,
|
||||
0
|
||||
};
|
||||
|
||||
struct charset charset_ascii = {
|
||||
1,
|
||||
&mbtowc_ascii,
|
||||
&wctomb_ascii,
|
||||
0
|
||||
};
|
||||
|
||||
struct charset *charset_find(const char *code)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Find good (MIME) name. */
|
||||
for (i = 0; names[i].bad; i++)
|
||||
if (!ascii_strcasecmp(code, names[i].bad)) {
|
||||
code = names[i].good;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Recognise some charsets for which we avoid using a table. */
|
||||
if (!ascii_strcasecmp(code, "UTF-8"))
|
||||
return &charset_utf8;
|
||||
if (!ascii_strcasecmp(code, "US-ASCII"))
|
||||
return &charset_ascii;
|
||||
if (!ascii_strcasecmp(code, "ISO-8859-1"))
|
||||
return &charset_iso1;
|
||||
|
||||
/* Look for a mapping for a simple 8-bit encoding. */
|
||||
for (i = 0; maps[i].name; i++)
|
||||
if (!ascii_strcasecmp(code, maps[i].name)) {
|
||||
if (!maps[i].charset) {
|
||||
maps[i].charset = (struct charset *)malloc(sizeof(struct charset));
|
||||
if (maps[i].charset) {
|
||||
struct map *map = (struct map *)malloc(sizeof(struct map));
|
||||
if (!map) {
|
||||
free(maps[i].charset);
|
||||
maps[i].charset = 0;
|
||||
}
|
||||
else {
|
||||
maps[i].charset->max = 1;
|
||||
maps[i].charset->mbtowc = &mbtowc_8bit;
|
||||
maps[i].charset->wctomb = &wctomb_8bit;
|
||||
maps[i].charset->map = map;
|
||||
map->from = maps[i].map;
|
||||
map->to = 0; /* inverse mapping is created when required */
|
||||
}
|
||||
}
|
||||
}
|
||||
return maps[i].charset;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function to convert a buffer from one encoding to another.
|
||||
* Invalid bytes are replaced by '#', and characters that are
|
||||
* not available in the target encoding are replaced by '?'.
|
||||
* Each of TO and TOLEN may be zero, if the result is not needed.
|
||||
* The output buffer is null-terminated, so it is all right to
|
||||
* use charset_convert(fromcode, tocode, s, strlen(s), &t, 0).
|
||||
*/
|
||||
|
||||
int charset_convert(const char *fromcode, const char *tocode,
|
||||
const char *from, size_t fromlen,
|
||||
char **to, size_t *tolen)
|
||||
{
|
||||
int ret = 0;
|
||||
struct charset *charset1, *charset2;
|
||||
char *tobuf, *p, *newbuf;
|
||||
int i, j, wc;
|
||||
|
||||
charset1 = charset_find(fromcode);
|
||||
charset2 = charset_find(tocode);
|
||||
if (!charset1 || !charset2 )
|
||||
return -1;
|
||||
|
||||
tobuf = (char *)safe_malloc_mul2add_(fromlen, /*times*/charset2->max, /*+*/1);
|
||||
if (!tobuf)
|
||||
return -2;
|
||||
|
||||
for (p = tobuf; fromlen; from += i, fromlen -= i, p += j) {
|
||||
i = charset_mbtowc(charset1, &wc, from, fromlen);
|
||||
if (!i)
|
||||
i = 1;
|
||||
else if (i == -1) {
|
||||
i = 1;
|
||||
wc = '#';
|
||||
ret = 2;
|
||||
}
|
||||
j = charset_wctomb(charset2, p, wc);
|
||||
if (j == -1) {
|
||||
if (!ret)
|
||||
ret = 1;
|
||||
j = charset_wctomb(charset2, p, '?');
|
||||
if (j == -1)
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (tolen)
|
||||
*tolen = p - tobuf;
|
||||
*p++ = '\0';
|
||||
if (to) {
|
||||
newbuf = realloc(tobuf, p - tobuf);
|
||||
*to = newbuf ? newbuf : tobuf;
|
||||
}
|
||||
else
|
||||
free(tobuf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* USE_CHARSET_ICONV */
|
||||
72
flac/src/share/utf8/charset.h
Normal file
72
flac/src/share/utf8/charset.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Edmund Grimley Evans <edmundo@rano.org>
|
||||
*
|
||||
* 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 <stdlib.h>
|
||||
|
||||
/*
|
||||
* These functions are like the C library's mbtowc() and wctomb(),
|
||||
* but instead of depending on the locale they always work in UTF-8,
|
||||
* and they use int instead of wchar_t.
|
||||
*/
|
||||
|
||||
int utf8_mbtowc(int *pwc, const char *s, size_t n);
|
||||
int utf8_wctomb(char *s, int wc);
|
||||
|
||||
/*
|
||||
* This is an object-oriented version of mbtowc() and wctomb().
|
||||
* The caller first uses charset_find() to get a pointer to struct
|
||||
* charset, then uses the mbtowc() and wctomb() methods on it.
|
||||
* The function charset_max() gives the maximum length of a
|
||||
* multibyte character in that encoding.
|
||||
* This API is only appropriate for stateless encodings like UTF-8
|
||||
* or ISO-8859-3, but I have no intention of implementing anything
|
||||
* other than UTF-8 and 8-bit encodings.
|
||||
*
|
||||
* MINOR BUG: If there is no memory charset_find() may return 0 and
|
||||
* there is no way to distinguish this case from an unknown encoding.
|
||||
*/
|
||||
|
||||
struct charset;
|
||||
|
||||
struct charset *charset_find(const char *code);
|
||||
|
||||
int charset_mbtowc(struct charset *charset, int *pwc, const char *s, size_t n);
|
||||
int charset_wctomb(struct charset *charset, char *s, int wc);
|
||||
int charset_max(struct charset *charset);
|
||||
|
||||
/*
|
||||
* Function to convert a buffer from one encoding to another.
|
||||
* Invalid bytes are replaced by '#', and characters that are
|
||||
* not available in the target encoding are replaced by '?'.
|
||||
* Each of TO and TOLEN may be zero if the result is not wanted.
|
||||
* The input or output may contain null bytes, but the output
|
||||
* buffer is also null-terminated, so it is all right to
|
||||
* use charset_convert(fromcode, tocode, s, strlen(s), &t, 0).
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* -2 : memory allocation failed
|
||||
* -1 : unknown encoding
|
||||
* 0 : data was converted exactly
|
||||
* 1 : valid data was converted approximately (using '?')
|
||||
* 2 : input was invalid (but still converted, using '#')
|
||||
*/
|
||||
|
||||
int charset_convert(const char *fromcode, const char *tocode,
|
||||
const char *from, size_t fromlen,
|
||||
char **to, size_t *tolen);
|
||||
263
flac/src/share/utf8/charset_test.c
Normal file
263
flac/src/share/utf8/charset_test.c
Normal file
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Edmund Grimley Evans <edmundo@rano.org>
|
||||
*
|
||||
* 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 <config.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "charset.h"
|
||||
|
||||
void test_any(struct charset *charset)
|
||||
{
|
||||
int wc;
|
||||
char s[2];
|
||||
|
||||
assert(charset);
|
||||
|
||||
/* Decoder */
|
||||
|
||||
assert(charset_mbtowc(charset, 0, 0, 0) == 0);
|
||||
assert(charset_mbtowc(charset, 0, 0, 1) == 0);
|
||||
assert(charset_mbtowc(charset, 0, (char *)(-1), 0) == 0);
|
||||
|
||||
assert(charset_mbtowc(charset, 0, "a", 0) == 0);
|
||||
assert(charset_mbtowc(charset, 0, "", 1) == 0);
|
||||
assert(charset_mbtowc(charset, 0, "b", 1) == 1);
|
||||
assert(charset_mbtowc(charset, 0, "", 2) == 0);
|
||||
assert(charset_mbtowc(charset, 0, "c", 2) == 1);
|
||||
|
||||
wc = 'x';
|
||||
assert(charset_mbtowc(charset, &wc, "a", 0) == 0 && wc == 'x');
|
||||
assert(charset_mbtowc(charset, &wc, "", 1) == 0 && wc == 0);
|
||||
assert(charset_mbtowc(charset, &wc, "b", 1) == 1 && wc == 'b');
|
||||
assert(charset_mbtowc(charset, &wc, "", 2) == 0 && wc == 0);
|
||||
assert(charset_mbtowc(charset, &wc, "c", 2) == 1 && wc == 'c');
|
||||
|
||||
/* Encoder */
|
||||
|
||||
assert(charset_wctomb(charset, 0, 0) == 0);
|
||||
|
||||
s[0] = s[1] = '.';
|
||||
assert(charset_wctomb(charset, s, 0) == 1 &&
|
||||
s[0] == '\0' && s[1] == '.');
|
||||
assert(charset_wctomb(charset, s, 'x') == 1 &&
|
||||
s[0] == 'x' && s[1] == '.');
|
||||
}
|
||||
|
||||
void test_utf8()
|
||||
{
|
||||
struct charset *charset;
|
||||
int wc;
|
||||
char s[8];
|
||||
|
||||
charset = charset_find("UTF-8");
|
||||
test_any(charset);
|
||||
|
||||
/* Decoder */
|
||||
wc = 0;
|
||||
assert(charset_mbtowc(charset, &wc, "\177", 1) == 1 && wc == 127);
|
||||
assert(charset_mbtowc(charset, &wc, "\200", 2) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\301\277", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\302\200", 1) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\302\200", 2) == 2 && wc == 128);
|
||||
assert(charset_mbtowc(charset, &wc, "\302\200", 3) == 2 && wc == 128);
|
||||
assert(charset_mbtowc(charset, &wc, "\340\237\200", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\340\240\200", 9) == 3 &&
|
||||
wc == 1 << 11);
|
||||
assert(charset_mbtowc(charset, &wc, "\360\217\277\277", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\360\220\200\200", 9) == 4 &&
|
||||
wc == 1 << 16);
|
||||
assert(charset_mbtowc(charset, &wc, "\370\207\277\277\277", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\370\210\200\200\200", 9) == 5 &&
|
||||
wc == 1 << 21);
|
||||
assert(charset_mbtowc(charset, &wc, "\374\203\277\277\277\277", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\374\204\200\200\200\200", 9) == 6 &&
|
||||
wc == 1 << 26);
|
||||
assert(charset_mbtowc(charset, &wc, "\375\277\277\277\277\277", 9) == 6 &&
|
||||
wc == 0x7fffffff);
|
||||
|
||||
assert(charset_mbtowc(charset, &wc, "\302\000", 2) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\302\300", 2) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\340\040\200", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\340\340\200", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\340\240\000", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\340\240\300", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\360\020\200\200", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\360\320\200\200", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\360\220\000\200", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\360\220\300\200", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\360\220\200\000", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\360\220\200\300", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\375\077\277\277\277\277", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\375\377\277\277\277\277", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\375\277\077\277\277\277", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\375\277\377\277\277\277", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\375\277\277\277\077\277", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\375\277\277\277\377\277", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\375\277\277\277\277\077", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\375\277\277\277\277\377", 9) == -1);
|
||||
|
||||
assert(charset_mbtowc(charset, &wc, "\376\277\277\277\277\277", 9) == -1);
|
||||
assert(charset_mbtowc(charset, &wc, "\377\277\277\277\277\277", 9) == -1);
|
||||
|
||||
/* Encoder */
|
||||
strcpy(s, ".......");
|
||||
assert(charset_wctomb(charset, s, 1 << 31) == -1 &&
|
||||
!strcmp(s, "......."));
|
||||
assert(charset_wctomb(charset, s, 127) == 1 &&
|
||||
!strcmp(s, "\177......"));
|
||||
assert(charset_wctomb(charset, s, 128) == 2 &&
|
||||
!strcmp(s, "\302\200....."));
|
||||
assert(charset_wctomb(charset, s, 0x7ff) == 2 &&
|
||||
!strcmp(s, "\337\277....."));
|
||||
assert(charset_wctomb(charset, s, 0x800) == 3 &&
|
||||
!strcmp(s, "\340\240\200...."));
|
||||
assert(charset_wctomb(charset, s, 0xffff) == 3 &&
|
||||
!strcmp(s, "\357\277\277...."));
|
||||
assert(charset_wctomb(charset, s, 0x10000) == 4 &&
|
||||
!strcmp(s, "\360\220\200\200..."));
|
||||
assert(charset_wctomb(charset, s, 0x1fffff) == 4 &&
|
||||
!strcmp(s, "\367\277\277\277..."));
|
||||
assert(charset_wctomb(charset, s, 0x200000) == 5 &&
|
||||
!strcmp(s, "\370\210\200\200\200.."));
|
||||
assert(charset_wctomb(charset, s, 0x3ffffff) == 5 &&
|
||||
!strcmp(s, "\373\277\277\277\277.."));
|
||||
assert(charset_wctomb(charset, s, 0x4000000) == 6 &&
|
||||
!strcmp(s, "\374\204\200\200\200\200."));
|
||||
assert(charset_wctomb(charset, s, 0x7fffffff) == 6 &&
|
||||
!strcmp(s, "\375\277\277\277\277\277."));
|
||||
}
|
||||
|
||||
void test_ascii()
|
||||
{
|
||||
struct charset *charset;
|
||||
int wc;
|
||||
char s[3];
|
||||
|
||||
charset = charset_find("us-ascii");
|
||||
test_any(charset);
|
||||
|
||||
/* Decoder */
|
||||
wc = 0;
|
||||
assert(charset_mbtowc(charset, &wc, "\177", 2) == 1 && wc == 127);
|
||||
assert(charset_mbtowc(charset, &wc, "\200", 2) == -1);
|
||||
|
||||
/* Encoder */
|
||||
strcpy(s, "..");
|
||||
assert(charset_wctomb(charset, s, 256) == -1 && !strcmp(s, ".."));
|
||||
assert(charset_wctomb(charset, s, 255) == -1);
|
||||
assert(charset_wctomb(charset, s, 128) == -1);
|
||||
assert(charset_wctomb(charset, s, 127) == 1 && !strcmp(s, "\177."));
|
||||
}
|
||||
|
||||
void test_iso1()
|
||||
{
|
||||
struct charset *charset;
|
||||
int wc;
|
||||
char s[3];
|
||||
|
||||
charset = charset_find("iso-8859-1");
|
||||
test_any(charset);
|
||||
|
||||
/* Decoder */
|
||||
wc = 0;
|
||||
assert(charset_mbtowc(charset, &wc, "\302\200", 9) == 1 && wc == 0xc2);
|
||||
|
||||
/* Encoder */
|
||||
strcpy(s, "..");
|
||||
assert(charset_wctomb(charset, s, 256) == -1 && !strcmp(s, ".."));
|
||||
assert(charset_wctomb(charset, s, 255) == 1 && !strcmp(s, "\377."));
|
||||
assert(charset_wctomb(charset, s, 128) == 1 && !strcmp(s, "\200."));
|
||||
}
|
||||
|
||||
void test_iso2()
|
||||
{
|
||||
struct charset *charset;
|
||||
int wc;
|
||||
char s[3];
|
||||
|
||||
charset = charset_find("iso-8859-2");
|
||||
test_any(charset);
|
||||
|
||||
/* Decoder */
|
||||
wc = 0;
|
||||
assert(charset_mbtowc(charset, &wc, "\302\200", 9) == 1 && wc == 0xc2);
|
||||
assert(charset_mbtowc(charset, &wc, "\377", 2) == 1 && wc == 0x2d9);
|
||||
|
||||
/* Encoder */
|
||||
strcpy(s, "..");
|
||||
assert(charset_wctomb(charset, s, 256) == -1 && !strcmp(s, ".."));
|
||||
assert(charset_wctomb(charset, s, 255) == -1 && !strcmp(s, ".."));
|
||||
assert(charset_wctomb(charset, s, 258) == 1 && !strcmp(s, "\303."));
|
||||
assert(charset_wctomb(charset, s, 128) == 1 && !strcmp(s, "\200."));
|
||||
}
|
||||
|
||||
void test_convert()
|
||||
{
|
||||
const char *p;
|
||||
char *q, *r;
|
||||
char s[256];
|
||||
size_t n, n2;
|
||||
int i;
|
||||
|
||||
p = "\000x\302\200\375\277\277\277\277\277";
|
||||
assert(charset_convert("UTF-8", "UTF-8", p, 10, &q, &n) == 0 &&
|
||||
n == 10 && !strcmp(p, q));
|
||||
assert(charset_convert("UTF-8", "UTF-8", "x\301\277y", 4, &q, &n) == 2 &&
|
||||
n == 4 && !strcmp(q, "x##y"));
|
||||
assert(charset_convert("UTF-8", "UTF-8", "x\301\277y", 4, 0, &n) == 2 &&
|
||||
n == 4);
|
||||
assert(charset_convert("UTF-8", "UTF-8", "x\301\277y", 4, &q, 0) == 2 &&
|
||||
!strcmp(q, "x##y"));
|
||||
assert(charset_convert("UTF-8", "iso-8859-1",
|
||||
"\302\200\304\200x", 5, &q, &n) == 1 &&
|
||||
n == 3 && !strcmp(q, "\200?x"));
|
||||
assert(charset_convert("iso-8859-1", "UTF-8",
|
||||
"\000\200\377", 3, &q, &n) == 0 &&
|
||||
n == 5 && !memcmp(q, "\000\302\200\303\277", 5));
|
||||
assert(charset_convert("iso-8859-1", "iso-8859-1",
|
||||
"\000\200\377", 3, &q, &n) == 0 &&
|
||||
n == 3 && !memcmp(q, "\000\200\377", 3));
|
||||
|
||||
assert(charset_convert("iso-8859-2", "utf-8", "\300", 1, &q, &n) == 0 &&
|
||||
n == 2 && !strcmp(q, "\305\224"));
|
||||
assert(charset_convert("utf-8", "iso-8859-2", "\305\224", 2, &q, &n) == 0 &&
|
||||
n == 1 && !strcmp(q, "\300"));
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
s[i] = i;
|
||||
|
||||
assert(charset_convert("iso-8859-2", "utf-8", s, 256, &q, &n) == 0);
|
||||
assert(charset_convert("utf-8", "iso-8859-2", q, n, &r, &n2) == 0);
|
||||
assert(n2 == 256 && !memcmp(r, s, n2));
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_utf8();
|
||||
test_ascii();
|
||||
test_iso1();
|
||||
test_iso2();
|
||||
|
||||
test_convert();
|
||||
|
||||
return 0;
|
||||
}
|
||||
79
flac/src/share/utf8/charsetmap.h
Normal file
79
flac/src/share/utf8/charsetmap.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/* This file was automatically generated by make_code_map.pl
|
||||
please don't edit directly
|
||||
Daniel Resare <noa@metamatrix.se>
|
||||
*/
|
||||
charset_map maps[] = {
|
||||
{"ISO-8859-1",
|
||||
{
|
||||
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
|
||||
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
|
||||
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
|
||||
0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F,
|
||||
0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,
|
||||
0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F,
|
||||
0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,
|
||||
0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F,
|
||||
0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,
|
||||
0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F,
|
||||
0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,
|
||||
0x0058,0x0059,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F,
|
||||
0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,
|
||||
0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F,
|
||||
0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,
|
||||
0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E,0x007F,
|
||||
0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087,
|
||||
0x0088,0x0089,0x008A,0x008B,0x008C,0x008D,0x008E,0x008F,
|
||||
0x0090,0x0091,0x0092,0x0093,0x0094,0x0095,0x0096,0x0097,
|
||||
0x0098,0x0099,0x009A,0x009B,0x009C,0x009D,0x009E,0x009F,
|
||||
0x00A0,0x00A1,0x00A2,0x00A3,0x00A4,0x00A5,0x00A6,0x00A7,
|
||||
0x00A8,0x00A9,0x00AA,0x00AB,0x00AC,0x00AD,0x00AE,0x00AF,
|
||||
0x00B0,0x00B1,0x00B2,0x00B3,0x00B4,0x00B5,0x00B6,0x00B7,
|
||||
0x00B8,0x00B9,0x00BA,0x00BB,0x00BC,0x00BD,0x00BE,0x00BF,
|
||||
0x00C0,0x00C1,0x00C2,0x00C3,0x00C4,0x00C5,0x00C6,0x00C7,
|
||||
0x00C8,0x00C9,0x00CA,0x00CB,0x00CC,0x00CD,0x00CE,0x00CF,
|
||||
0x00D0,0x00D1,0x00D2,0x00D3,0x00D4,0x00D5,0x00D6,0x00D7,
|
||||
0x00D8,0x00D9,0x00DA,0x00DB,0x00DC,0x00DD,0x00DE,0x00DF,
|
||||
0x00E0,0x00E1,0x00E2,0x00E3,0x00E4,0x00E5,0x00E6,0x00E7,
|
||||
0x00E8,0x00E9,0x00EA,0x00EB,0x00EC,0x00ED,0x00EE,0x00EF,
|
||||
0x00F0,0x00F1,0x00F2,0x00F3,0x00F4,0x00F5,0x00F6,0x00F7,
|
||||
0x00F8,0x00F9,0x00FA,0x00FB,0x00FC,0x00FD,0x00FE,0x00FF
|
||||
}
|
||||
},
|
||||
{"ISO-8859-2",
|
||||
{
|
||||
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
|
||||
0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
|
||||
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
|
||||
0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F,
|
||||
0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,
|
||||
0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F,
|
||||
0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,
|
||||
0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F,
|
||||
0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,
|
||||
0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F,
|
||||
0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,
|
||||
0x0058,0x0059,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F,
|
||||
0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,
|
||||
0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F,
|
||||
0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,
|
||||
0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E,0x007F,
|
||||
0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087,
|
||||
0x0088,0x0089,0x008A,0x008B,0x008C,0x008D,0x008E,0x008F,
|
||||
0x0090,0x0091,0x0092,0x0093,0x0094,0x0095,0x0096,0x0097,
|
||||
0x0098,0x0099,0x009A,0x009B,0x009C,0x009D,0x009E,0x009F,
|
||||
0x00A0,0x0104,0x02D8,0x0141,0x00A4,0x013D,0x015A,0x00A7,
|
||||
0x00A8,0x0160,0x015E,0x0164,0x0179,0x00AD,0x017D,0x017B,
|
||||
0x00B0,0x0105,0x02DB,0x0142,0x00B4,0x013E,0x015B,0x02C7,
|
||||
0x00B8,0x0161,0x015F,0x0165,0x017A,0x02DD,0x017E,0x017C,
|
||||
0x0154,0x00C1,0x00C2,0x0102,0x00C4,0x0139,0x0106,0x00C7,
|
||||
0x010C,0x00C9,0x0118,0x00CB,0x011A,0x00CD,0x00CE,0x010E,
|
||||
0x0110,0x0143,0x0147,0x00D3,0x00D4,0x0150,0x00D6,0x00D7,
|
||||
0x0158,0x016E,0x00DA,0x0170,0x00DC,0x00DD,0x0162,0x00DF,
|
||||
0x0155,0x00E1,0x00E2,0x0103,0x00E4,0x013A,0x0107,0x00E7,
|
||||
0x010D,0x00E9,0x0119,0x00EB,0x011B,0x00ED,0x00EE,0x010F,
|
||||
0x0111,0x0144,0x0148,0x00F3,0x00F4,0x0151,0x00F6,0x00F7,
|
||||
0x0159,0x016F,0x00FA,0x0171,0x00FC,0x00FD,0x0163,0x02D9
|
||||
}
|
||||
},
|
||||
{NULL}
|
||||
};
|
||||
253
flac/src/share/utf8/iconvert.c
Normal file
253
flac/src/share/utf8/iconvert.c
Normal file
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Edmund Grimley Evans <edmundo@rano.org>
|
||||
*
|
||||
* 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 <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ICONV
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <iconv.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "iconvert.h"
|
||||
#include "share/alloc.h"
|
||||
|
||||
/*
|
||||
* Convert data from one encoding to another. Return:
|
||||
*
|
||||
* -2 : memory allocation failed
|
||||
* -1 : unknown encoding
|
||||
* 0 : data was converted exactly
|
||||
* 1 : data was converted inexactly
|
||||
* 2 : data was invalid (but still converted)
|
||||
*
|
||||
* We convert in two steps, via UTF-8, as this is the only
|
||||
* reliable way of distinguishing between invalid input
|
||||
* and valid input which iconv refuses to transliterate.
|
||||
* We convert from UTF-8 twice, because we have no way of
|
||||
* knowing whether the conversion was exact if iconv returns
|
||||
* E2BIG (due to a bug in the specification of iconv).
|
||||
* An alternative approach is to assume that the output of
|
||||
* iconv is never more than 4 times as long as the input,
|
||||
* but I prefer to avoid that assumption if possible.
|
||||
*/
|
||||
|
||||
int iconvert(const char *fromcode, const char *tocode,
|
||||
const char *from, size_t fromlen,
|
||||
char **to, size_t *tolen)
|
||||
{
|
||||
int ret = 0;
|
||||
iconv_t cd1, cd2;
|
||||
char *ib;
|
||||
char *ob;
|
||||
char *utfbuf = 0, *outbuf, *newbuf;
|
||||
size_t utflen, outlen, ibl, obl, k;
|
||||
char tbuf[2048];
|
||||
|
||||
cd1 = iconv_open("UTF-8", fromcode);
|
||||
if (cd1 == (iconv_t)(-1))
|
||||
return -1;
|
||||
|
||||
cd2 = (iconv_t)(-1);
|
||||
/* Don't use strcasecmp() as it's locale-dependent. */
|
||||
if (!strchr("Uu", tocode[0]) ||
|
||||
!strchr("Tt", tocode[1]) ||
|
||||
!strchr("Ff", tocode[2]) ||
|
||||
tocode[3] != '-' ||
|
||||
tocode[4] != '8' ||
|
||||
tocode[5] != '\0') {
|
||||
char *tocode1;
|
||||
|
||||
/*
|
||||
* Try using this non-standard feature of glibc and libiconv.
|
||||
* This is deliberately not a config option as people often
|
||||
* change their iconv library without rebuilding applications.
|
||||
*/
|
||||
tocode1 = (char *)safe_malloc_add_2op_(strlen(tocode), /*+*/11);
|
||||
if (!tocode1)
|
||||
goto fail;
|
||||
|
||||
strcpy(tocode1, tocode);
|
||||
strcat(tocode1, "//TRANSLIT");
|
||||
cd2 = iconv_open(tocode1, "UTF-8");
|
||||
free(tocode1);
|
||||
|
||||
if (cd2 == (iconv_t)(-1))
|
||||
cd2 = iconv_open(tocode, fromcode);
|
||||
|
||||
if (cd2 == (iconv_t)(-1)) {
|
||||
iconv_close(cd1);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
utflen = 1; /*fromlen * 2 + 1; XXX */
|
||||
utfbuf = (char *)malloc(utflen);
|
||||
if (!utfbuf)
|
||||
goto fail;
|
||||
|
||||
/* Convert to UTF-8 */
|
||||
ib = (char *)from;
|
||||
ibl = fromlen;
|
||||
ob = utfbuf;
|
||||
obl = utflen;
|
||||
for (;;) {
|
||||
k = iconv(cd1, &ib, &ibl, &ob, &obl);
|
||||
assert((!k && !ibl) ||
|
||||
(k == (size_t)(-1) && errno == E2BIG && ibl && obl < 6) ||
|
||||
(k == (size_t)(-1) &&
|
||||
(errno == EILSEQ || errno == EINVAL) && ibl));
|
||||
if (!ibl)
|
||||
break;
|
||||
if (obl < 6) {
|
||||
/* Enlarge the buffer */
|
||||
if(utflen*2 < utflen) /* overflow check */
|
||||
goto fail;
|
||||
utflen *= 2;
|
||||
newbuf = (char *)realloc(utfbuf, utflen);
|
||||
if (!newbuf)
|
||||
goto fail;
|
||||
ob = (ob - utfbuf) + newbuf;
|
||||
obl = utflen - (ob - newbuf);
|
||||
utfbuf = newbuf;
|
||||
}
|
||||
else {
|
||||
/* Invalid input */
|
||||
ib++, ibl--;
|
||||
*ob++ = '#', obl--;
|
||||
ret = 2;
|
||||
iconv(cd1, 0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (cd2 == (iconv_t)(-1)) {
|
||||
/* The target encoding was UTF-8 */
|
||||
if (tolen)
|
||||
*tolen = ob - utfbuf;
|
||||
if (!to) {
|
||||
free(utfbuf);
|
||||
iconv_close(cd1);
|
||||
return ret;
|
||||
}
|
||||
newbuf = (char *)safe_realloc_add_2op_(utfbuf, (ob - utfbuf), /*+*/1);
|
||||
if (!newbuf)
|
||||
goto fail;
|
||||
ob = (ob - utfbuf) + newbuf;
|
||||
*ob = '\0';
|
||||
*to = newbuf;
|
||||
iconv_close(cd1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Truncate the buffer to be tidy */
|
||||
utflen = ob - utfbuf;
|
||||
newbuf = (char *)realloc(utfbuf, utflen);
|
||||
if (!newbuf)
|
||||
goto fail;
|
||||
utfbuf = newbuf;
|
||||
|
||||
/* Convert from UTF-8 to discover how long the output is */
|
||||
outlen = 0;
|
||||
ib = utfbuf;
|
||||
ibl = utflen;
|
||||
while (ibl) {
|
||||
ob = tbuf;
|
||||
obl = sizeof(tbuf);
|
||||
k = iconv(cd2, &ib, &ibl, &ob, &obl);
|
||||
assert((k != (size_t)(-1) && !ibl) ||
|
||||
(k == (size_t)(-1) && errno == E2BIG && ibl) ||
|
||||
(k == (size_t)(-1) && errno == EILSEQ && ibl));
|
||||
if (ibl && !(k == (size_t)(-1) && errno == E2BIG)) {
|
||||
/* Replace one character */
|
||||
char *tb = "?";
|
||||
size_t tbl = 1;
|
||||
|
||||
outlen += ob - tbuf;
|
||||
ob = tbuf;
|
||||
obl = sizeof(tbuf);
|
||||
k = iconv(cd2, &tb, &tbl, &ob, &obl);
|
||||
assert((!k && !tbl) ||
|
||||
(k == (size_t)(-1) && errno == EILSEQ && tbl));
|
||||
for (++ib, --ibl; ibl && (*ib & 0x80); ib++, ibl--)
|
||||
;
|
||||
}
|
||||
outlen += ob - tbuf;
|
||||
}
|
||||
ob = tbuf;
|
||||
obl = sizeof(tbuf);
|
||||
k = iconv(cd2, 0, 0, &ob, &obl);
|
||||
assert(!k);
|
||||
outlen += ob - tbuf;
|
||||
|
||||
/* Convert from UTF-8 for real */
|
||||
outbuf = (char *)safe_malloc_add_2op_(outlen, /*+*/1);
|
||||
if (!outbuf)
|
||||
goto fail;
|
||||
ib = utfbuf;
|
||||
ibl = utflen;
|
||||
ob = outbuf;
|
||||
obl = outlen;
|
||||
while (ibl) {
|
||||
k = iconv(cd2, &ib, &ibl, &ob, &obl);
|
||||
assert((k != (size_t)(-1) && !ibl) ||
|
||||
(k == (size_t)(-1) && errno == EILSEQ && ibl));
|
||||
if (k && !ret)
|
||||
ret = 1;
|
||||
if (ibl && !(k == (size_t)(-1) && errno == E2BIG)) {
|
||||
/* Replace one character */
|
||||
char *tb = "?";
|
||||
size_t tbl = 1;
|
||||
|
||||
k = iconv(cd2, &tb, &tbl, &ob, &obl);
|
||||
assert((!k && !tbl) ||
|
||||
(k == (size_t)(-1) && errno == EILSEQ && tbl));
|
||||
for (++ib, --ibl; ibl && (*ib & 0x80); ib++, ibl--)
|
||||
;
|
||||
}
|
||||
}
|
||||
k = iconv(cd2, 0, 0, &ob, &obl);
|
||||
assert(!k);
|
||||
assert(!obl);
|
||||
*ob = '\0';
|
||||
|
||||
free(utfbuf);
|
||||
iconv_close(cd1);
|
||||
iconv_close(cd2);
|
||||
if (tolen)
|
||||
*tolen = outlen;
|
||||
if (!to) {
|
||||
free(outbuf);
|
||||
return ret;
|
||||
}
|
||||
*to = outbuf;
|
||||
return ret;
|
||||
|
||||
fail:
|
||||
if(0 != utfbuf)
|
||||
free(utfbuf);
|
||||
iconv_close(cd1);
|
||||
if (cd2 != (iconv_t)(-1))
|
||||
iconv_close(cd2);
|
||||
return -2;
|
||||
}
|
||||
|
||||
#endif /* HAVE_ICONV */
|
||||
49
flac/src/share/utf8/iconvert.h
Normal file
49
flac/src/share/utf8/iconvert.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Edmund Grimley Evans <edmundo@rano.org>
|
||||
*
|
||||
* 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 <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ICONV
|
||||
|
||||
/*
|
||||
* Convert data from one encoding to another. Return:
|
||||
*
|
||||
* -2 : memory allocation failed
|
||||
* -1 : unknown encoding
|
||||
* 0 : data was converted exactly
|
||||
* 1 : data was converted inexactly
|
||||
* 2 : data was invalid (but still converted)
|
||||
*
|
||||
* We convert in two steps, via UTF-8, as this is the only
|
||||
* reliable way of distinguishing between invalid input
|
||||
* and valid input which iconv refuses to transliterate.
|
||||
* We convert from UTF-8 twice, because we have no way of
|
||||
* knowing whether the conversion was exact if iconv returns
|
||||
* E2BIG (due to a bug in the specification of iconv).
|
||||
* An alternative approach is to assume that the output of
|
||||
* iconv is never more than 4 times as long as the input,
|
||||
* but I prefer to avoid that assumption if possible.
|
||||
*/
|
||||
|
||||
int iconvert(const char *fromcode, const char *tocode,
|
||||
const char *from, size_t fromlen,
|
||||
char **to, size_t *tolen) ;
|
||||
|
||||
#endif /* HAVE_ICONV */
|
||||
81
flac/src/share/utf8/makemap.c
Normal file
81
flac/src/share/utf8/makemap.c
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Edmund Grimley Evans <edmundo@rano.org>
|
||||
*
|
||||
* 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 <config.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <iconv.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
iconv_t cd;
|
||||
const char *ib;
|
||||
char *ob;
|
||||
size_t ibl, obl, k;
|
||||
unsigned char c, buf[4];
|
||||
int i, wc;
|
||||
|
||||
if (argc != 2) {
|
||||
printf("Usage: %s ENCODING\n", argv[0]);
|
||||
printf("Output a charset map for the 8-bit ENCODING.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
cd = iconv_open("UCS-4", argv[1]);
|
||||
if (cd == (iconv_t)(-1)) {
|
||||
perror("iconv_open");
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
c = i;
|
||||
ib = &c;
|
||||
ibl = 1;
|
||||
ob = buf;
|
||||
obl = 4;
|
||||
k = iconv(cd, &ib, &ibl, &ob, &obl);
|
||||
if (!k && !ibl && !obl) {
|
||||
wc = (buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + buf[3];
|
||||
if (wc >= 0xffff) {
|
||||
printf("Dodgy value.\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (k == (size_t)(-1) && errno == EILSEQ)
|
||||
wc = 0xffff;
|
||||
else {
|
||||
printf("Non-standard iconv.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (i % 8 == 0)
|
||||
printf(" ");
|
||||
printf("0x%04x", wc);
|
||||
if (i == 255)
|
||||
printf("\n");
|
||||
else if (i % 8 == 7)
|
||||
printf(",\n");
|
||||
else
|
||||
printf(", ");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
319
flac/src/share/utf8/utf8.c
Normal file
319
flac/src/share/utf8/utf8.c
Normal file
@@ -0,0 +1,319 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Peter Harris <peter.harris@hummingbird.com>
|
||||
* Copyright (C) 2001 Edmund Grimley Evans <edmundo@rano.org>
|
||||
*
|
||||
* Buffer overflow checking added: Josh Coalson, 9/9/2007
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* Convert a string between UTF-8 and the locale's charset.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "share/alloc.h"
|
||||
#include "utf8.h"
|
||||
#include "charset.h"
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
/* Thanks to Peter Harris <peter.harris@hummingbird.com> for this win32
|
||||
* code.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
|
||||
static unsigned char *make_utf8_string(const wchar_t *unicode)
|
||||
{
|
||||
size_t size = 0, n;
|
||||
int index = 0, out_index = 0;
|
||||
unsigned char *out;
|
||||
unsigned short c;
|
||||
|
||||
/* first calculate the size of the target string */
|
||||
c = unicode[index++];
|
||||
while(c) {
|
||||
if(c < 0x0080) {
|
||||
n = 1;
|
||||
} else if(c < 0x0800) {
|
||||
n = 2;
|
||||
} else {
|
||||
n = 3;
|
||||
}
|
||||
if(size+n < size) /* overflow check */
|
||||
return NULL;
|
||||
size += n;
|
||||
c = unicode[index++];
|
||||
}
|
||||
|
||||
out = safe_malloc_add_2op_(size, /*+*/1);
|
||||
if (out == NULL)
|
||||
return NULL;
|
||||
index = 0;
|
||||
|
||||
c = unicode[index++];
|
||||
while(c)
|
||||
{
|
||||
if(c < 0x080) {
|
||||
out[out_index++] = (unsigned char)c;
|
||||
} else if(c < 0x800) {
|
||||
out[out_index++] = 0xc0 | (c >> 6);
|
||||
out[out_index++] = 0x80 | (c & 0x3f);
|
||||
} else {
|
||||
out[out_index++] = 0xe0 | (c >> 12);
|
||||
out[out_index++] = 0x80 | ((c >> 6) & 0x3f);
|
||||
out[out_index++] = 0x80 | (c & 0x3f);
|
||||
}
|
||||
c = unicode[index++];
|
||||
}
|
||||
out[out_index] = 0x00;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static wchar_t *make_unicode_string(const unsigned char *utf8)
|
||||
{
|
||||
size_t size = 0;
|
||||
int index = 0, out_index = 0;
|
||||
wchar_t *out;
|
||||
unsigned char c;
|
||||
|
||||
/* first calculate the size of the target string */
|
||||
c = utf8[index++];
|
||||
while(c) {
|
||||
if((c & 0x80) == 0) {
|
||||
index += 0;
|
||||
} else if((c & 0xe0) == 0xe0) {
|
||||
index += 2;
|
||||
} else {
|
||||
index += 1;
|
||||
}
|
||||
if(size + 1 == 0) /* overflow check */
|
||||
return NULL;
|
||||
size++;
|
||||
c = utf8[index++];
|
||||
}
|
||||
|
||||
if(size + 1 == 0) /* overflow check */
|
||||
return NULL;
|
||||
out = safe_malloc_mul_2op_(size+1, /*times*/sizeof(wchar_t));
|
||||
if (out == NULL)
|
||||
return NULL;
|
||||
index = 0;
|
||||
|
||||
c = utf8[index++];
|
||||
while(c)
|
||||
{
|
||||
if((c & 0x80) == 0) {
|
||||
out[out_index++] = c;
|
||||
} else if((c & 0xe0) == 0xe0) {
|
||||
out[out_index] = (c & 0x1F) << 12;
|
||||
c = utf8[index++];
|
||||
out[out_index] |= (c & 0x3F) << 6;
|
||||
c = utf8[index++];
|
||||
out[out_index++] |= (c & 0x3F);
|
||||
} else {
|
||||
out[out_index] = (c & 0x3F) << 6;
|
||||
c = utf8[index++];
|
||||
out[out_index++] |= (c & 0x3F);
|
||||
}
|
||||
c = utf8[index++];
|
||||
}
|
||||
out[out_index] = 0;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
int utf8_encode(const char *from, char **to)
|
||||
{
|
||||
wchar_t *unicode;
|
||||
int wchars, err;
|
||||
|
||||
wchars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, from,
|
||||
strlen(from), NULL, 0);
|
||||
|
||||
if(wchars == 0)
|
||||
{
|
||||
fprintf(stderr, "Unicode translation error %d\n", GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(wchars < 0) /* underflow check */
|
||||
return -1;
|
||||
|
||||
unicode = safe_calloc_((size_t)wchars + 1, sizeof(unsigned short));
|
||||
if(unicode == NULL)
|
||||
{
|
||||
fprintf(stderr, "Out of memory processing string to UTF8\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, from,
|
||||
strlen(from), unicode, wchars);
|
||||
if(err != wchars)
|
||||
{
|
||||
free(unicode);
|
||||
fprintf(stderr, "Unicode translation error %d\n", GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* On NT-based windows systems, we could use WideCharToMultiByte(), but
|
||||
* MS doesn't actually have a consistent API across win32.
|
||||
*/
|
||||
*to = make_utf8_string(unicode);
|
||||
|
||||
free(unicode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int utf8_decode(const char *from, char **to)
|
||||
{
|
||||
wchar_t *unicode;
|
||||
int chars, err;
|
||||
|
||||
/* On NT-based windows systems, we could use MultiByteToWideChar(CP_UTF8), but
|
||||
* MS doesn't actually have a consistent API across win32.
|
||||
*/
|
||||
unicode = make_unicode_string(from);
|
||||
if(unicode == NULL)
|
||||
{
|
||||
fprintf(stderr, "Out of memory processing string from UTF8 to UNICODE16\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
chars = WideCharToMultiByte(GetConsoleCP(), WC_COMPOSITECHECK, unicode,
|
||||
-1, NULL, 0, NULL, NULL);
|
||||
|
||||
if(chars < 0) /* underflow check */
|
||||
return -1;
|
||||
|
||||
if(chars == 0)
|
||||
{
|
||||
fprintf(stderr, "Unicode translation error %d\n", GetLastError());
|
||||
free(unicode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*to = safe_calloc_((size_t)chars + 1, sizeof(unsigned char));
|
||||
if(*to == NULL)
|
||||
{
|
||||
fprintf(stderr, "Out of memory processing string to local charset\n");
|
||||
free(unicode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = WideCharToMultiByte(GetConsoleCP(), WC_COMPOSITECHECK, unicode,
|
||||
-1, *to, chars, NULL, NULL);
|
||||
if(err != chars)
|
||||
{
|
||||
fprintf(stderr, "Unicode translation error %d\n", GetLastError());
|
||||
free(unicode);
|
||||
free(*to);
|
||||
*to = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(unicode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* End win32. Rest is for real operating systems */
|
||||
|
||||
|
||||
#ifdef HAVE_LANGINFO_CODESET
|
||||
#include <langinfo.h>
|
||||
#endif
|
||||
|
||||
#include "iconvert.h"
|
||||
|
||||
static const char *current_charset(void)
|
||||
{
|
||||
const char *c = 0;
|
||||
#ifdef HAVE_LANGINFO_CODESET
|
||||
c = nl_langinfo(CODESET);
|
||||
#endif
|
||||
|
||||
if (!c)
|
||||
c = getenv("CHARSET");
|
||||
|
||||
return c? c : "US-ASCII";
|
||||
}
|
||||
|
||||
static int convert_buffer(const char *fromcode, const char *tocode,
|
||||
const char *from, size_t fromlen,
|
||||
char **to, size_t *tolen)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
#ifdef HAVE_ICONV
|
||||
ret = iconvert(fromcode, tocode, from, fromlen, to, tolen);
|
||||
if (ret != -1)
|
||||
return ret;
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_ICONV /* should be ifdef USE_CHARSET_CONVERT */
|
||||
ret = charset_convert(fromcode, tocode, from, fromlen, to, tolen);
|
||||
if (ret != -1)
|
||||
return ret;
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int convert_string(const char *fromcode, const char *tocode,
|
||||
const char *from, char **to, char replace)
|
||||
{
|
||||
int ret;
|
||||
size_t fromlen;
|
||||
char *s;
|
||||
|
||||
fromlen = strlen(from);
|
||||
ret = convert_buffer(fromcode, tocode, from, fromlen, to, 0);
|
||||
if (ret == -2)
|
||||
return -1;
|
||||
if (ret != -1)
|
||||
return ret;
|
||||
|
||||
s = safe_malloc_add_2op_(fromlen, /*+*/1);
|
||||
if (!s)
|
||||
return -1;
|
||||
strcpy(s, from);
|
||||
*to = s;
|
||||
for (; *s; s++)
|
||||
if (*s & ~0x7f)
|
||||
*s = replace;
|
||||
return 3;
|
||||
}
|
||||
|
||||
int utf8_encode(const char *from, char **to)
|
||||
{
|
||||
return convert_string(current_charset(), "UTF-8", from, to, '#');
|
||||
}
|
||||
|
||||
int utf8_decode(const char *from, char **to)
|
||||
{
|
||||
return convert_string("UTF-8", current_charset(), from, to, '?');
|
||||
}
|
||||
|
||||
#endif
|
||||
116
flac/src/share/utf8/utf8_static.dsp
Normal file
116
flac/src/share/utf8/utf8_static.dsp
Normal file
@@ -0,0 +1,116 @@
|
||||
# Microsoft Developer Studio Project File - Name="utf8_static" - Package Owner=<4>
|
||||
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
|
||||
|
||||
# TARGTYPE "Win32 (x86) Static Library" 0x0104
|
||||
|
||||
|
||||
|
||||
CFG=utf8_static - 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 "utf8_static.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 "utf8_static.mak" CFG="utf8_static - Win32 Debug"
|
||||
|
||||
!MESSAGE
|
||||
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
|
||||
!MESSAGE
|
||||
|
||||
!MESSAGE "utf8_static - Win32 Release" (based on "Win32 (x86) Static Library")
|
||||
|
||||
!MESSAGE "utf8_static - Win32 Debug" (based on "Win32 (x86) Static Library")
|
||||
|
||||
!MESSAGE
|
||||
|
||||
|
||||
|
||||
# Begin Project
|
||||
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
|
||||
# PROP Scc_ProjName "utf8"
|
||||
|
||||
# PROP Scc_LocalPath "..\..\.."
|
||||
|
||||
CPP=cl.exe
|
||||
|
||||
RSC=rc.exe
|
||||
|
||||
|
||||
|
||||
!IF "$(CFG)" == "utf8_static - 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\lib"
|
||||
|
||||
# PROP Intermediate_Dir "Release_static"
|
||||
|
||||
# PROP Target_Dir ""
|
||||
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /I ".\include" /I "..\..\..\include" /I "..\..\..\include\share" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
|
||||
BSC32=bscmake.exe
|
||||
|
||||
# ADD BASE BSC32 /nologo
|
||||
|
||||
# ADD BSC32 /nologo
|
||||
|
||||
LIB32=link.exe -lib
|
||||
|
||||
# ADD BASE LIB32 /nologo
|
||||
|
||||
# ADD LIB32 /nologo /nodefaultlib
|
||||
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "utf8_static - Win32 Debug"
|
||||
|
||||
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
|
||||
338
flac/src/share/utf8/utf8_static.vcproj
Normal file
338
flac/src/share/utf8/utf8_static.vcproj
Normal file
@@ -0,0 +1,338 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8,00"
|
||||
Name="utf8_static"
|
||||
ProjectGUID="{4cefbc92-c215-11db-8314-0800200c9a66}"
|
||||
RootNamespace="utf8_static"
|
||||
Keyword="Win32Proj"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
<Platform
|
||||
Name="x64"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="..\..\..\obj\debug\lib"
|
||||
IntermediateDirectory="Debug_static"
|
||||
ConfigurationType="4"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=".\include;..\..\..\include;..\..\..\include\share"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;FLAC__NO_DLL;DEBUG"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="4"
|
||||
CompileAs="0"
|
||||
DisableSpecificWarnings="4267;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="..\..\..\obj\debug\lib\$(ProjectName).lib"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="..\..\..\obj\release\lib"
|
||||
IntermediateDirectory="Release_static"
|
||||
ConfigurationType="4"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
EnableIntrinsicFunctions="true"
|
||||
FavorSizeOrSpeed="1"
|
||||
OmitFramePointers="true"
|
||||
WholeProgramOptimization="true"
|
||||
AdditionalIncludeDirectories=".\include;..\..\..\include;..\..\..\include\share"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;FLAC__NO_DLL"
|
||||
RuntimeLibrary="0"
|
||||
BufferSecurityCheck="false"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"
|
||||
DisableSpecificWarnings="4267;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="..\..\..\obj\release\lib\$(ProjectName).lib"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug|x64"
|
||||
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TargetEnvironment="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=".\include;..\..\..\include;..\..\..\include\share"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;FLAC__NO_DLL;DEBUG"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"
|
||||
DisableSpecificWarnings="4267;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="..\..\..\obj\debug\lib\$(ProjectName).lib"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|x64"
|
||||
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TargetEnvironment="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
EnableIntrinsicFunctions="true"
|
||||
FavorSizeOrSpeed="1"
|
||||
OmitFramePointers="true"
|
||||
WholeProgramOptimization="true"
|
||||
AdditionalIncludeDirectories=".\include;..\..\..\include;..\..\..\include\share"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;FLAC__NO_DLL"
|
||||
RuntimeLibrary="0"
|
||||
BufferSecurityCheck="false"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"
|
||||
DisableSpecificWarnings="4267;4996"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="..\..\..\obj\release\lib\$(ProjectName).lib"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\charmaps.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\charset.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\charsetmap.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Public Header Files"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\..\include\share\utf8.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\charset.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\iconvert.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\utf8.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
Reference in New Issue
Block a user