SDL_Main isn't needed on sane platforms anyway. Remove it
[jpcrr.git] / streamtools / output-drv-wav.cpp
blobb2e298446b39897735fe317e0ffce499c060b256
1 #define RIFF_MAGIC 0x46464952
2 #define WAVE_MAGIC 0x45564157
3 #define FMT_MAGIC 0x20746d66
4 #define DATA_MAGIC 0x61746164
6 #include "output-drv.hpp"
7 #include <cstdio>
8 #include <stdexcept>
9 #include <string>
11 namespace
13 static void write_little32(unsigned char* to, uint32_t value)
15 to[0] = (value) & 0xFF;
16 to[1] = (value >> 8) & 0xFF;
17 to[2] = (value >> 16) & 0xFF;
18 to[3] = (value >> 24) & 0xFF;
21 static void write_little16(unsigned char* to, uint16_t value)
23 to[0] = (value) & 0xFF;
24 to[1] = (value >> 8) & 0xFF;
27 void write_wav_header(FILE* out, uint32_t rate, uint64_t samples)
29 unsigned char header[44];
30 uint32_t size1;
31 uint32_t size2;
32 size2 = (uint32_t)(samples << 2);
33 size1 = size2 + 36;
34 write_little32(header + 0, RIFF_MAGIC); //Main RIFF header magic
35 write_little32(header + 4, size1); //RIFF payload size.
36 write_little32(header + 8, WAVE_MAGIC); //This is WAVE data.
37 write_little32(header + 12, FMT_MAGIC); //Format data.
38 write_little32(header + 16, 16); //16 bytes of format data
39 write_little16(header + 20, 1); //PCM encoded.
40 write_little16(header + 22, 2); //Stereo
41 write_little32(header + 24, rate); //Sample rate.
42 write_little32(header + 28, rate << 2); //Data rate.
43 write_little16(header + 32, 4); //4 bytes per sample.
44 write_little16(header + 34, 16); //16 bits per sample and channel.
45 write_little32(header + 36, DATA_MAGIC); //Actual data.
46 write_little32(header + 40, size2); //Data size.
47 if(fseek(out, 0, SEEK_SET) < 0 || fwrite(header, 1, 44, out) < 44)
48 throw std::runtime_error("Failed to write WAV header");
51 class output_driver_wav : public output_driver
53 public:
54 output_driver_wav(const std::string& filename)
56 if(filename != "-")
57 out = fopen(filename.c_str(), "wb");
58 else
59 throw std::runtime_error("WAV driver does not support output to stdout");
60 if(!out)
61 throw std::runtime_error("Unable to open output file");
62 write_wav_header(out, 0, 0);
63 set_audio_callback<output_driver_wav>(*this, &output_driver_wav::audio_callback);
66 ~output_driver_wav()
68 write_wav_header(out, rate, samples);
69 fclose(out);
72 void ready()
74 rate = get_audio_settings().get_rate();
75 samples = 0;
78 void audio_callback(short left, short right)
80 uint8_t rawdata[4];
81 rawdata[1] = ((unsigned short)left >> 8) & 0xFF;
82 rawdata[0] = ((unsigned short)left) & 0xFF;
83 rawdata[3] = ((unsigned short)right >> 8) & 0xFF;
84 rawdata[2] = ((unsigned short)right) & 0xFF;
85 if(fwrite(rawdata, 1, 4, out) < 4)
86 throw std::runtime_error("Error writing sample to file");
87 samples++;
90 private:
91 FILE* out;
92 uint32_t rate;
93 uint64_t samples;
96 class output_driver_wav_factory : output_driver_factory
98 public:
99 output_driver_wav_factory()
100 : output_driver_factory("wav")
104 output_driver& make(const std::string& type, const std::string& name, const std::string& parameters)
106 if(parameters != "")
107 throw std::runtime_error("wav output does not take parameters");
108 return *new output_driver_wav(name);
110 } factory;