|
|
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:
1.1.1.6 root 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.
1.1 root 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: */
1.1.1.10! root 36: const char WAVFormat_rcsid[] = "Hatari $Id: wavFormat.c,v 1.16 2008/08/19 00:09:59 thothy Exp $";
1.1 root 37:
1.1.1.3 root 38: #include <SDL_endian.h>
39:
1.1 root 40: #include "main.h"
41: #include "audio.h"
1.1.1.6 root 42: #include "configuration.h"
1.1 root 43: #include "file.h"
1.1.1.6 root 44: #include "log.h"
1.1 root 45: #include "sound.h"
1.1.1.5 root 46: #include "wavFormat.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 */
1.1.1.10! root 51: bool bRecordingWav = FALSE; /* Is a WAV file open and recording? */
1.1.1.3 root 52:
1.1 root 53:
1.1.1.3 root 54: /*-----------------------------------------------------------------------*/
1.1.1.9 root 55: /**
56: *
57: */
1.1.1.10! root 58: bool WAVFormat_OpenFile(char *pszWavFileName)
1.1 root 59: {
1.1.1.6 root 60: const Uint32 Blank = 0;
61: const Uint32 FmtLength = SDL_SwapLE32(0x10);
1.1.1.10! root 62: const Uint16 LeOne = SDL_SwapLE16(0x01);
! 63: const Uint16 LeTwo = SDL_SwapLE16(0x02);
! 64: const Uint16 LeFour = SDL_SwapLE16(0x04);
! 65: const Uint32 BitsPerSample = SDL_SwapLE32(16);
1.1.1.6 root 66: Uint32 SampleLength;
67:
68: /* Set frequency (11Khz, 22Khz or 44Khz) */
69: SampleLength = SDL_SwapLE32(SoundPlayBackFrequencies[ConfigureParams.Sound.nPlaybackQuality]);
70:
71: /* Create our file */
72: WavFileHndl = fopen(pszWavFileName, "wb");
73:
74: if (WavFileHndl != NULL)
75: {
76: /* Create 'RIFF' chunk */
77: fwrite("RIFF", 1, 4, WavFileHndl); /* "RIFF" (ASCII Characters) */
78: fwrite(&Blank, sizeof(Uint32), 1, WavFileHndl); /* Total Length Of Package To Follow (Binary, little endian) */
79: fwrite("WAVE", 1, 4, WavFileHndl); /* "WAVE" (ASCII Characters) */
80:
81: /* Create 'FORMAT' chunk */
82: fwrite("fmt ", 1, 4, WavFileHndl); /* "fmt_" (ASCII Characters) */
83: fwrite(&FmtLength, sizeof(Uint32), 1, WavFileHndl); /* Length Of FORMAT Chunk (Binary, always 0x10) */
1.1.1.10! root 84: fwrite(&LeOne, sizeof(Uint16), 1, WavFileHndl); /* Always 0x01 */
! 85: fwrite(&LeTwo, sizeof(Uint16), 1, WavFileHndl); /* Channel Numbers (0x01=Mono, 0x02=Stereo) */
1.1.1.6 root 86: fwrite(&SampleLength, sizeof(Uint32), 1, WavFileHndl); /* Sample Rate (Binary, in Hz) */
87: fwrite(&SampleLength, sizeof(Uint32), 1, WavFileHndl); /* Bytes Per Second */
1.1.1.10! root 88: fwrite(&LeFour, sizeof(Uint16), 1, WavFileHndl); /* Bytes Per Sample: 1=8 bit Mono, 2=8 bit Stereo or 16 bit Mono, 4=16 bit Stereo */
1.1.1.6 root 89: fwrite(&BitsPerSample, sizeof(Uint16), 1, WavFileHndl); /* Bits Per Sample */
90:
91: /* Create 'DATA' chunk */
92: fwrite("data", 1, 4, WavFileHndl); /* "data" (ASCII Characters) */
93: fwrite(&Blank, sizeof(Uint32), 1, WavFileHndl); /* Length Of Data To Follow */
94:
95: nWavOutputBytes = 0;
96: bRecordingWav = TRUE;
97:
98: /* And inform user */
99: Log_AlertDlg(LOG_INFO, "WAV sound data recording has been started.");
100: }
101: else
102: bRecordingWav = FALSE;
1.1 root 103:
1.1.1.6 root 104: /* Ok, or failed? */
105: return bRecordingWav;
1.1 root 106: }
107:
1.1.1.3 root 108:
109: /*-----------------------------------------------------------------------*/
1.1.1.9 root 110: /**
111: *
112: */
113: void WAVFormat_CloseFile(void)
1.1 root 114: {
1.1.1.6 root 115: if (bRecordingWav)
116: {
117: Uint32 nWavFileBytes;
118: Uint32 nWavLEOutBytes;
119:
120: /* Update headers with sizes */
121: nWavFileBytes = SDL_SwapLE32((12+24+8+nWavOutputBytes)-8); /* File length, less 8 bytes for 'RIFF' and length */
122: fseek(WavFileHndl, 4, SEEK_SET); /* 'Total Length Of Package' element */
123: fwrite(&nWavFileBytes, sizeof(Uint32), 1, WavFileHndl); /* Total Length Of Package in 'RIFF' chunk */
124:
125: fseek(WavFileHndl, 12+24+4, SEEK_SET); /* 'Length' element */
126: nWavLEOutBytes = SDL_SwapLE32(nWavOutputBytes);
127: fwrite(&nWavLEOutBytes, sizeof(Uint32), 1, WavFileHndl); /* Length Of Data in 'DATA' chunk */
128:
129: /* Close file */
130: fclose(WavFileHndl);
131: WavFileHndl = NULL;
132: bRecordingWav = FALSE;
133:
134: /* And inform user */
135: Log_AlertDlg(LOG_INFO, "WAV Sound data recording has been stopped.");
136: }
1.1 root 137: }
138:
1.1.1.3 root 139:
140: /*-----------------------------------------------------------------------*/
1.1.1.9 root 141: /**
142: *
143: */
1.1.1.10! root 144: void WAVFormat_Update(Sint16 pSamples[][2], int Index, int Length)
1.1 root 145: {
1.1.1.10! root 146: Sint16 sample[2];
1.1.1.6 root 147: int i;
1.1.1.3 root 148:
1.1.1.6 root 149: if (bRecordingWav)
150: {
151: /* Output, better if did in two section if wrap */
152: for(i = 0; i < Length; i++)
153: {
1.1.1.10! root 154: /* Convert sample to little endian */
! 155: sample[0] = SDL_SwapLE16(pSamples[(Index+i)%MIXBUFFER_SIZE][0]);
! 156: sample[1] = SDL_SwapLE16(pSamples[(Index+i)%MIXBUFFER_SIZE][1]);
1.1.1.6 root 157: /* And store */
1.1.1.10! root 158: fwrite(&sample, sizeof(sample), 1, WavFileHndl);
1.1.1.6 root 159: }
160:
161: /* Add samples to wav file */
1.1.1.10! root 162: nWavOutputBytes += Length * 4;
1.1.1.6 root 163: }
1.1 root 164: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.