Skip to content

Commit aea72ad

Browse files
authored
mcpplibs.mwrap.miniaudio 0.11.25: miniaudio-m (miniaudio as C++23 modules) (#613)
* compat.miniaudio 0.11.25: compile at gnu11, so it builds for wasm32-emscripten On wasm32-emscripten miniaudio's Web Audio backend is JavaScript emitted through EM_ASM, and Emscripten refuses EM_ASM in a strict -std=c* mode ("EM_ASM does not work in -std=c* modes, use -std=gnu* modes instead"; miniaudio.h section 2.6: "You cannot use -std=c* compiler flags"). With c_standard = "c11" a consumer's `mcpp build --target wasm32-emscripten` failed to compile miniaudio.c; at gnu11 it builds and runs under node, its enabled backends Web Audio and Custom (upstream does not build the Null backend there: it needs a background thread). Nothing changes elsewhere: upstream's CMake sets no standard, so GCC and Clang compile it in their GNU default dialect on every platform. The same archive and sha256, the same version. * mcpplibs.mwrap.miniaudio 0.11.25: miniaudio-m (miniaudio as C++23 modules) Descriptor pkgs/mwrap/miniaudio.lua (form A, the immutable mwrap-0.11.25 release asset; CN is the gitcode mcpp-res/mwrap-miniaudio mirror with the same bytes), over compat.miniaudio 0.11.25 at gnu11 (the parent change). Consumer tests/mwrap/miniaudio-engine: the engine without a device mixing a sound through a group, a tone encoded as WAV in memory and decoded back sample for sample, a device on the Null backend, the mapped macros, the adapted inline helper, and the side header beside the import. The installed-template check in validate.yml with its deployment contract (the wrapper's LICENSE/NOTICE, miniaudio's README and LICENSE, byte for byte in a relocated bundle), and the plan.
1 parent a1486b2 commit aea72ad

9 files changed

Lines changed: 297 additions & 0 deletions

File tree

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Add mcpplibs.mwrap.miniaudio (miniaudio-m 0.11.25)
2+
3+
## Form
4+
5+
- Third-party upstream [mackron/miniaudio](https://github.com/mackron/miniaudio), release 0.11.25 (2026-03-03), a
6+
choice of MIT No Attribution or the Unlicense (`MIT-0 OR Unlicense`). The tag archive (`b900edcf…0274`) is the one
7+
compat.miniaudio 0.11.25 pins. The parent change (#609) compiles it at gnu11, which Emscripten's `EM_ASM` (the Web
8+
Audio backend) requires; nothing else of the descriptor changes.
9+
- Form A external mwrap module repository [mcpplibs/miniaudio-m](https://github.com/mcpplibs/miniaudio-m), package
10+
`mcpplibs.mwrap.miniaudio`, version 0.11.25 (first release of the identity, no revision suffix), tag series
11+
`mwrap-${version}` (`mwrap-0.11.25` on the merged main commit `4d338e4`); release asset `miniaudio-m-0.11.25.tar.gz`
12+
(`81fb7a80…7eb2`), CN mirror `gitcode.com/mcpp-res/mwrap-miniaudio` with identical bytes.
13+
- Implementation ownership: the library is compat.miniaudio's (upstream's `miniaudio.c`, the header with
14+
`MINIAUDIO_IMPLEMENTATION`, compiled once). The wrapper vendors no upstream code; the module includes the header
15+
without the implementation. It retains upstream's README.md and LICENSE under `upstream/miniaudio/`, with checksums
16+
in `upstream/documents.json`, and deploys them with its own LICENSE/NOTICE (`runtime.deploy`).
17+
18+
## Modules
19+
20+
- `mcpplibs.mwrap.miniaudio`: every type and struct tag (266), enumerator (368) and `MA_API` function (931) of the
21+
API section of `miniaudio.h`, by `export using`, generated from the pinned header, each under the preprocessor
22+
condition the header declares it under (the POSIX thread types, `ma_IMMNotificationClient` under WASAPI, the
23+
`MA_NO_*` sections). miniaudio's enums are typedef'd, so their enumerators have linkage and are exported as they
24+
are. The three `static MA_INLINE` helpers (`ma_get_bytes_per_frame`, `ma_offset_pcm_frames_ptr_f32`,
25+
`ma_offset_pcm_frames_const_ptr_f32`) are adapted in `mcpplibs::mwrap::miniaudio`, each calling upstream's.
26+
- `mcpplibs.mwrap.miniaudio.macros`: 27 value macros as `inline constexpr` of the type of their expansion; the
27+
header's compatibility names (`ma_resource_manager_job*`) as 3 type aliases and 8 constexpr function references.
28+
- Stay macros, in `<mwrap/miniaudio/macros.hpp>` (= `<miniaudio.h>`): 69 — stringification, attributes and storage
29+
classes (`MA_API` …), the token-pasting atomic declarations, the platform tests (`MA_WIN32` …) and the backend tests
30+
(`MA_SUPPORT_*`, `MA_HAS_*`). Not mapped: `NULL` and the include guard.
31+
32+
`tools/check_exports.py` fails when the generated sources are stale, a declaration of any branch is not exported, a
33+
macro is neither mapped nor listed, or a mapping is not checked against the raw header; and on each CI row, from the
34+
compiler's own preprocessing with the module's compile command, when a declaration of that target is not exported
35+
there or a macro defined there is unaccounted for.
36+
37+
## Verification
38+
39+
Wrapper CI (Linux x86_64 GCC 16.1 and LLVM 23.1.3, Linux arm64 GCC 16.1, macOS LLVM, Windows LLVM, and the Web:
40+
wasm32-emscripten with emsdk 6.0.9 through mcpp, tests under node; all required): build, the four test programs (a
41+
device on the Null backend, the engine without a device or threads, WAV encoding into memory, WAV/FLAC/MP3 decoding
42+
from memory and from a file, converters, a filter, the ring buffer, every macro mapping, header mixing), the export
43+
audit, and the audio file tool `examples/miniaudio` (tone, info, convert on WAV/FLAC/MP3; devices and playback on
44+
the default backend: Null on Linux, Core Audio on macOS, WASAPI on Windows). On the Web row the Null backend does not
45+
exist upstream and the Web Audio probe reports `MA_NO_BACKEND` under node (no `AudioContext`); every other test runs.
46+
This index's CI has no wasm32-emscripten row, so the Web is the wrapper's to cover. The templates job scaffolds the
47+
default `tone` template as an installed package and runs it. Until #609 is on this index's main, the wrapper's CI
48+
resolves the compat namespace from that branch (`tools/candidate_index.py`, a no-op once published).
49+
50+
Here, with the CI-pinned mcpp 2026.10.26.1:
51+
52+
- `bash tests/run_members.sh miniaudio-engine`: the real release archive through the candidate index; the engine
53+
mixing a sound through a group, a WAV round trip in memory, the Null device, the macros, the inline adaptation and
54+
the side header beside the import: `test result ok`.
55+
- `python3 tests/mwrap/check_installed_template.py --package mcpplibs.mwrap.miniaudio@0.11.25 --deploy`: the
56+
unmodified template from the real archive, then a relocated self-contained bundle whose `licenses/miniaudio/` holds
57+
the wrapper's LICENSE/NOTICE and miniaudio's README and LICENSE byte for byte.
58+
59+
## Motivation
60+
61+
openmui's audio engine (media.audio) plays, mixes and decodes through miniaudio on every platform it targets,
62+
the Web included.

‎.github/workflows/validate.yml‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1638,6 +1638,11 @@ jobs:
16381638
shell: bash
16391639
run: python3 tests/mwrap/check_installed_template.py --mcpp "$MCPP" --package mcpplibs.mwrap.sheenbidi@3.0.0 --deploy
16401640

1641+
- name: Installed miniaudio wrapper archive, actual default tone template and its relocated notices
1642+
if: contains(format(' {0} ', env.MEMBERS), ' miniaudio-engine ') && matrix.toolchain == 'default'
1643+
shell: bash
1644+
run: python3 tests/mwrap/check_installed_template.py --mcpp "$MCPP" --package mcpplibs.mwrap.miniaudio@0.11.25 --deploy
1645+
16411646
- name: Installed FreeType wrapper archive, actual default banner template and its relocated FTL notices
16421647
if: contains(format(' {0} ', env.MEMBERS), ' freetype-render ') && matrix.toolchain == 'default'
16431648
shell: bash

‎CHANGELOG.md‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@
99

1010
### Added
1111

12+
- **mcpplibs.mwrap.miniaudio 0.11.25(新包)。** miniaudio-m:以 C++23 模块(`import mcpplibs.mwrap.miniaudio;`)使用
13+
compat.miniaudio 0.11.25(MIT-0 或 Unlicense)。导出 `miniaudio.h` API 部分的全部 266 个类型与结构体标签、368 个枚举值与
14+
931 个 `MA_API` 函数(上游全局名不变),每个声明位于头文件声明它的同一预处理条件下;三个 `static MA_INLINE` 辅助函数在
15+
`mcpplibs::mwrap::miniaudio` 中适配;`mcpplibs.mwrap.miniaudio.macros` 把 27 个数值宏映射为常量,并把兼容名字
16+
(`ma_resource_manager_job*`)映射为类型别名与函数引用;属性、字符串化与平台/后端测试宏留在 `<mwrap/miniaudio/macros.hpp>`。
17+
包装仓库的 CI(Linux x86_64 GCC/LLVM、Linux arm64、macOS、Windows,以及 Web:wasm32-emscripten,node 下运行测试)
18+
在每个目标上依编译器自身的预处理审计导出。GLOBAL 为 `mwrap-0.11.25` 发布资产,CN 为 GitCode `mcpp-res/mwrap-miniaudio`
19+
镜像,sha256 一致。新增测试成员 `tests/mwrap/miniaudio-engine` 与已安装模板及其许可文件的部署检查。
1220
- **mcpplibs.mwrap.sheenbidi 3.0.0(新包)。** sheenbidi-m:以 C++23 模块(`import mcpplibs.mwrap.sheenbidi;`)
1321
使用 compat.sheenbidi 3.0.0。导出已安装头文件的全部类型、结构体标签与 51 个 `SB_PUBLIC` 函数(上游全局名不变);
1422
`mcpplibs.mwrap.sheenbidi.macros` 把宏映射为常量与 constexpr 函数,并把无名枚举的 236 个枚举值映射为其 typedef

‎mcpp.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ members = [
2323
"tests/mwrap/concurrentqueue-mpmc",
2424
"tests/mwrap/fribidi-bidi",
2525
"tests/mwrap/sheenbidi-bidi",
26+
"tests/mwrap/miniaudio-engine",
2627
"tests/mwrap/freetype-render",
2728
"tests/mwrap/harfbuzz-shape",
2829
"tests/mwrap/sdl3-headless",

‎pkgs/mwrap/miniaudio.lua‎

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
-- Immutable upstream-aligned mwrap source release (miniaudio-m mwrap-0.11.25);
2+
-- GLOBAL and CN bytes are identical.
3+
--
4+
-- The wrapper is Apache-2.0; the library it links, compat.miniaudio (miniaudio
5+
-- 0.11.25, compiled at gnu11 so that the Web Audio backend builds for
6+
-- wasm32-emscripten), is a choice of MIT No Attribution or the Unlicense, linked
7+
-- statically: the package deploys miniaudio's README and LICENSE beside
8+
-- programs (runtime.deploy). The wrapper's own CI covers Linux, macOS, Windows
9+
-- and the Web (wasm32-emscripten, tests under node).
10+
package = {
11+
spec = "1",
12+
namespace = "mcpplibs.mwrap",
13+
name = "miniaudio",
14+
description = "miniaudio-m: miniaudio (audio playback, capture, WAV/FLAC/MP3 decoding, mixing, the engine) as C++23 modules",
15+
licenses = { "Apache-2.0" },
16+
repo = "https://github.com/mcpplibs/miniaudio-m",
17+
type = "package",
18+
extensions = {
19+
autoupdate = {
20+
tag = "mwrap-${version}",
21+
url = "https://github.com/mcpplibs/miniaudio-m/releases/download/${tag}/miniaudio-m-${version}.tar.gz",
22+
},
23+
},
24+
xpm = {
25+
linux = {
26+
["0.11.25"] = {
27+
url = {
28+
GLOBAL = "https://github.com/mcpplibs/miniaudio-m/releases/download/mwrap-0.11.25/miniaudio-m-0.11.25.tar.gz",
29+
CN = "https://gitcode.com/mcpp-res/mwrap-miniaudio/releases/download/0.11.25/miniaudio-m-0.11.25.tar.gz",
30+
},
31+
sha256 = "81fb7a80252796069581483b5457271b0312f2a5f4b37431e2ced1bac2f97eb2",
32+
},
33+
},
34+
macosx = {
35+
["0.11.25"] = {
36+
url = {
37+
GLOBAL = "https://github.com/mcpplibs/miniaudio-m/releases/download/mwrap-0.11.25/miniaudio-m-0.11.25.tar.gz",
38+
CN = "https://gitcode.com/mcpp-res/mwrap-miniaudio/releases/download/0.11.25/miniaudio-m-0.11.25.tar.gz",
39+
},
40+
sha256 = "81fb7a80252796069581483b5457271b0312f2a5f4b37431e2ced1bac2f97eb2",
41+
},
42+
},
43+
windows = {
44+
["0.11.25"] = {
45+
url = {
46+
GLOBAL = "https://github.com/mcpplibs/miniaudio-m/releases/download/mwrap-0.11.25/miniaudio-m-0.11.25.tar.gz",
47+
CN = "https://gitcode.com/mcpp-res/mwrap-miniaudio/releases/download/0.11.25/miniaudio-m-0.11.25.tar.gz",
48+
},
49+
sha256 = "81fb7a80252796069581483b5457271b0312f2a5f4b37431e2ced1bac2f97eb2",
50+
},
51+
},
52+
},
53+
}

‎tests/mwrap/check_installed_template.py‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,27 @@ def main():
183183
notice = (roots[0] / "NOTICE").read_bytes()
184184
assert b"mcpp-community" in notice and b"Muhammad Tayyab Akram" in notice
185185
print(f"Verified {len(declared)} byte-identical wrapper/SheenBidi license files", flush=True)
186+
elif identity == "mcpplibs.mwrap.miniaudio":
187+
# miniaudio (MIT No Attribution or the Unlicense) is linked
188+
# statically: its LICENSE and README travel with the program
189+
# beside the wrapper's Apache-2.0 LICENSE and NOTICE.
190+
sources = [path for store in (home / "xpkgs", home / "registry/data/xpkgs")
191+
for path in store.glob(f"mcpplibs.mwrap-x-miniaudio/{version}/*/src/miniaudio.cppm")]
192+
assert len(sources) == 1, sources
193+
source = sources[0].parent.parent
194+
declared = tomllib.loads((source / "mcpp.toml").read_text(encoding="utf-8"))["runtime"]["deploy"]
195+
roots = list(relocated.rglob("licenses/miniaudio"))
196+
assert len(roots) == 1, f"Missing miniaudio runtime license tree: {roots}"
197+
for entry in declared:
198+
notice = source / entry["from"]
199+
copied = roots[0].parent.parent / entry["to"] / notice.name
200+
assert copied.is_file() and copied.read_bytes() == notice.read_bytes(), copied
201+
upstream_license = (roots[0] / "upstream/miniaudio/LICENSE").read_bytes()
202+
assert b"MIT No Attribution" in upstream_license and b"unlicense" in upstream_license.lower()
203+
assert b"Apache License" in (roots[0] / "LICENSE").read_bytes()
204+
notice = (roots[0] / "NOTICE").read_bytes()
205+
assert b"mcpp-community" in notice and b"David Reid" in notice
206+
print(f"Verified {len(declared)} byte-identical wrapper/miniaudio license files", flush=True)
186207
elif identity == "mcpplibs.mwrap.freetype":
187208
# FreeType is linked statically under the FreeType License (FTL),
188209
# whose credit the documentation carries: the license selector, the
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[package]
2+
name = "miniaudio-engine"
3+
version = "0.11.25"
4+
description = "Consume the immutable miniaudio wrapper: the engine without a device mixing a sound through a group, a tone encoded as WAV in memory and decoded back, the Null backend's device, the mapped macros, the side header beside the import"
5+
6+
[indices]
7+
# Use the complete candidate built-in index prepared by tests/run_members.sh.
8+
# An explicit empty table overrides the legacy workspace redirect.
9+
10+
[dependencies]
11+
"mcpplibs.mwrap.miniaudio" = "0.11.25"
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
// The miniaudio API through the installed wrapper, without an audio device.
2+
import std;
3+
import mcpplibs.mwrap.miniaudio;
4+
5+
using namespace mcpplibs::mwrap::miniaudio::macros;
6+
7+
namespace {
8+
float peak(std::span<const float> s) {
9+
float p = 0;
10+
for (float v : s) p = std::max(p, std::abs(v));
11+
return p;
12+
}
13+
} // namespace
14+
15+
int main() {
16+
if (std::string_view(ma_version_string()) != MA_VERSION_STRING || MA_VERSION_MINOR != 11) return 1;
17+
18+
// The engine mixes into a caller's buffer when it has no device; its
19+
// resource manager runs without job threads.
20+
ma_resource_manager_config rmConfig = ma_resource_manager_config_init();
21+
rmConfig.flags = MA_RESOURCE_MANAGER_FLAG_NO_THREADING;
22+
rmConfig.jobThreadCount = 0;
23+
ma_resource_manager rm;
24+
if (ma_resource_manager_init(&rmConfig, &rm) != MA_SUCCESS) return 2;
25+
ma_engine_config config = ma_engine_config_init();
26+
config.noDevice = MA_TRUE;
27+
config.channels = 2;
28+
config.sampleRate = 48000;
29+
config.pResourceManager = &rm;
30+
ma_engine engine;
31+
if (ma_engine_init(&config, &engine) != MA_SUCCESS) return 3;
32+
const ma_waveform_config wc = ma_waveform_config_init(ma_format_f32, 2, 48000, ma_waveform_type_square, 0.5, 100);
33+
ma_waveform wave;
34+
ma_waveform_init(&wc, &wave);
35+
ma_sound_group group;
36+
ma_sound_group_init(&engine, 0, nullptr, &group);
37+
ma_sound sound;
38+
if (ma_sound_init_from_data_source(&engine, &wave, MA_SOUND_FLAG_NO_SPATIALIZATION, &group, &sound) != MA_SUCCESS) return 4;
39+
ma_sound_start(&sound);
40+
std::vector<float> mix(2 * 480);
41+
ma_uint64 read = 0;
42+
ma_engine_read_pcm_frames(&engine, mix.data(), 480, &read);
43+
if (read != 480 || std::abs(peak(mix) - 0.5f) > 1e-3f) return 5;
44+
ma_sound_group_set_volume(&group, 0.5f);
45+
ma_engine_read_pcm_frames(&engine, mix.data(), 480, &read);
46+
if (std::abs(peak(mix) - 0.25f) > 1e-3f) return 6;
47+
ma_sound_uninit(&sound);
48+
ma_sound_group_uninit(&group);
49+
ma_waveform_uninit(&wave);
50+
ma_engine_uninit(&engine);
51+
ma_resource_manager_uninit(&rm);
52+
53+
// A tone encoded as WAV in memory and decoded back, sample for sample.
54+
struct Sink {
55+
std::vector<unsigned char> bytes;
56+
std::size_t at = 0;
57+
} sink;
58+
const auto write = [](ma_encoder* e, const void* data, std::size_t n, std::size_t* written) -> ma_result {
59+
auto& s = *static_cast<Sink*>(e->pUserData);
60+
if (s.bytes.size() < s.at + n) s.bytes.resize(s.at + n);
61+
std::memcpy(s.bytes.data() + s.at, data, n);
62+
s.at += n;
63+
*written = n;
64+
return MA_SUCCESS;
65+
};
66+
const auto seek = [](ma_encoder* e, ma_int64 offset, ma_seek_origin origin) -> ma_result {
67+
auto& s = *static_cast<Sink*>(e->pUserData);
68+
s.at = static_cast<std::size_t>((origin == ma_seek_origin_start ? 0 : static_cast<ma_int64>(s.at)) + offset);
69+
return MA_SUCCESS;
70+
};
71+
std::vector<ma_int16> pcm(4410);
72+
const ma_waveform_config tc = ma_waveform_config_init(ma_format_s16, 1, 44100, ma_waveform_type_sine, 0.5, 440);
73+
ma_waveform tone;
74+
ma_waveform_init(&tc, &tone);
75+
ma_waveform_read_pcm_frames(&tone, pcm.data(), pcm.size(), nullptr);
76+
const ma_encoder_config ec = ma_encoder_config_init(ma_encoding_format_wav, ma_format_s16, 1, 44100);
77+
ma_encoder encoder;
78+
if (ma_encoder_init(write, seek, &sink, &ec, &encoder) != MA_SUCCESS) return 7;
79+
ma_encoder_write_pcm_frames(&encoder, pcm.data(), pcm.size(), nullptr);
80+
ma_encoder_uninit(&encoder);
81+
const ma_decoder_config dc = ma_decoder_config_init(ma_format_s16, 0, 0);
82+
ma_decoder decoder;
83+
if (ma_decoder_init_memory(sink.bytes.data(), sink.bytes.size(), &dc, &decoder) != MA_SUCCESS) return 8;
84+
std::vector<ma_int16> back(pcm.size());
85+
ma_decoder_read_pcm_frames(&decoder, back.data(), back.size(), &read);
86+
const ma_uint32 rate = decoder.outputSampleRate;
87+
ma_decoder_uninit(&decoder);
88+
if (read != pcm.size() || back != pcm || rate != 44100) return 9;
89+
90+
// A device on the Null backend runs in real time without hardware.
91+
ma_backend null = ma_backend_null;
92+
ma_context context;
93+
if (ma_context_init(&null, 1, nullptr, &context) != MA_SUCCESS) return 10;
94+
ma_device_config dconfig = ma_device_config_init(ma_device_type_playback);
95+
dconfig.playback.format = ma_format_f32;
96+
dconfig.playback.channels = 2;
97+
dconfig.sampleRate = 48000;
98+
static std::atomic<ma_uint64> frames{0};
99+
dconfig.dataCallback = [](ma_device*, void* out, const void*, ma_uint32 n) {
100+
std::memset(out, 0, n * 2 * sizeof(float));
101+
frames += n;
102+
};
103+
ma_device device;
104+
if (ma_device_init(&context, &dconfig, &device) != MA_SUCCESS || ma_device_start(&device) != MA_SUCCESS) return 11;
105+
for (int i = 0; i < 1000 && frames < 2400; ++i) std::this_thread::sleep_for(std::chrono::milliseconds(5));
106+
ma_device_uninit(&device);
107+
ma_context_uninit(&context);
108+
if (frames < 2400) return 12;
109+
110+
// The adapted inline helper and a constant at compile time.
111+
static_assert(MA_MAX_CHANNELS == 254 && MA_ENGINE_MAX_LISTENERS == 4);
112+
return mcpplibs::mwrap::miniaudio::ma_get_bytes_per_frame(ma_format_s16, 2) == 4 ? 0 : 13;
113+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// The side header from the installed package, beside the import: the raw
2+
// header's macros with the module's entities.
3+
#include <mwrap/miniaudio/macros.hpp>
4+
5+
import std;
6+
import mcpplibs.mwrap.miniaudio;
7+
8+
extern "C" {
9+
MA_API int mwrap_miniaudio_consumer(int value);
10+
}
11+
int mwrap_miniaudio_consumer(int value) { return value * 2; }
12+
13+
int main() {
14+
static_assert(std::is_same_v<decltype(::MA_SUCCESS), ma_result>);
15+
#if !defined(MA_HAS_NULL) || !defined(MA_SUPPORT_CUSTOM)
16+
return 1;
17+
#endif
18+
if (&::ma_engine_init != &ma_engine_init) return 2;
19+
if (ma_is_backend_enabled(ma_backend_null) != MA_TRUE) return 3;
20+
if (std::string_view(MA_XSTRINGIFY(MA_VERSION_REVISION)) != "25") return 4;
21+
if (::ma_get_bytes_per_frame(ma_format_f32, 2) != mcpplibs::mwrap::miniaudio::ma_get_bytes_per_frame(ma_format_f32, 2)) return 5;
22+
return mwrap_miniaudio_consumer(21) == 42 ? 0 : 6;
23+
}

0 commit comments

Comments
 (0)