mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-03-06 14:27:16 +00:00
Add: Support sound effects in Ogg Opus format.
This commit is contained in:
parent
8b00661b22
commit
560ee2442d
3
.github/workflows/ci-linux.yml
vendored
3
.github/workflows/ci-linux.yml
vendored
@ -60,6 +60,9 @@ jobs:
|
||||
libicu-dev \
|
||||
liblzma-dev \
|
||||
liblzo2-dev \
|
||||
libogg-dev \
|
||||
libopus-dev \
|
||||
libopusfile-dev \
|
||||
${{ inputs.libraries }} \
|
||||
zlib1g-dev \
|
||||
# EOF
|
||||
|
3
.github/workflows/ci-mingw.yml
vendored
3
.github/workflows/ci-mingw.yml
vendored
@ -37,6 +37,9 @@ jobs:
|
||||
mingw-w64-${{ inputs.arch }}-libpng
|
||||
mingw-w64-${{ inputs.arch }}-lld
|
||||
mingw-w64-${{ inputs.arch }}-ninja
|
||||
mingw-w64-${{ inputs.arch }}-ogg
|
||||
mingw-w64-${{ inputs.arch }}-opus
|
||||
mingw-w64-${{ inputs.arch }}-opusfile
|
||||
|
||||
- name: Install OpenGFX
|
||||
shell: bash
|
||||
|
2
.github/workflows/codeql.yml
vendored
2
.github/workflows/codeql.yml
vendored
@ -54,6 +54,8 @@ jobs:
|
||||
libicu-dev \
|
||||
liblzma-dev \
|
||||
liblzo2-dev \
|
||||
libopus-dev \
|
||||
libopusfile-dev \
|
||||
libsdl2-dev \
|
||||
zlib1g-dev \
|
||||
# EOF
|
||||
|
@ -155,6 +155,7 @@ if(NOT OPTION_DEDICATED)
|
||||
find_package(ICU OPTIONAL_COMPONENTS i18n uc)
|
||||
endif()
|
||||
endif()
|
||||
find_package(OpusFile)
|
||||
endif()
|
||||
if(APPLE)
|
||||
enable_language(OBJCXX)
|
||||
@ -332,6 +333,7 @@ if(NOT OPTION_DEDICATED)
|
||||
link_package(Harfbuzz TARGET harfbuzz::harfbuzz)
|
||||
link_package(ICU_i18n)
|
||||
link_package(ICU_uc)
|
||||
link_package(OpusFile TARGET OpusFile::opusfile)
|
||||
|
||||
if(SDL2_FOUND AND OPENGL_FOUND AND UNIX)
|
||||
# SDL2 dynamically loads OpenGL if needed, so do not link to OpenGL when
|
||||
|
37
cmake/FindOgg.cmake
Normal file
37
cmake/FindOgg.cmake
Normal file
@ -0,0 +1,37 @@
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
find_library(Ogg_LIBRARY
|
||||
NAMES ogg
|
||||
)
|
||||
|
||||
set(Ogg_COMPILE_OPTIONS "" CACHE STRING "Extra compile options of ogg")
|
||||
|
||||
set(Ogg_LINK_LIBRARIES "" CACHE STRING "Extra link libraries of ogg")
|
||||
|
||||
set(Ogg_LINK_FLAGS "" CACHE STRING "Extra link flags of ogg")
|
||||
|
||||
find_path(Ogg_INCLUDE_PATH
|
||||
NAMES ogg.h
|
||||
PATH_SUFFIXES ogg
|
||||
)
|
||||
|
||||
find_package_handle_standard_args(Ogg
|
||||
REQUIRED_VARS Ogg_LIBRARY Ogg_INCLUDE_PATH
|
||||
)
|
||||
|
||||
if (Ogg_FOUND)
|
||||
set(Ogg_dirs ${Ogg_INCLUDE_PATH})
|
||||
if(EXISTS "${Ogg_INCLUDE_PATH}/ogg")
|
||||
list(APPEND Ogg_dirs "${Ogg_INCLUDE_PATH}/ogg")
|
||||
endif()
|
||||
if (NOT TARGET Ogg::ogg)
|
||||
add_library(Ogg::ogg UNKNOWN IMPORTED)
|
||||
set_target_properties(Ogg::ogg PROPERTIES
|
||||
IMPORTED_LOCATION "${Ogg_LIBRARY}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${Ogg_dirs}"
|
||||
INTERFACE_COMPILE_OPTIONS "${Ogg_COMPILE_OPTIONS}"
|
||||
INTERFACE_LINK_LIBRARIES "${Ogg_LINK_LIBRARIES}"
|
||||
INTERFACE_LINK_FLAGS "${Ogg_LINK_FLAGS}"
|
||||
)
|
||||
endif()
|
||||
endif()
|
37
cmake/FindOpus.cmake
Normal file
37
cmake/FindOpus.cmake
Normal file
@ -0,0 +1,37 @@
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
find_library(Opus_LIBRARY
|
||||
NAMES opus
|
||||
)
|
||||
|
||||
set(Opus_COMPILE_OPTIONS "" CACHE STRING "Extra compile options of opus")
|
||||
|
||||
set(Opus_LINK_LIBRARIES "" CACHE STRING "Extra link libraries of opus")
|
||||
|
||||
set(Opus_LINK_FLAGS "" CACHE STRING "Extra link flags of opus")
|
||||
|
||||
find_path(Opus_INCLUDE_PATH
|
||||
NAMES opus.h
|
||||
PATH_SUFFIXES opus
|
||||
)
|
||||
|
||||
find_package_handle_standard_args(Opus
|
||||
REQUIRED_VARS Opus_LIBRARY Opus_INCLUDE_PATH
|
||||
)
|
||||
|
||||
if (Opus_FOUND)
|
||||
set(Opus_dirs ${Opus_INCLUDE_PATH})
|
||||
if(EXISTS "${Opus_INCLUDE_PATH}/opus")
|
||||
list(APPEND Opus_dirs "${Opus_INCLUDE_PATH}/opus")
|
||||
endif()
|
||||
if (NOT TARGET Opus::opus)
|
||||
add_library(Opus::opus UNKNOWN IMPORTED)
|
||||
set_target_properties(Opus::opus PROPERTIES
|
||||
IMPORTED_LOCATION "${Opus_LIBRARY}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${Opus_dirs}"
|
||||
INTERFACE_COMPILE_OPTIONS "${Opus_COMPILE_OPTIONS}"
|
||||
INTERFACE_LINK_LIBRARIES "${Opus_LINK_LIBRARIES}"
|
||||
INTERFACE_LINK_FLAGS "${Opus_LINK_FLAGS}"
|
||||
)
|
||||
endif()
|
||||
endif()
|
40
cmake/FindOpusFile.cmake
Normal file
40
cmake/FindOpusFile.cmake
Normal file
@ -0,0 +1,40 @@
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
find_library(OpusFile_LIBRARY
|
||||
NAMES opusfile
|
||||
)
|
||||
|
||||
set(OpusFile_COMPILE_OPTIONS "" CACHE STRING "Extra compile options of opusfile")
|
||||
|
||||
set(OpusFile_LINK_LIBRARIES "" CACHE STRING "Extra link libraries of opusfile")
|
||||
|
||||
set(OpusFile_LINK_FLAGS "" CACHE STRING "Extra link flags of opusfile")
|
||||
|
||||
find_path(OpusFile_INCLUDE_PATH
|
||||
NAMES opusfile.h
|
||||
PATH_SUFFIXES opus
|
||||
)
|
||||
|
||||
find_package_handle_standard_args(OpusFile
|
||||
REQUIRED_VARS OpusFile_LIBRARY OpusFile_INCLUDE_PATH
|
||||
)
|
||||
|
||||
find_package(Ogg)
|
||||
find_package(Opus)
|
||||
|
||||
if (OpusFile_FOUND)
|
||||
set(OpusFile_dirs ${OpusFile_INCLUDE_PATH})
|
||||
if(EXISTS "${OpusFile_INCLUDE_PATH}/opus")
|
||||
list(APPEND OpusFile_dirs "${OpusFile_INCLUDE_PATH}/opus")
|
||||
endif()
|
||||
if (NOT TARGET OpusFile::opusfile)
|
||||
add_library(OpusFile::opusfile UNKNOWN IMPORTED)
|
||||
set_target_properties(OpusFile::opusfile PROPERTIES
|
||||
IMPORTED_LOCATION "${OpusFile_LIBRARY}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${OpusFile_dirs}"
|
||||
INTERFACE_COMPILE_OPTIONS "${OpusFile_COMPILE_OPTIONS}"
|
||||
INTERFACE_LINK_LIBRARIES "Ogg::ogg;Opus::opus;${OpusFile_LINK_LIBRARIES}"
|
||||
INTERFACE_LINK_FLAGS "${OpusFile_LINK_FLAGS}"
|
||||
)
|
||||
endif()
|
||||
endif()
|
@ -39,6 +39,11 @@ add_files(
|
||||
CONDITION ICU_i18n_FOUND AND HARFBUZZ_FOUND
|
||||
)
|
||||
|
||||
add_files(
|
||||
soundloader_opus.cpp
|
||||
CONDITION OpusFile_FOUND
|
||||
)
|
||||
|
||||
add_files(
|
||||
aircraft.h
|
||||
aircraft_cmd.cpp
|
||||
|
95
src/soundloader_opus.cpp
Normal file
95
src/soundloader_opus.cpp
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* 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.
|
||||
* 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.
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/** @file sound_opus.cpp Loading of opus sounds. */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "random_access_file_type.h"
|
||||
#include "sound_type.h"
|
||||
#include "soundloader_type.h"
|
||||
|
||||
#include <opusfile.h>
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
/** Opus sound loader. */
|
||||
class SoundLoader_Opus : public SoundLoader {
|
||||
public:
|
||||
SoundLoader_Opus() : SoundLoader("opus", "Opus sound loader", 10) {}
|
||||
|
||||
static constexpr uint16_t OPUS_SAMPLE_RATE = 48000; ///< OpusFile always decodes at 48kHz.
|
||||
static constexpr uint8_t OPUS_SAMPLE_BITS = 16; ///< OpusFile op_read() uses 16 bits per sample.
|
||||
|
||||
/* For good results, you will need at least 57 bytes (for a pure Opus-only stream). */
|
||||
static constexpr size_t MIN_OPUS_FILE_SIZE = 57U;
|
||||
|
||||
/* It is recommended that this be large enough for at least 120 ms of data at 48 kHz per channel (5760 values per channel).
|
||||
* Smaller buffers will simply return less data, possibly consuming more memory to buffer the data internally. */
|
||||
static constexpr size_t DECODE_BUFFER_SAMPLES = 5760 * 2;
|
||||
static constexpr size_t DECODE_BUFFER_BYTES = DECODE_BUFFER_SAMPLES * sizeof(opus_int16);
|
||||
|
||||
bool Load(SoundEntry &sound, bool new_format, std::vector<uint8_t> &data) override
|
||||
{
|
||||
if (!new_format) return false;
|
||||
|
||||
/* At least 57 bytes are needed for an Opus-only file. */
|
||||
if (sound.file_size < MIN_OPUS_FILE_SIZE) return false;
|
||||
|
||||
/* Test if data is an Ogg Opus stream, as identified by the initial file header. */
|
||||
auto filepos = sound.file->GetPos();
|
||||
std::vector<uint8_t> tmp(MIN_OPUS_FILE_SIZE);
|
||||
sound.file->ReadBlock(tmp.data(), tmp.size());
|
||||
if (op_test(nullptr, tmp.data(), tmp.size()) != 0) return false;
|
||||
|
||||
/* Read the whole file into memory. */
|
||||
tmp.resize(sound.file_size);
|
||||
sound.file->SeekTo(filepos, SEEK_SET);
|
||||
sound.file->ReadBlock(tmp.data(), tmp.size());
|
||||
|
||||
int error = 0;
|
||||
auto of = std::unique_ptr<OggOpusFile, OggOpusFileDeleter>(op_open_memory(tmp.data(), tmp.size(), &error));
|
||||
if (error != 0) return false;
|
||||
|
||||
size_t datapos = 0;
|
||||
for (;;) {
|
||||
data.resize(datapos + DECODE_BUFFER_BYTES);
|
||||
|
||||
int link_index;
|
||||
int read = op_read(of.get(), reinterpret_cast<opus_int16 *>(&data[datapos]), DECODE_BUFFER_BYTES, &link_index);
|
||||
if (read == 0) break;
|
||||
|
||||
if (read < 0 || op_channel_count(of.get(), link_index) != 1) {
|
||||
/* Error reading, or incorrect channel count. */
|
||||
data.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
datapos += read * sizeof(opus_int16);
|
||||
}
|
||||
|
||||
/* OpusFile always decodes at 48kHz. */
|
||||
sound.channels = 1;
|
||||
sound.bits_per_sample = OPUS_SAMPLE_BITS;
|
||||
sound.rate = OPUS_SAMPLE_RATE;
|
||||
|
||||
/* We resized by DECODE_BUFFER_BYTES just before finally reading zero bytes, undo this. */
|
||||
data.resize(data.size() - DECODE_BUFFER_BYTES);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
/** Helper class to RAII release an OggOpusFile. */
|
||||
struct OggOpusFileDeleter {
|
||||
void operator()(OggOpusFile *of)
|
||||
{
|
||||
if (of != nullptr) op_free(of);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
static SoundLoader_Opus s_sound_loader_opus;
|
@ -42,6 +42,9 @@
|
||||
{
|
||||
"name": "lzo"
|
||||
},
|
||||
{
|
||||
"name": "opusfile"
|
||||
},
|
||||
{
|
||||
"name": "sdl2",
|
||||
"platform": "linux"
|
||||
|
Loading…
Reference in New Issue
Block a user