[xiph-commits] r17747 - in websites/celt-codec.org: . squishyio
xiphmont at svn.xiph.org
xiphmont at svn.xiph.org
Sun Dec 12 01:17:39 PST 2010
Author: xiphmont
Date: 2010-12-12 01:17:39 -0800 (Sun, 12 Dec 2010)
New Revision: 17747
Added:
websites/celt-codec.org/squishyio/
websites/celt-codec.org/squishyio/Makefile.am
websites/celt-codec.org/squishyio/autogen.sh
websites/celt-codec.org/squishyio/configure.ac
websites/celt-codec.org/squishyio/squishyio.c
websites/celt-codec.org/squishyio/squishyio.h
Log:
Since someone wanted the fast prototype load/save lib....
Added: websites/celt-codec.org/squishyio/Makefile.am
===================================================================
--- websites/celt-codec.org/squishyio/Makefile.am (rev 0)
+++ websites/celt-codec.org/squishyio/Makefile.am 2010-12-12 09:17:39 UTC (rev 17747)
@@ -0,0 +1,18 @@
+## Process this file with automake to produce Makefile.in
+
+AUTOMAKE_OPTIONS = foreign 1.11
+
+EXTRA_DIST = COPYING autogen.sh
+
+
+lib_LTLIBRARIES = libsquishyio.la
+libsquishyio_la_SOURCES = squishyio.c squishyio.h
+libsquishyio_la_LDFLAGS = -no-undefined -version-info @SqI_LIB_CURRENT@:@SqI_LIB_REVISION@:@SqI_LIB_AGE@
+libsquishyioincludedir = $(includedir)/squishyio
+libsquishyioinclude_HEADERS = squishyio.h
+
+debug:
+ $(MAKE) all CFLAGS="@DEBUG@"
+
+profile:
+ $(MAKE) all CFLAGS="@PROFILE@"
Added: websites/celt-codec.org/squishyio/autogen.sh
===================================================================
--- websites/celt-codec.org/squishyio/autogen.sh (rev 0)
+++ websites/celt-codec.org/squishyio/autogen.sh 2010-12-12 09:17:39 UTC (rev 17747)
@@ -0,0 +1,128 @@
+#!/bin/sh
+# Run this to set up the build system: configure, makefiles, etc.
+# (based on the version in enlightenment's cvs)
+
+package="squishyball"
+
+ACLOCAL_FLAGS=""
+
+olddir=`pwd`
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+cd "$srcdir"
+DIE=0
+
+/bin/echo "checking for autoconf... "
+(autoconf --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "You must have autoconf installed to compile $package."
+ echo "Download the appropriate package for your distribution,"
+ echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
+ DIE=1
+}
+
+VERSIONGREP="sed -e s/.*[^0-9\.]\([0-9][0-9]*\.[0-9][0-9]*\).*/\1/"
+VERSIONMKMAJ="sed -e s/\([0-9][0-9]*\)[^0-9].*/\\1/"
+VERSIONMKMIN="sed -e s/.*[0-9][0-9]*\.//"
+
+# do we need automake?
+if test -r Makefile.am; then
+ AM_OPTIONS=`fgrep AUTOMAKE_OPTIONS Makefile.am`
+ AM_NEEDED=`echo $AM_OPTIONS | $VERSIONGREP`
+ if test x"$AM_NEEDED" = "x$AM_OPTIONS"; then
+ AM_NEEDED=""
+ fi
+ if test -z $AM_NEEDED; then
+ /bin/echo -n "checking for automake... "
+ AUTOMAKE=automake
+ ACLOCAL=aclocal
+ if ($AUTOMAKE --version < /dev/null > /dev/null 2>&1); then
+ /bin/echo "yes"
+ else
+ /bin/echo "no"
+ AUTOMAKE=
+ fi
+ else
+ /bin/echo -n "checking for automake $AM_NEEDED or later... "
+ majneeded=`echo $AM_NEEDED | $VERSIONMKMAJ`
+ minneeded=`echo $AM_NEEDED | $VERSIONMKMIN`
+ for am in automake-$AM_NEEDED automake$AM_NEEDED \
+ automake automake-1.7 automake-1.8 automake-1.9 \
+ automake-1.10 automake-1.11; do
+ ($am --version < /dev/null > /dev/null 2>&1) || continue
+ ver=`$am --version < /dev/null | head -n 1 | $VERSIONGREP`
+ maj=`echo $ver | $VERSIONMKMAJ`
+ min=`echo $ver | $VERSIONMKMIN`
+ if test $maj -eq $majneeded -a $min -ge $minneeded; then
+ AUTOMAKE=$am
+ /bin/echo $AUTOMAKE
+ break
+ fi
+ done
+ test -z $AUTOMAKE && /bin/echo "no"
+ /bin/echo -n "checking for aclocal $AM_NEEDED or later... "
+ for ac in aclocal-$AM_NEEDED aclocal$AM_NEEDED \
+ aclocal aclocal-1.7 aclocal-1.8 aclocal-1.9 aclocal-1.10 aclocal-1.11; do
+ ($ac --version < /dev/null > /dev/null 2>&1) || continue
+ ver=`$ac --version < /dev/null | head -n 1 | $VERSIONGREP`
+ maj=`echo $ver | $VERSIONMKMAJ`
+ min=`echo $ver | $VERSIONMKMIN`
+ if test $maj -eq $majneeded -a $min -ge $minneeded; then
+ ACLOCAL=$ac
+ /bin/echo $ACLOCAL
+ break
+ fi
+ done
+ test -z $ACLOCAL && /bin/echo "no"
+ fi
+ test -z $AUTOMAKE || test -z $ACLOCAL && {
+ echo
+ echo "You must have automake installed to compile $package."
+ echo "Download the appropriate package for your distribution,"
+ echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
+ exit 1
+ }
+fi
+
+/bin/echo -n "checking for libtool... "
+for LIBTOOLIZE in libtoolize glibtoolize nope; do
+ ($LIBTOOLIZE --version) < /dev/null > /dev/null 2>&1 && break
+done
+if test x$LIBTOOLIZE = xnope; then
+ /bin/echo "nope."
+ LIBTOOLIZE=libtoolize
+else
+ /bin/echo $LIBTOOLIZE
+fi
+($LIBTOOLIZE --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "You must have libtool installed to compile $package."
+ echo "Download the appropriate package for your system,"
+ echo "or get the source from one of the GNU ftp sites"
+ echo "listed in http://www.gnu.org/order/ftp.html"
+ DIE=1
+}
+
+if test "$DIE" -eq 1; then
+ exit 1
+fi
+
+if test -z "$*"; then
+ echo "I am going to run ./configure with no arguments - if you wish "
+ echo "to pass any to it, please specify them on the $0 command line."
+fi
+
+/bin/echo "Generating configuration files for $package, please wait...."
+
+/bin/echo " $ACLOCAL $ACLOCAL_FLAGS"
+$ACLOCAL $ACLOCAL_FLAGS || exit 1
+/bin/echo " $LIBTOOLIZE --automake --force"
+$LIBTOOLIZE --automake --force || exit 1
+/bin/echo " $AUTOMAKE --add-missing $AUTOMAKE_FLAGS"
+$AUTOMAKE --add-missing $AUTOMAKE_FLAGS || exit 1
+/bin/echo " autoconf"
+autoconf || exit 1
+
+cd $olddir
+$srcdir/configure "$@" && /bin/echo
Property changes on: websites/celt-codec.org/squishyio/autogen.sh
___________________________________________________________________
Added: svn:executable
+ *
Added: websites/celt-codec.org/squishyio/configure.ac
===================================================================
--- websites/celt-codec.org/squishyio/configure.ac (rev 0)
+++ websites/celt-codec.org/squishyio/configure.ac 2010-12-12 09:17:39 UTC (rev 17747)
@@ -0,0 +1,93 @@
+# -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+cflags_save="$CFLAGS"
+AC_PREREQ(2.57)
+AC_INIT(squishyio.c)
+AM_INIT_AUTOMAKE(squishyio, 20101208, [vorbis-dev at xiph.org])
+AC_CONFIG_FILES([Makefile])
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])], [AC_SUBST([AM_DEFAULT_VERBOSITY], [1])])
+
+SqI_LIB_CURRENT=0
+SqI_LIB_REVISION=0
+SqI_LIB_AGE=0
+AC_SUBST(SqI_LIB_CURRENT)
+AC_SUBST(SqI_LIB_REVISION)
+AC_SUBST(SqI_LIB_AGE)
+
+# Checks for programs.
+AC_PROG_CC
+AC_PROG_LIBTOOL
+
+# Checks for libraries.
+
+PKG_CHECK_MODULES([vorbisfile], [vorbisfile])
+PKG_CHECK_MODULES([FLAC], [flac >= 0.8.0])
+PKG_CHECK_MODULES([ao], [ao > 1.0.0])
+AC_CHECK_LIB([ncurses], [initscr],,[AC_MSG_ERROR([ncurses required!])])
+AC_CHECK_LIB([ncurses], [_nc_tinfo_fkeysf], USE_FKEYSF=1, USE_FKEYSF=0)
+AC_CHECK_LIB([m], [cos])
+AC_CHECK_LIB([pthread], [pthread_create])
+
+# Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS([stdlib.h string.h])
+AC_CHECK_HEADERS([vorbis/vorbisfile.h])
+AC_CHECK_HEADERS([ao/ao.h])
+AC_CHECK_HEADERS([FLAC/stream_decoder.h])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+
+if test -z "$GCC"; then
+ case $host in
+ *-*-irix*)
+ DEBUG="-g -signed"
+ CFLAGS="-O2 -w -signed"
+ PROFILE="-p -g3 -O2 -signed"
+ ;;
+ sparc-sun-solaris*)
+ DEBUG="-v -g"
+ CFLAGS="-xO4 -fast -w -fsimple -native -xcg92"
+ PROFILE="-v -xpg -g -xO4 -fast -native -fsimple -xcg92 -Dsuncc"
+ ;;
+ *)
+ DEBUG="-g"
+ CFLAGS="-O"
+ PROFILE="-g -p"
+ ;;
+ esac
+else
+ case $host in
+ *-*-linux*)
+ DEBUG="-g -Wall -fsigned-char"
+ CFLAGS="-O2 -fsigned-char -ffast-math"
+ PROFILE="-Wall -W -pg -g -O2 -fsigned-char -ffast-math"
+ ;;
+ sparc-sun-*)
+ DEBUG="-g -Wall -fsigned-char"
+ CFLAGS="-O2 -fsigned-char"
+ PROFILE="-pg -g -O2 -fsigned-char"
+ ;;
+ *-*-darwin*)
+ DEBUG="-fno-common -g -Wall -fsigned-char"
+ CFLAGS="-fno-common -O2 -Wall -fsigned-char -ffast-math"
+ PROFILE="-fno-common -O2 -Wall -pg -g -fsigned-char -ffast-math"
+ ;;
+ *)
+ DEBUG="-g -Wall -fsigned-char"
+ CFLAGS="-O2 -fsigned-char -ffast-math"
+ PROFILE="-O2 -g -pg -fsigned-char -ffast-math"
+ ;;
+ esac
+fi
+
+COMMON_FLAGS="$cflags_save $vorbisfile_CFLAGS $ao_CFLAGS $FLAC_CFLAGS -DUSE_FKEYSF=$USE_FKEYSF"
+CFLAGS="$CFLAGS -DVERSION='\"$VERSION\"' $COMMON_FLAGS"
+DEBUG="$DEBUG -DVERSION='\\\"$VERSION\\\"' $COMMON_FLAGS"
+PROFILE="$PROFILE -DVERSION='\\\"$VERSION\\\"' $COMMON_FLAGS"
+LIBS="$LIBS $vorbisfile_LIBS $ao_LIBS $FLAC_LIBS"
+AC_SUBST(DEBUG)
+AC_SUBST(PROFILE)
+
+AC_OUTPUT
Added: websites/celt-codec.org/squishyio/squishyio.c
===================================================================
--- websites/celt-codec.org/squishyio/squishyio.c (rev 0)
+++ websites/celt-codec.org/squishyio/squishyio.c 2010-12-12 09:17:39 UTC (rev 17747)
@@ -0,0 +1,1162 @@
+/*
+ *
+ * squishyio
+ *
+ * Copyright (C) 2010 Xiph.Org
+ *
+ * squishyball 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, or (at your option)
+ * any later version.
+ *
+ * squishyball 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 rtrecord; see the file COPYING. If not, write to the
+ * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ */
+
+#define _GNU_SOURCE
+#define _LARGEFILE_SOURCE
+#define _LARGEFILE64_SOURCE
+#define _FILE_OFFSET_BITS 64
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <errno.h>
+#include <ao/ao.h>
+#include <vorbis/vorbisfile.h>
+#include <FLAC/stream_decoder.h>
+#include <unistd.h>
+#include "squishyio.h"
+
+#define rbsize 4096
+static unsigned char rawbuf[rbsize];
+
+static inline int host_is_big_endian() {
+ union {
+ int32_t pattern;
+ unsigned char bytewise[4];
+ } m;
+ m.pattern = 0xfeedface; /* deadbeef */
+ if (m.bytewise[0] == 0xfe) return 1;
+ return 0;
+}
+
+static char *trim_path(const char *in){
+ /* search back to first /, \, or : */
+ if(in){
+ char *a = strrchr(in,'/');
+ char *b = strrchr(in,'\\');
+ char *c = strrchr(in,':');
+ int posa = (a ? a-in+1 : 0);
+ int posb = (b ? b-in+1 : 0);
+ int posc = (c ? c-in+1 : 0);
+ if(posb>posa)posa=posb;
+ if(posc>posa)posa=posc;
+ return (char *)in+posa;
+ }
+ return NULL;
+}
+
+typedef struct{
+ int (*id_func)(const char *path,unsigned char *buf);
+ pcm_t *(*load_func)(const char *path, FILE *in);
+ char *format;
+} input_format;
+
+/* steal/simplify/expand file ID/load code from oggenc */
+
+/* Macros to read header data */
+#define READ_U32_LE(buf) \
+ (((buf)[3]<<24)|((buf)[2]<<16)|((buf)[1]<<8)|((buf)[0]&0xff))
+
+#define READ_U16_LE(buf) \
+ (((buf)[1]<<8)|((buf)[0]&0xff))
+
+#define READ_U32_BE(buf) \
+ (((buf)[0]<<24)|((buf)[1]<<16)|((buf)[2]<<8)|((buf)[3]&0xff))
+
+#define READ_U16_BE(buf) \
+ (((buf)[0]<<8)|((buf)[1]&0xff))
+
+static int wav_id(const char *path,unsigned char *buf){
+ if(memcmp(buf, "RIFF", 4))
+ return 0; /* Not wave */
+ if(memcmp(buf+8, "WAVE",4))
+ return 0; /* RIFF, but not wave */
+ return 1;
+}
+
+static int aiff_id(const char *path,unsigned char *buf){
+ if(memcmp(buf, "FORM", 4))
+ return 0;
+ if(memcmp(buf+8, "AIF",3))
+ return 0;
+ if(buf[11]!='C' && buf[11]!='F')
+ return 0;
+ return 1;
+}
+
+static int flac_id(const char *path,unsigned char *buf){
+ return memcmp(buf, "fLaC", 4) == 0;
+}
+
+static int oggflac_id(const char *path,unsigned char *buf){
+ return memcmp(buf, "OggS", 4) == 0 &&
+ (memcmp (buf+28, "\177FLAC", 5) == 0 ||
+ flac_id(path,buf+28));
+}
+
+static int vorbis_id(const char *path,unsigned char *buf){
+ return memcmp(buf, "OggS", 4) == 0 &&
+ memcmp (buf+28, "\x01vorbis", 7) == 0;
+}
+
+static int sw_id(const char *path,unsigned char *buf){
+ /* if all else fails, look for JM's favorite extension */
+ return memcmp(path+strlen(path)-3,".sw",3)==0;
+}
+
+static int read_raw_samples(pcm_t *pcm, FILE *in, int s8, int bep){
+ union {
+ float f;
+ unsigned char c[4];
+ } m;
+
+ int i;
+ int bytesper,samplesper;
+ off_t sofar=0;
+ int bps=(abs(pcm->savebits)+7)>>3;
+ int cpf=pcm->ch;
+ int bpf=bps*cpf;
+
+ pcm->data = calloc(pcm->ch,sizeof(*pcm->data));
+ if(pcm->data == NULL){
+ fprintf(stderr,"Unable to allocate enough memory to load sample into memory\n");
+ goto err;
+ }
+ for(i=0;i<pcm->ch;i++){
+ pcm->data[i] = calloc(pcm->samples,sizeof(**pcm->data));
+ if(pcm->data[i] == NULL){
+ fprintf(stderr,"Unable to allocate enough memory to load sample into memory\n");
+ goto err;
+ }
+ }
+
+ samplesper = rbsize/bpf;
+ bytesper = samplesper*bpf;
+
+ while(sofar<pcm->samples){
+ unsigned char *d=rawbuf;
+ off_t bytes, samples=samplesper;
+ int i,j;
+ if((pcm->samples-sofar)<samples)samples=pcm->samples-sofar;
+ bytes = samples*bpf;
+
+ bytes=fread(d,1,bytes,in);
+ if(bytes==0)break;
+
+ switch(pcm->savebits){
+ case 8:
+ if(s8){
+ for(i=0;i<samples;i++){
+ for(j=0;j<cpf;j++){
+ pcm->data[j][sofar] = ((ogg_int16_t)(*d)<<8)*(1.f/32768.f);
+ d++;
+ }
+ sofar++;
+ }
+ }else{
+ for(i=0;i<samples;i++){
+ for(j=0;j<cpf;j++){
+ pcm->data[j][sofar] = (*d-128)*(1.f/128.f);
+ d++;
+ }
+ sofar++;
+ }
+ }
+ break;
+ case 16:
+ if(bep){
+ for(i=0;i<samples;i++){
+ for(j=0;j<cpf;j++){
+ pcm->data[j][sofar] = ((ogg_int16_t)((d[0]<<8)|(d[1])))*(1.f/32768.f);
+ d+=2;
+ }
+ sofar++;
+ }
+ }else{
+ for(i=0;i<samples;i++){
+ for(j=0;j<cpf;j++){
+ pcm->data[j][sofar] = ((ogg_int16_t)((d[1]<<8)|(d[0])))*(1.f/32768.f);
+ d+=2;
+ }
+ sofar++;
+ }
+ }
+ break;
+ case 24:
+ if(bep){
+ for(i=0;i<samples;i++){
+ for(j=0;j<cpf;j++){
+ pcm->data[j][sofar] = ((int)((d[0]<<24)|(d[1]<<16)|(d[2]<<8))>>8)*(1.f/8388608.f);
+ d+=3;
+ }
+ sofar++;
+ }
+ }else{
+ for(i=0;i<samples;i++){
+ for(j=0;j<cpf;j++){
+ pcm->data[j][sofar] = ((int)((d[2]<<24)|(d[1]<<16)|(d[0]<<8))>>8)*(1.f/8388608.f);
+ d+=3;
+ }
+ sofar++;
+ }
+ }
+ break;
+ case -32:
+ if((!bep)==(!host_is_big_endian())){
+ for(i=0;i<samples;i++){
+ for(j=0;j<cpf;j++){
+ m.c[0]=d[0];
+ m.c[1]=d[1];
+ m.c[2]=d[2];
+ m.c[3]=d[3];
+ d+=4;
+ pcm->data[j][sofar] = m.f;
+ }
+ sofar++;
+ }
+ }else{
+ for(i=0;i<samples;i++){
+ for(j=0;j<cpf;j++){
+ m.c[0]=d[3];
+ m.c[1]=d[2];
+ m.c[2]=d[1];
+ m.c[3]=d[0];
+ d+=4;
+ pcm->data[j][sofar] = m.f;
+ }
+ sofar++;
+ }
+ }
+ break;
+ default:
+ fprintf(stderr,"Unsupported input bit depth\n");
+ goto err;
+ }
+ }
+
+ if(sofar<pcm->samples){
+ fprintf(stderr,"Input file ended before declared length (%ld < %ld samples); continuing...\n",(long)sofar,(long)pcm->samples);
+ pcm->samples=sofar;
+ }
+
+ if(pcm->savebits==8)pcm->savebits=16;
+
+ return 0;
+ err:
+ free_pcm(pcm);
+ return 1;
+}
+
+
+
+/* WAV file support ***********************************************************/
+
+static int find_wav_chunk(FILE *in, const char *path, char *type, unsigned int *len){
+ unsigned char buf[8];
+
+ while(1){
+ if(fread(buf,1,8,in) < 8){
+ fprintf(stderr, "%s: Unexpected EOF in reading WAV header\n",path);
+ return 0; /* EOF before reaching the appropriate chunk */
+ }
+
+ if(memcmp(buf, type, 4)){
+ *len = READ_U32_LE(buf+4);
+ if(fseek(in, *len, SEEK_CUR))
+ return 0;
+
+ buf[4] = 0;
+ }else{
+ *len = READ_U32_LE(buf+4);
+ return 1;
+ }
+ }
+}
+
+static pcm_t *wav_load(const char *path, FILE *in){
+ unsigned char buf[40];
+ unsigned int len;
+ pcm_t *pcm = NULL;
+ int i;
+
+ if(fseek(in,12,SEEK_SET)==-1){
+ fprintf(stderr,"%s: Failed to seek\n",path);
+ goto err;
+ }
+
+ pcm = calloc(1,sizeof(pcm_t));
+ pcm->name=strdup(trim_path(path));
+
+ if(!find_wav_chunk(in, path, "fmt ", &len)){
+ fprintf(stderr,"%s: Failed to find fmt chunk in WAV file\n",path);
+ goto err;
+ }
+
+ if(len < 16){
+ fprintf(stderr, "%s: Unrecognised format chunk in WAV header\n",path);
+ goto err;
+ }
+
+ /* A common error is to have a format chunk that is not 16, 18 or
+ * 40 bytes in size. This is incorrect, but not fatal, so we only
+ * warn about it instead of refusing to work with the file.
+ * Please, if you have a program that's creating format chunks of
+ * sizes other than 16 or 18 bytes in size, report a bug to the
+ * author.
+ */
+ if(len!=16 && len!=18 && len!=40)
+ fprintf(stderr,
+ "%s: INVALID format chunk in WAV header.\n"
+ " Trying to read anyway (may not work)...\n",path);
+
+ if(len>40)len=40;
+
+ if(fread(buf,1,len,in) < len){
+ fprintf(stderr,"%s: Unexpected EOF in reading WAV header\n",path);
+ goto err;
+ }
+
+ unsigned int mask = 0;
+ unsigned int format = READ_U16_LE(buf);
+ unsigned int channels = READ_U16_LE(buf+2);
+ unsigned int samplerate = READ_U32_LE(buf+4);
+ //unsigned int bytespersec = READ_U32_LE(buf+8);
+ unsigned int align = READ_U16_LE(buf+12);
+ unsigned int samplesize = READ_U16_LE(buf+14);
+ const char *mask_map[32]={
+ "L","R","C","LFE", "BL","BR","CL","CR",
+ "BC","SL","SR","X", "X","X","X","X",
+ "X","X","X","X", "X","X","X","X",
+ "X","X","X","X", "X","X","X","X"};
+
+ if(format == 0xfffe){ /* WAVE_FORMAT_EXTENSIBLE */
+
+ if(len<40){
+ fprintf(stderr,"%s: Extended WAV format header invalid (too small)\n",path);
+ goto err;
+ }
+
+ mask = READ_U32_LE(buf+20);
+ format = READ_U16_LE(buf+24);
+ }
+
+ if(mask==0){
+ switch(channels){
+ case 1:
+ pcm->matrix = strdup("M");
+ break;
+ case 2:
+ pcm->matrix = strdup("L,R");
+ break;
+ case 3:
+ pcm->matrix = strdup("L,R,C");
+ break;
+ case 4:
+ pcm->matrix = strdup("L,R,BL,BR");
+ break;
+ case 5:
+ pcm->matrix = strdup("L,R,C,BL,BR");
+ break;
+ case 6:
+ pcm->matrix = strdup("L,R,C,LFE,BL,BR");
+ break;
+ case 7:
+ pcm->matrix = strdup("L,R,C,LFE,BC,SL,SR");
+ break;
+ default:
+ pcm->matrix = strdup("L,R,C,LFE,BL,BR,SL,SR");
+ break;
+ }
+ }else{
+ pcm->matrix = calloc(32*4,sizeof(char));
+ for(i=0;i<32;i++){
+ if(mask&(1<<i)){
+ strcat(pcm->matrix,mask_map[i]);
+ strcat(pcm->matrix,",");
+ }
+ }
+ pcm->matrix[strlen(pcm->matrix)-1]=0;
+ }
+
+ if(!find_wav_chunk(in, path, "data", &len)){
+ fprintf(stderr,"%s: Failed to find fmt chunk in WAV file\n",path);
+ goto err;
+ }
+
+ if(align != channels * ((samplesize+7)/8)) {
+ /* This is incorrect according to the spec. Warn loudly, then ignore
+ * this value.
+ */
+ fprintf(stderr, "%s: WAV 'block alignment' value is incorrect, "
+ "ignoring.\n"
+ "The software that created this file is incorrect.\n",path);
+ }
+
+ if((format==1 && (samplesize == 24 || samplesize == 16 || samplesize == 8)) ||
+ (samplesize == 32 && format == 3)){
+ /* OK, good - we have a supported format,
+ now we want to find the size of the file */
+ pcm->rate = samplerate;
+ pcm->ch = channels;
+ pcm->savebits = (format==3 ? -samplesize : samplesize);
+
+ if(len){
+ pcm->samples = len;
+ }else{
+ long pos;
+ pos = ftell(in);
+ if(fseek(in, 0, SEEK_END) == -1){
+ fprintf(stderr,"%s failed to seek: %s\n",path,strerror(errno));
+ goto err;
+ }else{
+ pcm->samples = ftell(in) - pos;
+ fseek(in,pos, SEEK_SET);
+ }
+ }
+
+ }else{
+ fprintf(stderr,
+ "%s: Wav file is unsupported subformat (must be 8,16, or 24-bit PCM\n"
+ "or floating point PCM\n",path);
+ goto err;
+ }
+
+ /* read the samples into memory */
+ pcm->samples/=pcm->ch;
+ pcm->samples/=((abs(pcm->savebits)+7)>>3);
+ if(read_raw_samples(pcm,in,0,0))
+ goto err;
+ return pcm;
+ err:
+ free_pcm(pcm);
+ return NULL;
+}
+
+/* AIFF file support ***********************************************************/
+
+static int find_aiff_chunk(FILE *in, const char *path, char *type, unsigned int *len){
+ unsigned char buf[8];
+ int restarted = 0;
+
+ while(1){
+ if(fread(buf,1,8,in)<8){
+ if(!restarted) {
+ /* Handle out of order chunks by seeking back to the start
+ * to retry */
+ restarted = 1;
+ fseek(in, 12, SEEK_SET);
+ continue;
+ }
+ fprintf(stderr,"%s: Unexpected EOF in AIFF chunk\n",path);
+ return 0;
+ }
+
+ *len = READ_U32_BE(buf+4);
+
+ if(memcmp(buf,type,4)){
+ if((*len) & 0x1)
+ (*len)++;
+
+ if(fseek(in,*len,SEEK_CUR))
+ return 0;
+ }else
+ return 1;
+ }
+}
+
+static double read_IEEE80(unsigned char *buf){
+ int s=buf[0]&0xff;
+ int e=((buf[0]&0x7f)<<8)|(buf[1]&0xff);
+ double f=((unsigned long)(buf[2]&0xff)<<24)|
+ ((buf[3]&0xff)<<16)|
+ ((buf[4]&0xff)<<8) |
+ (buf[5]&0xff);
+
+ if(e==32767){
+ if(buf[2]&0x80)
+ return HUGE_VAL; /* Really NaN, but this won't happen in reality */
+ else{
+ if(s)
+ return -HUGE_VAL;
+ else
+ return HUGE_VAL;
+ }
+ }
+
+ f=ldexp(f,32);
+ f+= ((buf[6]&0xff)<<24)|
+ ((buf[7]&0xff)<<16)|
+ ((buf[8]&0xff)<<8) |
+ (buf[9]&0xff);
+ return ldexp(f, e-16446);
+}
+
+static inline void swap(unsigned char *a, unsigned char *b){
+ unsigned char temp=*a;
+ *a=*b;
+ *b=temp;
+}
+
+static pcm_t *aiff_load(const char *path, FILE *in){
+ pcm_t *pcm = NULL;
+ int aifc; /* AIFC or AIFF? */
+ unsigned int len;
+ unsigned char *buffer;
+ unsigned char buf2[12];
+ int bend = 1;
+
+ if(fseek(in,0,SEEK_SET)==-1){
+ fprintf(stderr,"%s: Failed to seek\n",path);
+ goto err;
+ }
+ if(fread(buf2,1,12,in)!=12){
+ fprintf(stderr,"%s: Failed to read AIFF header\n",path);
+ goto err;
+ }
+
+ pcm = calloc(1,sizeof(pcm_t));
+ pcm->name=strdup(trim_path(path));
+
+ if(buf2[11]=='C')
+ aifc=1;
+ else
+ aifc=0;
+
+ if(!find_aiff_chunk(in, path, "COMM", &len)){
+ fprintf(stderr,"%s: No common chunk found in AIFF file\n",path);
+ goto err;
+ }
+
+ if(len < 18){
+ fprintf(stderr, "%s: Truncated common chunk in AIFF header\n",path);
+ goto err;
+ }
+
+ buffer = alloca(len);
+
+ if(fread(buffer,1,len,in) < len){
+ fprintf(stderr, "%s: Unexpected EOF in reading AIFF header\n",path);
+ goto err;
+ }
+
+ pcm->ch = READ_U16_BE(buffer);
+ pcm->rate = (int)read_IEEE80(buffer+8);
+ pcm->savebits = READ_U16_BE(buffer+6);
+ pcm->samples = READ_U32_BE(buffer+2)*pcm->ch*((pcm->savebits+7)/8);
+
+ switch(pcm->ch){
+ case 1:
+ pcm->matrix = strdup("M");
+ break;
+ case 2:
+ pcm->matrix = strdup("L,R");
+ break;
+ case 3:
+ pcm->matrix = strdup("L,R,C");
+ break;
+ default:
+ pcm->matrix = strdup("L,R,BL,BR");
+ break;
+ }
+
+ if(aifc){
+ if(len < 22){
+ fprintf(stderr, "%s: AIFF-C header truncated.\n",path);
+ goto err;
+ }
+
+ if(!memcmp(buffer+18, "NONE", 4)){
+ bend = 1;
+ }else if(!memcmp(buffer+18, "sowt", 4)){
+ bend = 0;
+ }else{
+ fprintf(stderr, "%s: Can't handle compressed AIFF-C (%c%c%c%c)\n", path,
+ *(buffer+18), *(buffer+19), *(buffer+20), *(buffer+21));
+ goto err;
+ }
+ }
+
+ if(!find_aiff_chunk(in, path, "SSND", &len)){
+ fprintf(stderr, "%s: No SSND chunk found in AIFF file\n",path);
+ goto err;
+ }
+ if(len < 8) {
+ fprintf(stderr,"%s: Corrupted SSND chunk in AIFF header\n",path);
+ goto err;
+ }
+
+ if(fread(buf2,1,8, in) < 8){
+ fprintf(stderr, "%s: Unexpected EOF reading AIFF header\n",path);
+ goto err;
+ }
+
+ int offset = READ_U32_BE(buf2);
+ int blocksize = READ_U32_BE(buf2+4);
+
+ if( blocksize != 0 ||
+ !(pcm->savebits==24 || pcm->savebits == 16 || pcm->savebits == 8)){
+ fprintf(stderr,
+ "%s: Unsupported type of AIFF/AIFC file\n"
+ " Must be 8-, 16- or 24-bit integer PCM.\n",path);
+ goto err;
+ }
+
+ fseek(in, offset, SEEK_CUR); /* Swallow some data */
+
+ /* read the samples into memory */
+ pcm->samples/=pcm->ch;
+ pcm->samples/=((abs(pcm->savebits)+7)>>3);
+ if(read_raw_samples(pcm,in,1,bend))
+ goto err;
+ return pcm;
+ err:
+ free_pcm(pcm);
+ return NULL;
+}
+
+/* SW loading to make JM happy *******************************************************/
+
+static pcm_t *sw_load(const char *path, FILE *in){
+
+ pcm_t *pcm = calloc(1,sizeof(pcm_t));
+ pcm->name=strdup(trim_path(path));
+ pcm->savebits=16;
+ pcm->ch=1;
+ pcm->rate=48000;
+ pcm->matrix=strdup("M");
+
+ if(fseek(in,0,SEEK_END)==-1){
+ fprintf(stderr,"%s: Failed to seek\n",path);
+ goto err;
+ }
+ pcm->samples=ftell(in);
+ if(pcm->samples==-1 || fseek(in,0,SEEK_SET)==-1){
+ fprintf(stderr,"%s: Failed to seek\n",path);
+ goto err;
+ }
+
+ pcm->samples/=2;
+ if(read_raw_samples(pcm,in,0,0))
+ goto err;
+ return pcm;
+ err:
+ free_pcm(pcm);
+ return NULL;
+}
+
+/* FLAC and OggFLAC load support *****************************************************************/
+
+typedef struct {
+ FILE *in;
+ pcm_t *pcm;
+ off_t fill;
+} flac_callback_arg;
+
+/* glorified fread wrapper */
+static FLAC__StreamDecoderReadStatus read_callback(const FLAC__StreamDecoder *decoder,
+ FLAC__byte buffer[],
+ size_t *bytes,
+ void *client_data){
+ flac_callback_arg *flac = (flac_callback_arg *)client_data;
+
+ if(feof(flac->in)){
+ *bytes = 0;
+ return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
+ }else if(ferror(flac->in)){
+ *bytes = 0;
+ return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
+ }
+
+ *bytes = fread(buffer, sizeof(FLAC__byte), *bytes, flac->in);
+
+ return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
+}
+
+static FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder,
+ const FLAC__Frame *frame,
+ const FLAC__int32 *const buffer[],
+ void *client_data){
+ flac_callback_arg *flac = (flac_callback_arg *)client_data;
+ pcm_t *pcm = flac->pcm;
+ int samples = frame->header.blocksize;
+ int channels = frame->header.channels;
+ int bits_per_sample = frame->header.bits_per_sample;
+ off_t sofar = flac->fill;
+ int i, j;
+
+ if(pcm->data == NULL){
+ /* lazy initialization */
+ pcm->ch = channels;
+ pcm->savebits = (bits_per_sample+7)/8*8;
+
+ pcm->data = calloc(pcm->ch,sizeof(*pcm->data));
+ if(pcm->data == NULL){
+ fprintf(stderr,"Unable to allocate enough memory to load sample into memory\n");
+ return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
+ }
+ for(i=0;i<pcm->ch;i++){
+ pcm->data[i] = calloc(pcm->samples,sizeof(**pcm->data));
+ if(pcm->data[i] == NULL){
+ fprintf(stderr,"Unable to allocate enough memory to load sample into memory\n");
+ return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
+ }
+ }
+ }
+
+ if(channels != pcm->ch){
+ fprintf(stderr,"\r%s: number of channels changes part way through file\n",pcm->name);
+ return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
+ }
+ if(pcm->savebits != (bits_per_sample+7)/8*8){
+ fprintf(stderr,"\r%s: bit depth changes part way through file\n",pcm->name);
+ return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
+ }
+
+ {
+ int shift = pcm->savebits - bits_per_sample;
+ off_t sofar=flac->fill;
+ switch(pcm->savebits){
+ case 16:
+ for (j = 0; j < samples; j++){
+ for (i = 0; i < channels; i++)
+ pcm->data[i][sofar] = (buffer[i][j]<<shift)*(1.f/32768.f);
+ sofar++;
+ }
+ break;
+ case 24:
+ for (j = 0; j < samples; j++){
+ for (i = 0; i < channels; i++)
+ pcm->data[i][sofar] = (buffer[i][j]<<shift)*(1.f/8388608.f);
+ sofar++;
+ }
+ break;
+ default:
+ fprintf(stderr,"\r%s: Only 16- and 24-bit FLACs are supported for decode right now.\n",pcm->name);
+ return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
+ }
+ }
+ flac->fill=sofar;
+
+ return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
+}
+
+static void metadata_callback(const FLAC__StreamDecoder *decoder,
+ const FLAC__StreamMetadata *metadata,
+ void *client_data){
+ flac_callback_arg *flac = (flac_callback_arg *)client_data;
+ pcm_t *pcm = flac->pcm;
+
+ switch (metadata->type){
+ case FLAC__METADATA_TYPE_STREAMINFO:
+ pcm->samples = metadata->data.stream_info.total_samples;
+ pcm->rate = metadata->data.stream_info.sample_rate;
+ break;
+ default:
+ break;
+ }
+}
+
+static void error_callback(const FLAC__StreamDecoder *decoder,
+ FLAC__StreamDecoderErrorStatus status,
+ void *client_data){
+
+ flac_callback_arg *flac = (flac_callback_arg *)client_data;
+ pcm_t *pcm = flac->pcm;
+ fprintf(stderr,"\r%s: Error decoding file.\n",pcm->name);
+}
+
+static FLAC__bool eof_callback(const FLAC__StreamDecoder *decoder,
+ void *client_data){
+ flac_callback_arg *flac = (flac_callback_arg *)client_data;
+ return feof(flac->in)? true : false;
+}
+
+static pcm_t *flac_load_i(const char *path, FILE *in, int oggp){
+ pcm_t *pcm;
+ flac_callback_arg *flac;
+ FLAC__StreamDecoder *decoder;
+ FLAC__bool ret;
+
+ if(fseek(in,0,SEEK_SET)==-1){
+ fprintf(stderr,"%s: Failed to seek\n",path);
+ goto err;
+ }
+
+ pcm = calloc(1,sizeof(pcm_t));
+ flac = calloc(1,sizeof(flac_callback_arg));
+ decoder = FLAC__stream_decoder_new();
+ FLAC__stream_decoder_set_md5_checking(decoder, true);
+ FLAC__stream_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_STREAMINFO);
+
+ pcm->name=strdup(trim_path(path));
+ flac->in=in;
+ flac->pcm=pcm;
+
+ if(oggp)
+ FLAC__stream_decoder_init_ogg_stream(decoder,
+ read_callback,
+ /*seek_callback=*/0,
+ /*tell_callback=*/0,
+ /*length_callback=*/0,
+ eof_callback,
+ write_callback,
+ metadata_callback,
+ error_callback,
+ flac);
+ else
+ FLAC__stream_decoder_init_stream(decoder,
+ read_callback,
+ /*seek_callback=*/0,
+ /*tell_callback=*/0,
+ /*length_callback=*/0,
+ eof_callback,
+ write_callback,
+ metadata_callback,
+ error_callback,
+ flac);
+
+ /* setup and sample reading handled by configured callbacks */
+ ret=FLAC__stream_decoder_process_until_end_of_stream(decoder);
+ FLAC__stream_decoder_finish(decoder);
+ FLAC__stream_decoder_delete(decoder);
+ free(flac);
+ if(!ret){
+ free_pcm(pcm);
+ return NULL;
+ }
+
+ /* set channel matrix */
+ switch(pcm->ch){
+ case 1:
+ pcm->matrix = strdup("M");
+ break;
+ case 2:
+ pcm->matrix = strdup("L,R");
+ break;
+ case 3:
+ pcm->matrix = strdup("L,R,C");
+ break;
+ case 4:
+ pcm->matrix = strdup("L,R,BL,BR");
+ break;
+ case 5:
+ pcm->matrix = strdup("L,R,C,BL,BR");
+ break;
+ case 6:
+ pcm->matrix = strdup("L,R,C,LFE,BL,BR");
+ break;
+ case 7:
+ pcm->matrix = strdup("L,R,C,LFE,BC,SL,SR");
+ break;
+ default:
+ pcm->matrix = strdup("L,R,C,LFE,BL,BR,SL,SR");
+ break;
+ }
+
+ return pcm;
+ err:
+ return NULL;
+}
+
+static pcm_t *flac_load(const char *path, FILE *in){
+ return flac_load_i(path,in,0);
+}
+
+static pcm_t *oggflac_load(const char *path, FILE *in){
+ return flac_load_i(path,in,1);
+}
+
+/* Vorbis load support **************************************************************************/
+static pcm_t *vorbis_load(const char *path, FILE *in){
+ OggVorbis_File vf;
+ vorbis_info *vi=NULL;
+ pcm_t *pcm=NULL;
+ off_t fill=0;
+ int last_section=-1;
+ int i;
+
+ memset(&vf,0,sizeof(vf));
+
+ if(fseek(in,0,SEEK_SET)==-1){
+ fprintf(stderr,"%s: Failed to seek\n",path);
+ goto err;
+ }
+
+ if(ov_open_callbacks(in, &vf, NULL, 0, OV_CALLBACKS_NOCLOSE) < 0) {
+ fprintf(stderr,"Input does not appear to be an Ogg bitstream.\n");
+ goto err;
+ }
+
+ vi=ov_info(&vf,-1);
+ pcm = calloc(1,sizeof(pcm_t));
+ pcm->name=strdup(trim_path(path));
+ pcm->savebits=16;
+ pcm->ch=vi->channels;
+ pcm->rate=vi->rate;
+ pcm->samples=ov_pcm_total(&vf,-1);
+
+ pcm->data = calloc(pcm->ch,sizeof(*pcm->data));
+ if(pcm->data == NULL){
+ fprintf(stderr,"Unable to allocate enough memory to load sample into memory\n");
+ goto err;
+ }
+ for(i=0;i<pcm->ch;i++){
+ pcm->data[i] = calloc(pcm->samples,sizeof(**pcm->data));
+ if(pcm->data[i] == NULL){
+ fprintf(stderr,"Unable to allocate enough memory to load sample into memory\n");
+ goto err;
+ }
+ }
+
+ switch(pcm->ch){
+ case 1:
+ pcm->matrix = strdup("M");
+ break;
+ case 2:
+ pcm->matrix = strdup("L,R");
+ break;
+ case 3:
+ pcm->matrix = strdup("L,C,R");
+ break;
+ case 4:
+ pcm->matrix = strdup("L,R,BL,BR");
+ break;
+ case 5:
+ pcm->matrix = strdup("L,C,R,BL,BR");
+ break;
+ case 6:
+ pcm->matrix = strdup("L,C,R,BL,BR,LFE");
+ break;
+ case 7:
+ pcm->matrix = strdup("L,C,R,SL,SR,BC,LFE");
+ break;
+ default:
+ pcm->matrix = strdup("L,C,R,SL,SR,BL,BR,LFE");
+ break;
+ }
+
+ while(fill<pcm->samples){
+ int current_section;
+ int i;
+ float **pcmout;
+ long ret=ov_read_float(&vf,&pcmout,4096,¤t_section);
+
+ if(current_section!=last_section){
+ last_section=current_section;
+ vi=ov_info(&vf,-1);
+ if(vi->channels != pcm->ch || vi->rate!=pcm->rate){
+ fprintf(stderr,"%s: Chained file changes channel count/sample rate\n",path);
+ goto err;
+ }
+ }
+
+ if(ret<0){
+ fprintf(stderr,"%s: Error while decoding file\n",path);
+ goto err;
+ }
+ if(ret==0){
+ fprintf(stderr,"%s: Audio data ended prematurely\n",path);
+ goto err;
+ }
+
+ for(i=0;i<pcm->ch;i++)
+ memcpy(pcm->data[i]+fill,pcmout[i],ret*sizeof(**pcm->data));
+ fill+=ret;
+ }
+ ov_clear(&vf);
+
+ return pcm;
+ err:
+ ov_clear(&vf);
+ free_pcm(pcm);
+ return NULL;
+}
+
+#define MAX_ID_LEN 35
+unsigned char buf[MAX_ID_LEN];
+
+/* Define the supported formats here */
+static input_format formats[] = {
+ {wav_id, wav_load, "wav"},
+ {aiff_id, aiff_load, "aiff"},
+ {flac_id, flac_load, "flac"},
+ {oggflac_id, oggflac_load,"oggflac"},
+ {vorbis_id, vorbis_load, "oggvorbis"},
+ {sw_id, sw_load, "sw"},
+ {NULL, NULL, NULL}
+};
+
+pcm_t *squishyio_load_file(const const char *path){
+ FILE *f = fopen(path,"rb");
+ int j=0;
+ int fill;
+
+ if(!f){
+ fprintf(stderr,"Unable to open file %s: %s\n",path,strerror(errno));
+ return NULL;
+ }
+
+ fill = fread(buf, 1, MAX_ID_LEN, f);
+ if(fill<MAX_ID_LEN){
+ fprintf(stderr,"%s: Input file truncated or NULL\n",path);
+ fclose(f);
+ return NULL;
+ }
+
+ while(formats[j].id_func){
+ if(formats[j].id_func(path,buf)){
+ pcm_t *ret=formats[j].load_func(path,f);
+ fclose(f);
+ return ret;
+ }
+ j++;
+ }
+ fprintf(stderr,"%s: Unrecognized file format\n",path);
+ return NULL;
+}
+
+void free_pcm(pcm_t *pcm){
+ if(pcm){
+ if(pcm->name)free(pcm->name);
+ if(pcm->matrix)free(pcm->matrix);
+ if(pcm->data)free(pcm->data);
+ memset(pcm,0,sizeof(pcm));
+ free(pcm);
+ }
+}
+
+static inline float triangle_ditherval(float *save){
+ float r = rand()/(float)RAND_MAX-.5f;
+ float ret = *save-r;
+ *save = r;
+ return ret;
+}
+
+int squishyio_save_file(const char *path, pcm_t *pcm, int overwrite){
+ ao_sample_format format;
+ ao_initialize();
+
+ format.bits = pcm->savebits;
+ format.rate = pcm->rate;
+ format.channels = pcm->ch;
+ format.byte_format = AO_FMT_LITTLE;
+ format.matrix = pcm->matrix;
+
+ {
+ float t[pcm->ch];
+ int ch=0;
+ int samplesper, bytesper;
+ off_t sofar=0;
+ int bps=(abs(pcm->savebits)+7)>>3;
+ int cpf=pcm->ch;
+ int bpf=bps*cpf;
+ int id = ao_driver_id("wav");
+ ao_device *a=ao_open_file(id, path, overwrite, &format, NULL);
+ if(!a){
+ fprintf(stderr,"Failed to open output file: %s",path);
+ return 1;
+ }
+
+ samplesper = rbsize/bpf;
+ bytesper = samplesper*bpf;
+ memset(t,0,sizeof(t));
+
+ while(sofar<pcm->samples){
+ unsigned char *d=rawbuf;
+ off_t bytes, samples=samplesper;
+ int i,j,val;
+ if((pcm->samples-sofar)<samples)samples=pcm->samples-sofar;
+ bytes = samples*bpf;
+
+ switch(pcm->savebits){
+ case 16:
+ for(i=0;i<samples;i++){
+ for(j=0;j<pcm->ch;j++){
+ if(pcm->savedither){
+ val = rint(pcm->data[j][sofar]*32768.f + triangle_ditherval(t+ch));
+ ch++;
+ if(ch>pcm->ch)ch=0;
+ }else{
+ val = rint(pcm->data[j][sofar]*32768.f);
+ }
+
+ if(val>=32767.f){
+ d[0]=0xff;
+ d[1]=0x7f;
+ }else if(val<=-32768.f){
+ d[0]=0x00;
+ d[1]=0x80;
+ }else{
+ int iv = (int)val;
+ d[0]=iv&0xff;
+ d[1]=(iv>>8)&0xff;
+ }
+ d+=2;
+ }
+ sofar++;
+ }
+ break;
+
+ case 24:
+ for(i=0;i<samples;i++){
+ for(j=0;j<pcm->ch;j++){
+ val = rint(pcm->data[j][sofar]*8388608);
+
+ if(val>=8388607.f){
+ d[0]=0xff;
+ d[1]=0x7f;
+ d[2]=0x7f;
+ }else if(val<=-8388608.f){
+ d[0]=0x00;
+ d[1]=0x00;
+ d[2]=0x80;
+ }else{
+ int iv = (int)val;
+ d[0]=iv&0xff;
+ d[1]=(iv>>8)&0xff;
+ d[2]=(iv>>16)&0xff;
+ }
+ d+=3;
+ }
+ sofar++;
+ }
+ break;
+ default:
+ fprintf(stderr,"Unsupported output bit depth :-(\n");
+ goto err;
+ }
+
+ if(!ao_play(a,(char *)rawbuf,bytes))
+ goto err;
+
+ }
+
+ ao_close(a);
+ return 0;
+
+ err:
+ ao_close(a);
+ return 1;
+ }
+}
+
Added: websites/celt-codec.org/squishyio/squishyio.h
===================================================================
--- websites/celt-codec.org/squishyio/squishyio.h (rev 0)
+++ websites/celt-codec.org/squishyio/squishyio.h 2010-12-12 09:17:39 UTC (rev 17747)
@@ -0,0 +1,46 @@
+/*
+ *
+ * squishyio
+ *
+ * Copyright (C) 2010 Xiph.Org
+ *
+ * squishyball 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, or (at your option)
+ * any later version.
+ *
+ * squishyball 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 rtrecord; see the file COPYING. If not, write to the
+ * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ */
+
+#ifndef _SqI__H_
+#define _SqI__H_
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+typedef struct pcm_struct pcm_t;
+
+struct pcm_struct {
+ char *name;
+ int rate;
+ int ch;
+ int savebits;
+ int savedither;
+ char *matrix;
+ float **data;
+ off_t samples;
+};
+
+extern pcm_t *squishyio_load_file(const char *path);
+extern int squishyio_save_file(const char *path, pcm_t *pcm,int clobber);
+extern void free_pcm(pcm_t *pcm);
+#endif
More information about the commits
mailing list