2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8 /** @file sound_opus.cpp Loading of opus sounds. */
11 #include "random_access_file_type.h"
12 #include "sound_type.h"
13 #include "soundloader_type.h"
17 #include "safeguards.h"
19 /** Opus sound loader. */
20 class SoundLoader_Opus
: public SoundLoader
{
22 SoundLoader_Opus() : SoundLoader("opus", "Opus sound loader", 10) {}
24 static constexpr uint16_t OPUS_SAMPLE_RATE
= 48000; ///< OpusFile always decodes at 48kHz.
25 static constexpr uint8_t OPUS_SAMPLE_BITS
= 16; ///< OpusFile op_read() uses 16 bits per sample.
27 /* For good results, you will need at least 57 bytes (for a pure Opus-only stream). */
28 static constexpr size_t MIN_OPUS_FILE_SIZE
= 57U;
30 /* It is recommended that this be large enough for at least 120 ms of data at 48 kHz per channel (5760 values per channel).
31 * Smaller buffers will simply return less data, possibly consuming more memory to buffer the data internally. */
32 static constexpr size_t DECODE_BUFFER_SAMPLES
= 5760 * 2;
33 static constexpr size_t DECODE_BUFFER_BYTES
= DECODE_BUFFER_SAMPLES
* sizeof(opus_int16
);
35 bool Load(SoundEntry
&sound
, bool new_format
, std::vector
<uint8_t> &data
) override
37 if (!new_format
) return false;
39 /* At least 57 bytes are needed for an Opus-only file. */
40 if (sound
.file_size
< MIN_OPUS_FILE_SIZE
) return false;
42 /* Test if data is an Ogg Opus stream, as identified by the initial file header. */
43 auto filepos
= sound
.file
->GetPos();
44 std::vector
<uint8_t> tmp(MIN_OPUS_FILE_SIZE
);
45 sound
.file
->ReadBlock(tmp
.data(), tmp
.size());
46 if (op_test(nullptr, tmp
.data(), tmp
.size()) != 0) return false;
48 /* Read the whole file into memory. */
49 tmp
.resize(sound
.file_size
);
50 sound
.file
->SeekTo(filepos
, SEEK_SET
);
51 sound
.file
->ReadBlock(tmp
.data(), tmp
.size());
54 auto of
= std::unique_ptr
<OggOpusFile
, OggOpusFileDeleter
>(op_open_memory(tmp
.data(), tmp
.size(), &error
));
55 if (error
!= 0) return false;
59 data
.resize(datapos
+ DECODE_BUFFER_BYTES
);
62 int read
= op_read(of
.get(), reinterpret_cast<opus_int16
*>(&data
[datapos
]), DECODE_BUFFER_BYTES
, &link_index
);
65 if (read
< 0 || op_channel_count(of
.get(), link_index
) != 1) {
66 /* Error reading, or incorrect channel count. */
71 datapos
+= read
* sizeof(opus_int16
);
74 /* OpusFile always decodes at 48kHz. */
76 sound
.bits_per_sample
= OPUS_SAMPLE_BITS
;
77 sound
.rate
= OPUS_SAMPLE_RATE
;
79 /* We resized by DECODE_BUFFER_BYTES just before finally reading zero bytes, undo this. */
80 data
.resize(data
.size() - DECODE_BUFFER_BYTES
);
86 /** Helper class to RAII release an OggOpusFile. */
87 struct OggOpusFileDeleter
{
88 void operator()(OggOpusFile
*of
)
90 if (of
!= nullptr) op_free(of
);
95 static SoundLoader_Opus s_sound_loader_opus
;