forked from OpenEnroth/OpenEnroth
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added Library/Snd, using it in AudioPlayer
- Loading branch information
1 parent
3cb7573
commit 0b5868c
Showing
11 changed files
with
221 additions
and
106 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
cmake_minimum_required(VERSION 3.24 FATAL_ERROR) | ||
|
||
set(LIBRARY_SND_SOURCES | ||
SndReader.cpp | ||
SndSnapshots.cpp) | ||
|
||
set(LIBRARY_SND_HEADERS | ||
SndReader.h | ||
SndSnapshots.h) | ||
|
||
add_library(library_snd STATIC ${LIBRARY_SND_SOURCES} ${LIBRARY_SND_HEADERS}) | ||
target_link_libraries(library_snd PUBLIC library_binary library_snapshots library_compression utility) | ||
target_check_style(library_snd) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
#include "SndReader.h" | ||
|
||
#include <algorithm> | ||
#include <utility> | ||
|
||
#include "Library/Compression/Compression.h" | ||
#include "Library/Snapshots/SnapshotSerialization.h" | ||
|
||
#include "Utility/Streams/BlobInputStream.h" | ||
#include "Utility/String.h" | ||
#include "Utility/Exception.h" | ||
|
||
#include "SndSnapshots.h" | ||
|
||
SndReader::SndReader() = default; | ||
|
||
SndReader::SndReader(std::string_view path) { | ||
open(path); | ||
} | ||
|
||
SndReader::~SndReader() = default; | ||
|
||
void SndReader::open(std::string_view path) { | ||
close(); | ||
|
||
Blob blob = Blob::fromFile(path); | ||
BlobInputStream stream(blob); | ||
|
||
std::vector<SndEntry> entries; | ||
deserialize(stream, &entries, tags::via<SndEntry_MM7>); | ||
|
||
std::unordered_map<std::string, SndEntry> files; | ||
for (const SndEntry &entry : entries) { | ||
std::string name = toLower(entry.name); | ||
if (files.contains(name)) | ||
throw Exception("File '{}' is not a valid SND: contains duplicate entries for '{}'", path, name); | ||
|
||
if (entry.offset + entry.size > blob.size()) | ||
throw Exception("File '{}' is not a valid SND: entry '{}' points outside the SND file", path, entry.name); | ||
|
||
files[name] = std::move(entry); | ||
} | ||
|
||
// All good, this is a valid SND, can update `this`. | ||
_snd = std::move(blob); | ||
_path = path; | ||
_files = std::move(files); | ||
} | ||
|
||
void SndReader::close() { | ||
// Double-closing is OK. | ||
_snd = Blob(); | ||
_path = {}; | ||
_files = {}; | ||
} | ||
|
||
bool SndReader::exists(const std::string &filename) const { | ||
assert(isOpen()); | ||
|
||
return _files.contains(toLower(filename)); | ||
} | ||
|
||
Blob SndReader::read(const std::string &filename) const { | ||
assert(isOpen()); | ||
|
||
const auto pos = _files.find(toLower(filename)); | ||
if (pos == _files.cend()) | ||
throw Exception("Entry '{}' doesn't exist in SND file '{}'", filename, _path); | ||
const SndEntry &entry = pos->second; | ||
|
||
Blob result = _snd.subBlob(entry.offset, entry.size); | ||
if (entry.decompressedSize) | ||
result = zlib::uncompress(result, entry.decompressedSize); | ||
return result; | ||
} | ||
|
||
std::vector<std::string> SndReader::ls() const { | ||
assert(isOpen()); | ||
|
||
std::vector<std::string> result; | ||
for (const auto &[name, _] : _files) | ||
result.push_back(name); | ||
std::sort(result.begin(), result.end()); | ||
return result; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
#pragma once | ||
|
||
#include <string> | ||
#include <string_view> | ||
#include <unordered_map> | ||
#include <vector> | ||
|
||
#include "Utility/Memory/Blob.h" | ||
|
||
struct SndEntry; | ||
|
||
/** | ||
* Reader for Might&Magic SND files. | ||
* | ||
* Note that compression is part of the container format in SND files, unlike in LOD, where it's part of the internal | ||
* lod-specific file formats. Thus, we're not exposing it as part of the interface, and there is no 'SndFormats' | ||
* library. | ||
*/ | ||
class SndReader { | ||
public: | ||
SndReader(); | ||
explicit SndReader(std::string_view path); | ||
~SndReader(); | ||
|
||
/** | ||
* @param path Path to the SND file to open for reading. | ||
* @throw Exception If the SND couldn't be opened - e.g., if the file doesn't exist, | ||
* or if it's not in SND format. | ||
*/ | ||
void open(std::string_view path); | ||
|
||
/** | ||
* Closes this SND reader & frees all associated resources. | ||
*/ | ||
void close(); | ||
|
||
[[nodiscard]] bool isOpen() const { | ||
return !!_snd; | ||
} | ||
|
||
/** | ||
* @param filename Name of the SND file entry. | ||
* @return Whether the file exists inside the SND. The check is case-insensitive. | ||
*/ | ||
[[nodiscard]] bool exists(const std::string &filename) const; | ||
|
||
/** | ||
* @param filename Name of the SND file entry. | ||
* @return Contents of the file inside the SND as a `Blob`. | ||
* @throws Exception If file doesn't exist inside the SND. | ||
*/ | ||
[[nodiscard]] Blob read(const std::string &filename) const; | ||
|
||
/** | ||
* @return List of all files in the SND. | ||
*/ | ||
[[nodiscard]] std::vector<std::string> ls() const; | ||
|
||
private: | ||
Blob _snd; | ||
std::string _path; | ||
std::unordered_map<std::string, SndEntry> _files; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
#include "SndSnapshots.h" | ||
|
||
#include "Library/Snapshots/CommonSnapshots.h" | ||
|
||
void reconstruct(const SndEntry_MM7 &src, SndEntry *dst) { | ||
reconstruct(src.name, &dst->name); | ||
dst->offset = src.offset; | ||
dst->size = src.size; | ||
dst->decompressedSize = src.decompressedSize; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
#pragma once | ||
|
||
#include <cstdint> | ||
#include <array> | ||
#include <string> | ||
|
||
#include "Library/Binary/MemCopySerialization.h" | ||
|
||
// | ||
// Runtime structs. | ||
// | ||
|
||
struct SndEntry { | ||
std::string name; | ||
size_t offset; | ||
size_t size; | ||
size_t decompressedSize; | ||
}; | ||
|
||
|
||
// | ||
// Snapshots. | ||
// | ||
|
||
#pragma pack(push, 1) | ||
|
||
// Note that there is no SndHeader_MM7. Entries are just stored as a serialized vector in the SND file. | ||
|
||
struct SndEntry_MM7 { | ||
std::array<char, 40> name; | ||
uint32_t offset; | ||
uint32_t size; | ||
uint32_t decompressedSize; | ||
}; | ||
static_assert(sizeof(SndEntry_MM7) == 52); | ||
MM_DECLARE_MEMCOPY_SERIALIZABLE(SndEntry_MM7) | ||
|
||
void reconstruct(const SndEntry_MM7 &src, SndEntry *dst); | ||
|
||
#pragma pack(pop) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.