Home | History | Annotate | Download | only in host_src
      1 /*----------------------------------------------------------------------------
      2  *
      3  * File:
      4  * eas_wave.c
      5  *
      6  * Contents and purpose:
      7  * This module contains .WAV file functions for the EAS synthesizer
      8  * test harness.
      9  *
     10  * Copyright Sonic Network Inc. 2005
     11 
     12  * Licensed under the Apache License, Version 2.0 (the "License");
     13  * you may not use this file except in compliance with the License.
     14  * You may obtain a copy of the License at
     15  *
     16  *      http://www.apache.org/licenses/LICENSE-2.0
     17  *
     18  * Unless required by applicable law or agreed to in writing, software
     19  * distributed under the License is distributed on an "AS IS" BASIS,
     20  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     21  * See the License for the specific language governing permissions and
     22  * limitations under the License.
     23  *----------------------------------------------------------------------------
     24  * Revision Control:
     25  *   $Revision: 658 $
     26  *   $Date: 2007-04-24 13:35:49 -0700 (Tue, 24 Apr 2007) $
     27  *----------------------------------------------------------------------------
     28 */
     29 
     30 /* lint complaints about most C library headers, so we use our own during lint step */
     31 #ifdef _lint
     32 #include "lint_stdlib.h"
     33 #else
     34 #include <stdio.h>
     35 #include <stdlib.h>
     36 #endif
     37 
     38 #include "eas_wave.h"
     39 
     40 /* .WAV file format tags */
     41 const EAS_U32 riffTag = 0x46464952;
     42 const EAS_U32 waveTag = 0x45564157;
     43 const EAS_U32 fmtTag = 0x20746d66;
     44 const EAS_U32 dataTag = 0x61746164;
     45 
     46 #ifdef _BIG_ENDIAN
     47 /*----------------------------------------------------------------------------
     48  * FlipDWord()
     49  *----------------------------------------------------------------------------
     50  * Purpose: Endian flip a DWORD for big-endian processors
     51  *
     52  * Inputs:
     53  *
     54  * Outputs:
     55  *
     56  *----------------------------------------------------------------------------
     57 */
     58 static void FlipDWord (EAS_U32 *pValue)
     59 {
     60     EAS_U8 *p;
     61     EAS_U32 temp;
     62 
     63     p = (EAS_U8*) pValue;
     64     temp = (((((p[3] << 8) | p[2]) << 8) | p[1]) << 8) | p[0];
     65     *pValue = temp;
     66 }
     67 
     68 /*----------------------------------------------------------------------------
     69  * FlipWord()
     70  *----------------------------------------------------------------------------
     71  * Purpose: Endian flip a WORD for big-endian processors
     72  *
     73  * Inputs:
     74  *
     75  * Outputs:
     76  *
     77  *----------------------------------------------------------------------------
     78 */
     79 static void FlipWord (EAS_U16 *pValue)
     80 {
     81     EAS_U8 *p;
     82     EAS_U16 temp;
     83 
     84     p = (EAS_U8*) pValue;
     85     temp = (p[1] << 8) | p[0];
     86     *pValue = temp;
     87 }
     88 
     89 /*----------------------------------------------------------------------------
     90  * FlipWaveHeader()
     91  *----------------------------------------------------------------------------
     92  * Purpose: Endian flip the wave header for big-endian processors
     93  *
     94  * Inputs:
     95  *
     96  * Outputs:
     97  *
     98  *----------------------------------------------------------------------------
     99 */
    100 static void FlipWaveHeader (WAVE_HEADER *p)
    101 {
    102 
    103     FlipDWord(&p->nRiffTag);
    104     FlipDWord(&p->nRiffSize);
    105     FlipDWord(&p->nWaveTag);
    106     FlipDWord(&p->nFmtTag);
    107     FlipDWord(&p->nFmtSize);
    108     FlipDWord(&p->nDataTag);
    109     FlipDWord(&p->nDataSize);
    110     FlipWord(&p->fc.wFormatTag);
    111     FlipWord(&p->fc.nChannels);
    112     FlipDWord(&p->fc.nSamplesPerSec);
    113     FlipDWord(&p->fc.nAvgBytesPerSec);
    114     FlipWord(&p->fc.nBlockAlign);
    115     FlipWord(&p->fc.wBitsPerSample);
    116 
    117 }
    118 #endif
    119 
    120 /*----------------------------------------------------------------------------
    121  * WaveFileCreate()
    122  *----------------------------------------------------------------------------
    123  * Purpose: Opens a wave file for writing and writes the header
    124  *
    125  * Inputs:
    126  *
    127  * Outputs:
    128  *
    129  *----------------------------------------------------------------------------
    130 */
    131 
    132 WAVE_FILE *WaveFileCreate (const char *filename, EAS_I32 nChannels, EAS_I32 nSamplesPerSec, EAS_I32 wBitsPerSample)
    133 {
    134     WAVE_FILE *wFile;
    135 
    136     /* allocate memory */
    137     wFile = malloc(sizeof(WAVE_FILE));
    138     if (!wFile)
    139         return NULL;
    140     wFile->write = EAS_TRUE;
    141 
    142     /* create the file */
    143     wFile->file = fopen(filename,"wb");
    144     if (!wFile->file)
    145     {
    146         free(wFile);
    147         return NULL;
    148     }
    149 
    150     /* initialize PCM format .WAV file header */
    151     wFile->wh.nRiffTag = riffTag;
    152     wFile->wh.nRiffSize = sizeof(WAVE_HEADER) - 8;
    153     wFile->wh.nWaveTag = waveTag;
    154     wFile->wh.nFmtTag = fmtTag;
    155     wFile->wh.nFmtSize = sizeof(FMT_CHUNK);
    156 
    157     /* initalize 'fmt' chunk */
    158     wFile->wh.fc.wFormatTag = 1;
    159     wFile->wh.fc.nChannels = (EAS_U16) nChannels;
    160     wFile->wh.fc.nSamplesPerSec = (EAS_U32) nSamplesPerSec;
    161     wFile->wh.fc.wBitsPerSample = (EAS_U16) wBitsPerSample;
    162     wFile->wh.fc.nBlockAlign = (EAS_U16) (nChannels * (EAS_U16) (wBitsPerSample / 8));
    163     wFile->wh.fc.nAvgBytesPerSec = wFile->wh.fc.nBlockAlign * (EAS_U32) nSamplesPerSec;
    164 
    165     /* initialize 'data' chunk */
    166     wFile->wh.nDataTag = dataTag;
    167     wFile->wh.nDataSize = 0;
    168 
    169 #ifdef _BIG_ENDIAN
    170     FlipWaveHeader(&wFile->wh);
    171 #endif
    172 
    173     /* write the header */
    174     if (fwrite(&wFile->wh, sizeof(WAVE_HEADER), 1, wFile->file) != 1)
    175     {
    176         fclose(wFile->file);
    177         free(wFile);
    178         return NULL;
    179     }
    180 
    181 #ifdef _BIG_ENDIAN
    182     FlipWaveHeader(&wFile->wh);
    183 #endif
    184 
    185     /* return the file handle */
    186     return wFile;
    187 } /* end WaveFileCreate */
    188 
    189 /*----------------------------------------------------------------------------
    190  * WaveFileWrite()
    191  *----------------------------------------------------------------------------
    192  * Purpose: Writes data to the wave file
    193  *
    194  * Inputs:
    195  *
    196  * Outputs:
    197  *
    198  *----------------------------------------------------------------------------
    199 */
    200 EAS_I32 WaveFileWrite (WAVE_FILE *wFile, void *buffer, EAS_I32 n)
    201 {
    202     EAS_I32 count;
    203 
    204     /* make sure we have an open file */
    205     if (wFile == NULL)
    206     {
    207         return 0;
    208     }
    209 
    210 #ifdef _BIG_ENDIAN
    211     {
    212         EAS_I32 i;
    213         EAS_U16 *p;
    214         p = buffer;
    215         i = n >> 1;
    216         while (i--)
    217             FlipWord(p++);
    218     }
    219 #endif
    220 
    221     /* write the data */
    222     count = (EAS_I32) fwrite(buffer, 1, (size_t) n, wFile->file);
    223 
    224     /* add the number of bytes written */
    225     wFile->wh.nRiffSize += (EAS_U32) count;
    226     wFile->wh.nDataSize += (EAS_U32) count;
    227 
    228     /* return the count of bytes written */
    229     return count;
    230 } /* end WriteWaveHeader */
    231 
    232 /*----------------------------------------------------------------------------
    233  * WaveFileClose()
    234  *----------------------------------------------------------------------------
    235  * Purpose: Opens a wave file for writing and writes the header
    236  *
    237  * Inputs:
    238  *
    239  * Outputs:
    240  *
    241  *----------------------------------------------------------------------------
    242 */
    243 
    244 EAS_BOOL WaveFileClose (WAVE_FILE *wFile)
    245 {
    246     EAS_I32 count = 1;
    247 
    248     /* return to beginning of file and write the header */
    249     if (wFile->write)
    250     {
    251         if (fseek(wFile->file, 0L, SEEK_SET) == 0)
    252         {
    253 
    254 #ifdef _BIG_ENDIAN
    255             FlipWaveHeader(&wFile->wh);
    256 #endif
    257             count = (EAS_I32) fwrite(&wFile->wh, sizeof(WAVE_HEADER), 1, wFile->file);
    258 #ifdef _BIG_ENDIAN
    259             FlipWaveHeader(&wFile->wh);
    260 #endif
    261         }
    262     }
    263 
    264     /* close the file */
    265     if (fclose(wFile->file) != 0)
    266         count = 0;
    267 
    268     /* free the memory */
    269     free(wFile);
    270 
    271     /* return the file handle */
    272     return (count == 1 ? EAS_TRUE : EAS_FALSE);
    273 } /* end WaveFileClose */
    274 
    275 #ifdef _WAVE_FILE_READ
    276 #ifdef _BIG_ENDIAN
    277 #error "WaveFileOpen not currently supported on big-endian processors"
    278 #endif
    279 /*----------------------------------------------------------------------------
    280  * WaveFileOpen()
    281  *----------------------------------------------------------------------------
    282  * Purpose: Opens a wave file for reading and reads the header
    283  *
    284  * Inputs:
    285  *
    286  * Outputs:
    287  *
    288  *----------------------------------------------------------------------------
    289 */
    290 
    291 WAVE_FILE *WaveFileOpen (const char *filename)
    292 {
    293     WAVE_FILE *wFile;
    294     struct
    295     {
    296         EAS_U32 tag;
    297         EAS_U32 size;
    298     } chunk;
    299     EAS_U32 tag;
    300     EAS_I32 startChunkPos;
    301     EAS_INT state;
    302     EAS_BOOL done;
    303 
    304     /* allocate memory */
    305     wFile = malloc(sizeof(WAVE_FILE));
    306     if (!wFile)
    307         return NULL;
    308 
    309     /* open the file */
    310     wFile->write = EAS_FALSE;
    311     wFile->file = fopen(filename,"rb");
    312     if (!wFile->file)
    313     {
    314         free(wFile);
    315         return NULL;
    316     }
    317 
    318     /* make lint happy */
    319     chunk.tag = chunk.size = 0;
    320     startChunkPos = 0;
    321 
    322     /* read the RIFF tag and file size */
    323     state = 0;
    324     done = EAS_FALSE;
    325     while (!done)
    326     {
    327 
    328         switch(state)
    329         {
    330             /* read the RIFF tag */
    331             case 0:
    332                 if (fread(&chunk, sizeof(chunk), 1, wFile->file) != 1)
    333                     done = EAS_TRUE;
    334                 else
    335                 {
    336                     if (chunk.tag != riffTag)
    337                         done = EAS_TRUE;
    338                     else
    339                         state++;
    340                 }
    341                 break;
    342 
    343             /* read the WAVE tag */
    344             case 1:
    345                 if (fread(&tag, sizeof(tag), 1, wFile->file) != 1)
    346                     done = EAS_TRUE;
    347                 else
    348                 {
    349                     if (tag != waveTag)
    350                         done = EAS_TRUE;
    351                     else
    352                         state++;
    353                 }
    354                 break;
    355 
    356             /* looking for fmt chunk */
    357             case 2:
    358                 if (fread(&chunk, sizeof(chunk), 1, wFile->file) != 1)
    359                     done = EAS_TRUE;
    360                 else
    361                 {
    362                     startChunkPos = ftell(wFile->file);
    363 
    364                     /* not fmt tag, skip it */
    365                     if (chunk.tag != fmtTag)
    366                         fseek(wFile->file, startChunkPos + (EAS_I32) chunk.size, SEEK_SET);
    367                     else
    368                         state++;
    369                 }
    370                 break;
    371 
    372             /* read fmt chunk */
    373             case 3:
    374                 if (fread(&wFile->wh.fc, sizeof(FMT_CHUNK), 1, wFile->file) != 1)
    375                     done = EAS_TRUE;
    376                 else
    377                 {
    378                     fseek(wFile->file, startChunkPos + (EAS_I32) chunk.size, SEEK_SET);
    379                     state++;
    380                 }
    381                 break;
    382 
    383             /* looking for data chunk */
    384             case 4:
    385                 if (fread(&chunk, sizeof(chunk), 1, wFile->file) != 1)
    386                     done = EAS_TRUE;
    387                 else
    388                 {
    389                     startChunkPos = ftell(wFile->file);
    390 
    391                     /* not data tag, skip it */
    392                     if (chunk.tag != dataTag)
    393                         fseek(wFile->file, startChunkPos + (EAS_I32) chunk.size, SEEK_SET);
    394                     else
    395                     {
    396                         wFile->dataSize = chunk.size;
    397                         state++;
    398                         done = EAS_TRUE;
    399                     }
    400                 }
    401                 break;
    402 
    403             default:
    404                 done = EAS_TRUE;
    405                 break;
    406         }
    407     }
    408 
    409     /* if not final state, an error occurred */
    410     if (state != 5)
    411     {
    412         fclose(wFile->file);
    413         free(wFile);
    414         return NULL;
    415     }
    416 
    417     /* return the file handle */
    418     return wFile;
    419 } /* end WaveFileOpen */
    420 #endif
    421 
    422 
    423 
    424