Annotation of hatari/src/wavFormat.c, revision 1.1.1.3

1.1       root        1: /*
                      2:   Hatari
                      3: 
                      4:   WAV File output
                      5: 
                      6:   As well as YM file output we also have output in Windows .WAV format. As currently there is no application that
                      7:   can re-play saved sample data from an ST emulator .WAV output seems a good idea. Also it's noticed that ST Sound's
                      8:   playback routine are not as good as the ones currently in Hatari.
                      9:   These .WAV files can then be run through convertors to any other format, such as MP3.
                     10:   We simply save out the WAVE format headers and then write the sample data(at the current rate of playback)
                     11:   as we build it up each frame. When we stop recording we complete the size information in the headers and close up.
                     12: 
                     13: 
                     14:   RIFF Chunk (12 bytes in length total) Byte Number
                     15:     0 - 3  "RIFF" (ASCII Characters)
                     16:     4 - 7  Total Length Of Package To Follow (Binary, little endian)
                     17:     8 - 12  "WAVE" (ASCII Characters)
                     18: 
                     19:   FORMAT Chunk (24 bytes in length total) Byte Number
                     20:     0 - 3  "fmt_" (ASCII Characters)
                     21:     4 - 7  Length Of FORMAT Chunk (Binary, always 0x10)
                     22:     8 - 9  Always 0x01
                     23:     10 - 11  Channel Numbers (Always 0x01=Mono, 0x02=Stereo)
                     24:     12 - 15  Sample Rate (Binary, in Hz)
                     25:     16 - 19  Bytes Per Second
                     26:     20 - 21  Bytes Per Sample: 1=8 bit Mono, 2=8 bit Stereo or 16 bit Mono, 4=16 bit Stereo
                     27:     22 - 23  Bits Per Sample
                     28: 
                     29:   DATA Chunk Byte Number
                     30:     0 - 3  "data" (ASCII Characters)
                     31:     4 - 7  Length Of Data To Follow
                     32:     8 - end  Data (Samples)
                     33: */
                     34: 
1.1.1.3 ! root       35: #include <SDL_endian.h>
        !            36: 
1.1       root       37: #include "main.h"
                     38: #include "audio.h"
                     39: #include "dialog.h"
                     40: #include "file.h"
                     41: #include "misc.h"
                     42: #include "sound.h"
1.1.1.2   root       43: 
1.1       root       44: 
1.1.1.3 ! root       45: static FILE *WavFileHndl;
        !            46: static int nWavOutputBytes;             /* Number of samples bytes saved */
        !            47: BOOL bRecordingWav = FALSE;             /* Is a WAV file open and recording? */
        !            48: 
1.1       root       49: 
1.1.1.3 ! root       50: /*-----------------------------------------------------------------------*/
1.1       root       51: /*
                     52: */
1.1.1.3 ! root       53: BOOL WAVFormat_OpenFile(char *pszWavFileName)
1.1       root       54: {
1.1.1.3 ! root       55:   const Uint32 Blank = 0;
        !            56:   const Uint32 FmtLength = SDL_SwapLE32(0x10);
        !            57:   const Uint16 SOne = SDL_SwapLE16(0x01);
        !            58:   const Uint32 BitsPerSample = SDL_SwapLE32(8);
        !            59:   Uint32 SampleLength;
        !            60: 
        !            61:   /* Set frequency (11Khz, 22Khz or 44Khz) */
        !            62:   SampleLength = SDL_SwapLE32(SoundPlayBackFrequencies[ConfigureParams.Sound.nPlaybackQuality]);
        !            63: 
        !            64:   /* Create our file */
        !            65:   WavFileHndl = fopen(pszWavFileName, "wb");
        !            66: 
        !            67:   if (WavFileHndl!=NULL)
        !            68:   {
        !            69:     /* Create 'RIFF' chunk */
        !            70:     fwrite("RIFF", 1, 4, WavFileHndl);               /* "RIFF" (ASCII Characters) */
        !            71:     fwrite(&Blank, sizeof(Uint32), 1, WavFileHndl);  /* Total Length Of Package To Follow (Binary, little endian) */
        !            72:     fwrite("WAVE", 1, 4, WavFileHndl);               /* "WAVE" (ASCII Characters) */
        !            73: 
        !            74:     /* Create 'FORMAT' chunk */
        !            75:     fwrite("fmt ", 1, 4, WavFileHndl);                     /* "fmt_" (ASCII Characters) */
        !            76:     fwrite(&FmtLength, sizeof(Uint32), 1, WavFileHndl);    /* Length Of FORMAT Chunk (Binary, always 0x10) */
        !            77:     fwrite(&SOne, sizeof(Uint16), 1, WavFileHndl);         /* Always 0x01 */
        !            78:     fwrite(&SOne, sizeof(Uint16), 1, WavFileHndl);         /* Channel Numbers (Always 0x01=Mono, 0x02=Stereo) */
        !            79:     fwrite(&SampleLength, sizeof(Uint32), 1, WavFileHndl); /* Sample Rate (Binary, in Hz) */
        !            80:     fwrite(&SampleLength, sizeof(Uint32), 1, WavFileHndl); /* Bytes Per Second */
        !            81:     fwrite(&SOne, sizeof(Uint16), 1, WavFileHndl);         /* Bytes Per Sample: 1=8 bit Mono, 2=8 bit Stereo or 16 bit Mono, 4=16 bit Stereo */
        !            82:     fwrite(&BitsPerSample, sizeof(Uint16), 1, WavFileHndl); /* Bits Per Sample */
        !            83: 
        !            84:     /* Create 'DATA' chunk */
        !            85:     fwrite("data", 1, 4, WavFileHndl);               /* "data" (ASCII Characters) */
        !            86:     fwrite(&Blank, sizeof(Uint32), 1, WavFileHndl);  /* Length Of Data To Follow */
1.1       root       87: 
                     88:     nWavOutputBytes = 0;
                     89:     bRecordingWav = TRUE;
                     90: 
1.1.1.3 ! root       91:     /* Set status bar */
        !            92:     /*StatusBar_SetIcon(STATUS_ICON_SOUND,ICONSTATE_ON);*/
        !            93:     /* And inform user */
        !            94:     Main_Message("WAV Sound data recording started.",PROG_NAME /*,MB_OK | MB_ICONINFORMATION*/);
1.1       root       95:   }
                     96:   else
                     97:     bRecordingWav = FALSE;
                     98: 
1.1.1.3 ! root       99:   /* Ok, or failed? */
1.1       root      100:   return(bRecordingWav);
                    101: }
                    102: 
1.1.1.3 ! root      103: 
        !           104: /*-----------------------------------------------------------------------*/
1.1       root      105: /*
                    106: */
1.1.1.3 ! root      107: void WAVFormat_CloseFile()
1.1       root      108: {
1.1.1.3 ! root      109:   /* Turn off icon */
        !           110:   /*StatusBar_SetIcon(STATUS_ICON_SOUND,ICONSTATE_OFF);*/
1.1       root      111: 
1.1.1.3 ! root      112:   if (bRecordingWav)
        !           113:   {
        !           114:     Uint32 nWavFileBytes;
        !           115:     Uint32 nWavLEOutBytes;
        !           116: 
        !           117:     /* Update headers with sizes */
        !           118:     nWavFileBytes = SDL_SwapLE32((12+24+8+nWavOutputBytes)-8);  /* File length, less 8 bytes for 'RIFF' and length */
        !           119:     fseek(WavFileHndl, 4, SEEK_SET);                            /* 'Total Length Of Package' element */
        !           120:     fwrite(&nWavFileBytes, sizeof(Uint32), 1, WavFileHndl);     /* Total Length Of Package in 'RIFF' chunk */
        !           121: 
        !           122:     fseek(WavFileHndl, 12+24+4, SEEK_SET);                      /* 'Length' element */
        !           123:     nWavLEOutBytes = SDL_SwapLE32(nWavOutputBytes);
        !           124:     fwrite(&nWavLEOutBytes, sizeof(Uint32), 1, WavFileHndl);    /* Length Of Data in 'DATA' chunk */
        !           125: 
        !           126:     /* Close file */
        !           127:     fclose(WavFileHndl);
        !           128:     WavFileHndl = NULL;
1.1       root      129:     bRecordingWav = FALSE;
                    130: 
1.1.1.3 ! root      131:     /* And inform user */
        !           132:     Main_Message("WAV Sound data recording stopped.",PROG_NAME /*,MB_OK | MB_ICONINFORMATION*/);
1.1       root      133:   }
                    134: }
                    135: 
1.1.1.3 ! root      136: 
        !           137: /*-----------------------------------------------------------------------*/
1.1       root      138: /*
                    139: */
                    140: void WAVFormat_Update(char *pSamples,int Index)
                    141: {
1.1.1.3 ! root      142:   Sint8 sample;
1.1       root      143:   int i;
1.1.1.3 ! root      144: 
        !           145:   if (bRecordingWav)
        !           146:   {
        !           147:     /* Output, better if did in two section if wrap */
        !           148:     for(i=0; i<SAMPLES_PER_FRAME; i++)
        !           149:     {
        !           150:       /* Convert sample to 'signed' byte */
        !           151:       sample = pSamples[(Index+i)&MIXBUFFER_LENGTH] - 127;
        !           152:       /* And store */
        !           153:       fwrite(&sample, sizeof(Sint8), 1, WavFileHndl);
1.1       root      154:     }
                    155: 
1.1.1.3 ! root      156:     /* Add samples to wav file */
1.1       root      157:     nWavOutputBytes += SAMPLES_PER_FRAME;
                    158:   }
                    159: }
1.1.1.3 ! root      160: 

unix.superglobalmegacorp.com

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