Annotation of previous_trunk/src/wavFormat.c, revision 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.