lsnes rr0-β21
[lsnes.git] / avi / sox.cpp
blobfe6ad56715f23c0cfc8dbc678cb2ca4939424c2c
1 #include "sox.hpp"
3 #include <iostream>
5 namespace
7 void write_double(uint8_t* buf, double v)
9 unsigned mag = 1023;
10 while(v >= 2) {
11 mag++;
12 v /= 2;
14 while(v < 1) {
15 mag--;
16 v *= 2;
18 uint64_t v2 = mag;
19 v -= 1;
20 for(unsigned i = 0; i < 52; i++) {
21 v *= 2;
22 v2 = 2 * v2 + ((v >= 1) ? 1 : 0);
23 if(v >= 1)
24 v -= 1;
26 buf[0] = v2;
27 buf[1] = v2 >> 8;
28 buf[2] = v2 >> 16;
29 buf[3] = v2 >> 24;
30 buf[4] = v2 >> 32;
31 buf[5] = v2 >> 40;
32 buf[6] = v2 >> 48;
33 buf[7] = v2 >> 56;
37 sox_dumper::sox_dumper(const std::string& filename, double samplerate, uint32_t channels) throw(std::bad_alloc,
38 std::runtime_error)
40 sox_file.open(filename.c_str(), std::ios::out | std::ios::binary);
41 if(!sox_file)
42 throw std::runtime_error("Can't open sox file for output");
43 try {
44 uint8_t buffer[32] = {0};
45 buffer[0] = 0x2E; //Magic.
46 buffer[1] = 0x53; //Magic.
47 buffer[2] = 0x6F; //Magic.
48 buffer[3] = 0x58; //Magic.
49 buffer[4] = 0x1C; //Header size.
50 write_double(buffer + 16, samplerate);
51 buffer[24] = channels;
52 buffer[25] = channels >> 8;
53 buffer[26] = channels >> 16;
54 buffer[27] = channels >> 24;
55 sox_file.write(reinterpret_cast<char*>(buffer), 32);
56 if(!sox_file)
57 throw std::runtime_error("Can't write audio header");
58 samplebuffer.resize(channels);
59 databuf.resize(channels << 2);
60 samples_dumped = 0;
61 } catch(...) {
62 sox_file.close();
63 throw;
67 sox_dumper::~sox_dumper() throw()
69 try {
70 close();
71 } catch(...) {
75 void sox_dumper::close() throw(std::bad_alloc, std::runtime_error)
77 sox_file.seekp(8, std::ios::beg);
78 uint8_t buffer[8];
79 uint64_t raw_samples = samples_dumped * samplebuffer.size();
80 buffer[0] = raw_samples;
81 buffer[1] = raw_samples >> 8;
82 buffer[2] = raw_samples >> 16;
83 buffer[3] = raw_samples >> 24;
84 buffer[4] = raw_samples >> 32;
85 buffer[5] = raw_samples >> 40;
86 buffer[6] = raw_samples >> 48;
87 buffer[7] = raw_samples >> 56;
88 sox_file.write(reinterpret_cast<char*>(buffer), 8);
89 if(!sox_file)
90 throw std::runtime_error("Can't fixup audio header");
91 sox_file.close();
94 void sox_dumper::internal_dump_sample()
96 for(size_t i = 0; i < samplebuffer.size(); ++i) {
97 uint32_t v = samplebuffer[i];
98 databuf[4 * i + 0] = v;
99 databuf[4 * i + 1] = v >> 8;
100 databuf[4 * i + 2] = v >> 16;
101 databuf[4 * i + 3] = v >> 24;
103 sox_file.write(&databuf[0], databuf.size());
104 if(!sox_file)
105 throw std::runtime_error("Failed to dump sample");
106 samples_dumped++;