/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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 U.S.A.-----------------------------------------------------------------------------*/ /*** libsndfile Copyright (C) 1999-2004 Erik de Castro Lopo <erikd@mega-nerd.com>**** This program 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 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 Lesser General Public License for more details.**** You should have received a copy of the GNU Lesser 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.*/ //-----------------------------------------------------------------------------// name: util_sndfile.c// desc: libsndfile for ChucK//// authors: Ge Wang (gewang@cs.princeton.edu)// Perry R. Cook (prc@cs.princeton.edu)// Ari Lazier (alazier@alumni.princeton.edu)// libsndfile: Erik de Castro Lopo (erikd@mega-nerd.com)//-----------------------------------------------------------------------------#include "util_sndfile.h"#include "chuck_def.h"#include <math.h> /* * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische * Universitaet Berlin. See the accompanying file "COPYRIGHT" for * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. */ /* * See private.h for the more commonly used macro versions. */ #include <stdio.h>#include <assert.h> #define saturate(x) \ ((x) < MIN_WORD ? MIN_WORD : (x) > MAX_WORD ? MAX_WORD: (x)) word gsm_add ( word a, word b){ longword sum = (longword)a + (longword)b; return saturate(sum);} word gsm_sub ( word a, word b){ longword diff = (longword)a - (longword)b; return saturate(diff);} word gsm_mult ( word a, word b){ if (a == MIN_WORD && b == MIN_WORD) return MAX_WORD; return SASR_L( (longword)a * (longword)b, 15 );} word gsm_mult_r ( word a, word b){ if (b == MIN_WORD && a == MIN_WORD) return MAX_WORD; else { longword prod = (longword)a * (longword)b + 16384; prod >>= 15; return prod & 0xFFFF; }} word gsm_abs (word a){ return a < 0 ? (a == MIN_WORD ? MAX_WORD : -a) : a;} longword gsm_L_mult (word a, word b){ assert( a != MIN_WORD || b != MIN_WORD ); return ((longword)a * (longword)b) << 1;} longword gsm_L_add ( longword a, longword b){ if (a < 0) { if (b >= 0) return a + b; else { ulongword A = (ulongword)-(a + 1) + (ulongword)-(b + 1); return A >= MAX_LONGWORD ? MIN_LONGWORD :-(longword)A-2; } } else if (b <= 0) return a + b; else { ulongword A = (ulongword)a + (ulongword)b; return A > MAX_LONGWORD ? MAX_LONGWORD : A; }} longword gsm_L_sub ( longword a, longword b){ if (a >= 0) { if (b >= 0) return a - b; else { /* a>=0, b<0 */ ulongword A = (ulongword)a + -(b + 1); return A >= MAX_LONGWORD ? MAX_LONGWORD : (A + 1); } } else if (b <= 0) return a - b; else { /* a<0, b>0 */ ulongword A = (ulongword)-(a + 1) + b; return A >= MAX_LONGWORD ? MIN_LONGWORD : -(longword)A - 1; }} static unsigned char const bitoff[ 256 ] = { 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; word gsm_norm (longword a )/* * the number of left shifts needed to normalize the 32 bit * variable L_var1 for positive values on the interval * * with minimum of * minimum of 1073741824 (01000000000000000000000000000000) and * maximum of 2147483647 (01111111111111111111111111111111) * * * and for negative values on the interval with * minimum of -2147483648 (-10000000000000000000000000000000) and * maximum of -1073741824 ( -1000000000000000000000000000000). * * in order to normalize the result, the following * operation must be done: L_norm_var1 = L_var1 << norm( L_var1 ); * * (That's 'ffs', only from the left, not the right..) */{ assert(a != 0); if (a < 0) { if (a <= -1073741824) return 0; a = ~a; } return a & 0xffff0000 ? ( a & 0xff000000 ? -1 + bitoff[ 0xFF & (a >> 24) ] : 7 + bitoff[ 0xFF & (a >> 16) ] ) : ( a & 0xff00 ? 15 + bitoff[ 0xFF & (a >> 8) ] : 23 + bitoff[ 0xFF & a ] );} longword gsm_L_asl (longword a, int n){ if (n >= 32) return 0; if (n <= -32) return -(a < 0); if (n < 0) return gsm_L_asr(a, -n); return a << n;} word gsm_asr (word a, int n){ if (n >= 16) return -(a < 0); if (n <= -16) return 0; if (n < 0) return a << -n; return SASR_W (a, (word) n);} word gsm_asl (word a, int n){ if (n >= 16) return 0; if (n <= -16) return -(a < 0); if (n < 0) return gsm_asr(a, -n); return a << n;} longword gsm_L_asr (longword a, int n){ if (n >= 32) return -(a < 0); if (n <= -32) return 0; if (n < 0) return a << -n; return SASR_L (a, (word) n);} /*** word gsm_asr (word a, int n)** {** if (n >= 16) return -(a < 0);** if (n <= -16) return 0;** if (n < 0) return a << -n;** ** # ifdef SASR_W** return a >> n;** # else** if (a >= 0) return a >> n;** else return -(word)( -(uword)a >> n );** # endif** }** *//* * (From p. 46, end of section 4.2.5) * * NOTE: The following lines gives [sic] one correct implementation * of the div(num, denum) arithmetic operation. Compute div * which is the integer division of num by denum: with denum * >= num > 0 */ word gsm_div (word num, word denum){ longword L_num = num; longword L_denum = denum; word div = 0; int k = 15; /* The parameter num sometimes becomes zero. * Although this is explicitly guarded against in 4.2.5, * we assume that the result should then be zero as well. */ /* assert(num != 0); */ assert(num >= 0 && denum >= num); if (num == 0) return 0; while (k--) { div <<= 1; L_num <<= 1; if (L_num >= L_denum) { L_num -= L_denum; div++; } } return div;}/*** Do not edit or modify anything in this comment block.** The arch-tag line is a file identity tag for the GNU Arch ** revision control system.**** arch-tag: a7398579-e2e1-4733-aa2d-4c6efc0c58ff*/ /*** Copyright (C) 1999-2004 Erik de Castro Lopo <erikd@mega-nerd.com>**** This program 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 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 Lesser General Public License for more details.**** You should have received a copy of the GNU Lesser 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 <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <ctype.h> /*------------------------------------------------------------------------------ * Macros to handle big/little endian issues. */ #define FORM_MARKER (MAKE_MARKER ('F', 'O', 'R', 'M'))#define AIFF_MARKER (MAKE_MARKER ('A', 'I', 'F', 'F'))#define AIFC_MARKER (MAKE_MARKER ('A', 'I', 'F', 'C'))#define COMM_MARKER (MAKE_MARKER ('C', 'O', 'M', 'M'))#define SSND_MARKER (MAKE_MARKER ('S', 'S', 'N', 'D'))#define MARK_MARKER (MAKE_MARKER ('M', 'A', 'R', 'K'))#define INST_MARKER (MAKE_MARKER ('I', 'N', 'S', 'T'))#define APPL_MARKER (MAKE_MARKER ('A', 'P', 'P', 'L')) #define c_MARKER (MAKE_MARKER ('(', 'c', ')', ' '))#define NAME_MARKER (MAKE_MARKER ('N', 'A', 'M', 'E'))#define AUTH_MARKER (MAKE_MARKER ('A', 'U', 'T', 'H'))#define ANNO_MARKER (MAKE_MARKER ('A', 'N', 'N', 'O'))#define COMT_MARKER (MAKE_MARKER ('C', 'O', 'M', 'T'))#define FVER_MARKER (MAKE_MARKER ('F', 'V', 'E', 'R'))#define SFX_MARKER (MAKE_MARKER ('S', 'F', 'X', '!')) #define PEAK_MARKER (MAKE_MARKER ('P', 'E', 'A', 'K')) /* Supported AIFC encodings.*/#define NONE_MARKER (MAKE_MARKER ('N', 'O', 'N', 'E'))#define sowt_MARKER (MAKE_MARKER ('s', 'o', 'w', 't'))#define twos_MARKER (MAKE_MARKER ('t', 'w', 'o', 's'))#define raw_MARKER (MAKE_MARKER ('r', 'a', 'w', ' '))#define in32_MARKER (MAKE_MARKER ('i', 'n', '3', '2'))#define ni32_MARKER (MAKE_MARKER ('2', '3', 'n', 'i')) #define fl32_MARKER (MAKE_MARKER ('f', 'l', '3', '2'))#define FL32_MARKER (MAKE_MARKER ('F', 'L', '3', '2'))#define fl64_MARKER (MAKE_MARKER ('f', 'l', '6', '4'))#define FL64_MARKER (MAKE_MARKER ('F', 'L', '6', '4')) #define ulaw_MARKER (MAKE_MARKER ('u', 'l', 'a', 'w'))#define ULAW_MARKER (MAKE_MARKER ('U', 'L', 'A', 'W'))#define alaw_MARKER (MAKE_MARKER ('a', 'l', 'a', 'w'))#define ALAW_MARKER (MAKE_MARKER ('A', 'L', 'A', 'W')) #define DWVW_MARKER (MAKE_MARKER ('D', 'W', 'V', 'W'))#define GSM_MARKER (MAKE_MARKER ('G', 'S', 'M', ' '))#define ima4_MARKER (MAKE_MARKER ('i', 'm', 'a', '4')) /* Unsupported AIFC encodings.*/ #define MAC3_MARKER (MAKE_MARKER ('M', 'A', 'C', '3'))#define MAC6_MARKER (MAKE_MARKER ('M', 'A', 'C', '6'))#define ADP4_MARKER (MAKE_MARKER ('A', 'D', 'P', '4')) /* Predfined chunk sizes. */#define SIZEOF_AIFF_COMM 18#define SIZEOF_AIFC_COMM_MIN 22#define SIZEOF_AIFC_COMM 24#define SIZEOF_SSND_CHUNK 8#define SIZEOF_INST_CHUNK 20 /* AIFC/IMA4 defines. */#define AIFC_IMA4_BLOCK_LEN 34#define AIFC_IMA4_SAMPLES_PER_BLOCK 64 /*------------------------------------------------------------------------------ * Typedefs for file chunks. */ enum{ aiffHAVE_FORM = 0x01, HAVE_AIFF = 0x02, HAVE_COMM = 0x04, HAVE_SSND = 0x08} ; typedef struct{ unsigned int size ; short numChannels ; unsigned int numSampleFrames ; short sampleSize ; unsigned char sampleRate [10] ; unsigned int encoding ; char zero_bytes [2] ;} COMM_CHUNK ; typedef struct{ unsigned int offset ; unsigned int blocksize ;} SSND_CHUNK ; typedef struct{ short playMode ; unsigned short beginLoop ; unsigned short endLoop ;} INST_LOOP ; typedef struct{ char baseNote ; /* all notes are MIDI note numbers */ char detune ; /* cents off, only -50 to +50 are significant */ char lowNote ; char highNote ; char lowVelocity ; /* 1 to 127 */ char highVelocity ; /* 1 to 127 */ short gain ; /* in dB, 0 is normal */ INST_LOOP sustain_loop ; INST_LOOP release_loop ;} INST_CHUNK ; /*------------------------------------------------------------------------------ * Private static functions. */ static int aiff_close (SF_PRIVATE *psf) ; static int tenbytefloat2int (unsigned char *bytes) ;static void uint2tenbytefloat (unsigned int num, unsigned char *bytes) ; static int aiff_read_comm_chunk (SF_PRIVATE *psf, COMM_CHUNK *comm_fmt) ; static int aiff_read_header (SF_PRIVATE *psf, COMM_CHUNK *comm_fmt) ; static int aiff_write_header (SF_PRIVATE *psf, int calc_length) ;static int aiff_write_tailer (SF_PRIVATE *psf) ;static void aiff_write_strings (SF_PRIVATE *psf, int location) ; static int aiff_command (SF_PRIVATE *psf, int command, void *data, int datasize) ; static const char *get_loop_mode_str (short mode) ; /*------------------------------------------------------------------------------** Public function.*/ intaiff_open (SF_PRIVATE *psf){ COMM_CHUNK comm_fmt ; int error, subformat ; subformat = psf->sf.format & SF_FORMAT_SUBMASK ; if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0)) { if ((error = aiff_read_header (psf, &comm_fmt))) return error ; psf_fseek (psf, psf->dataoffset, SEEK_SET) ; } ; if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) { if (psf->is_pipe) return SFE_NO_PIPE_WRITE ; if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_AIFF) return SFE_BAD_OPEN_FORMAT ; if (psf->mode == SFM_WRITE && (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE)) { psf->pchunk = calloc (1, sizeof (PEAK_CHUNK) * psf->sf.channels * sizeof (PEAK_POS)) ; if (psf->pchunk == NULL) return SFE_MALLOC_FAILED ; psf->has_peak = SF_TRUE ; psf->peak_loc = SF_PEAK_START ; } ; if (psf->mode != SFM_RDWR || psf->filelength < 40) { psf->filelength = 0 ; psf->datalength = 0 ; psf->dataoffset = 0 ; psf->sf.frames = 0 ; } ; psf->str_flags = SF_STR_ALLOW_START | SF_STR_ALLOW_END ; if ((error = aiff_write_header (psf, SF_FALSE))) return error ; Lines 1–500 of 34335. Load more
/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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 U.S.A. -----------------------------------------------------------------------------*/ /* ** libsndfile Copyright (C) 1999-2004 Erik de Castro Lopo <erikd@mega-nerd.com> ** ** This program 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 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser 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. */ //----------------------------------------------------------------------------- // name: util_sndfile.c // desc: libsndfile for ChucK // // authors: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // Ari Lazier (alazier@alumni.princeton.edu) // libsndfile: Erik de Castro Lopo (erikd@mega-nerd.com) //----------------------------------------------------------------------------- #include "util_sndfile.h" #include "chuck_def.h" #include <math.h> /* * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische * Universitaet Berlin. See the accompanying file "COPYRIGHT" for * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. */ /* * See private.h for the more commonly used macro versions. */ #include <stdio.h> #include <assert.h> #define saturate(x) \ ((x) < MIN_WORD ? MIN_WORD : (x) > MAX_WORD ? MAX_WORD: (x)) word gsm_add ( word a, word b) { longword sum = (longword)a + (longword)b; return saturate(sum); } word gsm_sub ( word a, word b) { longword diff = (longword)a - (longword)b; return saturate(diff); } word gsm_mult ( word a, word b) { if (a == MIN_WORD && b == MIN_WORD) return MAX_WORD; return SASR_L( (longword)a * (longword)b, 15 ); } word gsm_mult_r ( word a, word b) { if (b == MIN_WORD && a == MIN_WORD) return MAX_WORD; else { longword prod = (longword)a * (longword)b + 16384; prod >>= 15; return prod & 0xFFFF; } } word gsm_abs (word a) { return a < 0 ? (a == MIN_WORD ? MAX_WORD : -a) : a; } longword gsm_L_mult (word a, word b) { assert( a != MIN_WORD || b != MIN_WORD ); return ((longword)a * (longword)b) << 1; } longword gsm_L_add ( longword a, longword b) { if (a < 0) { if (b >= 0) return a + b; else { ulongword A = (ulongword)-(a + 1) + (ulongword)-(b + 1); return A >= MAX_LONGWORD ? MIN_LONGWORD :-(longword)A-2; } } else if (b <= 0) return a + b; else { ulongword A = (ulongword)a + (ulongword)b; return A > MAX_LONGWORD ? MAX_LONGWORD : A; } } longword gsm_L_sub ( longword a, longword b) { if (a >= 0) { if (b >= 0) return a - b; else { /* a>=0, b<0 */ ulongword A = (ulongword)a + -(b + 1); return A >= MAX_LONGWORD ? MAX_LONGWORD : (A + 1); } } else if (b <= 0) return a - b; else { /* a<0, b>0 */ ulongword A = (ulongword)-(a + 1) + b; return A >= MAX_LONGWORD ? MIN_LONGWORD : -(longword)A - 1; } } static unsigned char const bitoff[ 256 ] = { 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; word gsm_norm (longword a ) /* * the number of left shifts needed to normalize the 32 bit * variable L_var1 for positive values on the interval * * with minimum of * minimum of 1073741824 (01000000000000000000000000000000) and * maximum of 2147483647 (01111111111111111111111111111111) * * * and for negative values on the interval with * minimum of -2147483648 (-10000000000000000000000000000000) and * maximum of -1073741824 ( -1000000000000000000000000000000). * * in order to normalize the result, the following * operation must be done: L_norm_var1 = L_var1 << norm( L_var1 ); * * (That's 'ffs', only from the left, not the right..) */ { assert(a != 0); if (a < 0) { if (a <= -1073741824) return 0; a = ~a; } return a & 0xffff0000 ? ( a & 0xff000000 ? -1 + bitoff[ 0xFF & (a >> 24) ] : 7 + bitoff[ 0xFF & (a >> 16) ] ) : ( a & 0xff00 ? 15 + bitoff[ 0xFF & (a >> 8) ] : 23 + bitoff[ 0xFF & a ] ); } longword gsm_L_asl (longword a, int n) { if (n >= 32) return 0; if (n <= -32) return -(a < 0); if (n < 0) return gsm_L_asr(a, -n); return a << n; } word gsm_asr (word a, int n) { if (n >= 16) return -(a < 0); if (n <= -16) return 0; if (n < 0) return a << -n; return SASR_W (a, (word) n); } word gsm_asl (word a, int n) { if (n >= 16) return 0; if (n <= -16) return -(a < 0); if (n < 0) return gsm_asr(a, -n); return a << n; } longword gsm_L_asr (longword a, int n) { if (n >= 32) return -(a < 0); if (n <= -32) return 0; if (n < 0) return a << -n; return SASR_L (a, (word) n); } /* ** word gsm_asr (word a, int n) ** { ** if (n >= 16) return -(a < 0); ** if (n <= -16) return 0; ** if (n < 0) return a << -n; ** ** # ifdef SASR_W ** return a >> n; ** # else ** if (a >= 0) return a >> n; ** else return -(word)( -(uword)a >> n ); ** # endif ** } ** */ /* * (From p. 46, end of section 4.2.5) * * NOTE: The following lines gives [sic] one correct implementation * of the div(num, denum) arithmetic operation. Compute div * which is the integer division of num by denum: with denum * >= num > 0 */ word gsm_div (word num, word denum) { longword L_num = num; longword L_denum = denum; word div = 0; int k = 15; /* The parameter num sometimes becomes zero. * Although this is explicitly guarded against in 4.2.5, * we assume that the result should then be zero as well. */ /* assert(num != 0); */ assert(num >= 0 && denum >= num); if (num == 0) return 0; while (k--) { div <<= 1; L_num <<= 1; if (L_num >= L_denum) { L_num -= L_denum; div++; } } return div; } /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: a7398579-e2e1-4733-aa2d-4c6efc0c58ff */ /* ** Copyright (C) 1999-2004 Erik de Castro Lopo <erikd@mega-nerd.com> ** ** This program 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 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser 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 <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <ctype.h> /*------------------------------------------------------------------------------ * Macros to handle big/little endian issues. */ #define FORM_MARKER (MAKE_MARKER ('F', 'O', 'R', 'M')) #define AIFF_MARKER (MAKE_MARKER ('A', 'I', 'F', 'F')) #define AIFC_MARKER (MAKE_MARKER ('A', 'I', 'F', 'C')) #define COMM_MARKER (MAKE_MARKER ('C', 'O', 'M', 'M')) #define SSND_MARKER (MAKE_MARKER ('S', 'S', 'N', 'D')) #define MARK_MARKER (MAKE_MARKER ('M', 'A', 'R', 'K')) #define INST_MARKER (MAKE_MARKER ('I', 'N', 'S', 'T')) #define APPL_MARKER (MAKE_MARKER ('A', 'P', 'P', 'L')) #define c_MARKER (MAKE_MARKER ('(', 'c', ')', ' ')) #define NAME_MARKER (MAKE_MARKER ('N', 'A', 'M', 'E')) #define AUTH_MARKER (MAKE_MARKER ('A', 'U', 'T', 'H')) #define ANNO_MARKER (MAKE_MARKER ('A', 'N', 'N', 'O')) #define COMT_MARKER (MAKE_MARKER ('C', 'O', 'M', 'T')) #define FVER_MARKER (MAKE_MARKER ('F', 'V', 'E', 'R')) #define SFX_MARKER (MAKE_MARKER ('S', 'F', 'X', '!')) #define PEAK_MARKER (MAKE_MARKER ('P', 'E', 'A', 'K')) /* Supported AIFC encodings.*/ #define NONE_MARKER (MAKE_MARKER ('N', 'O', 'N', 'E')) #define sowt_MARKER (MAKE_MARKER ('s', 'o', 'w', 't')) #define twos_MARKER (MAKE_MARKER ('t', 'w', 'o', 's')) #define raw_MARKER (MAKE_MARKER ('r', 'a', 'w', ' ')) #define in32_MARKER (MAKE_MARKER ('i', 'n', '3', '2')) #define ni32_MARKER (MAKE_MARKER ('2', '3', 'n', 'i')) #define fl32_MARKER (MAKE_MARKER ('f', 'l', '3', '2')) #define FL32_MARKER (MAKE_MARKER ('F', 'L', '3', '2')) #define fl64_MARKER (MAKE_MARKER ('f', 'l', '6', '4')) #define FL64_MARKER (MAKE_MARKER ('F', 'L', '6', '4')) #define ulaw_MARKER (MAKE_MARKER ('u', 'l', 'a', 'w')) #define ULAW_MARKER (MAKE_MARKER ('U', 'L', 'A', 'W')) #define alaw_MARKER (MAKE_MARKER ('a', 'l', 'a', 'w')) #define ALAW_MARKER (MAKE_MARKER ('A', 'L', 'A', 'W')) #define DWVW_MARKER (MAKE_MARKER ('D', 'W', 'V', 'W')) #define GSM_MARKER (MAKE_MARKER ('G', 'S', 'M', ' ')) #define ima4_MARKER (MAKE_MARKER ('i', 'm', 'a', '4')) /* Unsupported AIFC encodings.*/ #define MAC3_MARKER (MAKE_MARKER ('M', 'A', 'C', '3')) #define MAC6_MARKER (MAKE_MARKER ('M', 'A', 'C', '6')) #define ADP4_MARKER (MAKE_MARKER ('A', 'D', 'P', '4')) /* Predfined chunk sizes. */ #define SIZEOF_AIFF_COMM 18 #define SIZEOF_AIFC_COMM_MIN 22 #define SIZEOF_AIFC_COMM 24 #define SIZEOF_SSND_CHUNK 8 #define SIZEOF_INST_CHUNK 20 /* AIFC/IMA4 defines. */ #define AIFC_IMA4_BLOCK_LEN 34 #define AIFC_IMA4_SAMPLES_PER_BLOCK 64 /*------------------------------------------------------------------------------ * Typedefs for file chunks. */ enum { aiffHAVE_FORM = 0x01, HAVE_AIFF = 0x02, HAVE_COMM = 0x04, HAVE_SSND = 0x08 } ; typedef struct { unsigned int size ; short numChannels ; unsigned int numSampleFrames ; short sampleSize ; unsigned char sampleRate [10] ; unsigned int encoding ; char zero_bytes [2] ; } COMM_CHUNK ; typedef struct { unsigned int offset ; unsigned int blocksize ; } SSND_CHUNK ; typedef struct { short playMode ; unsigned short beginLoop ; unsigned short endLoop ; } INST_LOOP ; typedef struct { char baseNote ; /* all notes are MIDI note numbers */ char detune ; /* cents off, only -50 to +50 are significant */ char lowNote ; char highNote ; char lowVelocity ; /* 1 to 127 */ char highVelocity ; /* 1 to 127 */ short gain ; /* in dB, 0 is normal */ INST_LOOP sustain_loop ; INST_LOOP release_loop ; } INST_CHUNK ; /*------------------------------------------------------------------------------ * Private static functions. */ static int aiff_close (SF_PRIVATE *psf) ; static int tenbytefloat2int (unsigned char *bytes) ; static void uint2tenbytefloat (unsigned int num, unsigned char *bytes) ; static int aiff_read_comm_chunk (SF_PRIVATE *psf, COMM_CHUNK *comm_fmt) ; static int aiff_read_header (SF_PRIVATE *psf, COMM_CHUNK *comm_fmt) ; static int aiff_write_header (SF_PRIVATE *psf, int calc_length) ; static int aiff_write_tailer (SF_PRIVATE *psf) ; static void aiff_write_strings (SF_PRIVATE *psf, int location) ; static int aiff_command (SF_PRIVATE *psf, int command, void *data, int datasize) ; static const char *get_loop_mode_str (short mode) ; /*------------------------------------------------------------------------------ ** Public function. */ int aiff_open (SF_PRIVATE *psf) { COMM_CHUNK comm_fmt ; int error, subformat ; subformat = psf->sf.format & SF_FORMAT_SUBMASK ; if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0)) { if ((error = aiff_read_header (psf, &comm_fmt))) return error ; psf_fseek (psf, psf->dataoffset, SEEK_SET) ; } ; if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) { if (psf->is_pipe) return SFE_NO_PIPE_WRITE ; if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_AIFF) return SFE_BAD_OPEN_FORMAT ; if (psf->mode == SFM_WRITE && (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE)) { psf->pchunk = calloc (1, sizeof (PEAK_CHUNK) * psf->sf.channels * sizeof (PEAK_POS)) ; if (psf->pchunk == NULL) return SFE_MALLOC_FAILED ; psf->has_peak = SF_TRUE ; psf->peak_loc = SF_PEAK_START ; } ; if (psf->mode != SFM_RDWR || psf->filelength < 40) { psf->filelength = 0 ; psf->datalength = 0 ; psf->dataoffset = 0 ; psf->sf.frames = 0 ; } ; psf->str_flags = SF_STR_ALLOW_START | SF_STR_ALLOW_END ; if ((error = aiff_write_header (psf, SF_FALSE))) return error ;