OpenTTD Source 20260815-master-gdf55704e7d
soundresampler_soxr.cpp
Go to the documentation of this file.
1/*
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/>.
6 */
7
9
10#include "stdafx.h"
11#include "core/math_func.hpp"
12#include "debug.h"
13#include "sound_type.h"
14#include "soundresampler_type.h"
15
16#include <soxr.h>
17
18#include "safeguards.h"
19
22public:
24 SoundResampler_Soxr() : SoundResampler("soxr", "SOXR sound resampler", 0) {}
25
32 static void ConvertInt8toInt16(std::span<const std::byte> in, std::span<std::byte> out)
33 {
34 assert(std::size(out) == std::size(in) * 2);
35
36 auto out_it = std::begin(out);
37 for (const std::byte &value : in) {
38 if constexpr (std::endian::native != std::endian::little) {
39 *out_it++ = value;
40 *out_it++ = std::byte{0};
41 } else {
42 *out_it++ = std::byte{0};
43 *out_it++ = value;
44 }
45 }
46 }
47
48 bool Resample(SoundEntry &sound, uint32_t play_rate) const override
49 {
50 /* The sound data to work on. */
51 std::vector<std::byte> &data = *sound.data;
52
53 std::vector<std::byte> tmp;
54 if (sound.bits_per_sample == 16) {
55 /* No conversion necessary so just move from sound data to temporary buffer. */
56 data.swap(tmp);
57 } else {
58 /* SoxR cannot resample 8-bit audio, so convert from 8-bit to 16-bit into temporary buffer. */
59 tmp.resize(std::size(data) * sizeof(int16_t));
60 ConvertInt8toInt16(data, tmp);
61 sound.bits_per_sample = 16;
62 }
63
64 /* Resize buffer ensuring it is correctly aligned. */
65 uint align = sound.channels * sound.bits_per_sample / 8;
66 data.resize(Align(std::size(tmp) * play_rate / sound.rate, align));
67
68 soxr_error_t error = soxr_oneshot(sound.rate, play_rate, sound.channels,
69 std::data(tmp), std::size(tmp) / align, nullptr,
70 std::data(data), std::size(data) / align, nullptr,
71 &this->io, &this->quality, &this->runtime);
72
73 if (error != nullptr) {
74 /* Could not resample, try using the original data as-is without resampling instead. */
75 Debug(misc, 0, "Failed to resample: {}", soxr_strerror(error));
76 data.swap(tmp);
77 } else {
78 sound.rate = play_rate;
79 }
80
81 return true;
82 }
83
84private:
86
87 const soxr_io_spec_t io = soxr_io_spec(SOXR_INT16_I, SOXR_INT16_I);
88 const soxr_quality_spec_t quality = soxr_quality_spec(SOXR_VHQ, 0);
89 const soxr_runtime_spec_t runtime = soxr_runtime_spec(1);
90};
91
Soxr SoundResampler implementation.
const soxr_quality_spec_t quality
Quality settings.
SoundResampler_Soxr()
Create this SoundResample_Soxr instance.
static SoundResampler_Soxr instance
Instance of this SoundResampler.
const soxr_runtime_spec_t runtime
Runtime settings.
static void ConvertInt8toInt16(std::span< const std::byte > in, std::span< std::byte > out)
Convert samples from 8 bits to 16 bits.
bool Resample(SoundEntry &sound, uint32_t play_rate) const override
Resample a loaded sound.
const soxr_io_spec_t io
Input/output settings.
SoundResampler(std::string_view name, std::string_view description, int priority)
Create the provider.
Functions related to debugging.
#define Debug(category, level, format_string,...)
Output a line of debugging information.
Definition debug.h:37
Integer math functions.
constexpr T Align(const T x, uint n)
Return the smallest multiple of n equal or greater than x.
Definition math_func.hpp:37
A number of safeguards to prevent using unsafe methods.
Types related to sounds.
Types related to sound resamplers.
Definition of base types and functions in a cross-platform compatible way.