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