1 /******************************************************************************/
2 /* Mednafen - Multi-system Emulator                                           */
3 /******************************************************************************/
4 /* WAVRecord.cpp:
5 **  Copyright (C) 2010-2016 Mednafen Team
6 **
7 ** This program is free software; you can redistribute it and/or
8 ** modify it under the terms of the GNU General Public License
9 ** as published by the Free Software Foundation; either version 2
10 ** of the License, or (at your option) any later version.
11 **
12 ** This program is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 ** GNU General Public License for more details.
16 **
17 ** You should have received a copy of the GNU General Public License
18 ** along with this program; if not, write to the Free Software Foundation, Inc.,
19 ** 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 */
21 
22 #include <mednafen/mednafen.h>
23 #include "WAVRecord.h"
24 
25 namespace Mednafen
26 {
27 
WAVRecord(const char * path,double SoundRate_arg,uint32 SoundChan_arg)28 WAVRecord::WAVRecord(const char *path, double SoundRate_arg, uint32 SoundChan_arg) : wavfile(path, FileStream::MODE_WRITE_SAFE)
29 {
30  Finished = false;
31  PCMBytesWritten = 0;
32 
33  SoundRate = SoundRate_arg;
34  SoundChan = SoundChan_arg;
35 
36  memset(&raw_headers, 0, sizeof(raw_headers));
37 
38  MDFN_en32msb(&raw_headers[0x00], 0x52494646);	// "RIFF"
39  // @ 0x04 = total file size - 8 bytes
40  MDFN_en32msb(&raw_headers[0x08], 0x57415645);	// "WAVE"
41 
42 
43  MDFN_en32msb(&raw_headers[0x0C], 0x666d7420);	// "fmt "
44  MDFN_en32lsb(&raw_headers[0x10], 16);
45  MDFN_en16lsb(&raw_headers[0x14], 1);		// PCM format
46  MDFN_en16lsb(&raw_headers[0x16], SoundChan);	// Number of sound channels
47  MDFN_en32lsb(&raw_headers[0x18], SoundRate);	// Sampling rate
48  MDFN_en32lsb(&raw_headers[0x1C], SoundRate * SoundChan * sizeof(int16));	//Byte rate
49  MDFN_en16lsb(&raw_headers[0x20], SoundChan * sizeof(int16));	// Block("audio frame" in Mednafen) alignment
50  MDFN_en16lsb(&raw_headers[0x22], sizeof(int16) * 8);	// Bits per sample.
51 
52  MDFN_en32msb(&raw_headers[0x24], 0x64617461);	// "data"
53  // @ 0x28 = bytes of PCM data following
54 
55  wavfile.write(raw_headers, sizeof(raw_headers));
56 }
57 
WriteSound(const int16 * SoundBuf,uint32 NumSoundFrames)58 void WAVRecord::WriteSound(const int16 *SoundBuf, uint32 NumSoundFrames)
59 {
60  uint32 NumSoundSamples = NumSoundFrames * SoundChan;
61 
62  while(NumSoundSamples > 0)
63  {
64   int16 swap_buf[256];
65   uint32 s_this_time = std::min((uint32)NumSoundSamples, (uint32)256);
66 
67   for(uint32 i = 0; i < s_this_time; i++)
68    MDFN_en16lsb((uint8 *)&swap_buf[i], SoundBuf[i]);
69 
70   wavfile.write(swap_buf, s_this_time * sizeof(int16));
71   PCMBytesWritten += s_this_time * sizeof(int16);
72   NumSoundSamples -= s_this_time;
73   SoundBuf += s_this_time;
74  }
75 
76 }
77 
78 
Finish(void)79 void WAVRecord::Finish(void)
80 {
81  if(Finished)
82   return;
83 
84  MDFN_en32lsb(&raw_headers[0x04], std::min<uint64>(wavfile.tell() - 8, 0xFFFFFFFF));
85 
86  MDFN_en32lsb(&raw_headers[0x28], std::min<uint64>(PCMBytesWritten, 0xFFFFFFFF));
87 
88  wavfile.seek(0, SEEK_SET);
89  wavfile.write(raw_headers, sizeof(raw_headers));
90  wavfile.close();
91 
92  Finished = true;
93 }
94 
~WAVRecord()95 WAVRecord::~WAVRecord()
96 {
97  try
98  {
99   Finish();
100  }
101  catch(std::exception &e)
102  {
103   MDFND_OutputNotice(MDFN_NOTICE_ERROR, e.what());
104  }
105 }
106 
107 }
108