|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.