mirror of
https://github.com/enduro2d/enduro2d.git
synced 2025-12-16 14:08:59 +07:00
Merge pull request #80 from enduro2d/feature/audio_resource
Feature/audio resource
This commit is contained in:
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -11,3 +11,4 @@
|
|||||||
*.dylib filter=lfs diff=lfs merge=lfs -text
|
*.dylib filter=lfs diff=lfs merge=lfs -text
|
||||||
*.pvr filter=lfs diff=lfs merge=lfs -text
|
*.pvr filter=lfs diff=lfs merge=lfs -text
|
||||||
*.dds filter=lfs diff=lfs merge=lfs -text
|
*.dds filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.ogg filter=lfs diff=lfs merge=lfs -text
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "assets/prefab_asset.hpp"
|
#include "assets/prefab_asset.hpp"
|
||||||
#include "assets/shader_asset.hpp"
|
#include "assets/shader_asset.hpp"
|
||||||
#include "assets/shape_asset.hpp"
|
#include "assets/shape_asset.hpp"
|
||||||
|
#include "assets/sound_asset.hpp"
|
||||||
#include "assets/sprite_asset.hpp"
|
#include "assets/sprite_asset.hpp"
|
||||||
#include "assets/text_asset.hpp"
|
#include "assets/text_asset.hpp"
|
||||||
#include "assets/texture_asset.hpp"
|
#include "assets/texture_asset.hpp"
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ namespace e2d
|
|||||||
class prefab_asset;
|
class prefab_asset;
|
||||||
class shader_asset;
|
class shader_asset;
|
||||||
class shape_asset;
|
class shape_asset;
|
||||||
|
class sound_asset;
|
||||||
class sprite_asset;
|
class sprite_asset;
|
||||||
class text_asset;
|
class text_asset;
|
||||||
class texture_asset;
|
class texture_asset;
|
||||||
|
|||||||
20
headers/enduro2d/high/assets/sound_asset.hpp
Normal file
20
headers/enduro2d/high/assets/sound_asset.hpp
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* This file is part of the "Enduro2D"
|
||||||
|
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||||
|
* Copyright (C) 2018-2019, by Matvey Cherevko (blackmatov@gmail.com)
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../_high.hpp"
|
||||||
|
|
||||||
|
#include "../library.hpp"
|
||||||
|
|
||||||
|
namespace e2d
|
||||||
|
{
|
||||||
|
class sound_asset final : public content_asset<sound_asset, sound_stream_ptr> {
|
||||||
|
public:
|
||||||
|
static const char* type_name() noexcept { return "sound_asset"; }
|
||||||
|
static load_async_result load_async(const library& library, str_view address);
|
||||||
|
};
|
||||||
|
}
|
||||||
136
sources/enduro2d/high/assets/sound_asset.cpp
Normal file
136
sources/enduro2d/high/assets/sound_asset.cpp
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* This file is part of the "Enduro2D"
|
||||||
|
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||||
|
* Copyright (C) 2018-2019, by Matvey Cherevko (blackmatov@gmail.com)
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include <enduro2d/high/assets/sound_asset.hpp>
|
||||||
|
|
||||||
|
#include <enduro2d/high/assets/json_asset.hpp>
|
||||||
|
#include <enduro2d/high/assets/binary_asset.hpp>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
using namespace e2d;
|
||||||
|
|
||||||
|
class sound_asset_loading_exception final : public asset_loading_exception {
|
||||||
|
const char* what() const noexcept final {
|
||||||
|
return "sound asset loading exception";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const char* sound_asset_schema_source = R"json({
|
||||||
|
"type" : "object",
|
||||||
|
"required" : [ "sound", "streaming" ],
|
||||||
|
"additionalProperties" : false,
|
||||||
|
"properties" : {
|
||||||
|
"sound" : { "$ref": "#/common_definitions/address" },
|
||||||
|
"streaming" : { "type" : "boolean" }
|
||||||
|
}
|
||||||
|
})json";
|
||||||
|
|
||||||
|
const rapidjson::SchemaDocument& sound_asset_schema() {
|
||||||
|
static std::mutex mutex;
|
||||||
|
static std::unique_ptr<rapidjson::SchemaDocument> schema;
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> guard(mutex);
|
||||||
|
if ( !schema ) {
|
||||||
|
rapidjson::Document doc;
|
||||||
|
if ( doc.Parse(sound_asset_schema_source).HasParseError() ) {
|
||||||
|
the<debug>().error("ASSETS: Failed to parse sound asset schema");
|
||||||
|
throw sound_asset_loading_exception();
|
||||||
|
}
|
||||||
|
json_utils::add_common_schema_definitions(doc);
|
||||||
|
schema = std::make_unique<rapidjson::SchemaDocument>(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
return *schema;
|
||||||
|
}
|
||||||
|
|
||||||
|
stdex::promise<sound_stream_ptr> parse_sound(
|
||||||
|
const library& library,
|
||||||
|
str_view parent_address,
|
||||||
|
const rapidjson::Value& root)
|
||||||
|
{
|
||||||
|
E2D_ASSERT(root.HasMember("sound") && root["sound"].IsString());
|
||||||
|
const str sound_address = path::combine(parent_address, root["sound"].GetString());
|
||||||
|
|
||||||
|
E2D_ASSERT(root.HasMember("streaming") && root["streaming"].IsBool());
|
||||||
|
const bool streaming = root["streaming"].GetBool();
|
||||||
|
|
||||||
|
if ( streaming ) {
|
||||||
|
return the<deferrer>().do_in_worker_thread([
|
||||||
|
sound_url = library.root() / sound_address
|
||||||
|
](){
|
||||||
|
auto sound_file_stream = the<vfs>().read(sound_url);
|
||||||
|
if ( !sound_file_stream ) {
|
||||||
|
throw sound_asset_loading_exception();
|
||||||
|
}
|
||||||
|
sound_stream_ptr content = the<audio>().create_stream(
|
||||||
|
std::move(sound_file_stream));
|
||||||
|
if ( !content ) {
|
||||||
|
throw sound_asset_loading_exception();
|
||||||
|
}
|
||||||
|
return content;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return library.load_asset_async<binary_asset>(sound_address)
|
||||||
|
.then([](const binary_asset::load_result& sound_data){
|
||||||
|
return the<deferrer>().do_in_worker_thread([sound_data](){
|
||||||
|
sound_stream_ptr content = the<audio>().preload_stream(
|
||||||
|
sound_data->content());
|
||||||
|
if ( !content ) {
|
||||||
|
throw sound_asset_loading_exception();
|
||||||
|
}
|
||||||
|
return content;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace e2d
|
||||||
|
{
|
||||||
|
sound_asset::load_async_result sound_asset::load_async(
|
||||||
|
const library& library, str_view address)
|
||||||
|
{
|
||||||
|
return library.load_asset_async<json_asset>(address)
|
||||||
|
.then([
|
||||||
|
&library,
|
||||||
|
address = str(address),
|
||||||
|
parent_address = path::parent_path(address)
|
||||||
|
](const json_asset::load_result& sound_data){
|
||||||
|
return the<deferrer>().do_in_worker_thread([address, sound_data](){
|
||||||
|
const rapidjson::Document& doc = *sound_data->content();
|
||||||
|
rapidjson::SchemaValidator validator(sound_asset_schema());
|
||||||
|
|
||||||
|
if ( doc.Accept(validator) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rapidjson::StringBuffer sb;
|
||||||
|
if ( validator.GetInvalidDocumentPointer().StringifyUriFragment(sb) ) {
|
||||||
|
the<debug>().error("ASSET: Failed to validate asset json:\n"
|
||||||
|
"--> Address: %0\n"
|
||||||
|
"--> Invalid schema keyword: %1\n"
|
||||||
|
"--> Invalid document pointer: %2",
|
||||||
|
address,
|
||||||
|
validator.GetInvalidSchemaKeyword(),
|
||||||
|
sb.GetString());
|
||||||
|
} else {
|
||||||
|
the<debug>().error("ASSET: Failed to validate asset json");
|
||||||
|
}
|
||||||
|
|
||||||
|
throw sound_asset_loading_exception();
|
||||||
|
})
|
||||||
|
.then([&library, parent_address, sound_data](){
|
||||||
|
return parse_sound(
|
||||||
|
library, parent_address, *sound_data->content());
|
||||||
|
})
|
||||||
|
.then([](auto&& content){
|
||||||
|
return sound_asset::create(
|
||||||
|
std::forward<decltype(content)>(content));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
4
untests/bin/library/music.json
Normal file
4
untests/bin/library/music.json
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"sound" : "sound.ogg",
|
||||||
|
"streaming" : true
|
||||||
|
}
|
||||||
4
untests/bin/library/sound.json
Normal file
4
untests/bin/library/sound.json
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"sound" : "sound.ogg",
|
||||||
|
"streaming" : false
|
||||||
|
}
|
||||||
3
untests/bin/library/sound.ogg
Executable file
3
untests/bin/library/sound.ogg
Executable file
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:910a0ad63ca51685b541e285550c5cc13ff04be2b48a77314d0bf138b044e3d6
|
||||||
|
size 15891
|
||||||
@@ -15,6 +15,7 @@ namespace
|
|||||||
modules::initialize<starter>(0, nullptr,
|
modules::initialize<starter>(0, nullptr,
|
||||||
starter::parameters(
|
starter::parameters(
|
||||||
engine::parameters("asset_untests", "enduro2d")
|
engine::parameters("asset_untests", "enduro2d")
|
||||||
|
.without_audio(true)
|
||||||
.without_graphics(true)));
|
.without_graphics(true)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ namespace
|
|||||||
modules::initialize<starter>(0, nullptr,
|
modules::initialize<starter>(0, nullptr,
|
||||||
starter::parameters(
|
starter::parameters(
|
||||||
engine::parameters("library_untests", "enduro2d")
|
engine::parameters("library_untests", "enduro2d")
|
||||||
|
.without_audio(true)
|
||||||
.without_graphics(true)));
|
.without_graphics(true)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,6 +156,20 @@ TEST_CASE("library"){
|
|||||||
REQUIRE_FALSE(l.cache().find<image_asset>("image.png"));
|
REQUIRE_FALSE(l.cache().find<image_asset>("image.png"));
|
||||||
REQUIRE_FALSE(l.cache().find<binary_asset>("image.png"));
|
REQUIRE_FALSE(l.cache().find<binary_asset>("image.png"));
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
if ( modules::is_initialized<audio>() ) {
|
||||||
|
auto sound_res = l.load_asset<sound_asset>("sound.json");
|
||||||
|
REQUIRE(sound_res);
|
||||||
|
REQUIRE(sound_res->content());
|
||||||
|
|
||||||
|
auto music_res = l.load_asset<sound_asset>("music.json");
|
||||||
|
REQUIRE(music_res);
|
||||||
|
REQUIRE(music_res->content());
|
||||||
|
|
||||||
|
auto fake_sound_res = l.load_asset<sound_asset>("fake_sound.json");
|
||||||
|
REQUIRE_FALSE(fake_sound_res);
|
||||||
|
}
|
||||||
|
}
|
||||||
{
|
{
|
||||||
if ( modules::is_initialized<render>() ) {
|
if ( modules::is_initialized<render>() ) {
|
||||||
auto shader_res = l.load_asset<shader_asset>("shader.json");
|
auto shader_res = l.load_asset<shader_asset>("shader.json");
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ namespace
|
|||||||
modules::initialize<starter>(0, nullptr,
|
modules::initialize<starter>(0, nullptr,
|
||||||
starter::parameters(
|
starter::parameters(
|
||||||
engine::parameters("world_untests", "enduro2d")
|
engine::parameters("world_untests", "enduro2d")
|
||||||
|
.without_audio(true)
|
||||||
.without_graphics(true)));
|
.without_graphics(true)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ TEST_CASE("starter"){
|
|||||||
modules::initialize<starter>(0, nullptr,
|
modules::initialize<starter>(0, nullptr,
|
||||||
starter::parameters(
|
starter::parameters(
|
||||||
engine::parameters("starter_untests", "enduro2d")
|
engine::parameters("starter_untests", "enduro2d")
|
||||||
|
.without_audio(true)
|
||||||
.without_graphics(true)));
|
.without_graphics(true)));
|
||||||
modules::shutdown<starter>();
|
modules::shutdown<starter>();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ namespace
|
|||||||
modules::initialize<starter>(0, nullptr,
|
modules::initialize<starter>(0, nullptr,
|
||||||
starter::parameters(
|
starter::parameters(
|
||||||
engine::parameters("world_untests", "enduro2d")
|
engine::parameters("world_untests", "enduro2d")
|
||||||
|
.without_audio(true)
|
||||||
.without_graphics(true)));
|
.without_graphics(true)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user