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