Annotation of previous_trunk/src/wavFormat.c, revision 1.1.1.1

1.1       root        1: /*
                      2:   Hatari - wavFormat.c
                      3: 
                      4:   This file is distributed under the GNU Public License, version 2 or at
                      5:   your option any later version. Read the file gpl.txt for details.
                      6: 
                      7:   WAV File output
                      8: 
                      9:   As well as YM file output we also have output in .WAV format. These .WAV
                     10:   files can then be run through convertors to any other format, such as MP3.
                     11:   We simply save out the WAVE format headers and then write the sample data
                     12:   (at the current rate of playback) as we build it up each frame. When we stop
                     13:   recording we complete the size information in the headers and close up.
                     14: 
                     15: 
                     16:   RIFF Chunk (12 bytes in length total) Byte Number
                     17:     0 - 3  "RIFF" (ASCII Characters)
                     18:     4 - 7  Total Length Of Package To Follow (Binary, little endian)
                     19:     8 - 12  "WAVE" (ASCII Characters)
                     20: 
                     21:   FORMAT Chunk (24 bytes in length total) Byte Number
                     22:     0 - 3  "fmt_" (ASCII Characters)
                     23:     4 - 7  Length Of FORMAT Chunk (Binary, always 0x10)
                     24:     8 - 9  Always 0x01
                     25:     10 - 11  Channel Numbers (Always 0x01=Mono, 0x02=Stereo)
                     26:     12 - 15  Sample Rate (Binary, in Hz)
                     27:     16 - 19  Bytes Per Second
                     28:     20 - 21  Bytes Per Sample: 1=8 bit Mono, 2=8 bit Stereo or 16 bit Mono, 4=16 bit Stereo
                     29:     22 - 23  Bits Per Sample
                     30: 
                     31:   DATA Chunk Byte Number
                     32:     0 - 3  "data" (ASCII Characters)
                     33:     4 - 7  Length Of Data To Follow
                     34:     8 - end  Data (Samples)
                     35: */
                     36: const char WAVFormat_fileid[] = "Hatari wavFormat.c : " __DATE__ " " __TIME__;
                     37: 
                     38: #include <SDL_endian.h>
                     39: 
                     40: #include "main.h"
                     41: #include "audio.h"
                     42: #include "configuration.h"
                     43: #include "file.h"
                     44: #include "log.h"
                     45: #include "sound.h"
                     46: #include "wavFormat.h"
                     47: 
                     48: 
                     49: static FILE *WavFileHndl;
                     50: static int nWavOutputBytes;             /* Number of samples bytes saved */
                     51: bool bRecordingWav = false;             /* Is a WAV file open and recording? */
                     52: 
                     53: 
                     54: static Uint8 WavHeader[] =
                     55: {
                     56:        /* RIFF chunk */
                     57:        'R', 'I', 'F', 'F',      /* "RIFF" (ASCII Characters) */
                     58:        0, 0, 0, 0,              /* Total Length Of Package To Follow (patched when file is closed) */
                     59:        'W', 'A', 'V', 'E',      /* "WAVE" (ASCII Characters) */
                     60:        /* Format chunk */
                     61:        'f', 'm', 't', ' ',      /* "fmt_" (ASCII Characters) */
                     62:        0x10, 0, 0, 0,           /* Length Of FORMAT Chunk (always 0x10) */
                     63:        0x01, 0,                 /* Always 0x01 */
                     64:        0x02, 0,                 /* Number of channels (2 for stereo) */
                     65:        0, 0, 0, 0,              /* Sample rate (patched when file header is written) */
                     66:        0, 0, 0, 0,              /* Bytes per second (patched when file header is written) */
                     67:        0x04, 0,                 /* Bytes per sample (4 = 16 bit stereo) */
                     68:        0x10, 0,                 /* Bits per sample (16 bit) */
                     69:        /* Data chunk */
                     70:        'd', 'a', 't', 'a',
                     71:        0, 0, 0, 0,              /* Length of data to follow (will be patched when file is closed) */
                     72: };
                     73: 
                     74: 
                     75: /**
                     76:  * Open WAV output file and write header.
                     77:  */
                     78: bool WAVFormat_OpenFile(char *pszWavFileName)
                     79: {
                     80: 
                     81:        Uint32 nSampleFreq, nBytesPerSec;
                     82: 
                     83:        bRecordingWav = false;
                     84:        nWavOutputBytes = 0;
                     85: 
                     86:        /* Set frequency (11Khz, 22Khz or 44Khz) */
                     87:        nSampleFreq = ConfigureParams.Sound.nPlaybackFreq;
                     88:        /* multiply by 4 for 16 bit stereo */
                     89:        nBytesPerSec = nSampleFreq * 4;
                     90: 
                     91:        /* Create our file */
                     92:        WavFileHndl = fopen(pszWavFileName, "wb");
                     93:        if (!WavFileHndl)
                     94:        {
                     95:                perror("WAVFormat_OpenFile");
                     96:                Log_AlertDlg(LOG_ERROR, "WAV recording: Failed to open file!");
                     97:                return false;
                     98:        }
                     99: 
                    100:        /* Patch sample frequency in header structure */
                    101:        WavHeader[24] = (Uint8)nSampleFreq;
                    102:        WavHeader[25] = (Uint8)(nSampleFreq >> 8);
                    103:        WavHeader[26] = (Uint8)(nSampleFreq >> 16);
                    104:        WavHeader[27] = (Uint8)(nSampleFreq >> 24);
                    105: 
                    106:        /* Patch bytes per second in header structure */
                    107:        WavHeader[28] = (Uint8)nBytesPerSec;
                    108:        WavHeader[29] = (Uint8)(nBytesPerSec >> 8);
                    109:        WavHeader[30] = (Uint8)(nBytesPerSec >> 16);
                    110:        WavHeader[31] = (Uint8)(nBytesPerSec >> 24);
                    111: 
                    112:        /* Write header to file */
                    113:        if (fwrite(&WavHeader, sizeof(WavHeader), 1, WavFileHndl) == 1)
                    114:        {
                    115:                bRecordingWav = true;
                    116:                Log_AlertDlg(LOG_INFO, "WAV sound data recording has been started.");
                    117:        }
                    118:        else
                    119:        {
                    120:                perror("WAVFormat_OpenFile");
                    121:                Log_AlertDlg(LOG_ERROR, "WAV recording: Failed to write header!");
                    122:        }
                    123: 
                    124:        /* Ok, or failed? */
                    125:        return bRecordingWav;
                    126: }
                    127: 
                    128: 
                    129: /**
                    130:  * Write sizes to WAV header, then close the WAV file.
                    131:  */
                    132: void WAVFormat_CloseFile(void)
                    133: {
                    134:        if (bRecordingWav)
                    135:        {
                    136:                Uint32 nWavFileBytes;
                    137:                Uint32 nWavLEOutBytes;
                    138: 
                    139:                bRecordingWav = false;
                    140: 
                    141:                /* Update headers with sizes */
                    142:                nWavFileBytes = SDL_SwapLE32((12+24+8+nWavOutputBytes)-8);  /* File length, less 8 bytes for 'RIFF' and length */
                    143:                fseek(WavFileHndl, 4, SEEK_SET);                            /* 'Total Length Of Package' element */
                    144:                /* Write total length of package in 'RIFF' chunk */
                    145:                if (fwrite(&nWavFileBytes, sizeof(Uint32), 1, WavFileHndl) != 1)
                    146:                {
                    147:                        perror("WAVFormat_CloseFile");
                    148:                        fclose(WavFileHndl);
                    149:                        WavFileHndl = NULL;
                    150:                        return;
                    151:                }
                    152: 
                    153:                fseek(WavFileHndl, 12+24+4, SEEK_SET);                      /* 'Length' element */
                    154:                nWavLEOutBytes = SDL_SwapLE32(nWavOutputBytes);
                    155:                /* Write length of data in 'DATA' chunk */
                    156:                if (fwrite(&nWavLEOutBytes, sizeof(Uint32), 1, WavFileHndl) != 1)
                    157:                {
                    158:                        perror("WAVFormat_CloseFile");
                    159:                }
                    160: 
                    161:                /* Close file */
                    162:                fclose(WavFileHndl);
                    163:                WavFileHndl = NULL;
                    164: 
                    165:                /* And inform user */
                    166:                Log_AlertDlg(LOG_INFO, "WAV Sound data recording has been stopped.");
                    167:        }
                    168: }
                    169: 
                    170: 
                    171: /**
                    172:  * Update WAV file with current samples
                    173:  */
                    174: void WAVFormat_Update(Sint16 pSamples[][2], int Index, int Length)
                    175: {
                    176:        Sint16 sample[2];
                    177:        int i;
                    178: 
                    179:        if (bRecordingWav)
                    180:        {
                    181:                /* Output, better if did in two section if wrap */
                    182:                for(i = 0; i < Length; i++)
                    183:                {
                    184:                        /* Convert sample to little endian */
                    185:                        sample[0] = SDL_SwapLE16(pSamples[(Index+i)%MIXBUFFER_SIZE][0]);
                    186:                        sample[1] = SDL_SwapLE16(pSamples[(Index+i)%MIXBUFFER_SIZE][1]);
                    187:                        /* And store */
                    188:                        if (fwrite(&sample, sizeof(sample), 1, WavFileHndl) != 1)
                    189:                        {
                    190:                                perror("WAVFormat_Update");
                    191:                                WAVFormat_CloseFile();
                    192:                                return;
                    193:                        }
                    194:                }
                    195: 
                    196:                /* Add samples to wav file length counter */
                    197:                nWavOutputBytes += Length * 4;
                    198:        }
                    199: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.