|
|
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: ! 35: #include "main.h" ! 36: #include "audio.h" ! 37: #include "dialog.h" ! 38: #include "file.h" ! 39: #include "misc.h" ! 40: #include "sound.h" ! 41: #include "statusBar.h" ! 42: ! 43: //HFILE WavFile; ! 44: //OFSTRUCT WavFileInfo; ! 45: BOOL bRecordingWav=FALSE; // Is a WAV file open and recording? ! 46: int nWavOutputBytes; // Number of samples bytes saved ! 47: ! 48: //----------------------------------------------------------------------- ! 49: /* ! 50: */ ! 51: BOOL WAVFormat_OpenFile(/*HWND hWnd,*/ char *pszWavFileName) ! 52: { ! 53: static char szRiff[] = { "RIFF" }; ! 54: static char szWave[] = { "WAVE" }; ! 55: static char szFmt[] = { "fmt " }; ! 56: static char szData[] = { "data" }; ! 57: static unsigned int Blank=0; ! 58: static unsigned int FmtLength=0x10; ! 59: static unsigned short int SOne=0x01; ! 60: static unsigned int SampleLength; ! 61: static unsigned int BitsPerSample=8; ! 62: /* FIXME */ ! 63: /* ! 64: // Set frequency ! 65: SampleLength = SoundPlayBackFrequencies[ConfigureParams.Sound.nPlaybackQuality]; // 11Khz, 22Khz or 44Khz ! 66: ! 67: // Create our file ! 68: WavFile = OpenFile(pszWavFileName,&WavFileInfo,OF_CREATE | OF_WRITE); ! 69: if (WavFile!=HFILE_ERROR) { ! 70: // Create 'RIFF' chunk ! 71: _hwrite(WavFile,(char *)szRiff,4); // "RIFF" (ASCII Characters) ! 72: _hwrite(WavFile,(char *)&Blank,sizeof(int)); // Total Length Of Package To Follow (Binary, little endian) ! 73: _hwrite(WavFile,(char *)szWave,4); // "WAVE" (ASCII Characters) ! 74: ! 75: // Create 'FORMAT' chunk ! 76: _hwrite(WavFile,(char *)szFmt,4); // "fmt_" (ASCII Characters) ! 77: _hwrite(WavFile,(char *)&FmtLength,sizeof(int)); // Length Of FORMAT Chunk (Binary, always 0x10) ! 78: _hwrite(WavFile,(char *)&SOne,sizeof(short int)); // Always 0x01 ! 79: _hwrite(WavFile,(char *)&SOne,sizeof(short int)); // Channel Numbers (Always 0x01=Mono, 0x02=Stereo) ! 80: _hwrite(WavFile,(char *)&SampleLength,sizeof(int)); // Sample Rate (Binary, in Hz) ! 81: _hwrite(WavFile,(char *)&SampleLength,sizeof(int)); // Bytes Per Second ! 82: _hwrite(WavFile,(char *)&SOne,sizeof(short int)); // Bytes Per Sample: 1=8 bit Mono, 2=8 bit Stereo or 16 bit Mono, 4=16 bit Stereo ! 83: _hwrite(WavFile,(char *)&BitsPerSample,sizeof(short int)); // Bits Per Sample ! 84: ! 85: // Create 'DATA' chunk ! 86: _hwrite(WavFile,(char *)szData,4); // "data" (ASCII Characters) ! 87: _hwrite(WavFile,(char *)&Blank,sizeof(int)); // Length Of Data To Follow ! 88: ! 89: nWavOutputBytes = 0; ! 90: bRecordingWav = TRUE; ! 91: ! 92: // Set status bar ! 93: StatusBar_SetIcon(STATUS_ICON_SOUND,ICONSTATE_ON); ! 94: // And inform user ! 95: if (hWnd) ! 96: Main_Message("WAV Sound data recording started.",PROG_NAME,MB_OK | MB_ICONINFORMATION); ! 97: } ! 98: else ! 99: bRecordingWav = FALSE; ! 100: ! 101: // Ok, or failed? ! 102: return(bRecordingWav); ! 103: */ ! 104: } ! 105: ! 106: //----------------------------------------------------------------------- ! 107: /* ! 108: */ ! 109: void WAVFormat_CloseFile(/*HWND hWnd*/) ! 110: { ! 111: int nWavFileBytes; ! 112: /* FIXME */ ! 113: /* ! 114: // Turn off icon ! 115: StatusBar_SetIcon(STATUS_ICON_SOUND,ICONSTATE_OFF); ! 116: ! 117: if (bRecordingWav) { ! 118: // Update headers with sizes ! 119: nWavFileBytes = (12+24+8+nWavOutputBytes)-8; // File length, less 8 bytes for 'RIFF' and length ! 120: _llseek(WavFile,4,FILE_BEGIN); // 'Total Length Of Package' element ! 121: _hwrite(WavFile,(char *)&nWavFileBytes,sizeof(int)); // Total Length Of Package in 'RIFF' chunk ! 122: ! 123: _llseek(WavFile,12+24+4,FILE_BEGIN); // 'Length' element ! 124: _hwrite(WavFile,(char *)&nWavOutputBytes,sizeof(int)); // Length Of Data in 'DATA' chunk ! 125: ! 126: // Close file ! 127: _lclose(WavFile); ! 128: bRecordingWav = FALSE; ! 129: ! 130: // And inform user(this only happens from dialog) ! 131: if (hWnd) ! 132: Main_Message("WAV Sound data recording stopped.",PROG_NAME,MB_OK | MB_ICONINFORMATION); ! 133: } ! 134: */ ! 135: } ! 136: ! 137: //----------------------------------------------------------------------- ! 138: /* ! 139: */ ! 140: void WAVFormat_Update(char *pSamples,int Index) ! 141: { ! 142: char Char; ! 143: int i; ! 144: /* FIXME */ ! 145: /* ! 146: if (bRecordingWav) { ! 147: // Output, better if did in two section if wrap ! 148: for(i=0; i<SAMPLES_PER_FRAME; i++) { ! 149: // Convert sample to 'signed' byte ! 150: Char = pSamples[(Index+i)&MIXBUFFER_LENGTH]; ! 151: Char -= 127; ! 152: // And store ! 153: _hwrite(WavFile,(char *)&Char,sizeof(unsigned char)); ! 154: } ! 155: ! 156: // Add samples to wav file ! 157: nWavOutputBytes += SAMPLES_PER_FRAME; ! 158: } ! 159: */ ! 160: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.