-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathopus2raw.cpp
More file actions
160 lines (137 loc) · 4.77 KB
/
Copy pathopus2raw.cpp
File metadata and controls
160 lines (137 loc) · 4.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#include <iostream>
#include <boost/exception/diagnostic_information.hpp>
#include <boost/program_options.hpp>
namespace po = boost::program_options;
// Do not include dnload.h, since this is not a minifiable binary.
// Instead, just rename the relevant calls.
#define dnload_free free
#define dnload_ogg_page_serialno ogg_page_serialno
#define dnload_ogg_stream_init ogg_stream_init
#define dnload_ogg_stream_packetout ogg_stream_packetout
#define dnload_ogg_stream_pagein ogg_stream_pagein
#define dnload_ogg_sync_buffer ogg_sync_buffer
#define dnload_ogg_sync_init ogg_sync_init
#define dnload_ogg_sync_pageout ogg_sync_pageout
#define dnload_ogg_sync_wrote ogg_sync_wrote
#define dnload_realloc realloc
// Disable some features.
#define VGL_DISABLE_OPUS
#include "vgl_filesystem.hpp"
#include "vgl_opus.hpp"
using vgl::optional;
using vgl::path;
using vgl::runtime_error;
using vgl::string;
using vgl::string_view;
using vgl::to_string;
using vgl::vector;
static const char *usage = ""
"Usage: opus2raw <options> [input-file]\n"
"Reads an ogg opus file and writes a raw opus file without the ogg container.\n"
"Decoder opus settings are printed to stdout as opposed to being saved.\n";
/// Read ogg opus file and store raw opus file.
///
/// \param infile Input file.
/// \param outfile Output file.
void opus2raw(const path& infile, const path& outfile)
{
optional<vector<uint8_t>> input_data = infile.readToVector();
if(!input_data)
{
VGL_THROW_RUNTIME_ERROR("opus2raw(): failure reading '" + to_string(infile) + "'");
}
if(input_data->empty())
{
VGL_THROW_RUNTIME_ERROR("opus2raw(): input file '" + to_string(infile) + "' contains no data");
}
vgl::detail::OggStream stream(input_data->data(), input_data->size());
ogg_packet packet;
stream.readPacket(packet);
// First packet - read header.
if((packet.bytes < 19) ||
(string_view(reinterpret_cast<const char*>(packet.packet), 8) != vgl::string_view("OpusHead")) ||
(packet.packet[8] != 1))
{
VGL_THROW_RUNTIME_ERROR("opus2raw(): first packet in '" + to_string(infile) + "' is not an opus header");
}
unsigned channels = static_cast<unsigned>(packet.packet[9]);
unsigned skip_bytes = static_cast<unsigned>(packet.packet[10]) + (static_cast<unsigned>(packet.packet[11]) << 8);
// Discard comment packet.
stream.readPacket(packet);
// Read until done.
vector<uint8_t> output_data;
while(stream.readPacket(packet))
{
uint16_t bytes = static_cast<int16_t>(packet.bytes);
uint8_t bh = static_cast<uint8_t>(bytes >> 8);
uint8_t bl = static_cast<uint8_t>(bytes & 0xFF);
output_data.push_back(bl);
output_data.push_back(bh);
for(uint16_t ii = 0; (ii < bytes); ++ii)
{
output_data.push_back(packet.packet[ii]);
}
}
outfile.write(output_data);
std::cout << " Channels: " << channels << "\n Skip bytes: " << skip_bytes << std::endl;
}
/// Main function.
///
/// \param argc Argument count.
/// \param argv Arguments.
/// \return Program return code.
int main(int argc, char **argv)
{
try
{
optional<path> input_file;
optional<path> output_file;
po::options_description desc("Options");
desc.add_options()
("help,h", "Print help text.")
("input-file", po::value<std::string>(), "Input file.")
("output-file,o", po::value<std::string>(), "Name of output file to write.\n(default: generated from input file name)");
if(argc > 0)
{
po::positional_options_description pdesc;
pdesc.add("input-file", -1);
po::variables_map vmap;
po::store(po::command_line_parser(argc, argv).options(desc).positional(pdesc).run(), vmap);
po::notify(vmap);
if(vmap.count("help"))
{
std::cout << usage << desc << std::endl;
return 0;
}
if(vmap.count("input-file"))
{
input_file = path(vmap["input-file"].as<std::string>().c_str());
}
if(vmap.count("output-file"))
{
output_file = path(vmap["output-file"].as<std::string>().c_str());
}
}
else
{
std::cout << usage << desc << std::endl;
return 0;
}
if(!input_file)
{
VGL_THROW_RUNTIME_ERROR("input file not specified");
}
if(!output_file)
{
output_file = *input_file;
output_file->replaceExtension(".opus.raw");
}
opus2raw(*input_file, *output_file);
}
catch(const boost::exception &err)
{
std::cerr << boost::diagnostic_information(err);
return 1;
}
return 0;
}