Audio.c

Go to the documentation of this file.
00001 /*
00002 *  Copyright (C) 2007 Jolien Creighton
00003 *
00004 *  This program is free software; you can redistribute it and/or modify
00005 *  it under the terms of the GNU General Public License as published by
00006 *  the Free Software Foundation; either version 2 of the License, or
00007 *  (at your option) any later version.
00008 *
00009 *  This program is distributed in the hope that it will be useful,
00010 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 *  GNU General Public License for more details.
00013 *
00014 *  You should have received a copy of the GNU General Public License
00015 *  along with with program; see the file COPYING. If not, write to the
00016 *  Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00017 *  MA  02111-1307  USA
00018 */
00019 
00020 /* vim: set noet ts=4 sw=4: */
00021 /** \file
00022  * \ingroup support
00023  * \author Creighton, J. D. E.
00024  * \date $Date: 2007/09/21 19:24:56 $
00025  * \brief Routines for exporting time series as sound files.
00026  *
00027  * $Id: Audio.c,v 1.3 2007/09/21 19:24:56 jolien Exp $
00028  */
00029 
00030 #include <math.h>
00031 #include <stdio.h>
00032 #include <lal/LALStdlib.h>
00033 #include <lal/LALStdio.h>
00034 #include <lal/Audio.h>
00035 
00036 #define LAL_SOUND_MAX 32760
00037 
00038 NRCSID( AUDIOC, "$Id: Audio.c,v 1.3 2007/09/21 19:24:56 jolien Exp $" );
00039 
00040 /* if file pointer is NULL then create a new file based on series name */
00041 static FILE * fopen_if_null( FILE *fp, const char *name, const char *extn )
00042 {
00043         if ( ! fp ) {
00044                 char fname[FILENAME_MAX];
00045                 LALSnprintf( fname, sizeof( fname ), "%s.%s", name, extn );
00046                 fp = fopen( fname, "w" );
00047         }
00048         return fp;
00049 }
00050 
00051 static int output_wav_hdr( FILE *fp, INT4 samplerate, UINT4 datasize )
00052 {
00053         UINT4 totalsize = datasize + 36; /* for header */
00054         INT4 byterate = samplerate * sizeof( UINT2 );
00055 
00056         /* 
00057          *
00058          * Write RIFF Header
00059          *
00060          */
00061 
00062         /* magic */
00063         fprintf( fp, "RIFF" );
00064 
00065         /* size of rest of file (bytes) */
00066         fputc( (totalsize & 0x000000ff)       , fp );
00067         fputc( (totalsize & 0x0000ff00) >> 8  , fp );
00068         fputc( (totalsize & 0x00ff0000) >> 16 , fp );
00069         fputc( (totalsize & 0xff000000) >> 24 , fp );
00070 
00071         /* file type "WAVE" */
00072         fprintf( fp, "WAVE" );
00073 
00074 
00075         /* 
00076          *
00077          * Write Format Chunk
00078          *
00079          */
00080 
00081 
00082         /* magic */
00083         fprintf( fp, "fmt " );
00084 
00085         /* chunk size */
00086         fputc( 16, fp );
00087         fputc( 0, fp );
00088         fputc( 0, fp );
00089         fputc( 0, fp );
00090 
00091         /* format tag (1=uncompressed) */
00092         fputc( 1, fp );
00093         fputc( 0, fp );
00094 
00095         /* number of channels */
00096         fputc( 1, fp );
00097         fputc( 0, fp );
00098 
00099         /* samples per second */
00100         fputc( (samplerate & 0x000000ff)      , fp );
00101         fputc( (samplerate & 0x0000ff00) >> 8 , fp );
00102         fputc( (samplerate & 0x00ff0000) >> 16, fp );
00103         fputc( (samplerate & 0xff000000) >> 24, fp );
00104 
00105         /* average bytes per second */
00106         fputc( (byterate & 0x000000ff)      , fp );
00107         fputc( (byterate & 0x0000ff00) >> 8 , fp );
00108         fputc( (byterate & 0x00ff0000) >> 16, fp );
00109         fputc( (byterate & 0xff000000) >> 24, fp );
00110 
00111         /* block alignment (bytes of data per time step) */
00112         /* i.e., number of channels times sample width in bytes */
00113         fputc( 2, fp );
00114         fputc( 0, fp );
00115 
00116         /* bits per sample */
00117         fputc( 16, fp );
00118         fputc( 0, fp );
00119 
00120 
00121         /*
00122          *
00123          * Write Data Chunk
00124          *
00125          */
00126 
00127 
00128         /* magic */
00129         fprintf( fp, "data" );
00130 
00131         /* size of this chunk in bytes */
00132         fputc( (datasize & 0x000000ff),       fp );
00133         fputc( (datasize & 0x0000ff00) >> 8,  fp );
00134         fputc( (datasize & 0x00ff0000) >> 16, fp );
00135         fputc( (datasize & 0xff000000) >> 24, fp );
00136 
00137         return 0;
00138 }
00139 
00140 static int output_au_hdr( FILE *fp, INT4 samplerate, UINT4 datasize )
00141 {
00142         /*
00143          *
00144          * Write header
00145          *
00146          */
00147 
00148         /* magic number */
00149         fprintf( fp, ".snd" );
00150 
00151         /* header length */
00152         fputc( 0, fp );
00153         fputc( 0, fp );
00154         fputc( 0, fp );
00155         fputc( 24, fp );
00156 
00157         /* data size (bytes) */
00158         fputc( (datasize & 0xff000000) >> 24, fp );
00159         fputc( (datasize & 0x00ff0000) >> 16, fp );
00160         fputc( (datasize & 0x0000ff00) >> 8,  fp );
00161         fputc( (datasize & 0x000000ff),       fp );
00162 
00163         /* encoding (16 bit pcm) */
00164         fputc( 0, fp );
00165         fputc( 0, fp );
00166         fputc( 0, fp );
00167         fputc( 3, fp );
00168 
00169         /* sample rate */
00170         fputc( (samplerate & 0xff000000) >> 24, fp );
00171         fputc( (samplerate & 0x00ff0000) >> 16, fp );
00172         fputc( (samplerate & 0x0000ff00) >> 8,  fp );
00173         fputc( (samplerate & 0x000000ff),       fp );
00174 
00175         /* number of channels */
00176         fputc( 0, fp );
00177         fputc( 0, fp );
00178         fputc( 0, fp );
00179         fputc( 1, fp );
00180 
00181         return 0;
00182 }
00183 
00184 static int output_REAL4Vector( FILE *fp, REAL4Vector *data, int wavfmt )
00185 {
00186         REAL4 maxval, minval, midval, scale;
00187         UINT4 i;
00188 
00189         /* compute range */
00190         maxval = minval = data->data[0];
00191         for ( i = 1; i < data->length; ++i ) {
00192                 if ( data->data[i] > maxval )
00193                         maxval = data->data[i];
00194                 if ( data->data[i] < minval )
00195                         minval = data->data[i];
00196         }
00197         midval  = 0.5*(maxval + minval);
00198         maxval -= midval;
00199         minval -= midval;
00200         if ( fabs( minval ) > fabs( maxval ) )
00201                 maxval = fabs( minval );
00202         scale = LAL_SOUND_MAX / maxval;
00203 
00204         /* output data */
00205         if ( wavfmt == 1 ) { /* wav format */
00206                 for ( i = 0; i < data->length; ++i ) {
00207                         UINT2 val;
00208                         val = (UINT2)( scale * (data->data[i] - midval) );
00209                         fputc( (val & 0x00ff),      fp );
00210                         fputc( (val & 0xff00) >> 8, fp );
00211                 }
00212         } else {  /* au format */
00213                 for ( i = 0; i < data->length; ++i ) {
00214                         UINT2 val;
00215                         val = (UINT2)(scale*data->data[i]);
00216                         fputc( (val & 0xff00) >> 8, fp );
00217                         fputc( (val & 0x00ff),      fp );
00218                 }
00219         }
00220         return 0;
00221 }
00222 
00223 static int output_REAL8Vector( FILE *fp, REAL8Vector *data, int wavfmt )
00224 {
00225         REAL4 maxval, minval, midval, scale;
00226         UINT4 i;
00227 
00228         /* compute range */
00229         maxval = minval = data->data[0];
00230         for ( i = 1; i < data->length; ++i ) {
00231                 if ( data->data[i] > maxval )
00232                         maxval = data->data[i];
00233                 if ( data->data[i] < minval )
00234                         minval = data->data[i];
00235         }
00236         midval  = 0.5*(maxval + minval);
00237         maxval -= midval;
00238         minval -= midval;
00239         if ( fabs( minval ) > fabs( maxval ) )
00240                 maxval = fabs( minval );
00241         scale = LAL_SOUND_MAX / maxval;
00242 
00243         /* output data */
00244         if ( wavfmt == 1 ) { /* wav format */
00245                 for ( i = 0; i < data->length; ++i ) {
00246                         UINT2 val;
00247                         val = (UINT2)( scale * (data->data[i] - midval) );
00248                         fputc( (val & 0x00ff),      fp );
00249                         fputc( (val & 0xff00) >> 8, fp );
00250                 }
00251         } else {  /* au format */
00252                 for ( i = 0; i < data->length; ++i ) {
00253                         UINT2 val;
00254                         val = (UINT2)(scale*data->data[i]);
00255                         fputc( (val & 0xff00) >> 8, fp );
00256                         fputc( (val & 0x00ff),      fp );
00257                 }
00258         }
00259 
00260         return 0;
00261 }
00262 
00263 /** Records a time series as a .wav audio file */
00264 int XLALAudioWAVRecordREAL4TimeSeries( FILE *fp, REAL4TimeSeries *series )
00265 {
00266         static const char * func = "XLALAudioWAVRecordREAL4TimeSeries";
00267         INT4  samplerate;
00268         UINT4 datasize;
00269         FILE *fpout;
00270 
00271         if ( ! series )
00272                 XLAL_ERROR( func, XLAL_EFAULT );
00273         if ( ! series->data )
00274                 XLAL_ERROR( func, XLAL_EINVAL );
00275         if ( ! series->data->length )
00276                 XLAL_ERROR( func, XLAL_EBADLEN );
00277 
00278         datasize  = series->data->length * sizeof( UINT2 ); 
00279         samplerate = (INT4)(1.0/series->deltaT);
00280         if ( samplerate < 1 )
00281                 XLAL_ERROR( func, XLAL_EINVAL );
00282 
00283         fpout = fopen_if_null( fp, series->name, "wav" );
00284         if ( ! fpout )
00285                 XLAL_ERROR( func, XLAL_EIO );
00286 
00287         /* write header */
00288         output_wav_hdr( fpout, samplerate, datasize );
00289 
00290         /* write data */
00291         output_REAL4Vector( fpout, series->data, 1 );
00292 
00293         if ( !fp )
00294                 fclose( fpout );
00295 
00296         return 0;
00297 }
00298 
00299 /** Records a time series as a .wav audio file */
00300 int XLALAudioWAVRecordREAL8TimeSeries( FILE *fp, REAL8TimeSeries *series )
00301 {
00302         static const char * func = "XLALAudioWAVRecordREAL8TimeSeries";
00303         INT4  samplerate;
00304         UINT4 datasize;
00305         FILE *fpout;
00306 
00307         if ( ! series )
00308                 XLAL_ERROR( func, XLAL_EFAULT );
00309         if ( ! series->data )
00310                 XLAL_ERROR( func, XLAL_EINVAL );
00311         if ( ! series->data->length )
00312                 XLAL_ERROR( func, XLAL_EBADLEN );
00313 
00314         datasize  = series->data->length * sizeof( UINT2 ); 
00315         samplerate = (INT4)(1.0/series->deltaT);
00316         if ( samplerate < 1 )
00317                 XLAL_ERROR( func, XLAL_EINVAL );
00318 
00319         fpout = fopen_if_null( fp, series->name, "wav" );
00320         if ( ! fpout )
00321                 XLAL_ERROR( func, XLAL_EIO );
00322 
00323         /* write header */
00324         output_wav_hdr( fpout, samplerate, datasize );
00325 
00326         /* write data */
00327         output_REAL8Vector( fpout, series->data, 1 );
00328 
00329         if ( !fp )
00330                 fclose( fpout );
00331 
00332         return 0;
00333 }
00334 
00335 
00336 /** Records a time series as a .au audio file */
00337 int XLALAudioAURecordREAL4TimeSeries( FILE *fp, REAL4TimeSeries *series )
00338 {
00339         static const char * func = "XLALAudioAURecordREAL4TimeSeries";
00340         INT4  samplerate;
00341         UINT4 datasize;
00342         FILE *fpout;
00343 
00344         if ( ! series )
00345                 XLAL_ERROR( func, XLAL_EFAULT );
00346         if ( ! series->data )
00347                 XLAL_ERROR( func, XLAL_EINVAL );
00348         if ( ! series->data->length )
00349                 XLAL_ERROR( func, XLAL_EBADLEN );
00350 
00351         datasize  = series->data->length * sizeof( UINT2 ); 
00352         samplerate = (INT4)(1.0/series->deltaT);
00353         if ( samplerate < 1 )
00354                 XLAL_ERROR( func, XLAL_EINVAL );
00355 
00356         fpout = fopen_if_null( fp, series->name, "au" );
00357         if ( ! fpout )
00358                 XLAL_ERROR( func, XLAL_EIO );
00359 
00360         /* write header */
00361         output_au_hdr( fpout, samplerate, datasize );
00362 
00363         /* write data */
00364         output_REAL4Vector( fpout, series->data, 0 );
00365 
00366         if ( !fp )
00367                 fclose( fpout );
00368 
00369         return 0;
00370 }
00371 
00372 /** Records a time series as a .au audio file */
00373 int XLALAudioAURecordREAL8TimeSeries( FILE *fp, REAL8TimeSeries *series )
00374 {
00375         static const char * func = "XLALAudioAURecordREAL8TimeSeries";
00376         INT4  samplerate;
00377         UINT4 datasize;
00378         FILE *fpout;
00379 
00380         if ( ! series )
00381                 XLAL_ERROR( func, XLAL_EFAULT );
00382         if ( ! series->data )
00383                 XLAL_ERROR( func, XLAL_EINVAL );
00384         if ( ! series->data->length )
00385                 XLAL_ERROR( func, XLAL_EBADLEN );
00386 
00387         datasize  = series->data->length * sizeof( UINT2 ); 
00388         samplerate = (INT4)(1.0/series->deltaT);
00389         if ( samplerate < 1 )
00390                 XLAL_ERROR( func, XLAL_EINVAL );
00391 
00392         fpout = fopen_if_null( fp, series->name, "au" );
00393         if ( ! fpout )
00394                 XLAL_ERROR( func, XLAL_EIO );
00395 
00396         /* write header */
00397         output_au_hdr( fpout, samplerate, datasize );
00398 
00399         /* write data */
00400         output_REAL8Vector( fpout, series->data, 0 );
00401 
00402         if ( !fp )
00403                 fclose( fpout );
00404 
00405         return 0;
00406 }

Generated on Sun Oct 12 02:31:31 2008 for LAL by  doxygen 1.5.2