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