1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-11-22 02:12:45 +01:00

Implement basic tests for audio decoding and playing

This commit is contained in:
Filip Gawin 2018-12-06 22:49:46 +01:00
parent 50c6eedf4f
commit a63b084d31
10 changed files with 86 additions and 38 deletions

View File

@ -84,10 +84,18 @@ find_package_handle_standard_args(FFmpeg
) )
set(FFMPEG_FOUND "${FFmpeg_FOUND}") set(FFMPEG_FOUND "${FFmpeg_FOUND}")
if(FFmpeg_FOUND) find_package(Threads REQUIRED)
add_library(ffmpeg::ffmpeg INTERFACE IMPORTED)
set_property(TARGET ffmpeg::ffmpeg if(FFMPEG_FOUND)
PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${FFMPEG_INCLUDE_DIR}) add_library(ffmpeg INTERFACE)
set_property(TARGET ffmpeg::ffmpeg target_link_libraries(ffmpeg
PROPERTY INTERFACE_LINK_LIBRARIES ${FFMPEG_LIBRARIES}) INTERFACE
${FFMPEG_LIBRARIES}
Threads::Threads
)
target_include_directories(ffmpeg SYSTEM
INTERFACE
"${FFMPEG_INCLUDE_DIR}"
)
add_library(ffmpeg::ffmpeg ALIAS ffmpeg)
endif() endif()

View File

@ -17,7 +17,7 @@ extern "C" {
#include <rw/types.hpp> #include <rw/types.hpp>
Sound& SoundManager::getSoundRef(size_t name) { Sound& SoundManager::getSfxBufferRef(size_t name) {
auto ref = buffers.find(name); auto ref = buffers.find(name);
if (ref != buffers.end()) { if (ref != buffers.end()) {
return ref->second; return ref->second;
@ -27,6 +27,10 @@ Sound& SoundManager::getSoundRef(size_t name) {
return buffers[name]; return buffers[name];
} }
Sound& SoundManager::getSfxSourceRef(size_t name) {
return sfx[name];
}
Sound& SoundManager::getSoundRef(const std::string& name) { Sound& SoundManager::getSoundRef(const std::string& name) {
return sounds[name]; // @todo reloading, how to check is it wav/mp3? return sounds[name]; // @todo reloading, how to check is it wav/mp3?
} }

View File

@ -34,7 +34,8 @@ public:
/// Load selected sfx sound /// Load selected sfx sound
void loadSound(size_t index); void loadSound(size_t index);
Sound& getSoundRef(size_t name); Sound& getSfxBufferRef(size_t name);
Sound& getSfxSourceRef(size_t name);
Sound& getSoundRef(const std::string& name); Sound& getSoundRef(const std::string& name);
size_t createSfxInstance(size_t index); size_t createSfxInstance(size_t index);

View File

@ -273,9 +273,7 @@ bool SoundSource::prepareCodecContextSfx() {
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 37, 100) #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 37, 100)
void SoundSource::decodeFramesLegacy(size_t framesToDecode) { void SoundSource::decodeFramesLegacy(size_t framesToDecode) {
size_t decoded = 0; while ((framesToDecode == 0 || decodedFrames < framesToDecode) &&
while ((framesToDecode == 0 || decoded < framesToDecode) &&
av_read_frame(formatContext, &readingPacket) == 0) { av_read_frame(formatContext, &readingPacket) == 0) {
if (readingPacket.stream_index == audioStream->index) { if (readingPacket.stream_index == audioStream->index) {
AVPacket decodingPacket = readingPacket; AVPacket decodingPacket = readingPacket;
@ -308,7 +306,7 @@ void SoundSource::decodeFramesLegacy(size_t framesToDecode) {
} }
} }
av_free_packet(&readingPacket); av_free_packet(&readingPacket);
++decoded; ++decodedFrames;
} }
} }
#endif #endif
@ -322,9 +320,7 @@ void SoundSource::decodeFramesSfxWrap() {
} }
void SoundSource::decodeFrames(size_t framesToDecode) { void SoundSource::decodeFrames(size_t framesToDecode) {
size_t decoded = 0; while ((framesToDecode == 0 || decodedFrames < framesToDecode) &&
while ((framesToDecode == 0 || decoded < framesToDecode) &&
av_read_frame(formatContext, &readingPacket) == 0) { av_read_frame(formatContext, &readingPacket) == 0) {
if (readingPacket.stream_index == audioStream->index) { if (readingPacket.stream_index == audioStream->index) {
AVPacket decodingPacket = readingPacket; AVPacket decodingPacket = readingPacket;
@ -353,7 +349,7 @@ void SoundSource::decodeFrames(size_t framesToDecode) {
} }
} }
av_packet_unref(&readingPacket); av_packet_unref(&readingPacket);
++decoded; ++decodedFrames;
} }
} }
@ -370,9 +366,7 @@ void SoundSource::decodeAndResampleFrames(const rwfs::path& filePath,
RW_UNUSED(filePath); // it's used by macro RW_UNUSED(filePath); // it's used by macro
AVFrame* resampled = av_frame_alloc(); AVFrame* resampled = av_frame_alloc();
size_t decoded = 0; while ((framesToDecode == 0 || decodedFrames < framesToDecode) &&
while ((framesToDecode == 0 || decoded < framesToDecode) &&
av_read_frame(formatContext, &readingPacket) == 0) { av_read_frame(formatContext, &readingPacket) == 0) {
if (readingPacket.stream_index == audioStream->index) { if (readingPacket.stream_index == audioStream->index) {
int sendPacket = avcodec_send_packet(codecContext, &readingPacket); int sendPacket = avcodec_send_packet(codecContext, &readingPacket);
@ -435,7 +429,7 @@ void SoundSource::decodeAndResampleFrames(const rwfs::path& filePath,
} }
} }
++decoded; ++decodedFrames;
} }
/// Free all data used by the resampled frame. /// Free all data used by the resampled frame.

View File

@ -77,6 +77,8 @@ public:
void loadSfx(LoaderSDT& sdt, std::size_t index, bool asWave = true, void loadSfx(LoaderSDT& sdt, std::size_t index, bool asWave = true,
bool streaming = false); bool streaming = false);
unsigned int decodedFrames = 0u;
private: private:
/// Raw data /// Raw data
std::vector<int16_t> data; std::vector<int16_t> data;

View File

@ -245,7 +245,7 @@ ScriptObjectType<Sound> ScriptArguments::getScriptObject(
unsigned int arg) const { unsigned int arg) const {
auto& param = (*this)[arg]; auto& param = (*this)[arg];
RW_CHECK(param.isLvalue(), "Non lvalue passed as object"); RW_CHECK(param.isLvalue(), "Non lvalue passed as object");
return {param.handleValue(), &getWorld()->sound.getSoundRef(arg)}; return {param.handleValue(), &getWorld()->sound.getSfxBufferRef(arg)};
} }
template <> template <>

View File

@ -4305,7 +4305,7 @@ void opcode_018d(const ScriptArguments& args, ScriptVec3 coord, const ScriptSoun
auto metaData = getSoundInstanceData(sound0); auto metaData = getSoundInstanceData(sound0);
auto bufferName = world->sound.createSfxInstance(metaData->sfx); auto bufferName = world->sound.createSfxInstance(metaData->sfx);
world->sound.playSfx(bufferName, coord, true, metaData->range); world->sound.playSfx(bufferName, coord, true, metaData->range);
sound1 = &world->sound.getSoundRef(bufferName); sound1 = &world->sound.getSfxBufferRef(bufferName);
} }
/** /**

View File

@ -1,6 +1,7 @@
set(TESTS set(TESTS
Animation Animation
Archive Archive
AudioLoading
Buoyancy Buoyancy
Character Character
Chase Chase

View File

@ -0,0 +1,54 @@
#include "test_Globals.hpp"
#include <engine/GameWorld.hpp>
#include <audio/SoundSource.hpp>
BOOST_AUTO_TEST_SUITE(AudioLoadingTests, DATA_TEST_PREDICATE)
// @todo Shfil119 implement
// This test requires assets
BOOST_AUTO_TEST_CASE(testBufferIsPlaying) {
SoundManager manager{Global::get().e};
auto audioPath =
Global::get().e->data->index.findFilePath("audio/A1_a.wav");
manager.loadSound("A1_a", audioPath.string());
auto& sound = manager.getSoundRef("A1_a");
BOOST_REQUIRE(sound.source->decodedFrames > 0);
BOOST_REQUIRE(sound.isPlaying() == false);
sound.play();
BOOST_REQUIRE(sound.isPlaying() == true);
sound.pause();
BOOST_REQUIRE(sound.isPaused() == true);
sound.stop();
BOOST_REQUIRE(sound.isStopped() == true);
}
BOOST_AUTO_TEST_CASE(testDecodingFramesOfMusic) {
SoundManager manager{Global::get().e};
auto audioPath =
Global::get().e->data->index.findFilePath("audio/A1_a.wav");
manager.loadSound("A1_a", audioPath.string());
auto& sound = manager.getSoundRef("A1_a");
BOOST_REQUIRE(sound.source->decodedFrames > 0);
}
BOOST_AUTO_TEST_CASE(testDecodingFramesOfSfx) {
SoundManager manager{Global::get().e};
manager.createSfxInstance(157); // Callahan Bridge fire
auto& sound = manager.getSfxSourceRef(157);
BOOST_REQUIRE(sound.source->decodedFrames > 0);
}
BOOST_AUTO_TEST_SUITE_END()

View File

@ -19,22 +19,6 @@ BOOST_FIXTURE_TEST_CASE(creates_empty_sound, F) {
BOOST_REQUIRE(sound.source == nullptr); BOOST_REQUIRE(sound.source == nullptr);
} }
// @todo Shfil119 implement
// This test requires assets
//BOOST_AUTO_TEST_CASE(testBufferIsPlaying) {
// sound.buffer = std::make_unique<SoundBuffer>();
// BOOST_REQUIRE(sound.isPlaying() == false);
// sound.play();
// BOOST_REQUIRE(sound.isPlaying() == true);
// sound.pause();
// BOOST_REQUIRE(sound.isPaused() == true);
// sound.stop();
// BOOST_REQUIRE(sound.isStopped() == true);
//}
BOOST_FIXTURE_TEST_CASE(sound_sets_openal_source_position, F) { BOOST_FIXTURE_TEST_CASE(sound_sets_openal_source_position, F) {
sound.buffer = std::make_unique<SoundBuffer>(); sound.buffer = std::make_unique<SoundBuffer>();