Skip to content

Commit 147d663

Browse files
committed
Add: Use LibSoxr for high quality sample-rate conversion.
If not present the existing bad quality linear conversion can still be used.
1 parent f5d78f9 commit 147d663

File tree

12 files changed

+169
-1
lines changed

12 files changed

+169
-1
lines changed

.github/workflows/ci-linux.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ jobs:
6363
libogg-dev \
6464
libopus-dev \
6565
libopusfile-dev \
66+
libsoxr-dev \
6667
${{ inputs.libraries }} \
6768
zlib1g-dev \
6869
# EOF

.github/workflows/ci-mingw.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ jobs:
4040
mingw-w64-${{ inputs.arch }}-libogg
4141
mingw-w64-${{ inputs.arch }}-opus
4242
mingw-w64-${{ inputs.arch }}-opusfile
43+
mingw-w64-${{ inputs.arch }}-libsoxr
4344
4445
- name: Install OpenGFX
4546
shell: bash

.github/workflows/codeql.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ jobs:
5757
libopus-dev \
5858
libopusfile-dev \
5959
libsdl2-dev \
60+
libsoxr-dev \
6061
zlib1g-dev \
6162
# EOF
6263

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ if(NOT OPTION_DEDICATED)
156156
endif()
157157
endif()
158158
find_package(OpusFile)
159+
find_package(Soxr)
159160
endif()
160161
if(APPLE)
161162
enable_language(OBJCXX)
@@ -334,6 +335,7 @@ if(NOT OPTION_DEDICATED)
334335
link_package(ICU_i18n)
335336
link_package(ICU_uc)
336337
link_package(OpusFile TARGET OpusFile::opusfile)
338+
link_package(Soxr)
337339

338340
if(SDL2_FOUND AND OPENGL_FOUND AND UNIX)
339341
# SDL2 dynamically loads OpenGL if needed, so do not link to OpenGL when

cmake/FindSoxr.cmake

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
include(FindPackageHandleStandardArgs)
2+
3+
find_library(Soxr_LIBRARY
4+
NAMES soxr
5+
)
6+
7+
set(Soxr_COMPILE_OPTIONS "" CACHE STRING "Extra compile options of soxr")
8+
9+
set(Soxr_LINK_LIBRARIES "" CACHE STRING "Extra link libraries of soxr")
10+
11+
set(Soxr_LINK_FLAGS "" CACHE STRING "Extra link flags of soxr")
12+
13+
find_path(Soxr_INCLUDE_PATH
14+
NAMES soxr.h
15+
)
16+
17+
find_package_handle_standard_args(Soxr
18+
REQUIRED_VARS Soxr_LIBRARY Soxr_INCLUDE_PATH
19+
)
20+
21+
if(Soxr_FOUND)
22+
if(NOT TARGET Soxr::soxr)
23+
add_library(Soxr::soxr UNKNOWN IMPORTED)
24+
set_target_properties(Soxr::soxr PROPERTIES
25+
IMPORTED_LOCATION "${Soxr_LIBRARY}"
26+
INTERFACE_INCLUDE_DIRECTORIES "${Soxr_INCLUDE_PATH}"
27+
INTERFACE_COMPILE_OPTIONS "${Soxr_COMPILE_OPTIONS}"
28+
INTERFACE_LINK_LIBRARIES "${Soxr_LINK_LIBRARIES}"
29+
INTERFACE_LINK_FLAGS "${Soxr_LINK_FLAGS}"
30+
)
31+
endif()
32+
endif()

src/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ add_files(
4444
CONDITION OpusFile_FOUND
4545
)
4646

47+
add_files(
48+
soundresampler_soxr.cpp
49+
CONDITION Soxr_FOUND
50+
)
51+
4752
add_files(
4853
aircraft.h
4954
aircraft_cmd.cpp

src/mixer.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,11 @@ bool MxInitialize(uint rate)
248248
return true;
249249
}
250250

251+
uint32_t MxGetRate()
252+
{
253+
return _play_rate;
254+
}
255+
251256
void SetEffectVolume(uint8_t volume)
252257
{
253258
_effect_vol.store(volume, std::memory_order_relaxed);

src/mixer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ struct MixerChannel;
2121
typedef void(*MxStreamCallback)(int16_t *buffer, size_t samples);
2222

2323
bool MxInitialize(uint rate);
24+
uint32_t MxGetRate();
2425
void MxMixSamples(void *buffer, uint samples);
2526

2627
MixerChannel *MxAllocateChannel();

src/soundloader.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,14 @@
1313
#include "soundloader_type.h"
1414
#include "soundloader_func.h"
1515
#include "string_func.h"
16+
#include "mixer.h"
1617
#include "newgrf_sound.h"
1718
#include "random_access_file_type.h"
1819

1920
#include "safeguards.h"
2021

2122
template class ProviderManager<SoundLoader>;
23+
template class ProviderManager<SoundResampler>;
2224

2325
bool LoadSoundData(SoundEntry &sound, bool new_format, SoundID sound_id, const std::string &name)
2426
{
@@ -43,6 +45,14 @@ bool LoadSoundData(SoundEntry &sound, bool new_format, SoundID sound_id, const s
4345

4446
Debug(grf, 2, "LoadSound [{}]: channels {}, sample rate {}, bits per sample {}, length {}", sound.file->GetSimplifiedFilename(), sound.channels, sound.rate, sound.bits_per_sample, sound.file_size);
4547

48+
/* Convert sample rate if needed. */
49+
const uint32_t play_rate = MxGetRate();
50+
if (play_rate != sound.rate) {
51+
for (auto &resampler : ProviderManager<SoundResampler>::GetProviders()) {
52+
if (resampler->Resample(sound, play_rate)) break;
53+
}
54+
}
55+
4656
/* Mixer always requires an extra sample at the end for the built-in linear resampler. */
4757
sound.data->resize(sound.data->size() + sound.channels * sound.bits_per_sample / 8);
4858
sound.data->shrink_to_fit();

src/soundloader_type.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* 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/>.
66
*/
77

8-
/** @file soundloader_type.h Types related to sound loaders. */
8+
/** @file soundloader_type.h Types related to sound loaders and resamplers. */
99

1010
#ifndef SOUNDLOADER_TYPE_H
1111
#define SOUNDLOADER_TYPE_H
@@ -29,4 +29,20 @@ class SoundLoader : public PriorityBaseProvider<SoundLoader> {
2929
virtual bool Load(SoundEntry &sound, bool new_format, std::vector<uint8_t> &data) = 0;
3030
};
3131

32+
/** Base interface for a SoundResampler implementation. */
33+
class SoundResampler : public PriorityBaseProvider<SoundResampler> {
34+
public:
35+
SoundResampler(std::string_view name, std::string_view description, int priority) : PriorityBaseProvider<SoundResampler>(name, description, priority)
36+
{
37+
ProviderManager<SoundResampler>::Register(*this);
38+
}
39+
40+
virtual ~SoundResampler()
41+
{
42+
ProviderManager<SoundResampler>::Unregister(*this);
43+
}
44+
45+
virtual bool Resample(SoundEntry &sound, uint32_t play_rate) = 0;
46+
};
47+
3248
#endif /* SOUNDLOADER_TYPE_H */

0 commit comments

Comments
 (0)