Babel  1
The voip software that only works on your local network
Loading...
Searching...
No Matches
Manager.cpp
Go to the documentation of this file.
1/*
2** EPITECH PROJECT, 2024
3** record_compress_decompress_play
4** File description:
5** Compressor.cpp
6*/
7
14
16{
17 PRETTY_INFO << "Initialising the Opus manager" << std::endl;
18 PRETTY_INFO << "Initialising the encoder..." << std::endl;
19 _encoder = opus_encoder_create(
20 static_cast<opus_int32>(48000),
21 1,
22 OPUS_APPLICATION_AUDIO,
23 &_error
24 );
25 if (_error != OPUS_OK) {
26 PRETTY_ERROR << "Opus encoder initialization error: " << opus_strerror(_error) << std::endl;
27 handleOpusError(_error, "Opus encoder initialization");
28 }
29 PRETTY_SUCCESS << "Encoder initialised" << std::endl;
30
31 PRETTY_INFO << "Initialising the decoder..." << std::endl;
32
33 _decoder = opus_decoder_create(
34 static_cast<opus_int32>(48000),
35 1,
36 &_error
37 );
38 if (_error != OPUS_OK) {
39 handleOpusError(_error, "Opus decoder initialization");
40 }
41 PRETTY_SUCCESS << "Decoder initialised" << std::endl;
42 PRETTY_SUCCESS << "Opus manager initialised" << std::endl;
43}
44
46{
47 PRETTY_INFO << "Initialising the Opus manager" << std::endl;
48 PRETTY_INFO << "Checking arguments" << std::endl;
49 if (sample.sampleRate != 24000 && sample.sampleRate != 48000) {
50 throw std::invalid_argument("Invalid sample rate, supported values are 24000 and 48000.");
51 }
52
53 if (sample.numChannelsPlayback != 1 && sample.numChannelsPlayback != 2) {
54 throw std::invalid_argument("Invalid number of channels, supported values are 1 (mono) or 2 (stereo).");
55 }
56 PRETTY_SUCCESS << "Arguments are valid" << std::endl;
57
58 PRETTY_INFO << "Initialising the encoder..." << std::endl;
59 _encoder = opus_encoder_create(
60 static_cast<opus_int32>(sample.sampleRate),
61 static_cast<int>(sample.numChannelsPlayback),
62 OPUS_APPLICATION_AUDIO,
63 &_error
64 );
65 if (_error != OPUS_OK) {
66 handleOpusError(_error, "Opus encoder initialization");
67 }
68 PRETTY_SUCCESS << "Encoder initialised" << std::endl;
69
70 PRETTY_INFO << "Initialising the decoder..." << std::endl;
71
72 _decoder = opus_decoder_create(
73 static_cast<opus_int32>(sample.sampleRate),
74 static_cast<int>(sample.numChannelsPlayback),
75 &_error
76 );
77 if (_error != OPUS_OK) {
78 handleOpusError(_error, "Opus decoder initialization");
79 }
80 PRETTY_SUCCESS << "Decoder initialised" << std::endl;
81 PRETTY_SUCCESS << "Opus manager initialised" << std::endl;
82}
83
85{
86 PRETTY_INFO << "Destroying the Opus manager" << std::endl;
87 if (_encoder) {
88 PRETTY_INFO << "Destroying the encoder..." << std::endl;
89 opus_encoder_destroy(_encoder);
90 PRETTY_SUCCESS << "Encoder destroyed" << std::endl;
91 }
92 PRETTY_INFO << "Checking if the decoder exists..." << std::endl;
93 if (_decoder) {
94 PRETTY_INFO << "Destroying the decoder..." << std::endl;
95 opus_decoder_destroy(_decoder);
96 PRETTY_SUCCESS << "Decoder destroyed" << std::endl;
97 }
98 PRETTY_SUCCESS << "Opus manager destroyed" << std::endl;
99}
100
106void Compressor::Manager::setMaxPacketSize(const unsigned int maxPacketSize)
107{
108 PRETTY_INFO << "Setting the maximum packet size to " << maxPacketSize << std::endl;
109 _maxPacketSize = maxPacketSize;
110 PRETTY_SUCCESS << "Maximum packet size set" << std::endl;
111}
112
119{
120 PRETTY_INFO << "Fetching the maximum packet size" << std::endl;
121 return _maxPacketSize;
122}
123
128{
129 PRETTY_INFO << "Checking materials before compressing..." << std::endl;
130 if (!_rawStreamSet) {
131 PRETTY_ERROR << "Uncompressed stream not set" << std::endl;
132 std::cerr << "Uncompressed stream not set" << std::endl;
133 throw std::runtime_error("Uncompressed stream not set");
134 }
135
136 PRETTY_DEBUG << "Checking if the encoder exists..." << std::endl;
137 if (!_encoder) {
138 PRETTY_ERROR << "Encoder not set" << std::endl;
139 std::cerr << "Encoder not set" << std::endl;
140 throw std::runtime_error("Encoder not set");
141 }
142
143 PRETTY_INFO << "Locking the mutex..." << std::endl;
144 std::lock_guard<std::mutex> lock(_mutex);
145
146 PRETTY_INFO << "Initialising the compressed stream..." << std::endl;
147 const int maxPacketSize = _maxPacketSize;
148 int frameSize = _uncompressedStream.framesPerBuffer * (_uncompressedStream.numChannelsRecording == 2 ? 2 : 1);
149
150 PRETTY_DEBUG << "Check if the uncompressed stream has enough data" << std::endl;
151 if (_uncompressedStream.sample.size() < frameSize * _uncompressedStream.numChannelsRecording) {
152 PRETTY_ERROR << "Uncompressed stream size is insufficient for encoding" << std::endl;
153 std::cerr << "Uncompressed stream size is insufficient for encoding" << std::endl;
154 return;
155 }
156 PRETTY_DEBUG << "Max packet size: " << maxPacketSize << ", frameSize: " << frameSize << std::endl;
157 _compressedStream.data.resize(maxPacketSize);
158
159 PRETTY_DEBUG << "Compressed stream size: " << _compressedStream.data.size() << std::endl;
160 PRETTY_DEBUG << "Uncompressed sample data size: " << _uncompressedStream.sample.size() << std::endl;
161
162 PRETTY_INFO << "Compressing the stream..." << std::endl;
163 int compressedSize = opus_encode_float(_encoder, _uncompressedStream.sample.data(), frameSize, _compressedStream.data.data(), maxPacketSize);
164 PRETTY_DEBUG << "Compressed size: " << compressedSize << std::endl;
165 if (compressedSize < 0) {
166 PRETTY_ERROR << "Opus encode error: " << opus_strerror(compressedSize) << std::endl;
167 std::cerr << "Opus encode error: " << opus_strerror(compressedSize) << std::endl;
168 return;
169 }
170
171 PRETTY_INFO << "Setting the compressed stream size..." << std::endl;
172 _compressedStream.size = compressedSize;
173 _compressedStream.data.resize(compressedSize);
174 _hasBeenCompressed = true;
175 PRETTY_SUCCESS << "Stream compressed" << std::endl;
176}
177
182{
183 PRETTY_INFO << "Decompressing the stream..." << std::endl;
184 if (!_hasBeenCompressed) {
185 PRETTY_ERROR << "Compressed stream not set" << std::endl;
186 std::cerr << "Compressed stream not set" << std::endl;
187 throw std::runtime_error("Compressed stream not set");
188 }
189
190 PRETTY_INFO << "Locking the mutex..." << std::endl;
191 std::lock_guard<std::mutex> lock(_mutex);
192
193 PRETTY_INFO << "Initialising the uncompressed stream..." << std::endl;
194 int frameSize = _uncompressedStream.framesPerBuffer;
195 _uncompressedStream.sample.resize(frameSize * _uncompressedStream.numChannelsPlayback);
196
197 PRETTY_INFO << "Decompressing the stream..." << std::endl;
198 int decodedSamples = opus_decode_float(_decoder, _compressedStream.data.data(), _compressedStream.size, _uncompressedStream.sample.data(), frameSize, 0);
199 if (decodedSamples < 0) {
200 PRETTY_ERROR << "Opus decode error: " << opus_strerror(decodedSamples) << std::endl;
201 std::cerr << "Opus decode error: " << opus_strerror(decodedSamples) << std::endl;
202 return;
203 }
204
205 _rawStreamSet = true;
206 PRETTY_SUCCESS << "Stream has been decompressed" << std::endl;
207}
208
215{
216 PRETTY_INFO << "Fetching the compressed stream" << std::endl;
217 if (!_hasBeenCompressed) {
218 PRETTY_ERROR << "Compressed stream not set" << std::endl;
219 std::cerr << "Compressed stream not set" << std::endl;
220 throw std::runtime_error("Compressed stream not set");
221 }
222 PRETTY_SUCCESS << "Compressed stream fetched" << std::endl;
223 return _compressedStream;
224}
225
232{
233 PRETTY_INFO << "Setting the compressed stream" << std::endl;
234 std::lock_guard<std::mutex> lock(_mutex);
235 _compressedStream = data;
236 _hasBeenCompressed = true;
237 PRETTY_SUCCESS << "Compressed stream set" << std::endl;
238}
239
246{
247 PRETTY_INFO << "Fetching the uncompressed stream" << std::endl;
248 if (!_rawStreamSet) {
249 PRETTY_ERROR << "Uncompressed stream not set" << std::endl;
250 std::cerr << "Uncompressed stream not set" << std::endl;
251 throw std::runtime_error("Uncompressed stream not set");
252 }
253 PRETTY_SUCCESS << "Uncompressed stream fetched" << std::endl;
254 return _uncompressedStream;
255}
256
263{
264 PRETTY_INFO << "Setting the uncompressed stream" << std::endl;
265 PRETTY_INFO << "Checking arguments" << std::endl;
266 if (data.sampleRate != 24000 && data.sampleRate != 48000) {
267 throw std::invalid_argument("Invalid sample rate, supported values are 24000 and 48000.");
268 }
269
270 if (data.numChannelsPlayback != 1 && data.numChannelsPlayback != 2) {
271 throw std::invalid_argument("Invalid number of channels, supported values are 1 (mono) or 2 (stereo).");
272 }
273 PRETTY_SUCCESS << "Arguments are valid" << std::endl;
274 std::lock_guard<std::mutex> lock(_mutex);
275 _uncompressedStream = data;
276 _rawStreamSet = true;
277 PRETTY_SUCCESS << "Uncompressed stream set" << std::endl;
278}
279
286void Compressor::Manager::encode(std::vector<float> &sound, std::vector<unsigned char> &output)
287{
288 PRETTY_INFO << "Encoding the sound..." << std::endl;
289 int nbBytes = 0;
290 const int framesPerBuffer = 480;
291 std::array<unsigned char, 4000> cbits;
292
293 if (sound.empty()) {
294 PRETTY_WARNING << "The sound is empty, skipping" << std::endl;
295 return;
296 }
297 nbBytes = opus_encode_float(_encoder, sound.data(), framesPerBuffer, cbits.data(), 4000);
298 if (nbBytes <= 1) {
299 PRETTY_ERROR << "Failed to encode float" << std::endl;
300 handleOpusError(nbBytes, "failed to encode float ");
301 }
302 for (int i = 0; i != nbBytes; i++) {
303 output.push_back(cbits[i]);
304 }
305 PRETTY_SUCCESS << "Sound encoded" << std::endl;
306}
307
308// void Compressor::Manager::encode(std::vector<float> &sound, std::vector<unsigned char> &output)
309// {
310// PRETTY_INFO << "Encoding the sound..." << std::endl;
311// int nbBytes = 0;
312// const int cbits_length = 4000;
313// std::array<unsigned char, cbits_length> cbits;
314// std::vector<float> croppedSound;
315
316
317// if (sound.empty()) {
318// PRETTY_WARNING << "Sound is empty" << std::endl;
319// return;
320// }
321// if (sound.size() > cbits_length) {
322// PRETTY_WARNING << "Sound is too big, size is: " << sound.size() << ", reducing" << std::endl;
323// for (int i = 0; i < cbits_length - 1; i++) {
324// croppedSound.push_back(sound[i]);
325// }
326// } else {
327// croppedSound = sound;
328// }
329// PRETTY_INFO << "Sound size is " << croppedSound.size() << std::endl;
330// nbBytes = opus_encode_float(_encoder, croppedSound.data(), 256, cbits.data(), cbits_length);
331// if (nbBytes <= 1) {
332// PRETTY_ERROR << "Failed to encode float" << std::endl;
333// handleOpusError(nbBytes, "failed to encode float ");
334// }
335// for (int i = 0; i != nbBytes; i++) {
336// PRETTY_DEBUG << "Encoded sound: " << cbits[i] << std::endl;
337// output.push_back(cbits[i]);
338// }
339// PRETTY_INFO << "Sound encoded" << std::endl;
340// }
341
348void Compressor::Manager::decode(std::vector<unsigned char> &sound, std::vector<float> &output)
349{
350 PRETTY_INFO << "Decoding the sound..." << std::endl;
351 int nbBytes = 0;
352 const int cbit_length = 4000;
353 std::array<float, cbit_length> cbits;
354
355 if (sound.empty()) {
356 PRETTY_WARNING << "Sound is empty" << std::endl;
357 return;
358 }
359 nbBytes = opus_decode_float(_decoder, sound.data(), sound.size(), cbits.data(), cbit_length, 0);
360 if (nbBytes <= 1) {
361 PRETTY_ERROR << "Failed to decode float" << std::endl;
362 handleOpusError(nbBytes, "failed to decode float ");
363 }
364 for (int i = 0; i != nbBytes; i++) {
365 PRETTY_DEBUG << "Decoded sound: " << cbits[i] << std::endl;
366 output.push_back(cbits[i]);
367 }
368 PRETTY_INFO << "Sound decoded" << std::endl;
369}
370
377void Compressor::Manager::handleOpusError(int errorCode, const std::string &context) const
378{
379 PRETTY_INFO << "Handling Opus error..." << std::endl;
380 if (errorCode != OPUS_OK) {
381 throw std::runtime_error(context + " failed: " + opus_strerror(errorCode));
382 }
383}
#define PRETTY_ERROR
Error log with details and colour.
#define PRETTY_DEBUG
Debug log with details and colour.
#define PRETTY_INFO
Info log with details and colour.
#define PRETTY_WARNING
Warning log with details and colour.
#define PRETTY_SUCCESS
Success log with details and colour.
This file contains the definition of the Manager class responsible for managing audio compression and...
void decompress()
Decompress the compressed audio stream.
Definition Manager.cpp:181
const Audio::Sample & getUncompressedStream() const
Get the uncompressed audio stream.
Definition Manager.cpp:245
void decode(std::vector< unsigned char > &sound, std::vector< float > &output)
Decode compressed audio data into raw format.
Definition Manager.cpp:348
~Manager()
Destructor.
Definition Manager.cpp:84
void compress()
Compress the uncompressed audio stream.
Definition Manager.cpp:127
void setUncompressedStream(const Audio::Sample &data)
Set the uncompressed audio stream.
Definition Manager.cpp:262
void setMaxPacketSize(const unsigned int maxPacketSize)
Set the maximum packet size for compression.
Definition Manager.cpp:106
void encode(std::vector< float > &sound, std::vector< unsigned char > &output)
Encode raw audio data into compressed format.
Definition Manager.cpp:286
void setCompressedStream(const Compressor::Packet &data)
Set the compressed audio stream.
Definition Manager.cpp:231
const unsigned int getMaxPacketSize() const
Get the maximum packet size for compression.
Definition Manager.cpp:118
const Compressor::Packet & getCompressedStream() const
Get the compressed audio stream.
Definition Manager.cpp:214
Manager()
Default constructor.
Definition Manager.cpp:15
Structure representing an audio sample.
Definition Sample.hpp:22
unsigned int numChannelsPlayback
Number of playback channels.
Definition Sample.hpp:28
unsigned int sampleRate
Sample rate of the audio in Hz.
Definition Sample.hpp:26
Structure representing a packet of compressed audio data.
Definition Packet.hpp:22