audio: run-time mixing and reverberation, with on-screen UI
This commit is contained in:
parent
0dbe1a3c7a
commit
76b3edcf1b
24
Makefile
24
Makefile
@ -7,7 +7,7 @@ OBJARCH = elf64-x86-64
|
|||||||
|
|
||||||
UNAME := $(shell uname -s)
|
UNAME := $(shell uname -s)
|
||||||
|
|
||||||
OPT += -O3
|
OPT += -O0
|
||||||
OPT += -march=core-avx2
|
OPT += -march=core-avx2
|
||||||
|
|
||||||
DEBUG = -g
|
DEBUG = -g
|
||||||
@ -17,12 +17,13 @@ CXXSTD = -std=gnu++20
|
|||||||
CFLAGS += -Wall -Werror
|
CFLAGS += -Wall -Werror
|
||||||
CFLAGS += -Wfatal-errors
|
CFLAGS += -Wfatal-errors
|
||||||
CFLAGS += -Wno-error=unused-variable
|
CFLAGS += -Wno-error=unused-variable
|
||||||
#CFLAGS += -Wno-error=unused-but-set-variable
|
CFLAGS += -Wno-error=unused-but-set-variable
|
||||||
CFLAGS += -Wno-format-security
|
CFLAGS += -Wno-format-security
|
||||||
CFLAGS += -Wno-format
|
CFLAGS += -Wno-format
|
||||||
CFLAGS += -Wno-error=unused-function
|
CFLAGS += -Wno-error=unused-function
|
||||||
CFLAGS += -Wno-error=array-bounds
|
CFLAGS += -Wno-error=array-bounds
|
||||||
CFLAGS += -Wno-unknown-pragmas
|
CFLAGS += -Wno-unknown-pragmas
|
||||||
|
CFLAGS += -Wno-vla-cxx-extension
|
||||||
CFLAGS += -fno-strict-aliasing
|
CFLAGS += -fno-strict-aliasing
|
||||||
CFLAGS += -I./include
|
CFLAGS += -I./include
|
||||||
CFLAGS += -I./data
|
CFLAGS += -I./data
|
||||||
@ -35,13 +36,14 @@ CFLAGS += -fpic
|
|||||||
CFLAGS += -ffunction-sections
|
CFLAGS += -ffunction-sections
|
||||||
CFLAGS += -fdata-sections
|
CFLAGS += -fdata-sections
|
||||||
|
|
||||||
#FLAGS += -fstack-protector -fstack-protector-all -fno-omit-frame-pointer -fsanitize=address
|
FLAGS += -fstack-protector -fstack-protector-all -fno-omit-frame-pointer -fsanitize=address
|
||||||
|
CXXFLAGS += -fno-exceptions -fno-non-call-exceptions -fno-rtti -fno-threadsafe-statics
|
||||||
|
|
||||||
LDFLAGS += -lm
|
LDFLAGS += -lm
|
||||||
#LDFLAGS += -Wl,--gc-sections
|
#LDFLAGS += -Wl,--gc-sections
|
||||||
#-Wl,--print-gc-sections
|
#-Wl,--print-gc-sections
|
||||||
ifeq ($(UNAME),Linux)
|
ifeq ($(UNAME),Linux)
|
||||||
LDFLAGS += -Wl,-z noexecstack
|
#LDFLAGS += -Wl,-z noexecstack
|
||||||
endif
|
endif
|
||||||
ifeq ($(UNAME),Darwin)
|
ifeq ($(UNAME),Darwin)
|
||||||
LDFLAGS += -framework Foundation -framework Cocoa -framework IOKit -framework AVFoundation -framework CoreVideo -framework CoreAudio -framework CoreMedia -framework CoreHaptics -framework AudioToolbox -framework GameController -framework ForceFeedback -framework Carbon -framework Metal -framework QuartzCore -framework UniformTypeIdentifiers
|
LDFLAGS += -framework Foundation -framework Cocoa -framework IOKit -framework AVFoundation -framework CoreVideo -framework CoreAudio -framework CoreMedia -framework CoreHaptics -framework AudioToolbox -framework GameController -framework ForceFeedback -framework Carbon -framework Metal -framework QuartzCore -framework UniformTypeIdentifiers
|
||||||
@ -67,8 +69,10 @@ OBJS = \
|
|||||||
src/pack.o \
|
src/pack.o \
|
||||||
src/dds/validate.o \
|
src/dds/validate.o \
|
||||||
src/vulkan_helper.o \
|
src/vulkan_helper.o \
|
||||||
|
src/vulkan_state.o \
|
||||||
src/tga/tga.o \
|
src/tga/tga.o \
|
||||||
src/font/outline.o \
|
src/font/outline.o \
|
||||||
|
src/font/bitmap/vulkan.o \
|
||||||
src/renpy/vulkan.o \
|
src/renpy/vulkan.o \
|
||||||
src/renpy/composite/vulkan.o \
|
src/renpy/composite/vulkan.o \
|
||||||
src/renpy/script.o \
|
src/renpy/script.o \
|
||||||
@ -77,7 +81,10 @@ OBJS = \
|
|||||||
src/audio.o \
|
src/audio.o \
|
||||||
src/poem/birdsong.o \
|
src/poem/birdsong.o \
|
||||||
src/poem/eleanorthehero.o \
|
src/poem/eleanorthehero.o \
|
||||||
src/poem/kiristella.o
|
src/poem/kiristella.o \
|
||||||
|
src/ui/vulkan.o \
|
||||||
|
src/ui/widget.o \
|
||||||
|
src/ui.o
|
||||||
|
|
||||||
ZLIB = ../zlib-1.3.2
|
ZLIB = ../zlib-1.3.2
|
||||||
CFLAGS += -I$(ZLIB)
|
CFLAGS += -I$(ZLIB)
|
||||||
@ -107,11 +114,14 @@ endif
|
|||||||
|
|
||||||
all: main
|
all: main
|
||||||
|
|
||||||
|
CC = clang
|
||||||
|
CXX = clang++
|
||||||
|
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
$(CC) $(ARCH) $(CSTD) $(CFLAGS) $(FLAGS) $(OPT) $(DEBUG) -c $< -o $@
|
$(CC) $(ARCH) $(CSTD) $(CFLAGS) $(FLAGS) $(OPT) $(DEBUG) -c $< -o $@
|
||||||
|
|
||||||
%.o: %.cpp
|
%.o: %.cpp
|
||||||
$(CXX) $(ARCH) $(CXXSTD) $(CFLAGS) $(FLAGS) $(OPT) $(DEBUG) -c $< -o $@
|
$(CXX) $(ARCH) $(CXXSTD) $(CFLAGS) $(CXXFLAGS) $(FLAGS) $(OPT) $(DEBUG) -c $< -o $@
|
||||||
|
|
||||||
%.o: %.s
|
%.o: %.s
|
||||||
$(AS) $< -o $@
|
$(AS) $< -o $@
|
||||||
@ -132,7 +142,7 @@ all: main
|
|||||||
# ./tools/opus_encode $< $@
|
# ./tools/opus_encode $< $@
|
||||||
|
|
||||||
main: $(OBJS) $(LIBS)
|
main: $(OBJS) $(LIBS)
|
||||||
$(CC) $(ARCH) $(LDFLAGS) $(FLAGS) $(OPT) $(DEBUG) $^ -o $@
|
$(CXX) $(ARCH) $(LDFLAGS) $(FLAGS) $(OPT) $(DEBUG) $^ -o $@
|
||||||
|
|
||||||
%.spv: %.hlsl
|
%.spv: %.hlsl
|
||||||
../dxc/bin/dxc -spirv -T lib_6_3 -fspv-target-env=vulkan1.3 $< -Fo $@
|
../dxc/bin/dxc -spirv -T lib_6_3 -fspv-target-env=vulkan1.3 $< -Fo $@
|
||||||
|
|||||||
BIN
data/font/bitmap/terminus_128x64_6x12.data
Normal file
BIN
data/font/bitmap/terminus_128x64_6x12.data
Normal file
Binary file not shown.
@ -1,9 +1,13 @@
|
|||||||
shader/font.spv
|
shader/font.spv
|
||||||
|
shader/font/bitmap.spv
|
||||||
data/font/outline/medieval_sharp_24.data
|
data/font/outline/medieval_sharp_24.data
|
||||||
|
data/font/bitmap/terminus_128x64_6x12.data
|
||||||
|
|
||||||
shader/renpy.spv
|
shader/renpy.spv
|
||||||
shader/renpy_composite.spv
|
shader/renpy_composite.spv
|
||||||
|
|
||||||
|
shader/ui/solid.spv
|
||||||
|
|
||||||
audio/sfx/Chime.opus.bin
|
audio/sfx/Chime.opus.bin
|
||||||
audio/music/MistAmbience.opus.bin
|
audio/music/MistAmbience.opus.bin
|
||||||
audio/music/Preludium.opus.bin
|
audio/music/Preludium.opus.bin
|
||||||
|
|||||||
@ -4,6 +4,105 @@
|
|||||||
#include "poem.h"
|
#include "poem.h"
|
||||||
|
|
||||||
namespace audio {
|
namespace audio {
|
||||||
|
constexpr int sample_rate = 48000;
|
||||||
|
constexpr int channels = 2;
|
||||||
|
|
||||||
|
template <int maxDelay>
|
||||||
|
struct FeedbackCombFilter {
|
||||||
|
private:
|
||||||
|
//float * buffer;
|
||||||
|
float buffer[maxDelay];
|
||||||
|
int index;
|
||||||
|
public:
|
||||||
|
int delay;
|
||||||
|
float gain0;
|
||||||
|
float gainM;
|
||||||
|
|
||||||
|
FeedbackCombFilter(int delay, float gain0, float gainM);
|
||||||
|
void reset();
|
||||||
|
float feed(float value);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <int maxDelay>
|
||||||
|
struct FeedforwardCombFilter {
|
||||||
|
private:
|
||||||
|
//float * buffer;
|
||||||
|
float buffer[maxDelay];
|
||||||
|
int index;
|
||||||
|
public:
|
||||||
|
int delay;
|
||||||
|
float gain0;
|
||||||
|
float gainM;
|
||||||
|
|
||||||
|
FeedforwardCombFilter(int delay, float gain0, float gainM);
|
||||||
|
void reset();
|
||||||
|
float feed(float value);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <int maxDelay>
|
||||||
|
struct AllpassFilter {
|
||||||
|
private:
|
||||||
|
//float * buffer;
|
||||||
|
float buffer[maxDelay];
|
||||||
|
int index;
|
||||||
|
|
||||||
|
public:
|
||||||
|
int delay;
|
||||||
|
float gain0;
|
||||||
|
float gainM;
|
||||||
|
|
||||||
|
AllpassFilter(int delay, float gain0, float gainM);
|
||||||
|
void reset();
|
||||||
|
float feed(float x);
|
||||||
|
};
|
||||||
|
|
||||||
|
using FBCF = FeedbackCombFilter<15000>;
|
||||||
|
using FFCF = FeedforwardCombFilter<15000>;
|
||||||
|
using AP = AllpassFilter<2500>;
|
||||||
|
|
||||||
|
struct lr { float l; float r; };
|
||||||
|
|
||||||
|
struct FBReverb {
|
||||||
|
static constexpr int cfCount = 4;
|
||||||
|
static constexpr int apCount = 3;
|
||||||
|
|
||||||
|
FBCF cf[cfCount];
|
||||||
|
AP ap[apCount];
|
||||||
|
|
||||||
|
FBReverb();
|
||||||
|
void reset();
|
||||||
|
lr feed(float x);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FFReverb {
|
||||||
|
static constexpr int __cfCount = 4;
|
||||||
|
static constexpr int apCount = 3;
|
||||||
|
|
||||||
|
FFCF cf[__cfCount];
|
||||||
|
AP ap[apCount];
|
||||||
|
|
||||||
|
FFReverb();
|
||||||
|
void reset();
|
||||||
|
lr feed(float x);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern int reverbIndex;
|
||||||
|
extern FBReverb fbreverb;
|
||||||
|
extern FFReverb ffreverb;
|
||||||
|
|
||||||
|
extern float wetGain;
|
||||||
|
extern float dryGain;
|
||||||
|
|
||||||
|
struct mix_channel {
|
||||||
|
enum {
|
||||||
|
music = 0,
|
||||||
|
poem = 1,
|
||||||
|
voice = 2,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr int mixChannelCount = 3;
|
||||||
|
extern float mixChannelGain[mixChannelCount];
|
||||||
|
|
||||||
extern int poem_timestamp_index;
|
extern int poem_timestamp_index;
|
||||||
extern int poem_line_index;
|
extern int poem_line_index;
|
||||||
|
|||||||
18
include/font/bitmap.h
Normal file
18
include/font/bitmap.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "instance_data.h"
|
||||||
|
|
||||||
|
namespace font::bitmap {
|
||||||
|
static inline uint16_2 glyphIndex(int c)
|
||||||
|
{
|
||||||
|
assert(c >= 32 && c <= 127);
|
||||||
|
|
||||||
|
c -= 32;
|
||||||
|
|
||||||
|
int stride = 128 / 6;
|
||||||
|
|
||||||
|
int x = c % stride;
|
||||||
|
int y = c / stride;
|
||||||
|
return {(uint16_t)x, (uint16_t)y};
|
||||||
|
}
|
||||||
|
}
|
||||||
64
include/font/bitmap/vulkan.h
Normal file
64
include/font/bitmap/vulkan.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "vulkan_state.h"
|
||||||
|
#include "font/instance_data.h"
|
||||||
|
|
||||||
|
namespace font::bitmap {
|
||||||
|
struct LoadedFont {
|
||||||
|
VkImage image;
|
||||||
|
VkDeviceMemory memory;
|
||||||
|
VkImageView imageView;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vulkan {
|
||||||
|
static constexpr int maximumGlyphCount = 1024;
|
||||||
|
static constexpr VkDeviceSize instanceBufferSize{ maximumGlyphCount * (sizeof (BitmapInstance)) };
|
||||||
|
|
||||||
|
VulkanState const * const vk;
|
||||||
|
|
||||||
|
VkPipelineLayout pipelineLayout;
|
||||||
|
VkPipeline pipeline;
|
||||||
|
::InstanceBuffer instanceBuffer;
|
||||||
|
BitmapInstance * bitmapInstance[2];
|
||||||
|
|
||||||
|
VkDescriptorPool descriptorPool;
|
||||||
|
static constexpr uint32_t descriptorSetLayoutCount = 1;
|
||||||
|
VkDescriptorSetLayout descriptorSetLayouts[descriptorSetLayoutCount];
|
||||||
|
VkDescriptorSet descriptorSet0;
|
||||||
|
|
||||||
|
LoadedFont loadedFont;
|
||||||
|
|
||||||
|
vulkan(VulkanState const * vk)
|
||||||
|
: vk(vk)
|
||||||
|
{
|
||||||
|
createDescriptorSets();
|
||||||
|
createPipeline();
|
||||||
|
|
||||||
|
loadedFont = loadFont();
|
||||||
|
writeDescriptorSets(loadedFont.imageView);
|
||||||
|
|
||||||
|
createInstanceBuffer(vk->device,
|
||||||
|
vk->physicalDeviceProperties,
|
||||||
|
vk->physicalDeviceMemoryProperties,
|
||||||
|
instanceBufferSize,
|
||||||
|
&instanceBuffer);
|
||||||
|
|
||||||
|
bitmapInstance[0] = (BitmapInstance *)(((ptrdiff_t)instanceBuffer.mappedData) + instanceBuffer.offset[0]);
|
||||||
|
bitmapInstance[1] = (BitmapInstance *)(((ptrdiff_t)instanceBuffer.mappedData) + instanceBuffer.offset[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
LoadedFont loadFont();
|
||||||
|
void createDescriptorSets();
|
||||||
|
void writeDescriptorSets(VkImageView imageView);
|
||||||
|
|
||||||
|
void update(uint32_t frameIndex,
|
||||||
|
uint32_t glyphCount) const;
|
||||||
|
|
||||||
|
void draw(VkCommandBuffer commandBuffer,
|
||||||
|
uint32_t frameIndex,
|
||||||
|
uint32_t glyphCount) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void createPipeline();
|
||||||
|
};
|
||||||
|
}
|
||||||
15
include/font/instance_data.h
Normal file
15
include/font/instance_data.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "mapped_instance_data.h"
|
||||||
|
|
||||||
|
namespace font {
|
||||||
|
|
||||||
|
struct BitmapInstance {
|
||||||
|
uint16_2 position;
|
||||||
|
uint16_2 glyph;
|
||||||
|
};
|
||||||
|
static_assert((sizeof (BitmapInstance)) == 2 * 2 + 4);
|
||||||
|
}
|
||||||
54
include/intstring.h
Normal file
54
include/intstring.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
namespace string {
|
||||||
|
static inline int decLength(int32_t n)
|
||||||
|
{
|
||||||
|
if (n >= 1000000000) return 10;
|
||||||
|
if (n >= 100000000) return 9;
|
||||||
|
if (n >= 10000000) return 8;
|
||||||
|
if (n >= 1000000) return 7;
|
||||||
|
if (n >= 100000) return 6;
|
||||||
|
if (n >= 10000) return 5;
|
||||||
|
if (n >= 1000) return 4;
|
||||||
|
if (n >= 100) return 3;
|
||||||
|
if (n >= 10) return 2;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, int fixed=0>
|
||||||
|
static inline int dec(T * c, int len, int32_t n)
|
||||||
|
{
|
||||||
|
int index = 0;
|
||||||
|
if (n < 0) {
|
||||||
|
c[index++] = '-';
|
||||||
|
n = -n;
|
||||||
|
}
|
||||||
|
int numLength = fixed > 0 ? fixed : decLength(n);
|
||||||
|
assert(len >= (numLength + index));
|
||||||
|
for (int i = (numLength - 1); i >= 0; i--) {
|
||||||
|
const int32_t digit = n % 10;
|
||||||
|
n = n / 10;
|
||||||
|
c[index + i] = digit + 48;
|
||||||
|
}
|
||||||
|
return numLength + index;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static inline int flt(T * c, int len, float n)
|
||||||
|
{
|
||||||
|
int index = 0;
|
||||||
|
if (n < 0) {
|
||||||
|
c[index++] = '-';
|
||||||
|
n = -n;
|
||||||
|
}
|
||||||
|
int32_t whole = n;
|
||||||
|
index += dec<T>(&c[index], len - index, whole);
|
||||||
|
c[index++] = '.';
|
||||||
|
int32_t fraction = (int32_t)((n - (float)whole) * 1000.0f);
|
||||||
|
index += dec<T, 3>(&c[index], len - index, fraction);
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
22
include/mapped_instance_data.h
Normal file
22
include/mapped_instance_data.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct uint16_2 {
|
||||||
|
uint16_t x;
|
||||||
|
uint16_t y;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct MappedInstanceData {
|
||||||
|
T * buffer;
|
||||||
|
int length;
|
||||||
|
int index;
|
||||||
|
|
||||||
|
void append(T const & value)
|
||||||
|
{
|
||||||
|
assert(index < length);
|
||||||
|
buffer[index] = value;
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -17,3 +17,11 @@ inline static constexpr T clamp(T n, T minVal, T maxVal)
|
|||||||
{
|
{
|
||||||
return min(max(n, minVal), maxVal);
|
return min(max(n, minVal), maxVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static inline T clamp01(T a)
|
||||||
|
{
|
||||||
|
if (a < 0.0) return 0.0;
|
||||||
|
if (a > 1.0) return 1.0;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|||||||
17
include/mouse.h
Normal file
17
include/mouse.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
namespace mouse
|
||||||
|
{
|
||||||
|
void normalize(int windowWidth, int windowHeight, float mx, float my, float * mxf, float * myf)
|
||||||
|
{
|
||||||
|
int canonicalSizeX = 1280;
|
||||||
|
int canonicalSizeY = 720;
|
||||||
|
int scaleFactor = 1;
|
||||||
|
while (canonicalSizeX * (scaleFactor + 1) <= windowWidth && canonicalSizeY * (scaleFactor + 1) <= windowHeight) {
|
||||||
|
scaleFactor += 1;
|
||||||
|
}
|
||||||
|
float scaleFactorInverse = 1.0f / ((float)scaleFactor);
|
||||||
|
int offsetX = (windowWidth - (canonicalSizeX * scaleFactor)) / 2;
|
||||||
|
int offsetY = (windowHeight - (canonicalSizeY * scaleFactor)) / 2;
|
||||||
|
*mxf = ((float)(mx - offsetX)) * scaleFactorInverse;
|
||||||
|
*myf = ((float)(my - offsetY)) * scaleFactorInverse;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -12,11 +12,11 @@ namespace renpy {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static constexpr top_left transforms[] = {
|
static constexpr top_left transforms[] = {
|
||||||
[language::transform::left] = { .top = 192, .left = 0 },
|
/*[language::transform::left] =*/ { .top = 192, .left = 0 },
|
||||||
[language::transform::centerleft] = { .top = 192, .left = 240 },
|
/*[language::transform::centerleft] =*/ { .top = 192, .left = 240 },
|
||||||
[language::transform::center] = { .top = 192, .left = 416 },
|
/*[language::transform::center] =*/ { .top = 192, .left = 416 },
|
||||||
[language::transform::centerright] = { .top = 192, .left = 588 },
|
/*[language::transform::centerright] =*/ { .top = 192, .left = 588 },
|
||||||
[language::transform::right] = { .top = 192, .left = 828 },
|
/*[language::transform::right] =*/ { .top = 192, .left = 828 },
|
||||||
};
|
};
|
||||||
static constexpr int transformsCount = (sizeof (transforms)) / (sizeof (transforms[0]));
|
static constexpr int transformsCount = (sizeof (transforms)) / (sizeof (transforms[0]));
|
||||||
|
|
||||||
|
|||||||
@ -47,7 +47,7 @@ namespace renpy::language {
|
|||||||
char const * const path;
|
char const * const path;
|
||||||
double loop_end;
|
double loop_end;
|
||||||
uint32_t audio_flags;
|
uint32_t audio_flags;
|
||||||
double attenuation;
|
double gain;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct image {
|
struct image {
|
||||||
|
|||||||
10
include/ui.h
Normal file
10
include/ui.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ui/widget.h"
|
||||||
|
|
||||||
|
namespace ui
|
||||||
|
{
|
||||||
|
void draw(MappedInstanceData<SolidInstance> & data,
|
||||||
|
MappedInstanceData<font::BitmapInstance> & fontData);
|
||||||
|
void update(float mx, float my, bool mLeft, bool mEdge);
|
||||||
|
}
|
||||||
16
include/ui/instance_data.h
Normal file
16
include/ui/instance_data.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "mapped_instance_data.h"
|
||||||
|
|
||||||
|
namespace ui {
|
||||||
|
|
||||||
|
struct SolidInstance {
|
||||||
|
uint16_2 position;
|
||||||
|
uint16_2 size;
|
||||||
|
uint32_t color;
|
||||||
|
};
|
||||||
|
static_assert((sizeof (SolidInstance)) == 2 * 2 * 2 + 4);
|
||||||
|
}
|
||||||
45
include/ui/vulkan.h
Normal file
45
include/ui/vulkan.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "vulkan_state.h"
|
||||||
|
#include "ui/instance_data.h"
|
||||||
|
|
||||||
|
#include "font/instance_data.h"
|
||||||
|
|
||||||
|
namespace ui {
|
||||||
|
struct vulkan {
|
||||||
|
static constexpr int maximumUIElements = 1024;
|
||||||
|
static constexpr VkDeviceSize instanceBufferSize{ maximumUIElements * (sizeof (SolidInstance)) };
|
||||||
|
|
||||||
|
VulkanState const * const vk;
|
||||||
|
|
||||||
|
VkPipelineLayout pipelineLayout;
|
||||||
|
VkPipeline pipeline;
|
||||||
|
::InstanceBuffer instanceBuffer;
|
||||||
|
SolidInstance * solidInstance[2];
|
||||||
|
|
||||||
|
vulkan(VulkanState const * vk)
|
||||||
|
: vk(vk)
|
||||||
|
{
|
||||||
|
createPipeline();
|
||||||
|
|
||||||
|
createInstanceBuffer(vk->device,
|
||||||
|
vk->physicalDeviceProperties,
|
||||||
|
vk->physicalDeviceMemoryProperties,
|
||||||
|
instanceBufferSize,
|
||||||
|
&instanceBuffer);
|
||||||
|
|
||||||
|
solidInstance[0] = (SolidInstance *)(((ptrdiff_t)instanceBuffer.mappedData) + instanceBuffer.offset[0]);
|
||||||
|
solidInstance[1] = (SolidInstance *)(((ptrdiff_t)instanceBuffer.mappedData) + instanceBuffer.offset[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
int update(uint32_t frameIndex,
|
||||||
|
MappedInstanceData<font::BitmapInstance> & bitmapData) const;
|
||||||
|
|
||||||
|
void draw(VkCommandBuffer commandBuffer,
|
||||||
|
uint32_t frameIndex,
|
||||||
|
MappedInstanceData<font::BitmapInstance> & bitmapData) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void createPipeline();
|
||||||
|
};
|
||||||
|
}
|
||||||
151
include/ui/widget.h
Normal file
151
include/ui/widget.h
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ui/instance_data.h"
|
||||||
|
#include "font/bitmap.h"
|
||||||
|
|
||||||
|
namespace ui::widget
|
||||||
|
{
|
||||||
|
struct BoundingBox
|
||||||
|
{
|
||||||
|
int left;
|
||||||
|
int top;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
|
||||||
|
bool inside(float x, float y)
|
||||||
|
{
|
||||||
|
return (x >= left) && (x <= (left + width))
|
||||||
|
&& (y >= top) && (y <= (top + height));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Widget {
|
||||||
|
//virtual void mouseDown(float x, float y) {};
|
||||||
|
virtual void draw(MappedInstanceData<SolidInstance> & data,
|
||||||
|
MappedInstanceData<font::BitmapInstance> & fontData) = 0;
|
||||||
|
|
||||||
|
virtual void update(float mx, float my, bool mLeft, bool mEdge) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <int optionCount>
|
||||||
|
struct Radio : public Widget
|
||||||
|
{
|
||||||
|
char const * label;
|
||||||
|
char const ** boxLabels;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int * selected;
|
||||||
|
BoundingBox box[optionCount];
|
||||||
|
|
||||||
|
Radio(char const * label,
|
||||||
|
char const ** boxLabels,
|
||||||
|
int left, int top, int width, int height,
|
||||||
|
int hSpace, int vSpace,
|
||||||
|
int * selected)
|
||||||
|
: label(label)
|
||||||
|
, boxLabels(boxLabels)
|
||||||
|
, width((optionCount - 1) * hSpace + width)
|
||||||
|
, height((optionCount - 1) * vSpace + height)
|
||||||
|
, selected(selected)
|
||||||
|
{
|
||||||
|
int x = left;
|
||||||
|
int y = top;
|
||||||
|
for (int i = 0; i < optionCount; i++) {
|
||||||
|
box[i].left = x;
|
||||||
|
box[i].top = y;
|
||||||
|
box[i].width = width;
|
||||||
|
box[i].height = height;
|
||||||
|
x += hSpace;
|
||||||
|
y += vSpace;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw(MappedInstanceData<SolidInstance> & data,
|
||||||
|
MappedInstanceData<font::BitmapInstance> & fontData) override;
|
||||||
|
|
||||||
|
void update(float mx, float my, bool mLeft, bool mEdge) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, bool under>
|
||||||
|
struct Slider : public Widget
|
||||||
|
{
|
||||||
|
bool drag;
|
||||||
|
|
||||||
|
char const * label;
|
||||||
|
|
||||||
|
BoundingBox sliderBorder;
|
||||||
|
BoundingBox slider;
|
||||||
|
BoundingBox lminus;
|
||||||
|
BoundingBox lplus;
|
||||||
|
BoundingBox rminus;
|
||||||
|
BoundingBox rplus;
|
||||||
|
|
||||||
|
T minValue;
|
||||||
|
T maxValue;
|
||||||
|
T minExtent;
|
||||||
|
T maxExtent;
|
||||||
|
T * value;
|
||||||
|
|
||||||
|
Slider(char const * label,
|
||||||
|
int left, int top, int width, int height,
|
||||||
|
T minValue, T maxValue,
|
||||||
|
T minExtent, T maxExtent,
|
||||||
|
T * value)
|
||||||
|
: drag{ false }
|
||||||
|
, label{ label }
|
||||||
|
, sliderBorder{ left, top, width, height }
|
||||||
|
, slider{ left, top + 2, width, height - 4 }
|
||||||
|
, lminus{ left - 21, top + 3, 8, 8 }
|
||||||
|
, lplus{ left - 11, top + 3, 8, 8 }
|
||||||
|
, rminus{ left + width + 3, top + 3, 8, 8 }
|
||||||
|
, rplus{ left + width + 13, top + 3, 8, 8 }
|
||||||
|
, minValue{ minValue }
|
||||||
|
, maxValue{ maxValue }
|
||||||
|
, minExtent{ minExtent }
|
||||||
|
, maxExtent{ maxExtent }
|
||||||
|
, value{ value }
|
||||||
|
{}
|
||||||
|
|
||||||
|
void draw(MappedInstanceData<SolidInstance> & data,
|
||||||
|
MappedInstanceData<font::BitmapInstance> & fontData) override;
|
||||||
|
|
||||||
|
void update(float mx, float my, bool mLeft, bool mEdge) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DelayGainSlider : public Widget
|
||||||
|
{
|
||||||
|
char const * label;
|
||||||
|
|
||||||
|
Slider<int, true> delay;
|
||||||
|
Slider<float, true> gain0;
|
||||||
|
Slider<float, true> gainM;
|
||||||
|
|
||||||
|
DelayGainSlider(char const * label,
|
||||||
|
int left, int top,
|
||||||
|
int delayMin, int delayMax, int * delayValue,
|
||||||
|
float gainMin, float gainMax,
|
||||||
|
float * gain0Value, float * gainMValue)
|
||||||
|
: label(label)
|
||||||
|
, delay("delay",
|
||||||
|
left, top, 150, 14,
|
||||||
|
delayMin, delayMax,
|
||||||
|
delayMin, delayMax,
|
||||||
|
delayValue)
|
||||||
|
, gain0("gain0",
|
||||||
|
left, top + 30, 150, 14,
|
||||||
|
gainMin, gainMax,
|
||||||
|
gainMin, gainMax,
|
||||||
|
gain0Value)
|
||||||
|
, gainM("gainM",
|
||||||
|
left, top + 60, 150, 14,
|
||||||
|
gainMin, gainMax,
|
||||||
|
gainMin, gainMax,
|
||||||
|
gainMValue)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void draw(MappedInstanceData<SolidInstance> & data,
|
||||||
|
MappedInstanceData<font::BitmapInstance> & fontData) override;
|
||||||
|
|
||||||
|
void update(float mx, float my, bool mLeft, bool mEdge) override;
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -94,7 +94,7 @@ void textureTransfer(VkDevice device,
|
|||||||
VkDeviceSize nonCoherentAtomSize,
|
VkDeviceSize nonCoherentAtomSize,
|
||||||
VkPhysicalDeviceMemoryProperties const & physicalDeviceMemoryProperties,
|
VkPhysicalDeviceMemoryProperties const & physicalDeviceMemoryProperties,
|
||||||
uint32_t imageDataSize,
|
uint32_t imageDataSize,
|
||||||
void * imageData,
|
void const * imageData,
|
||||||
VkImage image,
|
VkImage image,
|
||||||
uint32_t width,
|
uint32_t width,
|
||||||
uint32_t height,
|
uint32_t height,
|
||||||
@ -114,3 +114,34 @@ VertexIndex createVertexIndexBuffer(VkDevice device,
|
|||||||
uint32_t vertexSize,
|
uint32_t vertexSize,
|
||||||
void const * indexStart,
|
void const * indexStart,
|
||||||
uint32_t indexSize);
|
uint32_t indexSize);
|
||||||
|
|
||||||
|
void createQuadPipeline(VkDevice device,
|
||||||
|
VkFormat colorFormat,
|
||||||
|
VkFormat depthFormat,
|
||||||
|
uint32_t descriptorSetLayoutCount,
|
||||||
|
VkDescriptorSetLayout const * descriptorSetLayouts,
|
||||||
|
uint32_t pushConstantRangeCount,
|
||||||
|
VkPushConstantRange const * pushConstantRanges,
|
||||||
|
VkShaderModule shaderModule,
|
||||||
|
uint32_t perInstanceStride,
|
||||||
|
uint32_t instanceAttributeDescriptionCount,
|
||||||
|
VkVertexInputAttributeDescription * instanceAttributeDescriptions,
|
||||||
|
VkPipelineLayout * pipelineLayout,
|
||||||
|
VkPipeline * pipeline);
|
||||||
|
|
||||||
|
VkShaderModule loadShader(VkDevice device,
|
||||||
|
char const * const path);
|
||||||
|
|
||||||
|
struct InstanceBuffer {
|
||||||
|
VkDeviceSize offset[2];
|
||||||
|
VkBuffer buffer;
|
||||||
|
VkDeviceMemory memory;
|
||||||
|
VkDeviceSize memorySize;
|
||||||
|
void * mappedData;
|
||||||
|
};
|
||||||
|
|
||||||
|
void createInstanceBuffer(VkDevice device,
|
||||||
|
VkPhysicalDeviceProperties const & physicalDeviceProperties,
|
||||||
|
VkPhysicalDeviceMemoryProperties const & physicalDeviceMemoryProperties,
|
||||||
|
VkDeviceSize bufferSize,
|
||||||
|
InstanceBuffer * instanceBuffer);
|
||||||
|
|||||||
31
include/vulkan_state.h
Normal file
31
include/vulkan_state.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include "vulkan/vulkan.h"
|
||||||
|
#else
|
||||||
|
#include "volk/volk.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "vulkan_helper.h"
|
||||||
|
|
||||||
|
struct VulkanState {
|
||||||
|
VkInstance instance;
|
||||||
|
VkDevice device;
|
||||||
|
VkQueue queue;
|
||||||
|
VkCommandPool commandPool;
|
||||||
|
VkPhysicalDeviceProperties physicalDeviceProperties;
|
||||||
|
VkPhysicalDeviceMemoryProperties physicalDeviceMemoryProperties;
|
||||||
|
VkFormat colorFormat;
|
||||||
|
VkFormat depthFormat;
|
||||||
|
|
||||||
|
VertexIndex quadVertexIndex;
|
||||||
|
|
||||||
|
VulkanState(VkInstance instance,
|
||||||
|
VkDevice device,
|
||||||
|
VkQueue queue,
|
||||||
|
VkCommandPool commandPool,
|
||||||
|
VkPhysicalDeviceProperties const & physicalDeviceProperties,
|
||||||
|
VkPhysicalDeviceMemoryProperties const & physicalDeviceMemoryProperties,
|
||||||
|
VkFormat colorFormat,
|
||||||
|
VkFormat depthFormat);
|
||||||
|
};
|
||||||
@ -333,7 +333,7 @@ def pass2_audio(state):
|
|||||||
else:
|
else:
|
||||||
audio_type = "0"
|
audio_type = "0"
|
||||||
|
|
||||||
yield f"{{ .path = \"audio/{path}.opus.bin\", .loop_end = {float(loop)}, .audio_flags = {audio_type}, .attenuation = {attenuation} }}, // {i} {orig_path}"
|
yield f"{{ .path = \"audio/{path}.opus.bin\", .loop_end = {float(loop)}, .audio_flags = {audio_type}, .gain = {attenuation} }}, // {i} {orig_path}"
|
||||||
yield "};"
|
yield "};"
|
||||||
yield "const int audio_length = (sizeof (audio)) / (sizeof (audio[0]));"
|
yield "const int audio_length = (sizeof (audio)) / (sizeof (audio[0]));"
|
||||||
|
|
||||||
|
|||||||
48
shader/font/bitmap.hlsl
Normal file
48
shader/font/bitmap.hlsl
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
struct GlyphBitmap
|
||||||
|
{
|
||||||
|
uint2 Position; // x y, in texels
|
||||||
|
uint2 Size; // width height
|
||||||
|
};
|
||||||
|
|
||||||
|
// set 0: constant
|
||||||
|
[[vk::binding(0, 0)]] Texture2D FontTexture;
|
||||||
|
|
||||||
|
struct VSInput
|
||||||
|
{
|
||||||
|
float2 Position : POSITION0;
|
||||||
|
float2 Texture : TEXCOORD0;
|
||||||
|
// per-instance
|
||||||
|
uint2 InstancePosition : InstancePosition;
|
||||||
|
uint2 InstanceGlyph : InstanceGlyph;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VSOutput
|
||||||
|
{
|
||||||
|
float4 Position : SV_POSITION;
|
||||||
|
float2 Texture : NORMAL0;
|
||||||
|
};
|
||||||
|
|
||||||
|
[shader("vertex")]
|
||||||
|
VSOutput VSMain(VSInput input)
|
||||||
|
{
|
||||||
|
//float2 inverseTexel = float2(1.0 / 128.0, 1.0 / 64.0);
|
||||||
|
float2 inversePixel = float2(1.0 / 1280.0, 1.0 / 720.0);
|
||||||
|
|
||||||
|
float2 Size = float2(6, 12);
|
||||||
|
|
||||||
|
VSOutput output = (VSOutput)0;
|
||||||
|
float2 position = (input.Texture * Size + input.InstancePosition) * inversePixel;
|
||||||
|
output.Position = float4(position * 2.0 - 1.0, 0, 1);
|
||||||
|
output.Texture = (input.Texture * Size + input.InstanceGlyph * Size);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
[shader("pixel")]
|
||||||
|
float4 PSMain(VSOutput input) : SV_TARGET
|
||||||
|
{
|
||||||
|
float4 color = FontTexture.Load(int3(input.Texture, 0));
|
||||||
|
float c = (color.x == 0) ? 0 : 1;
|
||||||
|
|
||||||
|
return float4(1, 1, 1, c.x);
|
||||||
|
}
|
||||||
38
shader/ui/solid.hlsl
Normal file
38
shader/ui/solid.hlsl
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
struct VSInput
|
||||||
|
{
|
||||||
|
float2 Position : POSITION0;
|
||||||
|
float2 Texture : TEXCOORD0;
|
||||||
|
// per-instance
|
||||||
|
int2 InstancePosition : InstancePosition;
|
||||||
|
int2 InstanceSize : InstanceSize;
|
||||||
|
float4 Color : Color;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VSOutput
|
||||||
|
{
|
||||||
|
float4 Position : SV_POSITION;
|
||||||
|
float2 Texture : Texture;
|
||||||
|
float4 Color : Color;
|
||||||
|
};
|
||||||
|
|
||||||
|
[shader("vertex")]
|
||||||
|
VSOutput VSMain(VSInput input)
|
||||||
|
{
|
||||||
|
float2 inversePixel = float2(1.0 / 1280.0, 1.0 / 720.0);
|
||||||
|
|
||||||
|
float2 position = (input.Texture * input.InstanceSize + input.InstancePosition) * inversePixel;
|
||||||
|
|
||||||
|
VSOutput output = (VSOutput)0;
|
||||||
|
output.Position = float4(position * 2.0 - 1.0, 0, 1);
|
||||||
|
output.Texture = input.Texture;
|
||||||
|
output.Color = input.Color.zyxw;
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
[shader("pixel")]
|
||||||
|
float4 PSMain(VSOutput input) : SV_TARGET
|
||||||
|
{
|
||||||
|
//return float4(input.Texture, 0, 1);
|
||||||
|
return float4(input.Color.xyzw);
|
||||||
|
}
|
||||||
303
src/audio.cpp
303
src/audio.cpp
@ -13,10 +13,7 @@
|
|||||||
#include "poem.h"
|
#include "poem.h"
|
||||||
|
|
||||||
namespace audio {
|
namespace audio {
|
||||||
|
|
||||||
static int const frame_samples = 960; // 20 milliseconds @ 48kHz
|
static int const frame_samples = 960; // 20 milliseconds @ 48kHz
|
||||||
static int const sample_rate = 48000;
|
|
||||||
static int const channels = 2;
|
|
||||||
static int const sample_size = (sizeof (int16_t));
|
static int const sample_size = (sizeof (int16_t));
|
||||||
|
|
||||||
static int const max_frame_size = 960 * 3; // 20ms at 48kHz
|
static int const max_frame_size = 960 * 3; // 20ms at 48kHz
|
||||||
@ -31,6 +28,79 @@ namespace audio {
|
|||||||
uint32_t sample_count;
|
uint32_t sample_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <int maxDelay>
|
||||||
|
FeedbackCombFilter<maxDelay>::FeedbackCombFilter(int delay, float gain0, float gainM)
|
||||||
|
: delay(delay), gain0(gain0), gainM(gainM)
|
||||||
|
{
|
||||||
|
//buffer = (float *)malloc((sizeof (float)) * maxDelay);
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <int maxDelay>
|
||||||
|
void FeedbackCombFilter<maxDelay>::reset()
|
||||||
|
{
|
||||||
|
index = 0;
|
||||||
|
memset(buffer, 0, (sizeof (float)) * maxDelay);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <int maxDelay>
|
||||||
|
float FeedbackCombFilter<maxDelay>::feed(float value)
|
||||||
|
{
|
||||||
|
float y = gain0 * value + gainM * buffer[index];
|
||||||
|
buffer[index] = y;
|
||||||
|
index = (index + 1) % delay;
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <int maxDelay>
|
||||||
|
FeedforwardCombFilter<maxDelay>::FeedforwardCombFilter(int delay, float gain0, float gainM)
|
||||||
|
: delay(delay), gain0(gain0), gainM(gainM)
|
||||||
|
{
|
||||||
|
//buffer = (float *)malloc((sizeof (float)) * maxDelay);
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <int maxDelay>
|
||||||
|
void FeedforwardCombFilter<maxDelay>::reset()
|
||||||
|
{
|
||||||
|
index = 0;
|
||||||
|
memset(buffer, 0, (sizeof (float)) * maxDelay);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <int maxDelay>
|
||||||
|
float FeedforwardCombFilter<maxDelay>::feed(float value)
|
||||||
|
{
|
||||||
|
float y = gain0 * value + gainM * buffer[index];
|
||||||
|
buffer[index] = value;
|
||||||
|
index = (index + 1) % delay;
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <int maxDelay>
|
||||||
|
AllpassFilter<maxDelay>::AllpassFilter(int delay, float gain0, float gainM)
|
||||||
|
: delay(delay), gain0(gain0), gainM(gainM)
|
||||||
|
{
|
||||||
|
//buffer = (float *)malloc((sizeof (float)) * maxDelay);
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <int maxDelay>
|
||||||
|
void AllpassFilter<maxDelay>::reset()
|
||||||
|
{
|
||||||
|
index = 0;
|
||||||
|
memset(buffer, 0, (sizeof (float)) * maxDelay);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <int maxDelay>
|
||||||
|
float AllpassFilter<maxDelay>::feed(float x)
|
||||||
|
{
|
||||||
|
float v = x + -gainM * buffer[index];
|
||||||
|
float y = buffer[index] + gain0 * v;
|
||||||
|
buffer[index] = v;
|
||||||
|
index = (index + 1) % delay;
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
struct AudioInstance {
|
struct AudioInstance {
|
||||||
int audio_index;
|
int audio_index;
|
||||||
AudioBuffer * audio_buffer;
|
AudioBuffer * audio_buffer;
|
||||||
@ -41,13 +111,99 @@ namespace audio {
|
|||||||
poem::poem const * poem;
|
poem::poem const * poem;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FBReverb::FBReverb()
|
||||||
|
: cf{FBCF(3229, 1.0f, 0.733f), // 1687
|
||||||
|
FBCF(3079, 1.0f, 0.802f), // 1601
|
||||||
|
FBCF(3943, 1.0f, 0.753f), // 2053
|
||||||
|
FBCF(4327, 1.0f, 0.733f), // 2251
|
||||||
|
}
|
||||||
|
, ap{AP(661, 0.7f, 0.7f), // 347
|
||||||
|
AP(257, 0.7f, 0.7f), // 113
|
||||||
|
AP(71, 0.7f, 0.7f), // 37
|
||||||
|
}
|
||||||
|
{ }
|
||||||
|
|
||||||
|
void FBReverb::reset()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < cfCount; i++)
|
||||||
|
cf[i].reset();
|
||||||
|
|
||||||
|
for (int i = 0; i < apCount; i++)
|
||||||
|
ap[i].reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
lr FBReverb::feed(float x)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < apCount; i++) {
|
||||||
|
x = ap[i].feed(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
float x0 = cf[0].feed(x);
|
||||||
|
float x1 = cf[1].feed(x);
|
||||||
|
float x2 = cf[2].feed(x);
|
||||||
|
float x3 = cf[3].feed(x);
|
||||||
|
|
||||||
|
float s0 = x0 + x2;
|
||||||
|
float s1 = x1 + x3;
|
||||||
|
|
||||||
|
float a = s0 + s1;
|
||||||
|
float b = s0 - s1;
|
||||||
|
return {a, b};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FFReverb::FFReverb()
|
||||||
|
: cf{FFCF{9209, 1.0f, 0.742f},
|
||||||
|
FFCF{9601, 1.0f, 0.733f},
|
||||||
|
FFCF{10369, 1.0f, 0.715f},
|
||||||
|
FFCF{11131, 1.0f, 0.697f},
|
||||||
|
}
|
||||||
|
, ap{AP{2017, 0.7f, 0.7f},
|
||||||
|
AP{647, 0.7f, 0.7f},
|
||||||
|
AP{137, 0.7f, 0.7f},
|
||||||
|
}
|
||||||
|
{ }
|
||||||
|
|
||||||
|
void FFReverb::reset()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < __cfCount; i++) {
|
||||||
|
printf("reset cf %d\n", i);
|
||||||
|
cf[i].reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < apCount; i++)
|
||||||
|
ap[i].reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
lr FFReverb::feed(float x)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < apCount; i++) {
|
||||||
|
x = ap[i].feed(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
float x0 = cf[0].feed(x);
|
||||||
|
float x1 = cf[1].feed(x);
|
||||||
|
float x2 = cf[2].feed(x);
|
||||||
|
float x3 = cf[3].feed(x);
|
||||||
|
|
||||||
|
float s0 = x0 + x1 + x2 + x3;
|
||||||
|
//float s0 = x0 + x1 + x2;
|
||||||
|
return {s0, s0};
|
||||||
|
}
|
||||||
|
|
||||||
|
int reverbIndex = 0;
|
||||||
|
FBReverb fbreverb;
|
||||||
|
FFReverb ffreverb;
|
||||||
|
|
||||||
|
float dryGain = 1.0;
|
||||||
|
float wetGain = 0.25;
|
||||||
|
float mixChannelGain[mixChannelCount];
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
static SDL_AudioStream * audio_stream;
|
static SDL_AudioStream * audio_stream;
|
||||||
static SDL_AudioSpec audio_spec;
|
static SDL_AudioSpec audio_spec;
|
||||||
|
|
||||||
static OpusDecoder * opus_decoder;
|
|
||||||
|
|
||||||
static AudioBuffer * audio_buffers;
|
static AudioBuffer * audio_buffers;
|
||||||
static int audio_buffers_count;
|
static int audio_buffers_count;
|
||||||
|
|
||||||
@ -64,17 +220,16 @@ namespace audio {
|
|||||||
assert(audio_stream);
|
assert(audio_stream);
|
||||||
SDL_ResumeAudioStreamDevice(audio_stream);
|
SDL_ResumeAudioStreamDevice(audio_stream);
|
||||||
|
|
||||||
int err;
|
|
||||||
opus_decoder = opus_decoder_create(sample_rate, channels, &err);
|
|
||||||
if (err < 0) {
|
|
||||||
fprintf(stderr, "opus_decoder_create: %s\n", opus_strerror(err));
|
|
||||||
assert(!"opus_decoder_create");
|
|
||||||
}
|
|
||||||
|
|
||||||
audio_instances_count = 0;
|
audio_instances_count = 0;
|
||||||
|
fbreverb.reset();
|
||||||
|
ffreverb.reset();
|
||||||
|
|
||||||
|
for (int i = 0; i < mixChannelCount; i++) {
|
||||||
|
mixChannelGain[i] = 1.0f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void decode(char const * const filename, AudioBuffer * audio_buffer)
|
void decode(OpusDecoder * opus_decoder, char const * const filename, AudioBuffer * audio_buffer)
|
||||||
{
|
{
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
uint8_t const * buf = (uint8_t const *)file::open(filename, &size);
|
uint8_t const * buf = (uint8_t const *)file::open(filename, &size);
|
||||||
@ -127,14 +282,63 @@ namespace audio {
|
|||||||
assert(audio_buffer->sample_count / 2);
|
assert(audio_buffer->sample_count / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct LoadState {
|
||||||
|
OpusDecoder * opus_decoder;
|
||||||
|
renpy::language::audio const * audio;
|
||||||
|
int start;
|
||||||
|
int count;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int loadAudio(void * data)
|
||||||
|
{
|
||||||
|
LoadState * loadState = (LoadState *)data;
|
||||||
|
for (int i = loadState->start; i < loadState->start + loadState->count; i++) {
|
||||||
|
audio_buffers[i].audio = &loadState->audio[i];
|
||||||
|
decode(loadState->opus_decoder, loadState->audio[i].path, &audio_buffers[i]);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void load(renpy::language::audio const * const audio, int count)
|
void load(renpy::language::audio const * const audio, int count)
|
||||||
{
|
{
|
||||||
audio_buffers = NewM<AudioBuffer>(count);
|
audio_buffers = NewM<AudioBuffer>(count);
|
||||||
audio_buffers_count = count;
|
audio_buffers_count = count;
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
audio_buffers[i].audio = &audio[i];
|
int core_count = SDL_GetNumLogicalCPUCores();
|
||||||
decode(audio[i].path, &audio_buffers[i]);
|
assert(core_count >= 1);
|
||||||
|
SDL_Thread ** threads = NewM<SDL_Thread *>(core_count);
|
||||||
|
LoadState * loadStates = NewM<LoadState>(core_count);
|
||||||
|
|
||||||
|
int per_core_count = count / core_count;
|
||||||
|
int remainder = count % core_count;
|
||||||
|
int start = 0;
|
||||||
|
for (int i = 0; i < core_count; i++) {
|
||||||
|
int this_core_count = per_core_count;
|
||||||
|
if (remainder) {
|
||||||
|
this_core_count += 1;
|
||||||
|
remainder -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int err;
|
||||||
|
loadStates[i].opus_decoder = opus_decoder_create(sample_rate, channels, &err);
|
||||||
|
if (err < 0) {
|
||||||
|
fprintf(stderr, "opus_decoder_create: %s\n", opus_strerror(err));
|
||||||
|
assert(!"opus_decoder_create");
|
||||||
|
}
|
||||||
|
|
||||||
|
loadStates[i].audio = audio;
|
||||||
|
loadStates[i].start = start;
|
||||||
|
loadStates[i].count = this_core_count;
|
||||||
|
start += this_core_count;
|
||||||
|
threads[i] = SDL_CreateThread(loadAudio, "loadAudio", &loadStates[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < core_count; i++) {
|
||||||
|
SDL_WaitThread(threads[i], nullptr);
|
||||||
|
opus_decoder_destroy(loadStates[i].opus_decoder);
|
||||||
|
}
|
||||||
|
free(threads);
|
||||||
|
free(loadStates);
|
||||||
}
|
}
|
||||||
|
|
||||||
void play(int audio_index)
|
void play(int audio_index)
|
||||||
@ -205,6 +409,7 @@ namespace audio {
|
|||||||
return 1.0f;
|
return 1.0f;
|
||||||
if (v < -1.0f)
|
if (v < -1.0f)
|
||||||
return -1.0f;
|
return -1.0f;
|
||||||
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void remove_instance(int instance_index)
|
static inline void remove_instance(int instance_index)
|
||||||
@ -223,6 +428,9 @@ namespace audio {
|
|||||||
uint32_t const sample_count = instance.audio_buffer->sample_count;
|
uint32_t const sample_count = instance.audio_buffer->sample_count;
|
||||||
uint32_t const loop_end = instance.audio_buffer->audio->loop_end * (double)sample_rate;
|
uint32_t const loop_end = instance.audio_buffer->audio->loop_end * (double)sample_rate;
|
||||||
uint32_t mix_index = 0;
|
uint32_t mix_index = 0;
|
||||||
|
|
||||||
|
float bufferGain = instance.audio_buffer->audio->gain;
|
||||||
|
|
||||||
for (int i = 0; i < half_period_samples; i++) {
|
for (int i = 0; i < half_period_samples; i++) {
|
||||||
if (loop_end != 0.0) {
|
if (loop_end != 0.0) {
|
||||||
if (instance.sample_index >= loop_end) {
|
if (instance.sample_index >= loop_end) {
|
||||||
@ -241,23 +449,19 @@ namespace audio {
|
|||||||
assert(instance.sample_index < sample_count);
|
assert(instance.sample_index < sample_count);
|
||||||
assert(instance.tail_index <= sample_count);
|
assert(instance.tail_index <= sample_count);
|
||||||
|
|
||||||
double fadeout = 1.0;
|
float fadeout = 1.0;
|
||||||
double attenuation = instance.audio_buffer->audio->attenuation;
|
|
||||||
assert(attenuation != 0.0);
|
|
||||||
//bool is_music = (instance.audio_buffer->audio->audio_flags & renpy::language::audio::music) != 0;
|
|
||||||
//if (is_music)
|
|
||||||
//fprintf(stderr, "attenuation %f\n", attenuation);
|
|
||||||
if (instance.fadeout_end != 0) {
|
if (instance.fadeout_end != 0) {
|
||||||
fadeout = 1.0 - ((double)instance.fadeout_index / (double)instance.fadeout_end);
|
fadeout = 1.0 - ((float)instance.fadeout_index / (float)instance.fadeout_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int ch = 0; ch < channels; ch++) {
|
for (int ch = 0; ch < channels; ch++) {
|
||||||
int32_t value = buf[instance.sample_index * channels + ch];
|
float value = buf[instance.sample_index * channels + ch];
|
||||||
if (instance.tail_index != sample_count) {
|
if (instance.tail_index != sample_count) {
|
||||||
value += buf[instance.tail_index * channels + ch];
|
value += buf[instance.tail_index * channels + ch];
|
||||||
}
|
}
|
||||||
constexpr double scale = 1.0f / 32768.0f;
|
constexpr float scale = 1.0f / 32768.0f;
|
||||||
mix_buffer[mix_index * channels + ch] += (double)value * fadeout * attenuation * scale;
|
float output = value * fadeout * bufferGain * scale;
|
||||||
|
mix_buffer[mix_index * channels + ch] += output;
|
||||||
}
|
}
|
||||||
instance.sample_index += 1;
|
instance.sample_index += 1;
|
||||||
instance.fadeout_index += 1;
|
instance.fadeout_index += 1;
|
||||||
@ -308,18 +512,32 @@ namespace audio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int getMixChannel(AudioInstance & instance)
|
||||||
|
{
|
||||||
|
if (instance.audio_buffer->audio->audio_flags & renpy::language::audio::music) {
|
||||||
|
return mix_channel::music;
|
||||||
|
} else if (instance.audio_buffer->audio->audio_flags & renpy::language::audio::poem) {
|
||||||
|
return mix_channel::poem;
|
||||||
|
} else {
|
||||||
|
return mix_channel::voice;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void update()
|
void update()
|
||||||
{
|
{
|
||||||
float mix_buffer[half_period_samples * channels];
|
float mix_buffer[half_period_samples * channels];
|
||||||
|
float channel_buffer[mixChannelCount][half_period_samples * channels];
|
||||||
|
static_assert((sizeof (channel_buffer)) == half_period_samples * channels * mixChannelCount * (sizeof (float)));
|
||||||
|
|
||||||
if (SDL_GetAudioStreamQueued(audio_stream) >= (int)(sizeof (mix_buffer)))
|
if (SDL_GetAudioStreamQueued(audio_stream) >= (int)(sizeof (mix_buffer)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
memset(mix_buffer, 0, (sizeof (mix_buffer)));
|
memset(&mix_buffer[0], 0, (sizeof (mix_buffer)));
|
||||||
|
memset(&channel_buffer[0][0], 0, (sizeof (channel_buffer)));
|
||||||
|
|
||||||
poem_playing = nullptr;
|
poem_playing = nullptr;
|
||||||
for (int i = 0; i < audio_instances_count; i++) {
|
for (int i = 0; i < audio_instances_count; i++) {
|
||||||
update_instance(mix_buffer, audio_instances[i]);
|
update_instance(channel_buffer[getMixChannel(audio_instances[i])], audio_instances[i]);
|
||||||
|
|
||||||
update_poem(audio_instances[i]);
|
update_poem(audio_instances[i]);
|
||||||
}
|
}
|
||||||
@ -336,6 +554,35 @@ namespace audio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// audio configuration "B"
|
||||||
|
// mono reverberation
|
||||||
|
for (int i = 0; i < half_period_samples; i++) {
|
||||||
|
float value = channel_buffer[mix_channel::voice][i * channels + 0];
|
||||||
|
|
||||||
|
lr wet;
|
||||||
|
if (reverbIndex == 0) {
|
||||||
|
wet = fbreverb.feed(value);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
wet = ffreverb.feed(value);
|
||||||
|
}
|
||||||
|
float left = value * dryGain + wet.l * wetGain;
|
||||||
|
float right = value * dryGain + wet.r * wetGain;
|
||||||
|
channel_buffer[mix_channel::voice][i * channels + 0] = left;
|
||||||
|
channel_buffer[mix_channel::voice][i * channels + 1] = right;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < half_period_samples; i++) {
|
||||||
|
for (int ch = 0; ch < channels; ch++) {
|
||||||
|
float value = 0;
|
||||||
|
for (int mixChannel = 0; mixChannel < mixChannelCount; mixChannel++) {
|
||||||
|
float gain = mixChannelGain[mixChannel];
|
||||||
|
value += channel_buffer[mixChannel][i * channels + ch] * gain;
|
||||||
|
}
|
||||||
|
mix_buffer[i * channels + ch] = clampf(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SDL_PutAudioStreamData(audio_stream, (void *)mix_buffer, (int)(sizeof (mix_buffer)));
|
SDL_PutAudioStreamData(audio_stream, (void *)mix_buffer, (int)(sizeof (mix_buffer)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
269
src/font/bitmap/vulkan.cpp
Normal file
269
src/font/bitmap/vulkan.cpp
Normal file
@ -0,0 +1,269 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include "vulkan/vulkan.h"
|
||||||
|
#else
|
||||||
|
#include "volk/volk.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "vulkan/vk_enum_string_helper.h"
|
||||||
|
|
||||||
|
#include "vulkan_helper.h"
|
||||||
|
#include "check.h"
|
||||||
|
#include "file.h"
|
||||||
|
|
||||||
|
#include "font/bitmap/vulkan.h"
|
||||||
|
|
||||||
|
namespace font::bitmap {
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// pipeline
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void vulkan::createPipeline()
|
||||||
|
{
|
||||||
|
uint32_t pushConstantRangeCount = 0;
|
||||||
|
VkPushConstantRange const * pushConstantRanges = nullptr;
|
||||||
|
VkShaderModule shaderModule = loadShader(vk->device, "shader/font/bitmap.spv");
|
||||||
|
uint32_t perInstanceStride = (sizeof (BitmapInstance));
|
||||||
|
constexpr uint32_t instanceAttributeDescriptionCount = 2;
|
||||||
|
VkVertexInputAttributeDescription instanceAttributeDescriptions[instanceAttributeDescriptionCount] {
|
||||||
|
{ // position
|
||||||
|
.location = 2,
|
||||||
|
.binding = 1,
|
||||||
|
.format = VK_FORMAT_R16G16_UINT,
|
||||||
|
.offset = 0,
|
||||||
|
},
|
||||||
|
{ // glyph
|
||||||
|
.location = 3,
|
||||||
|
.binding = 1,
|
||||||
|
.format = VK_FORMAT_R16G16_UINT,
|
||||||
|
.offset = 4,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
createQuadPipeline(vk->device,
|
||||||
|
vk->colorFormat,
|
||||||
|
vk->depthFormat,
|
||||||
|
descriptorSetLayoutCount,
|
||||||
|
descriptorSetLayouts,
|
||||||
|
pushConstantRangeCount,
|
||||||
|
pushConstantRanges,
|
||||||
|
shaderModule,
|
||||||
|
perInstanceStride,
|
||||||
|
instanceAttributeDescriptionCount,
|
||||||
|
instanceAttributeDescriptions,
|
||||||
|
&pipelineLayout,
|
||||||
|
&pipeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// descriptor sets
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void vulkan::createDescriptorSets()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// pool
|
||||||
|
//
|
||||||
|
constexpr int descriptorPoolSizesCount = 1;
|
||||||
|
VkDescriptorPoolSize descriptorPoolSizes[descriptorPoolSizesCount]{
|
||||||
|
{
|
||||||
|
.type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
VkDescriptorPoolCreateInfo descriptorPoolCreateInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
|
||||||
|
.maxSets = 1,
|
||||||
|
.poolSizeCount = descriptorPoolSizesCount,
|
||||||
|
.pPoolSizes = descriptorPoolSizes
|
||||||
|
};
|
||||||
|
VK_CHECK(vkCreateDescriptorPool(vk->device, &descriptorPoolCreateInfo, nullptr, &descriptorPool));
|
||||||
|
|
||||||
|
//
|
||||||
|
// (set 0, constant)
|
||||||
|
//
|
||||||
|
{
|
||||||
|
constexpr int bindingCount = 1;
|
||||||
|
VkDescriptorSetLayoutBinding descriptorSetLayoutBindings[bindingCount]{
|
||||||
|
{ // font image
|
||||||
|
.binding = 0,
|
||||||
|
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
||||||
|
.bindingCount = bindingCount,
|
||||||
|
.pBindings = descriptorSetLayoutBindings
|
||||||
|
};
|
||||||
|
VK_CHECK(vkCreateDescriptorSetLayout(vk->device, &descriptorSetLayoutCreateInfo, nullptr, &descriptorSetLayouts[0]));
|
||||||
|
|
||||||
|
VkDescriptorSetAllocateInfo descriptorSetAllocateInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
|
||||||
|
.descriptorPool = descriptorPool,
|
||||||
|
.descriptorSetCount = 1,
|
||||||
|
.pSetLayouts = &descriptorSetLayouts[0]
|
||||||
|
};
|
||||||
|
VK_CHECK(vkAllocateDescriptorSets(vk->device, &descriptorSetAllocateInfo, &descriptorSet0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// descriptor set writes
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void vulkan::writeDescriptorSets(VkImageView imageView)
|
||||||
|
{
|
||||||
|
constexpr uint32_t writeCount = 1;
|
||||||
|
VkWriteDescriptorSet writeDescriptorSets[writeCount];
|
||||||
|
uint32_t writeIndex = 0;
|
||||||
|
|
||||||
|
// set0 bindings
|
||||||
|
VkDescriptorImageInfo terrainDescriptorImageInfo = {
|
||||||
|
.imageView = imageView,
|
||||||
|
.imageLayout = VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL
|
||||||
|
};
|
||||||
|
writeDescriptorSets[writeIndex++] = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||||
|
.dstSet = descriptorSet0,
|
||||||
|
.dstBinding = 0,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
||||||
|
.pImageInfo = &terrainDescriptorImageInfo
|
||||||
|
};
|
||||||
|
|
||||||
|
assert(writeIndex == writeCount);
|
||||||
|
vkUpdateDescriptorSets(vk->device, writeIndex, writeDescriptorSets, 0, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// load font
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
LoadedFont vulkan::loadFont()
|
||||||
|
{
|
||||||
|
uint32_t font_data_size;
|
||||||
|
void const * font_data = file::open("data/font/bitmap/terminus_128x64_6x12.data", &font_data_size);
|
||||||
|
assert(font_data != nullptr);
|
||||||
|
|
||||||
|
void const * texture_data = font_data;
|
||||||
|
uint32_t texture_size = font_data_size;
|
||||||
|
uint32_t texture_width = 128;
|
||||||
|
uint32_t texture_height = 64;
|
||||||
|
|
||||||
|
// transfer texture
|
||||||
|
|
||||||
|
VkCommandBuffer commandBuffer{};
|
||||||
|
VkCommandBufferAllocateInfo commandBufferAllocateInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
||||||
|
.commandPool = vk->commandPool,
|
||||||
|
.commandBufferCount = 1
|
||||||
|
};
|
||||||
|
VK_CHECK(vkAllocateCommandBuffers(vk->device, &commandBufferAllocateInfo, &commandBuffer));
|
||||||
|
|
||||||
|
VkFenceCreateInfo fenceCreateInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO
|
||||||
|
};
|
||||||
|
VkFence fence{};
|
||||||
|
VK_CHECK(vkCreateFence(vk->device, &fenceCreateInfo, nullptr, &fence));
|
||||||
|
|
||||||
|
void const * imageData = texture_data;
|
||||||
|
uint32_t imageDataSize = texture_size;
|
||||||
|
VkFormat format = VK_FORMAT_R8_UNORM;
|
||||||
|
uint32_t width = texture_width;
|
||||||
|
uint32_t height = texture_height;
|
||||||
|
uint32_t levelCount = 1;
|
||||||
|
uint32_t levelOffset = 0;
|
||||||
|
VkImage outImage;
|
||||||
|
VkDeviceMemory outMemory;
|
||||||
|
VkImageView outImageView;
|
||||||
|
|
||||||
|
createImage(vk->device,
|
||||||
|
vk->physicalDeviceProperties.limits.nonCoherentAtomSize,
|
||||||
|
vk->physicalDeviceMemoryProperties,
|
||||||
|
format,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
levelCount,
|
||||||
|
&outImage,
|
||||||
|
&outMemory,
|
||||||
|
&outImageView);
|
||||||
|
|
||||||
|
textureTransfer(vk->device,
|
||||||
|
vk->queue,
|
||||||
|
commandBuffer,
|
||||||
|
fence,
|
||||||
|
vk->physicalDeviceProperties.limits.nonCoherentAtomSize,
|
||||||
|
vk->physicalDeviceMemoryProperties,
|
||||||
|
imageDataSize,
|
||||||
|
imageData,
|
||||||
|
outImage,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
levelCount,
|
||||||
|
&levelOffset);
|
||||||
|
|
||||||
|
vkDestroyFence(vk->device, fence, nullptr);
|
||||||
|
vkFreeCommandBuffers(vk->device,
|
||||||
|
vk->commandPool,
|
||||||
|
1,
|
||||||
|
&commandBuffer);
|
||||||
|
|
||||||
|
// return
|
||||||
|
return {
|
||||||
|
.image = outImage,
|
||||||
|
.memory = outMemory,
|
||||||
|
.imageView = outImageView,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void vulkan::update(uint32_t frameIndex, uint32_t glyphCount) const
|
||||||
|
{
|
||||||
|
constexpr int mappedMemoryRangesCount = 1;
|
||||||
|
VkMappedMemoryRange mappedMemoryRanges[mappedMemoryRangesCount]{
|
||||||
|
{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
|
||||||
|
.memory = instanceBuffer.memory,
|
||||||
|
.offset = instanceBuffer.offset[frameIndex],
|
||||||
|
.size = (sizeof (BitmapInstance)) * glyphCount,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
alignMappedMemoryRanges(vk->physicalDeviceProperties.limits.nonCoherentAtomSize,
|
||||||
|
instanceBuffer.memorySize,
|
||||||
|
mappedMemoryRangesCount,
|
||||||
|
mappedMemoryRanges);
|
||||||
|
vkFlushMappedMemoryRanges(vk->device, mappedMemoryRangesCount, mappedMemoryRanges);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vulkan::draw(VkCommandBuffer commandBuffer,
|
||||||
|
uint32_t frameIndex,
|
||||||
|
uint32_t glyphCount) const
|
||||||
|
{
|
||||||
|
update(frameIndex, glyphCount);
|
||||||
|
//
|
||||||
|
uint32_t outputIndex = glyphCount;
|
||||||
|
|
||||||
|
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||||
|
|
||||||
|
VkDescriptorSet descriptorSets[1] = {
|
||||||
|
descriptorSet0,
|
||||||
|
};
|
||||||
|
vkCmdBindDescriptorSets(commandBuffer,
|
||||||
|
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
|
pipelineLayout,
|
||||||
|
0, 1, descriptorSets,
|
||||||
|
0, nullptr);
|
||||||
|
|
||||||
|
vkCmdBindIndexBuffer(commandBuffer, vk->quadVertexIndex.buffer, vk->quadVertexIndex.indexOffset, VK_INDEX_TYPE_UINT16);
|
||||||
|
|
||||||
|
VkDeviceSize vertexOffsets[2]{ 0, instanceBuffer.offset[frameIndex] };
|
||||||
|
VkBuffer vertexBuffers[2]{ vk->quadVertexIndex.buffer, instanceBuffer.buffer };
|
||||||
|
vkCmdBindVertexBuffers(commandBuffer, 0, 2, vertexBuffers, vertexOffsets);
|
||||||
|
|
||||||
|
vkCmdDrawIndexed(commandBuffer, 4, outputIndex, 0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -805,7 +805,7 @@ namespace font::outline {
|
|||||||
{
|
{
|
||||||
.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
|
.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
|
||||||
.memory = instanceMemory,
|
.memory = instanceMemory,
|
||||||
.offset = 0,
|
.offset = instanceBufferOffset[frameIndex],
|
||||||
.size = (sizeof (GlyphInstance)) * outputIndex,
|
.size = (sizeof (GlyphInstance)) * outputIndex,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
68
src/main.cpp
68
src/main.cpp
@ -20,14 +20,20 @@
|
|||||||
#include "shader_data.h"
|
#include "shader_data.h"
|
||||||
#include "minmax.h"
|
#include "minmax.h"
|
||||||
#include "view.h"
|
#include "view.h"
|
||||||
|
#include "mouse.h"
|
||||||
|
|
||||||
#include "font/outline.h"
|
#include "font/outline.h"
|
||||||
|
#include "font/bitmap.h"
|
||||||
|
#include "font/bitmap/vulkan.h"
|
||||||
#include "renpy/vulkan.h"
|
#include "renpy/vulkan.h"
|
||||||
#include "renpy/composite/vulkan.h"
|
#include "renpy/composite/vulkan.h"
|
||||||
#include "renpy/interpreter.h"
|
#include "renpy/interpreter.h"
|
||||||
#include "renpy/interact.h"
|
#include "renpy/interact.h"
|
||||||
#include "renpy/script.h"
|
#include "renpy/script.h"
|
||||||
|
|
||||||
|
#include "ui/vulkan.h"
|
||||||
|
#include "ui.h"
|
||||||
|
|
||||||
#include "audio.h"
|
#include "audio.h"
|
||||||
|
|
||||||
VkInstance instance{ VK_NULL_HANDLE };
|
VkInstance instance{ VK_NULL_HANDLE };
|
||||||
@ -369,6 +375,8 @@ void offscreenRender(VkCommandBuffer commandBuffer, int frameIndex,
|
|||||||
renpy::vulkan const & renpy_state,
|
renpy::vulkan const & renpy_state,
|
||||||
renpy::interpreter const & interpreter_state,
|
renpy::interpreter const & interpreter_state,
|
||||||
font::outline::font const & font_state,
|
font::outline::font const & font_state,
|
||||||
|
font::bitmap::vulkan const & bitmap_font_state,
|
||||||
|
ui::vulkan const & ui_state,
|
||||||
VkSurfaceCapabilitiesKHR const & surfaceCapabilities)
|
VkSurfaceCapabilitiesKHR const & surfaceCapabilities)
|
||||||
{
|
{
|
||||||
// barrier
|
// barrier
|
||||||
@ -474,6 +482,11 @@ void offscreenRender(VkCommandBuffer commandBuffer, int frameIndex,
|
|||||||
font_state.draw(commandBuffer, frameIndex, interpreter_state);
|
font_state.draw(commandBuffer, frameIndex, interpreter_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MappedInstanceData<font::BitmapInstance> bitmapData{ bitmap_font_state.bitmapInstance[frameIndex],
|
||||||
|
font::bitmap::vulkan::maximumGlyphCount, 0 };
|
||||||
|
ui_state.draw(commandBuffer, frameIndex, bitmapData);
|
||||||
|
bitmap_font_state.draw(commandBuffer, frameIndex, bitmapData.index);
|
||||||
|
|
||||||
vkCmdEndRendering(commandBuffer);
|
vkCmdEndRendering(commandBuffer);
|
||||||
|
|
||||||
// barrier
|
// barrier
|
||||||
@ -505,13 +518,6 @@ void offscreenRender(VkCommandBuffer commandBuffer, int frameIndex,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline double clamp01(double a)
|
|
||||||
{
|
|
||||||
if (a < 0.0) return 0.0;
|
|
||||||
if (a > 1.0) return 1.0;
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
void handlePause(renpy::interpreter & interpreter_state,
|
void handlePause(renpy::interpreter & interpreter_state,
|
||||||
int64_t const start_time,
|
int64_t const start_time,
|
||||||
double & pause_start,
|
double & pause_start,
|
||||||
@ -929,6 +935,15 @@ int main()
|
|||||||
minecraft_state.init();
|
minecraft_state.init();
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
VulkanState vulkan_state(instance,
|
||||||
|
device,
|
||||||
|
queue,
|
||||||
|
commandPool,
|
||||||
|
physicalDeviceProperties,
|
||||||
|
physicalDeviceMemoryProperties,
|
||||||
|
surfaceFormat.format,
|
||||||
|
depthFormat);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// initialize font
|
// initialize font
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
@ -945,6 +960,16 @@ int main()
|
|||||||
textureSamplers[2]);
|
textureSamplers[2]);
|
||||||
font_state.init();
|
font_state.init();
|
||||||
|
|
||||||
|
// bitmap font
|
||||||
|
|
||||||
|
font::bitmap::vulkan bitmap_font_state(&vulkan_state);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// ui
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ui::vulkan ui_state(&vulkan_state);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// initialize renpy
|
// initialize renpy
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
@ -966,7 +991,14 @@ int main()
|
|||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
audio::init();
|
audio::init();
|
||||||
|
int64_t audio_start;
|
||||||
|
SDL_GetCurrentTime(&audio_start);
|
||||||
audio::load(renpy::script::audio, renpy::script::audio_length);
|
audio::load(renpy::script::audio, renpy::script::audio_length);
|
||||||
|
int64_t audio_end;
|
||||||
|
SDL_GetCurrentTime(&audio_end);
|
||||||
|
double audio_time = (double)(audio_end - audio_start) * (0.000000001);
|
||||||
|
// 2.17
|
||||||
|
printf("audio_time %f\n", audio_time);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// interpreter
|
// interpreter
|
||||||
@ -975,7 +1007,7 @@ int main()
|
|||||||
renpy::interpreter interpreter_state;
|
renpy::interpreter interpreter_state;
|
||||||
//interpreter_state.reset(88);
|
//interpreter_state.reset(88);
|
||||||
//interpreter_state.reset(427);
|
//interpreter_state.reset(427);
|
||||||
interpreter_state.reset(0);
|
interpreter_state.reset(347);
|
||||||
//while (interpreter_state.pc < 543) {
|
//while (interpreter_state.pc < 543) {
|
||||||
/*
|
/*
|
||||||
while (interpreter_state.pc < 26) {
|
while (interpreter_state.pc < 26) {
|
||||||
@ -1054,7 +1086,8 @@ int main()
|
|||||||
bool useGamepad = false;
|
bool useGamepad = false;
|
||||||
uint32_t whichGamepad = 0;
|
uint32_t whichGamepad = 0;
|
||||||
|
|
||||||
SDL_Thread * audio_thread = SDL_CreateThread(mainAudio, "audio", &quit);
|
SDL_Thread * audio_thread = nullptr;
|
||||||
|
audio_thread = SDL_CreateThread(mainAudio, "audio", &quit);
|
||||||
|
|
||||||
while (quit == false) {
|
while (quit == false) {
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
@ -1125,7 +1158,10 @@ int main()
|
|||||||
float mx;
|
float mx;
|
||||||
float my;
|
float my;
|
||||||
uint32_t mouseFlags = SDL_GetMouseState(&mx, &my);
|
uint32_t mouseFlags = SDL_GetMouseState(&mx, &my);
|
||||||
|
static bool mLastLeft = false;
|
||||||
bool mLeft = (mouseFlags & SDL_BUTTON_LMASK) != 0;
|
bool mLeft = (mouseFlags & SDL_BUTTON_LMASK) != 0;
|
||||||
|
bool mEdge = (mLeft && (mLeft != mLastLeft));
|
||||||
|
mLastLeft = mLeft;
|
||||||
bool gUp = false;
|
bool gUp = false;
|
||||||
bool gDown = false;
|
bool gDown = false;
|
||||||
bool gAccept = false;
|
bool gAccept = false;
|
||||||
@ -1140,6 +1176,13 @@ int main()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float mxf;
|
||||||
|
float myf;
|
||||||
|
mouse::normalize(surfaceCapabilities.currentExtent.width,
|
||||||
|
surfaceCapabilities.currentExtent.height,
|
||||||
|
mx, my, &mxf, &myf);
|
||||||
|
ui::update(mxf, myf, mLeft, mEdge);
|
||||||
|
|
||||||
renpy::update(interpreter_state, mx, my, mLeft,
|
renpy::update(interpreter_state, mx, my, mLeft,
|
||||||
gUp, gDown, gAccept, useGamepad,
|
gUp, gDown, gAccept, useGamepad,
|
||||||
surfaceCapabilities.currentExtent.width,
|
surfaceCapabilities.currentExtent.width,
|
||||||
@ -1329,10 +1372,10 @@ int main()
|
|||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
if (interpreter_state.pause.dissolve) {
|
if (interpreter_state.pause.dissolve) {
|
||||||
offscreenRender(commandBuffer, frameIndex, mx, my, 2, true, renpy_state, interpreter_state, font_state, surfaceCapabilities);
|
offscreenRender(commandBuffer, frameIndex, mx, my, 2, true, renpy_state, interpreter_state, font_state, bitmap_font_state, ui_state, surfaceCapabilities);
|
||||||
} else {
|
} else {
|
||||||
offscreenRender(commandBuffer, frameIndex, mx, my, 0, true, renpy_state, interpreter_state, font_state, surfaceCapabilities);
|
offscreenRender(commandBuffer, frameIndex, mx, my, 0, true, renpy_state, interpreter_state, font_state, bitmap_font_state, ui_state, surfaceCapabilities);
|
||||||
offscreenRender(commandBuffer, frameIndex, mx, my, 1, false, renpy_state, interpreter_state, font_state, surfaceCapabilities);
|
offscreenRender(commandBuffer, frameIndex, mx, my, 1, false, renpy_state, interpreter_state, font_state, bitmap_font_state, ui_state, surfaceCapabilities);
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
@ -1541,6 +1584,7 @@ int main()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (audio_thread != nullptr)
|
||||||
SDL_WaitThread(audio_thread, nullptr);
|
SDL_WaitThread(audio_thread, nullptr);
|
||||||
VK_CHECK(vkDeviceWaitIdle(device));
|
VK_CHECK(vkDeviceWaitIdle(device));
|
||||||
|
|
||||||
|
|||||||
@ -285,241 +285,241 @@ const language::character characters[] = {
|
|||||||
const int characters_length = (sizeof (characters)) / (sizeof (characters[0]));
|
const int characters_length = (sizeof (characters)) / (sizeof (characters[0]));
|
||||||
|
|
||||||
const language::audio audio[] = {
|
const language::audio audio[] = {
|
||||||
{ .path = "audio/music/MistAmbience.opus.bin", .loop_end = 22.0, .audio_flags = audio::music, .attenuation = 1.0 }, // 0 music/MistAmbience.ogg
|
{ .path = "audio/music/MistAmbience.opus.bin", .loop_end = 22.0, .audio_flags = audio::music, .gain = 1.0 }, // 0 music/MistAmbience.ogg
|
||||||
{ .path = "audio/sfx/Chime.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 1 sfx/Chime.ogg
|
{ .path = "audio/sfx/Chime.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 1 sfx/Chime.ogg
|
||||||
{ .path = "audio/nara/n1.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 2 nara/n1.ogg
|
{ .path = "audio/nara/n1.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 2 nara/n1.ogg
|
||||||
{ .path = "audio/nara/n2.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 3 nara/n2.ogg
|
{ .path = "audio/nara/n2.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 3 nara/n2.ogg
|
||||||
{ .path = "audio/nara/n3.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 4 nara/n3.ogg
|
{ .path = "audio/nara/n3.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 4 nara/n3.ogg
|
||||||
{ .path = "audio/music/TinyForestMinstrels.opus.bin", .loop_end = 44.0, .audio_flags = audio::music, .attenuation = 0.45 }, // 5 music/TinyForestMinstrels.ogg
|
{ .path = "audio/music/TinyForestMinstrels.opus.bin", .loop_end = 44.0, .audio_flags = audio::music, .gain = 0.45 }, // 5 music/TinyForestMinstrels.ogg
|
||||||
{ .path = "audio/nara/n4.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 6 nara/n4.ogg
|
{ .path = "audio/nara/n4.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 6 nara/n4.ogg
|
||||||
{ .path = "audio/alice/a1.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 7 alice/a1.ogg
|
{ .path = "audio/alice/a1.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 7 alice/a1.ogg
|
||||||
{ .path = "audio/eily/e1.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 8 eily/e1.ogg
|
{ .path = "audio/eily/e1.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 8 eily/e1.ogg
|
||||||
{ .path = "audio/alice/a2.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 9 alice/a2.ogg
|
{ .path = "audio/alice/a2.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 9 alice/a2.ogg
|
||||||
{ .path = "audio/eily/e2.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 10 eily/e2.ogg
|
{ .path = "audio/eily/e2.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 10 eily/e2.ogg
|
||||||
{ .path = "audio/alice/a3.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 11 alice/a3.ogg
|
{ .path = "audio/alice/a3.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 11 alice/a3.ogg
|
||||||
{ .path = "audio/eily/e3.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 12 eily/e3.ogg
|
{ .path = "audio/eily/e3.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 12 eily/e3.ogg
|
||||||
{ .path = "audio/alice/a4.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 13 alice/a4.ogg
|
{ .path = "audio/alice/a4.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 13 alice/a4.ogg
|
||||||
{ .path = "audio/alice/a5.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 14 alice/a5.ogg
|
{ .path = "audio/alice/a5.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 14 alice/a5.ogg
|
||||||
{ .path = "audio/eily/e4.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 15 eily/e4.ogg
|
{ .path = "audio/eily/e4.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 15 eily/e4.ogg
|
||||||
{ .path = "audio/eily/e5.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 16 eily/e5.ogg
|
{ .path = "audio/eily/e5.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 16 eily/e5.ogg
|
||||||
{ .path = "audio/alice/a6.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 17 alice/a6.ogg
|
{ .path = "audio/alice/a6.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 17 alice/a6.ogg
|
||||||
{ .path = "audio/eily/e6.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 18 eily/e6.ogg
|
{ .path = "audio/eily/e6.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 18 eily/e6.ogg
|
||||||
{ .path = "audio/alice/a7.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 19 alice/a7.ogg
|
{ .path = "audio/alice/a7.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 19 alice/a7.ogg
|
||||||
{ .path = "audio/eily/e7.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 20 eily/e7.ogg
|
{ .path = "audio/eily/e7.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 20 eily/e7.ogg
|
||||||
{ .path = "audio/nara/n5.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 21 nara/n5.ogg
|
{ .path = "audio/nara/n5.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 21 nara/n5.ogg
|
||||||
{ .path = "audio/music/PhrygianButterflies.opus.bin", .loop_end = 40.2, .audio_flags = audio::music, .attenuation = 0.5 }, // 22 music/PhrygianButterflies.ogg
|
{ .path = "audio/music/PhrygianButterflies.opus.bin", .loop_end = 40.2, .audio_flags = audio::music, .gain = 0.5 }, // 22 music/PhrygianButterflies.ogg
|
||||||
{ .path = "audio/eily/e8.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 23 eily/e8.ogg
|
{ .path = "audio/eily/e8.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 23 eily/e8.ogg
|
||||||
{ .path = "audio/alice/a8.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 24 alice/a8.ogg
|
{ .path = "audio/alice/a8.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 24 alice/a8.ogg
|
||||||
{ .path = "audio/eily/e9.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 25 eily/e9.ogg
|
{ .path = "audio/eily/e9.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 25 eily/e9.ogg
|
||||||
{ .path = "audio/eily/e10.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 26 eily/e10.ogg
|
{ .path = "audio/eily/e10.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 26 eily/e10.ogg
|
||||||
{ .path = "audio/alice/a9.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 27 alice/a9.ogg
|
{ .path = "audio/alice/a9.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 27 alice/a9.ogg
|
||||||
{ .path = "audio/eily/e11.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 28 eily/e11.ogg
|
{ .path = "audio/eily/e11.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 28 eily/e11.ogg
|
||||||
{ .path = "audio/eily/e12.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 29 eily/e12.ogg
|
{ .path = "audio/eily/e12.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 29 eily/e12.ogg
|
||||||
{ .path = "audio/alice/a10.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 30 alice/a10.ogg
|
{ .path = "audio/alice/a10.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 30 alice/a10.ogg
|
||||||
{ .path = "audio/eily/e13.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 31 eily/e13.ogg
|
{ .path = "audio/eily/e13.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 31 eily/e13.ogg
|
||||||
{ .path = "audio/eily/e14.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 32 eily/e14.ogg
|
{ .path = "audio/eily/e14.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 32 eily/e14.ogg
|
||||||
{ .path = "audio/alice/a11.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 33 alice/a11.ogg
|
{ .path = "audio/alice/a11.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 33 alice/a11.ogg
|
||||||
{ .path = "audio/eily/e15.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 34 eily/e15.ogg
|
{ .path = "audio/eily/e15.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 34 eily/e15.ogg
|
||||||
{ .path = "audio/poem/EleanorTheHero.opus.bin", .loop_end = 0.0, .audio_flags = audio::poem, .attenuation = 1.0 }, // 35 poem/EleanorTheHero.ogg
|
{ .path = "audio/poem/EleanorTheHero.opus.bin", .loop_end = 0.0, .audio_flags = audio::poem, .gain = 1.0 }, // 35 poem/EleanorTheHero.ogg
|
||||||
{ .path = "audio/eily/e16.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 36 eily/e16.ogg
|
{ .path = "audio/eily/e16.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 36 eily/e16.ogg
|
||||||
{ .path = "audio/alice/a12.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 37 alice/a12.ogg
|
{ .path = "audio/alice/a12.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 37 alice/a12.ogg
|
||||||
{ .path = "audio/leona/c1.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 38 leona/c1.ogg
|
{ .path = "audio/leona/c1.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 38 leona/c1.ogg
|
||||||
{ .path = "audio/music/ScaredMice.opus.bin", .loop_end = 8.0, .audio_flags = audio::music, .attenuation = 1.0 }, // 39 music/ScaredMice.ogg
|
{ .path = "audio/music/ScaredMice.opus.bin", .loop_end = 8.0, .audio_flags = audio::music, .gain = 1.0 }, // 39 music/ScaredMice.ogg
|
||||||
{ .path = "audio/mousegirls/mg1.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 40 mousegirls/mg1.ogg
|
{ .path = "audio/mousegirls/mg1.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 40 mousegirls/mg1.ogg
|
||||||
{ .path = "audio/leona/c2.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 41 leona/c2.ogg
|
{ .path = "audio/leona/c2.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 41 leona/c2.ogg
|
||||||
{ .path = "audio/leona/c3.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 42 leona/c3.ogg
|
{ .path = "audio/leona/c3.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 42 leona/c3.ogg
|
||||||
{ .path = "audio/alice/a14.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 43 alice/a14.ogg
|
{ .path = "audio/alice/a14.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 43 alice/a14.ogg
|
||||||
{ .path = "audio/eily/e18.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 44 eily/e18.ogg
|
{ .path = "audio/eily/e18.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 44 eily/e18.ogg
|
||||||
{ .path = "audio/eily/e19.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 45 eily/e19.ogg
|
{ .path = "audio/eily/e19.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 45 eily/e19.ogg
|
||||||
{ .path = "audio/leona/c4.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 46 leona/c4.ogg
|
{ .path = "audio/leona/c4.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 46 leona/c4.ogg
|
||||||
{ .path = "audio/leona/c5.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 47 leona/c5.ogg
|
{ .path = "audio/leona/c5.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 47 leona/c5.ogg
|
||||||
{ .path = "audio/leona/c6.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 48 leona/c6.ogg
|
{ .path = "audio/leona/c6.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 48 leona/c6.ogg
|
||||||
{ .path = "audio/eily/e20.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 49 eily/e20.ogg
|
{ .path = "audio/eily/e20.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 49 eily/e20.ogg
|
||||||
{ .path = "audio/alice/a15.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 50 alice/a15.ogg
|
{ .path = "audio/alice/a15.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 50 alice/a15.ogg
|
||||||
{ .path = "audio/eily/e21.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 51 eily/e21.ogg
|
{ .path = "audio/eily/e21.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 51 eily/e21.ogg
|
||||||
{ .path = "audio/leona/c7.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 52 leona/c7.ogg
|
{ .path = "audio/leona/c7.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 52 leona/c7.ogg
|
||||||
{ .path = "audio/leona/c8.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 53 leona/c8.ogg
|
{ .path = "audio/leona/c8.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 53 leona/c8.ogg
|
||||||
{ .path = "audio/eily/e22.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 54 eily/e22.ogg
|
{ .path = "audio/eily/e22.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 54 eily/e22.ogg
|
||||||
{ .path = "audio/leona/c9.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 55 leona/c9.ogg
|
{ .path = "audio/leona/c9.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 55 leona/c9.ogg
|
||||||
{ .path = "audio/eily/e23.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 56 eily/e23.ogg
|
{ .path = "audio/eily/e23.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 56 eily/e23.ogg
|
||||||
{ .path = "audio/leona/c10.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 57 leona/c10.ogg
|
{ .path = "audio/leona/c10.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 57 leona/c10.ogg
|
||||||
{ .path = "audio/eily/e24.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 58 eily/e24.ogg
|
{ .path = "audio/eily/e24.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 58 eily/e24.ogg
|
||||||
{ .path = "audio/leona/c11.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 59 leona/c11.ogg
|
{ .path = "audio/leona/c11.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 59 leona/c11.ogg
|
||||||
{ .path = "audio/eily/e25.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 60 eily/e25.ogg
|
{ .path = "audio/eily/e25.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 60 eily/e25.ogg
|
||||||
{ .path = "audio/leona/c12.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 61 leona/c12.ogg
|
{ .path = "audio/leona/c12.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 61 leona/c12.ogg
|
||||||
{ .path = "audio/leona/c13.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 62 leona/c13.ogg
|
{ .path = "audio/leona/c13.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 62 leona/c13.ogg
|
||||||
{ .path = "audio/eily/e26.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 63 eily/e26.ogg
|
{ .path = "audio/eily/e26.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 63 eily/e26.ogg
|
||||||
{ .path = "audio/eily/e27.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 64 eily/e27.ogg
|
{ .path = "audio/eily/e27.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 64 eily/e27.ogg
|
||||||
{ .path = "audio/leona/c14.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 65 leona/c14.ogg
|
{ .path = "audio/leona/c14.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 65 leona/c14.ogg
|
||||||
{ .path = "audio/alice/a16.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 66 alice/a16.ogg
|
{ .path = "audio/alice/a16.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 66 alice/a16.ogg
|
||||||
{ .path = "audio/leona/c15.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 67 leona/c15.ogg
|
{ .path = "audio/leona/c15.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 67 leona/c15.ogg
|
||||||
{ .path = "audio/leona/c16.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 68 leona/c16.ogg
|
{ .path = "audio/leona/c16.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 68 leona/c16.ogg
|
||||||
{ .path = "audio/leona/c17.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 69 leona/c17.ogg
|
{ .path = "audio/leona/c17.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 69 leona/c17.ogg
|
||||||
{ .path = "audio/alice/a17.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 70 alice/a17.ogg
|
{ .path = "audio/alice/a17.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 70 alice/a17.ogg
|
||||||
{ .path = "audio/eily/e28.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 71 eily/e28.ogg
|
{ .path = "audio/eily/e28.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 71 eily/e28.ogg
|
||||||
{ .path = "audio/alice/a18.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 72 alice/a18.ogg
|
{ .path = "audio/alice/a18.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 72 alice/a18.ogg
|
||||||
{ .path = "audio/eily/e29.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 73 eily/e29.ogg
|
{ .path = "audio/eily/e29.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 73 eily/e29.ogg
|
||||||
{ .path = "audio/nara/n6.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 74 nara/n6.ogg
|
{ .path = "audio/nara/n6.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 74 nara/n6.ogg
|
||||||
{ .path = "audio/eily/e30.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 75 eily/e30.ogg
|
{ .path = "audio/eily/e30.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 75 eily/e30.ogg
|
||||||
{ .path = "audio/alice/a19.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 76 alice/a19.ogg
|
{ .path = "audio/alice/a19.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 76 alice/a19.ogg
|
||||||
{ .path = "audio/eily/e31.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 77 eily/e31.ogg
|
{ .path = "audio/eily/e31.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 77 eily/e31.ogg
|
||||||
{ .path = "audio/alice/a20.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 78 alice/a20.ogg
|
{ .path = "audio/alice/a20.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 78 alice/a20.ogg
|
||||||
{ .path = "audio/leona/c18.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 79 leona/c18.ogg
|
{ .path = "audio/leona/c18.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 79 leona/c18.ogg
|
||||||
{ .path = "audio/eily/e32.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 80 eily/e32.ogg
|
{ .path = "audio/eily/e32.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 80 eily/e32.ogg
|
||||||
{ .path = "audio/alice/a21.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 81 alice/a21.ogg
|
{ .path = "audio/alice/a21.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 81 alice/a21.ogg
|
||||||
{ .path = "audio/eily/e33.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 82 eily/e33.ogg
|
{ .path = "audio/eily/e33.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 82 eily/e33.ogg
|
||||||
{ .path = "audio/leona/c19.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 83 leona/c19.ogg
|
{ .path = "audio/leona/c19.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 83 leona/c19.ogg
|
||||||
{ .path = "audio/leona/c20.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 84 leona/c20.ogg
|
{ .path = "audio/leona/c20.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 84 leona/c20.ogg
|
||||||
{ .path = "audio/leona/c21.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 85 leona/c21.ogg
|
{ .path = "audio/leona/c21.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 85 leona/c21.ogg
|
||||||
{ .path = "audio/alice/a22.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 86 alice/a22.ogg
|
{ .path = "audio/alice/a22.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 86 alice/a22.ogg
|
||||||
{ .path = "audio/leona/c22.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 87 leona/c22.ogg
|
{ .path = "audio/leona/c22.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 87 leona/c22.ogg
|
||||||
{ .path = "audio/leona/c23.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 88 leona/c23.ogg
|
{ .path = "audio/leona/c23.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 88 leona/c23.ogg
|
||||||
{ .path = "audio/alice/a23.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 89 alice/a23.ogg
|
{ .path = "audio/alice/a23.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 89 alice/a23.ogg
|
||||||
{ .path = "audio/eily/e34.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 90 eily/e34.ogg
|
{ .path = "audio/eily/e34.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 90 eily/e34.ogg
|
||||||
{ .path = "audio/alice/a24.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 91 alice/a24.ogg
|
{ .path = "audio/alice/a24.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 91 alice/a24.ogg
|
||||||
{ .path = "audio/eily/e35.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 92 eily/e35.ogg
|
{ .path = "audio/eily/e35.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 92 eily/e35.ogg
|
||||||
{ .path = "audio/leona/c24.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 93 leona/c24.ogg
|
{ .path = "audio/leona/c24.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 93 leona/c24.ogg
|
||||||
{ .path = "audio/leona/c25.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 94 leona/c25.ogg
|
{ .path = "audio/leona/c25.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 94 leona/c25.ogg
|
||||||
{ .path = "audio/leona/c26.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 95 leona/c26.ogg
|
{ .path = "audio/leona/c26.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 95 leona/c26.ogg
|
||||||
{ .path = "audio/eily/e36.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 96 eily/e36.ogg
|
{ .path = "audio/eily/e36.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 96 eily/e36.ogg
|
||||||
{ .path = "audio/eily/e37.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 97 eily/e37.ogg
|
{ .path = "audio/eily/e37.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 97 eily/e37.ogg
|
||||||
{ .path = "audio/eily/e38.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 98 eily/e38.ogg
|
{ .path = "audio/eily/e38.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 98 eily/e38.ogg
|
||||||
{ .path = "audio/eily/e39.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 99 eily/e39.ogg
|
{ .path = "audio/eily/e39.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 99 eily/e39.ogg
|
||||||
{ .path = "audio/eily/e40.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 100 eily/e40.ogg
|
{ .path = "audio/eily/e40.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 100 eily/e40.ogg
|
||||||
{ .path = "audio/eily/e41.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 101 eily/e41.ogg
|
{ .path = "audio/eily/e41.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 101 eily/e41.ogg
|
||||||
{ .path = "audio/eily/e42.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 102 eily/e42.ogg
|
{ .path = "audio/eily/e42.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 102 eily/e42.ogg
|
||||||
{ .path = "audio/alice/a25.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 103 alice/a25.ogg
|
{ .path = "audio/alice/a25.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 103 alice/a25.ogg
|
||||||
{ .path = "audio/eily/e43.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 104 eily/e43.ogg
|
{ .path = "audio/eily/e43.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 104 eily/e43.ogg
|
||||||
{ .path = "audio/alice/a26.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 105 alice/a26.ogg
|
{ .path = "audio/alice/a26.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 105 alice/a26.ogg
|
||||||
{ .path = "audio/eily/e44.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 106 eily/e44.ogg
|
{ .path = "audio/eily/e44.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 106 eily/e44.ogg
|
||||||
{ .path = "audio/eily/e45.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 107 eily/e45.ogg
|
{ .path = "audio/eily/e45.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 107 eily/e45.ogg
|
||||||
{ .path = "audio/alice/a27.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 108 alice/a27.ogg
|
{ .path = "audio/alice/a27.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 108 alice/a27.ogg
|
||||||
{ .path = "audio/eily/e46.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 109 eily/e46.ogg
|
{ .path = "audio/eily/e46.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 109 eily/e46.ogg
|
||||||
{ .path = "audio/alice/a28.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 110 alice/a28.ogg
|
{ .path = "audio/alice/a28.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 110 alice/a28.ogg
|
||||||
{ .path = "audio/leona/c27.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 111 leona/c27.ogg
|
{ .path = "audio/leona/c27.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 111 leona/c27.ogg
|
||||||
{ .path = "audio/eily/e47.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 112 eily/e47.ogg
|
{ .path = "audio/eily/e47.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 112 eily/e47.ogg
|
||||||
{ .path = "audio/alice/a29.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 113 alice/a29.ogg
|
{ .path = "audio/alice/a29.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 113 alice/a29.ogg
|
||||||
{ .path = "audio/leona/c28.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 114 leona/c28.ogg
|
{ .path = "audio/leona/c28.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 114 leona/c28.ogg
|
||||||
{ .path = "audio/leona/c29.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 115 leona/c29.ogg
|
{ .path = "audio/leona/c29.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 115 leona/c29.ogg
|
||||||
{ .path = "audio/eily/e48.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 116 eily/e48.ogg
|
{ .path = "audio/eily/e48.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 116 eily/e48.ogg
|
||||||
{ .path = "audio/leona/c30.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 117 leona/c30.ogg
|
{ .path = "audio/leona/c30.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 117 leona/c30.ogg
|
||||||
{ .path = "audio/alice/a30.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 118 alice/a30.ogg
|
{ .path = "audio/alice/a30.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 118 alice/a30.ogg
|
||||||
{ .path = "audio/eily/e49.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 119 eily/e49.ogg
|
{ .path = "audio/eily/e49.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 119 eily/e49.ogg
|
||||||
{ .path = "audio/eily/e50.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 120 eily/e50.ogg
|
{ .path = "audio/eily/e50.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 120 eily/e50.ogg
|
||||||
{ .path = "audio/eily/e51.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 121 eily/e51.ogg
|
{ .path = "audio/eily/e51.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 121 eily/e51.ogg
|
||||||
{ .path = "audio/eily/e52.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 122 eily/e52.ogg
|
{ .path = "audio/eily/e52.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 122 eily/e52.ogg
|
||||||
{ .path = "audio/eily/e53.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 123 eily/e53.ogg
|
{ .path = "audio/eily/e53.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 123 eily/e53.ogg
|
||||||
{ .path = "audio/eily/e54.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 124 eily/e54.ogg
|
{ .path = "audio/eily/e54.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 124 eily/e54.ogg
|
||||||
{ .path = "audio/alice/a31.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 125 alice/a31.ogg
|
{ .path = "audio/alice/a31.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 125 alice/a31.ogg
|
||||||
{ .path = "audio/leona/c31.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 126 leona/c31.ogg
|
{ .path = "audio/leona/c31.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 126 leona/c31.ogg
|
||||||
{ .path = "audio/leona/c32.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 127 leona/c32.ogg
|
{ .path = "audio/leona/c32.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 127 leona/c32.ogg
|
||||||
{ .path = "audio/alice/a32.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 128 alice/a32.ogg
|
{ .path = "audio/alice/a32.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 128 alice/a32.ogg
|
||||||
{ .path = "audio/leona/c33.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 129 leona/c33.ogg
|
{ .path = "audio/leona/c33.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 129 leona/c33.ogg
|
||||||
{ .path = "audio/mousegirls/mg2.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 130 mousegirls/mg2.ogg
|
{ .path = "audio/mousegirls/mg2.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 130 mousegirls/mg2.ogg
|
||||||
{ .path = "audio/leona/c34.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 131 leona/c34.ogg
|
{ .path = "audio/leona/c34.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 131 leona/c34.ogg
|
||||||
{ .path = "audio/leona/c35.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 132 leona/c35.ogg
|
{ .path = "audio/leona/c35.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 132 leona/c35.ogg
|
||||||
{ .path = "audio/alice/a33.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 133 alice/a33.ogg
|
{ .path = "audio/alice/a33.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 133 alice/a33.ogg
|
||||||
{ .path = "audio/eily/e55.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 134 eily/e55.ogg
|
{ .path = "audio/eily/e55.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 134 eily/e55.ogg
|
||||||
{ .path = "audio/leona/c36.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 135 leona/c36.ogg
|
{ .path = "audio/leona/c36.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 135 leona/c36.ogg
|
||||||
{ .path = "audio/alice/a34.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 136 alice/a34.ogg
|
{ .path = "audio/alice/a34.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 136 alice/a34.ogg
|
||||||
{ .path = "audio/eily/e56.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 137 eily/e56.ogg
|
{ .path = "audio/eily/e56.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 137 eily/e56.ogg
|
||||||
{ .path = "audio/nara/n7.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 138 nara/n7.ogg
|
{ .path = "audio/nara/n7.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 138 nara/n7.ogg
|
||||||
{ .path = "audio/music/WheatFields.opus.bin", .loop_end = 34.0, .audio_flags = audio::music, .attenuation = 1.0 }, // 139 music/WheatFields.ogg
|
{ .path = "audio/music/WheatFields.opus.bin", .loop_end = 34.0, .audio_flags = audio::music, .gain = 1.0 }, // 139 music/WheatFields.ogg
|
||||||
{ .path = "audio/leona/c37.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 140 leona/c37.ogg
|
{ .path = "audio/leona/c37.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 140 leona/c37.ogg
|
||||||
{ .path = "audio/alice/a35.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 141 alice/a35.ogg
|
{ .path = "audio/alice/a35.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 141 alice/a35.ogg
|
||||||
{ .path = "audio/eily/e57.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 142 eily/e57.ogg
|
{ .path = "audio/eily/e57.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 142 eily/e57.ogg
|
||||||
{ .path = "audio/leona/c38.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 143 leona/c38.ogg
|
{ .path = "audio/leona/c38.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 143 leona/c38.ogg
|
||||||
{ .path = "audio/leona/c39.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 144 leona/c39.ogg
|
{ .path = "audio/leona/c39.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 144 leona/c39.ogg
|
||||||
{ .path = "audio/eily/e58.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 145 eily/e58.ogg
|
{ .path = "audio/eily/e58.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 145 eily/e58.ogg
|
||||||
{ .path = "audio/alice/a36.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 146 alice/a36.ogg
|
{ .path = "audio/alice/a36.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 146 alice/a36.ogg
|
||||||
{ .path = "audio/eily/e59.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 147 eily/e59.ogg
|
{ .path = "audio/eily/e59.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 147 eily/e59.ogg
|
||||||
{ .path = "audio/eily/e60.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 148 eily/e60.ogg
|
{ .path = "audio/eily/e60.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 148 eily/e60.ogg
|
||||||
{ .path = "audio/leona/c40.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 149 leona/c40.ogg
|
{ .path = "audio/leona/c40.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 149 leona/c40.ogg
|
||||||
{ .path = "audio/eily/e61.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 150 eily/e61.ogg
|
{ .path = "audio/eily/e61.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 150 eily/e61.ogg
|
||||||
{ .path = "audio/leona/c41.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 151 leona/c41.ogg
|
{ .path = "audio/leona/c41.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 151 leona/c41.ogg
|
||||||
{ .path = "audio/leona/c42.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 152 leona/c42.ogg
|
{ .path = "audio/leona/c42.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 152 leona/c42.ogg
|
||||||
{ .path = "audio/alice/a37.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 153 alice/a37.ogg
|
{ .path = "audio/alice/a37.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 153 alice/a37.ogg
|
||||||
{ .path = "audio/eily/e62.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 154 eily/e62.ogg
|
{ .path = "audio/eily/e62.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 154 eily/e62.ogg
|
||||||
{ .path = "audio/leona/c43.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 155 leona/c43.ogg
|
{ .path = "audio/leona/c43.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 155 leona/c43.ogg
|
||||||
{ .path = "audio/eily/e63.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 156 eily/e63.ogg
|
{ .path = "audio/eily/e63.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 156 eily/e63.ogg
|
||||||
{ .path = "audio/leona/c44.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 157 leona/c44.ogg
|
{ .path = "audio/leona/c44.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 157 leona/c44.ogg
|
||||||
{ .path = "audio/leona/c45.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 158 leona/c45.ogg
|
{ .path = "audio/leona/c45.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 158 leona/c45.ogg
|
||||||
{ .path = "audio/leona/c46.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 159 leona/c46.ogg
|
{ .path = "audio/leona/c46.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 159 leona/c46.ogg
|
||||||
{ .path = "audio/eily/e64.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 160 eily/e64.ogg
|
{ .path = "audio/eily/e64.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 160 eily/e64.ogg
|
||||||
{ .path = "audio/leona/c47.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 161 leona/c47.ogg
|
{ .path = "audio/leona/c47.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 161 leona/c47.ogg
|
||||||
{ .path = "audio/eily/e65.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 162 eily/e65.ogg
|
{ .path = "audio/eily/e65.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 162 eily/e65.ogg
|
||||||
{ .path = "audio/leona/c48.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 163 leona/c48.ogg
|
{ .path = "audio/leona/c48.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 163 leona/c48.ogg
|
||||||
{ .path = "audio/leona/c49.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 164 leona/c49.ogg
|
{ .path = "audio/leona/c49.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 164 leona/c49.ogg
|
||||||
{ .path = "audio/leona/c50.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 165 leona/c50.ogg
|
{ .path = "audio/leona/c50.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 165 leona/c50.ogg
|
||||||
{ .path = "audio/mousegirls/mg3.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 166 mousegirls/mg3.ogg
|
{ .path = "audio/mousegirls/mg3.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 166 mousegirls/mg3.ogg
|
||||||
{ .path = "audio/leona/c51.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 167 leona/c51.ogg
|
{ .path = "audio/leona/c51.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 167 leona/c51.ogg
|
||||||
{ .path = "audio/leona/c52.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 168 leona/c52.ogg
|
{ .path = "audio/leona/c52.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 168 leona/c52.ogg
|
||||||
{ .path = "audio/leona/c53.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 169 leona/c53.ogg
|
{ .path = "audio/leona/c53.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 169 leona/c53.ogg
|
||||||
{ .path = "audio/poem/KiriStella.opus.bin", .loop_end = 0.0, .audio_flags = audio::poem, .attenuation = 1.0 }, // 170 poem/KiriStella.ogg
|
{ .path = "audio/poem/KiriStella.opus.bin", .loop_end = 0.0, .audio_flags = audio::poem, .gain = 1.0 }, // 170 poem/KiriStella.ogg
|
||||||
{ .path = "audio/leona/c54.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 171 leona/c54.ogg
|
{ .path = "audio/leona/c54.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 171 leona/c54.ogg
|
||||||
{ .path = "audio/leona/c55.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 172 leona/c55.ogg
|
{ .path = "audio/leona/c55.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 172 leona/c55.ogg
|
||||||
{ .path = "audio/alice/a39.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 173 alice/a39.ogg
|
{ .path = "audio/alice/a39.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 173 alice/a39.ogg
|
||||||
{ .path = "audio/eily/e67.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 174 eily/e67.ogg
|
{ .path = "audio/eily/e67.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 174 eily/e67.ogg
|
||||||
{ .path = "audio/eily/e68.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 175 eily/e68.ogg
|
{ .path = "audio/eily/e68.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 175 eily/e68.ogg
|
||||||
{ .path = "audio/leona/c56.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 176 leona/c56.ogg
|
{ .path = "audio/leona/c56.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 176 leona/c56.ogg
|
||||||
{ .path = "audio/nara/n8.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 177 nara/n8.ogg
|
{ .path = "audio/nara/n8.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 177 nara/n8.ogg
|
||||||
{ .path = "audio/nara/n9.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 178 nara/n9.ogg
|
{ .path = "audio/nara/n9.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 178 nara/n9.ogg
|
||||||
{ .path = "audio/nara/n10.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 179 nara/n10.ogg
|
{ .path = "audio/nara/n10.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 179 nara/n10.ogg
|
||||||
{ .path = "audio/hera/h1.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 180 hera/h1.ogg
|
{ .path = "audio/hera/h1.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 180 hera/h1.ogg
|
||||||
{ .path = "audio/music/Preludium.opus.bin", .loop_end = 58.2, .audio_flags = audio::music, .attenuation = 0.45 }, // 181 music/Preludium.ogg
|
{ .path = "audio/music/Preludium.opus.bin", .loop_end = 58.2, .audio_flags = audio::music, .gain = 0.45 }, // 181 music/Preludium.ogg
|
||||||
{ .path = "audio/hera/h2.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 182 hera/h2.ogg
|
{ .path = "audio/hera/h2.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 182 hera/h2.ogg
|
||||||
{ .path = "audio/leona/c57.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 183 leona/c57.ogg
|
{ .path = "audio/leona/c57.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 183 leona/c57.ogg
|
||||||
{ .path = "audio/hera/h3.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 184 hera/h3.ogg
|
{ .path = "audio/hera/h3.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 184 hera/h3.ogg
|
||||||
{ .path = "audio/eily/e69.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 185 eily/e69.ogg
|
{ .path = "audio/eily/e69.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 185 eily/e69.ogg
|
||||||
{ .path = "audio/hera/h4.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 186 hera/h4.ogg
|
{ .path = "audio/hera/h4.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 186 hera/h4.ogg
|
||||||
{ .path = "audio/sfx/Glass.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 187 sfx/Glass.ogg
|
{ .path = "audio/sfx/Glass.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 187 sfx/Glass.ogg
|
||||||
{ .path = "audio/alice/a40.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 188 alice/a40.ogg
|
{ .path = "audio/alice/a40.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 188 alice/a40.ogg
|
||||||
{ .path = "audio/alice/a41.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 189 alice/a41.ogg
|
{ .path = "audio/alice/a41.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 189 alice/a41.ogg
|
||||||
{ .path = "audio/leona/c58.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 190 leona/c58.ogg
|
{ .path = "audio/leona/c58.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 190 leona/c58.ogg
|
||||||
{ .path = "audio/bird/b1.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 191 bird/b1.ogg
|
{ .path = "audio/bird/b1.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 191 bird/b1.ogg
|
||||||
{ .path = "audio/bird/b2.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 192 bird/b2.ogg
|
{ .path = "audio/bird/b2.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 192 bird/b2.ogg
|
||||||
{ .path = "audio/bird/b3.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 193 bird/b3.ogg
|
{ .path = "audio/bird/b3.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 193 bird/b3.ogg
|
||||||
{ .path = "audio/leona/c59.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 194 leona/c59.ogg
|
{ .path = "audio/leona/c59.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 194 leona/c59.ogg
|
||||||
{ .path = "audio/eily/e70.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 195 eily/e70.ogg
|
{ .path = "audio/eily/e70.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 195 eily/e70.ogg
|
||||||
{ .path = "audio/bird/b4.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 196 bird/b4.ogg
|
{ .path = "audio/bird/b4.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 196 bird/b4.ogg
|
||||||
{ .path = "audio/bird/b5.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 197 bird/b5.ogg
|
{ .path = "audio/bird/b5.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 197 bird/b5.ogg
|
||||||
{ .path = "audio/leona/c60.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 198 leona/c60.ogg
|
{ .path = "audio/leona/c60.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 198 leona/c60.ogg
|
||||||
{ .path = "audio/leona/c61.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 199 leona/c61.ogg
|
{ .path = "audio/leona/c61.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 199 leona/c61.ogg
|
||||||
{ .path = "audio/bird/b6.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 200 bird/b6.ogg
|
{ .path = "audio/bird/b6.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 200 bird/b6.ogg
|
||||||
{ .path = "audio/bird/b7.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 201 bird/b7.ogg
|
{ .path = "audio/bird/b7.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 201 bird/b7.ogg
|
||||||
{ .path = "audio/leona/c0.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 202 leona/c0.ogg
|
{ .path = "audio/leona/c0.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 202 leona/c0.ogg
|
||||||
{ .path = "audio/bird/b8.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 203 bird/b8.ogg
|
{ .path = "audio/bird/b8.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 203 bird/b8.ogg
|
||||||
{ .path = "audio/bird/b9.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 204 bird/b9.ogg
|
{ .path = "audio/bird/b9.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 204 bird/b9.ogg
|
||||||
{ .path = "audio/bird/b10.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 205 bird/b10.ogg
|
{ .path = "audio/bird/b10.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 205 bird/b10.ogg
|
||||||
{ .path = "audio/leona/c62.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 206 leona/c62.ogg
|
{ .path = "audio/leona/c62.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 206 leona/c62.ogg
|
||||||
{ .path = "audio/bird/b11.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 207 bird/b11.ogg
|
{ .path = "audio/bird/b11.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 207 bird/b11.ogg
|
||||||
{ .path = "audio/bird/b12.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 208 bird/b12.ogg
|
{ .path = "audio/bird/b12.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 208 bird/b12.ogg
|
||||||
{ .path = "audio/bird/b13.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 209 bird/b13.ogg
|
{ .path = "audio/bird/b13.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 209 bird/b13.ogg
|
||||||
{ .path = "audio/leona/c63.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 210 leona/c63.ogg
|
{ .path = "audio/leona/c63.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 210 leona/c63.ogg
|
||||||
{ .path = "audio/bird/b14.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 211 bird/b14.ogg
|
{ .path = "audio/bird/b14.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 211 bird/b14.ogg
|
||||||
{ .path = "audio/leona/c64.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 212 leona/c64.ogg
|
{ .path = "audio/leona/c64.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 212 leona/c64.ogg
|
||||||
{ .path = "audio/bird/b15.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 213 bird/b15.ogg
|
{ .path = "audio/bird/b15.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 213 bird/b15.ogg
|
||||||
{ .path = "audio/leona/c65.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 214 leona/c65.ogg
|
{ .path = "audio/leona/c65.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 214 leona/c65.ogg
|
||||||
{ .path = "audio/leona/c66.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 215 leona/c66.ogg
|
{ .path = "audio/leona/c66.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 215 leona/c66.ogg
|
||||||
{ .path = "audio/bird/b16.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 216 bird/b16.ogg
|
{ .path = "audio/bird/b16.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 216 bird/b16.ogg
|
||||||
{ .path = "audio/bird/b17.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 217 bird/b17.ogg
|
{ .path = "audio/bird/b17.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 217 bird/b17.ogg
|
||||||
{ .path = "audio/alice/a42.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 218 alice/a42.ogg
|
{ .path = "audio/alice/a42.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 218 alice/a42.ogg
|
||||||
{ .path = "audio/eily/e71.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 219 eily/e71.ogg
|
{ .path = "audio/eily/e71.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 219 eily/e71.ogg
|
||||||
{ .path = "audio/eily/e72.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 220 eily/e72.ogg
|
{ .path = "audio/eily/e72.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 220 eily/e72.ogg
|
||||||
{ .path = "audio/eily/e73.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 221 eily/e73.ogg
|
{ .path = "audio/eily/e73.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 221 eily/e73.ogg
|
||||||
{ .path = "audio/eily/e74.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 222 eily/e74.ogg
|
{ .path = "audio/eily/e74.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 222 eily/e74.ogg
|
||||||
{ .path = "audio/eily/e75.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 223 eily/e75.ogg
|
{ .path = "audio/eily/e75.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 223 eily/e75.ogg
|
||||||
{ .path = "audio/eily/e76.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 224 eily/e76.ogg
|
{ .path = "audio/eily/e76.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 224 eily/e76.ogg
|
||||||
{ .path = "audio/bird/b18.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 225 bird/b18.ogg
|
{ .path = "audio/bird/b18.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 225 bird/b18.ogg
|
||||||
{ .path = "audio/leona/c67.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 226 leona/c67.ogg
|
{ .path = "audio/leona/c67.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 226 leona/c67.ogg
|
||||||
{ .path = "audio/alice/a43.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 227 alice/a43.ogg
|
{ .path = "audio/alice/a43.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 227 alice/a43.ogg
|
||||||
{ .path = "audio/eily/e77.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 228 eily/e77.ogg
|
{ .path = "audio/eily/e77.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 228 eily/e77.ogg
|
||||||
{ .path = "audio/bird/b19.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 229 bird/b19.ogg
|
{ .path = "audio/bird/b19.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 229 bird/b19.ogg
|
||||||
{ .path = "audio/bird/b20.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 230 bird/b20.ogg
|
{ .path = "audio/bird/b20.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 230 bird/b20.ogg
|
||||||
{ .path = "audio/poem/BirdSong.opus.bin", .loop_end = 0.0, .audio_flags = audio::poem, .attenuation = 1.0 }, // 231 poem/BirdSong.ogg
|
{ .path = "audio/poem/BirdSong.opus.bin", .loop_end = 0.0, .audio_flags = audio::poem, .gain = 1.0 }, // 231 poem/BirdSong.ogg
|
||||||
{ .path = "audio/nara/n11.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 232 nara/n11.ogg
|
{ .path = "audio/nara/n11.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 232 nara/n11.ogg
|
||||||
{ .path = "audio/nara/n12.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 233 nara/n12.ogg
|
{ .path = "audio/nara/n12.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 233 nara/n12.ogg
|
||||||
{ .path = "audio/nara/n13.opus.bin", .loop_end = 0.0, .audio_flags = 0, .attenuation = 1.0 }, // 234 nara/n13.ogg
|
{ .path = "audio/nara/n13.opus.bin", .loop_end = 0.0, .audio_flags = 0, .gain = 1.0 }, // 234 nara/n13.ogg
|
||||||
};
|
};
|
||||||
|
|
||||||
const int audio_length = (sizeof (audio)) / (sizeof (audio[0]));
|
const int audio_length = (sizeof (audio)) / (sizeof (audio[0]));
|
||||||
|
|||||||
@ -640,7 +640,7 @@ namespace renpy {
|
|||||||
{
|
{
|
||||||
.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
|
.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
|
||||||
.memory = instanceMemory,
|
.memory = instanceMemory,
|
||||||
.offset = 0,
|
.offset = instanceBufferOffset[frameIndex],
|
||||||
.size = (sizeof (ImageInstance)) * outputIndex,
|
.size = (sizeof (ImageInstance)) * outputIndex,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
169
src/ui.cpp
Normal file
169
src/ui.cpp
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
#include "ui.h"
|
||||||
|
#include "audio.h"
|
||||||
|
|
||||||
|
namespace ui
|
||||||
|
{
|
||||||
|
constexpr int top = 75;
|
||||||
|
constexpr int ySpace = 120;
|
||||||
|
constexpr int yMixSpace = 60;
|
||||||
|
|
||||||
|
constexpr int inputMixLeft = 100;
|
||||||
|
constexpr int allpassLeft = 400;
|
||||||
|
constexpr int combLeft = 700;
|
||||||
|
constexpr int outputMixLeft = 1000;
|
||||||
|
|
||||||
|
#define BREVERB audio::fbreverb
|
||||||
|
#define FREVERB audio::ffreverb
|
||||||
|
|
||||||
|
widget::DelayGainSlider fap[3] {
|
||||||
|
widget::DelayGainSlider("allpass 0",
|
||||||
|
allpassLeft, top + ySpace * 0,
|
||||||
|
1, 2500, &FREVERB.ap[0].delay,
|
||||||
|
0.0, 1.0, &FREVERB.ap[0].gain0, &FREVERB.ap[0].gainM),
|
||||||
|
widget::DelayGainSlider("allpass 1",
|
||||||
|
allpassLeft, top + ySpace * 1,
|
||||||
|
1, 2500, &FREVERB.ap[1].delay,
|
||||||
|
0.0, 1.0, &FREVERB.ap[1].gain0, &FREVERB.ap[1].gainM),
|
||||||
|
widget::DelayGainSlider("allpass 2",
|
||||||
|
allpassLeft, top + ySpace * 2,
|
||||||
|
1, 2500, &FREVERB.ap[2].delay,
|
||||||
|
0.0, 1.0, &FREVERB.ap[2].gain0, &FREVERB.ap[2].gainM),
|
||||||
|
};
|
||||||
|
|
||||||
|
widget::DelayGainSlider fcomb[4] {
|
||||||
|
widget::DelayGainSlider("comb 0",
|
||||||
|
combLeft, top + ySpace * 0,
|
||||||
|
100, 15000, &FREVERB.cf[0].delay,
|
||||||
|
0.0, 1.0, &FREVERB.cf[0].gain0, &FREVERB.cf[0].gainM),
|
||||||
|
widget::DelayGainSlider("comb 1",
|
||||||
|
combLeft, top + ySpace * 1,
|
||||||
|
100, 15000, &FREVERB.cf[1].delay,
|
||||||
|
0.0, 1.0, &FREVERB.cf[1].gain0, &FREVERB.cf[1].gainM),
|
||||||
|
widget::DelayGainSlider("comb 2",
|
||||||
|
combLeft, top + ySpace * 2,
|
||||||
|
100, 15000, &FREVERB.cf[2].delay,
|
||||||
|
0.0, 1.0, &FREVERB.cf[2].gain0, &FREVERB.cf[2].gainM),
|
||||||
|
widget::DelayGainSlider("comb 3",
|
||||||
|
combLeft, top + ySpace * 3,
|
||||||
|
100, 15000, &FREVERB.cf[3].delay,
|
||||||
|
0.0, 1.0, &FREVERB.cf[3].gain0, &FREVERB.cf[3].gainM),
|
||||||
|
};
|
||||||
|
|
||||||
|
widget::DelayGainSlider bap[3] {
|
||||||
|
widget::DelayGainSlider("allpass 0",
|
||||||
|
allpassLeft, top + ySpace * 0,
|
||||||
|
1, 2500, &BREVERB.ap[0].delay,
|
||||||
|
0.0, 1.0, &BREVERB.ap[0].gain0, &BREVERB.ap[0].gainM),
|
||||||
|
widget::DelayGainSlider("allpass 1",
|
||||||
|
allpassLeft, top + ySpace * 1,
|
||||||
|
1, 2500, &BREVERB.ap[1].delay,
|
||||||
|
0.0, 1.0, &BREVERB.ap[1].gain0, &BREVERB.ap[1].gainM),
|
||||||
|
widget::DelayGainSlider("allpass 2",
|
||||||
|
allpassLeft, top + ySpace * 2,
|
||||||
|
1, 2500, &BREVERB.ap[2].delay,
|
||||||
|
0.0, 1.0, &BREVERB.ap[2].gain0, &BREVERB.ap[2].gainM),
|
||||||
|
};
|
||||||
|
|
||||||
|
widget::DelayGainSlider bcomb[4] {
|
||||||
|
widget::DelayGainSlider("comb 0",
|
||||||
|
combLeft, top + ySpace * 0,
|
||||||
|
100, 15000, &BREVERB.cf[0].delay,
|
||||||
|
0.0, 1.0, &BREVERB.cf[0].gain0, &BREVERB.cf[0].gainM),
|
||||||
|
widget::DelayGainSlider("comb 1",
|
||||||
|
combLeft, top + ySpace * 1,
|
||||||
|
100, 15000, &BREVERB.cf[1].delay,
|
||||||
|
0.0, 1.0, &BREVERB.cf[1].gain0, &BREVERB.cf[1].gainM),
|
||||||
|
widget::DelayGainSlider("comb 2",
|
||||||
|
combLeft, top + ySpace * 2,
|
||||||
|
100, 15000, &BREVERB.cf[2].delay,
|
||||||
|
0.0, 1.0, &BREVERB.cf[2].gain0, &BREVERB.cf[2].gainM),
|
||||||
|
widget::DelayGainSlider("comb 3",
|
||||||
|
combLeft, top + ySpace * 3,
|
||||||
|
100, 15000, &BREVERB.cf[3].delay,
|
||||||
|
0.0, 1.0, &BREVERB.cf[3].gain0, &BREVERB.cf[3].gainM),
|
||||||
|
};
|
||||||
|
|
||||||
|
widget::Slider<float, false> dryGain("dry gain",
|
||||||
|
outputMixLeft, top + yMixSpace * 0, 150, 14,
|
||||||
|
0.0, 1.0, 0.0, 1.0,
|
||||||
|
&audio::dryGain);
|
||||||
|
|
||||||
|
widget::Slider<float, false> wetGain("wet gain",
|
||||||
|
outputMixLeft, top + yMixSpace * 1, 150, 14,
|
||||||
|
0.0, 1.0, 0.0, 1.0,
|
||||||
|
&audio::wetGain);
|
||||||
|
|
||||||
|
widget::Slider<float, false> voiceGain("voice gain",
|
||||||
|
inputMixLeft, top + yMixSpace * 0, 150, 14,
|
||||||
|
0.0, 1.0, 0.0, 1.0,
|
||||||
|
&audio::mixChannelGain[audio::mix_channel::voice]);
|
||||||
|
|
||||||
|
widget::Slider<float, false> poemGain("poem gain",
|
||||||
|
inputMixLeft, top + yMixSpace * 1, 150, 14,
|
||||||
|
0.0, 1.0, 0.0, 1.0,
|
||||||
|
&audio::mixChannelGain[audio::mix_channel::poem]);
|
||||||
|
|
||||||
|
widget::Slider<float, false> musicGain("music gain",
|
||||||
|
inputMixLeft, top + yMixSpace * 2, 150, 14,
|
||||||
|
0.0, 1.0, 0.0, 1.0,
|
||||||
|
&audio::mixChannelGain[audio::mix_channel::music]);
|
||||||
|
|
||||||
|
const char * reverberatorNames[] = {
|
||||||
|
"feed-back",
|
||||||
|
"feed-forward",
|
||||||
|
};
|
||||||
|
widget::Radio<2> reverberators("reverberator",
|
||||||
|
reverberatorNames,
|
||||||
|
950, 200, 100, 40,
|
||||||
|
120, 0,
|
||||||
|
&audio::reverbIndex);
|
||||||
|
|
||||||
|
void draw(MappedInstanceData<SolidInstance> & data,
|
||||||
|
MappedInstanceData<font::BitmapInstance> & fontData)
|
||||||
|
{
|
||||||
|
data.append({
|
||||||
|
{ (uint16_t)0, (uint16_t)0 },
|
||||||
|
{ (uint16_t)1280, (uint16_t)720 },
|
||||||
|
0x80000000,
|
||||||
|
});
|
||||||
|
|
||||||
|
widget::DelayGainSlider * ap = (audio::reverbIndex == 0) ? bap : fap;
|
||||||
|
widget::DelayGainSlider * comb = (audio::reverbIndex == 0) ? bcomb : fcomb;
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
ap[i].draw(data, fontData);
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
comb[i].draw(data, fontData);
|
||||||
|
|
||||||
|
dryGain.draw(data, fontData);
|
||||||
|
wetGain.draw(data, fontData);
|
||||||
|
|
||||||
|
voiceGain.draw(data, fontData);
|
||||||
|
poemGain.draw(data, fontData);
|
||||||
|
musicGain.draw(data, fontData);
|
||||||
|
|
||||||
|
reverberators.draw(data, fontData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void update(float mx, float my, bool mLeft, bool mEdge)
|
||||||
|
{
|
||||||
|
widget::DelayGainSlider * ap = (audio::reverbIndex == 0) ? bap : fap;
|
||||||
|
widget::DelayGainSlider * comb = (audio::reverbIndex == 0) ? bcomb : fcomb;
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
ap[i].update(mx, my, mLeft, mEdge);
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
comb[i].update(mx, my, mLeft, mEdge);
|
||||||
|
|
||||||
|
dryGain.update(mx, my, mLeft, mEdge);
|
||||||
|
wetGain.update(mx, my, mLeft, mEdge);
|
||||||
|
|
||||||
|
voiceGain.update(mx, my, mLeft, mEdge);
|
||||||
|
poemGain.update(mx, my, mLeft, mEdge);
|
||||||
|
musicGain.update(mx, my, mLeft, mEdge);
|
||||||
|
|
||||||
|
reverberators.update(mx, my, mLeft, mEdge);
|
||||||
|
}
|
||||||
|
}
|
||||||
118
src/ui/vulkan.cpp
Normal file
118
src/ui/vulkan.cpp
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include "vulkan/vulkan.h"
|
||||||
|
#else
|
||||||
|
#include "volk/volk.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "vulkan_helper.h"
|
||||||
|
|
||||||
|
#include "ui/vulkan.h"
|
||||||
|
#include "ui/instance_data.h"
|
||||||
|
#include "ui.h"
|
||||||
|
|
||||||
|
#include "font/bitmap.h"
|
||||||
|
|
||||||
|
namespace ui {
|
||||||
|
|
||||||
|
void vulkan::createPipeline()
|
||||||
|
{
|
||||||
|
uint32_t descriptorSetLayoutCount = 0;
|
||||||
|
VkDescriptorSetLayout const * descriptorSetLayouts = nullptr;
|
||||||
|
uint32_t pushConstantRangeCount = 0;
|
||||||
|
VkPushConstantRange const * pushConstantRanges = nullptr;
|
||||||
|
VkShaderModule shaderModule = loadShader(vk->device, "shader/ui/solid.spv");
|
||||||
|
uint32_t perInstanceStride = (sizeof (SolidInstance));
|
||||||
|
constexpr uint32_t instanceAttributeDescriptionCount = 3;
|
||||||
|
VkVertexInputAttributeDescription instanceAttributeDescriptions[instanceAttributeDescriptionCount] {
|
||||||
|
{ // position
|
||||||
|
.location = 2,
|
||||||
|
.binding = 1,
|
||||||
|
.format = VK_FORMAT_R16G16_UINT,
|
||||||
|
.offset = 0,
|
||||||
|
},
|
||||||
|
{ // size
|
||||||
|
.location = 3,
|
||||||
|
.binding = 1,
|
||||||
|
.format = VK_FORMAT_R16G16_UINT,
|
||||||
|
.offset = 4,
|
||||||
|
},
|
||||||
|
{ // color
|
||||||
|
.location = 4,
|
||||||
|
.binding = 1,
|
||||||
|
.format = VK_FORMAT_R8G8B8A8_UNORM,
|
||||||
|
.offset = 8,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
createQuadPipeline(vk->device,
|
||||||
|
vk->colorFormat,
|
||||||
|
vk->depthFormat,
|
||||||
|
descriptorSetLayoutCount,
|
||||||
|
descriptorSetLayouts,
|
||||||
|
pushConstantRangeCount,
|
||||||
|
pushConstantRanges,
|
||||||
|
shaderModule,
|
||||||
|
perInstanceStride,
|
||||||
|
instanceAttributeDescriptionCount,
|
||||||
|
instanceAttributeDescriptions,
|
||||||
|
&pipelineLayout,
|
||||||
|
&pipeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
int vulkan::update(uint32_t frameIndex, MappedInstanceData<font::BitmapInstance> & bitmapData) const
|
||||||
|
{
|
||||||
|
MappedInstanceData<SolidInstance> solidData{ solidInstance[frameIndex], maximumUIElements, 0 };
|
||||||
|
ui::draw(solidData, bitmapData);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// flush
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
constexpr int mappedMemoryRangesCount = 1;
|
||||||
|
VkMappedMemoryRange mappedMemoryRanges[mappedMemoryRangesCount]{
|
||||||
|
{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
|
||||||
|
.memory = instanceBuffer.memory,
|
||||||
|
.offset = instanceBuffer.offset[frameIndex],
|
||||||
|
.size = (sizeof (SolidInstance)) * solidData.index,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
alignMappedMemoryRanges(vk->physicalDeviceProperties.limits.nonCoherentAtomSize,
|
||||||
|
instanceBuffer.memorySize,
|
||||||
|
mappedMemoryRangesCount,
|
||||||
|
mappedMemoryRanges);
|
||||||
|
vkFlushMappedMemoryRanges(vk->device, mappedMemoryRangesCount, mappedMemoryRanges);
|
||||||
|
|
||||||
|
return solidData.index;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vulkan::draw(VkCommandBuffer commandBuffer,
|
||||||
|
uint32_t frameIndex,
|
||||||
|
MappedInstanceData<font::BitmapInstance> & bitmapData) const
|
||||||
|
{
|
||||||
|
int outputIndex = update(frameIndex, bitmapData);
|
||||||
|
|
||||||
|
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||||
|
|
||||||
|
/*
|
||||||
|
VkDescriptorSet descriptorSets[1] = {
|
||||||
|
descriptorSet0,
|
||||||
|
};
|
||||||
|
vkCmdBindDescriptorSets(commandBuffer,
|
||||||
|
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
|
pipelineLayout,
|
||||||
|
0, 1, descriptorSets,
|
||||||
|
0, nullptr);
|
||||||
|
*/
|
||||||
|
|
||||||
|
vkCmdBindIndexBuffer(commandBuffer, vk->quadVertexIndex.buffer, vk->quadVertexIndex.indexOffset, VK_INDEX_TYPE_UINT16);
|
||||||
|
|
||||||
|
VkDeviceSize vertexOffsets[2]{ 0, instanceBuffer.offset[frameIndex] };
|
||||||
|
VkBuffer vertexBuffers[2]{ vk->quadVertexIndex.buffer, instanceBuffer.buffer };
|
||||||
|
vkCmdBindVertexBuffers(commandBuffer, 0, 2, vertexBuffers, vertexOffsets);
|
||||||
|
|
||||||
|
vkCmdDrawIndexed(commandBuffer, 4, outputIndex, 0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
221
src/ui/widget.cpp
Normal file
221
src/ui/widget.cpp
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "ui/widget.h"
|
||||||
|
#include "intstring.h"
|
||||||
|
#include "minmax.h"
|
||||||
|
|
||||||
|
namespace ui::widget
|
||||||
|
{
|
||||||
|
static void drawBoundingBox(MappedInstanceData<SolidInstance> & data,
|
||||||
|
BoundingBox const & bb, uint32_t color)
|
||||||
|
{
|
||||||
|
if ((color & 0xff000000) == 0)
|
||||||
|
color |= 0xff000000;
|
||||||
|
data.append({
|
||||||
|
{ (uint16_t)bb.left, (uint16_t)bb.top },
|
||||||
|
{ (uint16_t)bb.width, (uint16_t)bb.height },
|
||||||
|
color,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void drawGlyph(MappedInstanceData<font::BitmapInstance> & fontData,
|
||||||
|
int x, int y,
|
||||||
|
int c)
|
||||||
|
{
|
||||||
|
fontData.append({ {(uint16_t)(x), (uint16_t)(y)}, font::bitmap::glyphIndex(c) });
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline void drawNumberCentered(MappedInstanceData<font::BitmapInstance> & fontData,
|
||||||
|
int x, int y,
|
||||||
|
T number);
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline void drawNumberCentered<int>(MappedInstanceData<font::BitmapInstance> & fontData,
|
||||||
|
int x, int y,
|
||||||
|
int number)
|
||||||
|
{
|
||||||
|
char buf[16];
|
||||||
|
int numLength = string::dec(buf, 16, number);
|
||||||
|
int width = numLength * 6;
|
||||||
|
int left = x - (width / 2);
|
||||||
|
for (int i = 0; i < numLength; i++) {
|
||||||
|
fontData.append({ {(uint16_t)(left + 6 * i), (uint16_t)(y)}, font::bitmap::glyphIndex(buf[i]) });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline void drawNumberCentered<float>(MappedInstanceData<font::BitmapInstance> & fontData,
|
||||||
|
int x, int y,
|
||||||
|
float number)
|
||||||
|
{
|
||||||
|
|
||||||
|
char buf[64];
|
||||||
|
int numLength = string::flt(buf, 64, number);
|
||||||
|
int width = numLength * 6;
|
||||||
|
int left = x - (width / 2);
|
||||||
|
for (int i = 0; i < numLength; i++) {
|
||||||
|
fontData.append({ {(uint16_t)(left + 6 * i), (uint16_t)(y)}, font::bitmap::glyphIndex(buf[i]) });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void drawStringCentered(MappedInstanceData<font::BitmapInstance> & fontData,
|
||||||
|
int x, int y,
|
||||||
|
const char * string)
|
||||||
|
{
|
||||||
|
int length = strlen(string);
|
||||||
|
int width = length * 6;
|
||||||
|
int left = x - (width / 2);
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
fontData.append({ {(uint16_t)(left + 6 * i), (uint16_t)(y)}, font::bitmap::glyphIndex(string[i]) });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void drawStringLeft(MappedInstanceData<font::BitmapInstance> & fontData,
|
||||||
|
int x, int y,
|
||||||
|
const char * string)
|
||||||
|
{
|
||||||
|
int length = strlen(string);
|
||||||
|
int left = x;
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
fontData.append({ {(uint16_t)(left + 6 * i), (uint16_t)(y)}, font::bitmap::glyphIndex(string[i]) });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void drawStringRight(MappedInstanceData<font::BitmapInstance> & fontData,
|
||||||
|
int x, int y,
|
||||||
|
const char * string)
|
||||||
|
{
|
||||||
|
int length = strlen(string);
|
||||||
|
|
||||||
|
int width = length * 6;
|
||||||
|
int left = x - width;
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
fontData.append({ {(uint16_t)(left + 6 * i), (uint16_t)(y)}, font::bitmap::glyphIndex(string[i]) });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, bool under>
|
||||||
|
void Slider<T, under>::draw(MappedInstanceData<SolidInstance> & data,
|
||||||
|
MappedInstanceData<font::BitmapInstance> & fontData)
|
||||||
|
{
|
||||||
|
drawBoundingBox(data, sliderBorder, 0x545454);
|
||||||
|
|
||||||
|
float sliderInterp = (float)(*value - minExtent) / (float)(maxExtent - minExtent);
|
||||||
|
int sliderWidth = (float)slider.width * clamp01(sliderInterp);
|
||||||
|
|
||||||
|
drawBoundingBox(data, {
|
||||||
|
slider.left,
|
||||||
|
slider.top,
|
||||||
|
sliderWidth,
|
||||||
|
slider.height,
|
||||||
|
}, 0x800000);
|
||||||
|
|
||||||
|
drawBoundingBox(data, lminus, 0x008080);
|
||||||
|
drawGlyph(fontData, lminus.left + 2, lminus.top - 3, '-');
|
||||||
|
drawBoundingBox(data, lplus, 0x008080);
|
||||||
|
drawGlyph(fontData, lplus.left + 2, lplus.top - 3, '+');
|
||||||
|
|
||||||
|
drawBoundingBox(data, rminus, 0x008000);
|
||||||
|
drawGlyph(fontData, rminus.left + 2, lminus.top - 3, '-');
|
||||||
|
drawBoundingBox(data, rplus, 0x008000);
|
||||||
|
drawGlyph(fontData, rplus.left + 2, lplus.top - 3, '+');
|
||||||
|
|
||||||
|
constexpr int yOffset = under ? 14 : -16;
|
||||||
|
|
||||||
|
drawNumberCentered<T>(fontData, slider.left, slider.top + yOffset, minExtent);
|
||||||
|
drawNumberCentered<T>(fontData, slider.left + slider.width, slider.top + yOffset, maxExtent);
|
||||||
|
|
||||||
|
drawNumberCentered<T>(fontData, slider.left + slider.width / 2, slider.top + yOffset, *value);
|
||||||
|
|
||||||
|
drawStringRight(fontData, slider.left - 25, slider.top - 1, label);
|
||||||
|
//drawStringRight(fontData, slider.left - 25, slider.top + 5, label);
|
||||||
|
//drawStringLeft(fontData, slider.left + slider.width + 26, slider.top - 1, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, bool under>
|
||||||
|
void Slider<T, under>::update(float mx, float my, bool mLeft, bool mEdge)
|
||||||
|
{
|
||||||
|
if (!mLeft) {
|
||||||
|
drag = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mEdge) {
|
||||||
|
double eWidth2 = (double)(maxExtent - minExtent) / 2.0f;
|
||||||
|
double vWidth2 = (double)(maxValue - minValue) / 2.0f;
|
||||||
|
double width2 = min(eWidth2, vWidth2);
|
||||||
|
|
||||||
|
if (lminus.inside(mx, my)) {
|
||||||
|
minExtent = clamp<double>(minExtent + width2, minValue, maxValue);
|
||||||
|
} else if (lplus.inside(mx, my)) {
|
||||||
|
minExtent = clamp<double>(minExtent - width2, minValue, maxValue);
|
||||||
|
} else if (rminus.inside(mx, my)) {
|
||||||
|
maxExtent = clamp<double>(maxExtent - width2, minValue, maxValue);
|
||||||
|
} else if (rplus.inside(mx, my)) {
|
||||||
|
maxExtent = clamp<double>(maxExtent + width2, minValue, maxValue);
|
||||||
|
} else if (slider.inside(mx, my)) {
|
||||||
|
drag = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (drag) {
|
||||||
|
float lerp = clamp01((mx - (float)slider.left) / (float)(slider.width));
|
||||||
|
|
||||||
|
float valueScale = maxExtent - minExtent;
|
||||||
|
*value = (T)(lerp * valueScale + minExtent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template struct Slider<int, true>;
|
||||||
|
template struct Slider<int, false>;
|
||||||
|
template struct Slider<float, true>;
|
||||||
|
template struct Slider<float, false>;
|
||||||
|
|
||||||
|
void DelayGainSlider::draw(MappedInstanceData<SolidInstance> & data,
|
||||||
|
MappedInstanceData<font::BitmapInstance> & fontData)
|
||||||
|
{
|
||||||
|
drawStringCentered(fontData, delay.slider.left + delay.slider.width / 2, delay.slider.top - 16, label);
|
||||||
|
|
||||||
|
delay.draw(data, fontData);
|
||||||
|
gain0.draw(data, fontData);
|
||||||
|
gainM.draw(data, fontData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DelayGainSlider::update(float mx, float my, bool mLeft, bool mEdge)
|
||||||
|
{
|
||||||
|
delay.update(mx, my, mLeft, mEdge);
|
||||||
|
gain0.update(mx, my, mLeft, mEdge);
|
||||||
|
gainM.update(mx, my, mLeft, mEdge);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <int optionCount>
|
||||||
|
void Radio<optionCount>::draw(MappedInstanceData<SolidInstance> & data,
|
||||||
|
MappedInstanceData<font::BitmapInstance> & fontData)
|
||||||
|
{
|
||||||
|
drawStringCentered(fontData, box[0].left + width / 2, box[0].top - 16, label);
|
||||||
|
|
||||||
|
for (int i = 0; i < optionCount; i++) {
|
||||||
|
uint32_t color = (i == *selected) ? 0xa0800080 : 0x80300030;
|
||||||
|
drawBoundingBox(data, box[i], color);
|
||||||
|
drawStringCentered(fontData, box[i].left + box[i].width / 2, box[0].top + box[i].height / 2 - 6, boxLabels[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <int optionCount>
|
||||||
|
void Radio<optionCount>::update(float mx, float my, bool mLeft, bool mEdge)
|
||||||
|
{
|
||||||
|
if (!mEdge)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int i = 0; i < optionCount; i++) {
|
||||||
|
if (box[i].inside(mx, my)) {
|
||||||
|
*selected = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template struct widget::Radio<2>;
|
||||||
|
}
|
||||||
@ -9,7 +9,6 @@
|
|||||||
#include "volk/volk.h"
|
#include "volk/volk.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "vulkan/vulkan.h"
|
|
||||||
#include "vulkan/vk_enum_string_helper.h"
|
#include "vulkan/vk_enum_string_helper.h"
|
||||||
|
|
||||||
#include "minmax.h"
|
#include "minmax.h"
|
||||||
@ -134,7 +133,7 @@ void textureTransfer(VkDevice device,
|
|||||||
VkDeviceSize nonCoherentAtomSize,
|
VkDeviceSize nonCoherentAtomSize,
|
||||||
VkPhysicalDeviceMemoryProperties const & physicalDeviceMemoryProperties,
|
VkPhysicalDeviceMemoryProperties const & physicalDeviceMemoryProperties,
|
||||||
uint32_t imageDataSize,
|
uint32_t imageDataSize,
|
||||||
void * imageData,
|
void const * imageData,
|
||||||
VkImage image,
|
VkImage image,
|
||||||
uint32_t width,
|
uint32_t width,
|
||||||
uint32_t height,
|
uint32_t height,
|
||||||
@ -491,3 +490,244 @@ VertexIndex createVertexIndexBuffer(VkDevice device,
|
|||||||
|
|
||||||
return vertexIndex;
|
return vertexIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void createQuadPipeline(VkDevice device,
|
||||||
|
VkFormat colorFormat,
|
||||||
|
VkFormat depthFormat,
|
||||||
|
uint32_t descriptorSetLayoutCount,
|
||||||
|
VkDescriptorSetLayout const * descriptorSetLayouts,
|
||||||
|
uint32_t pushConstantRangeCount,
|
||||||
|
VkPushConstantRange const * pushConstantRanges,
|
||||||
|
VkShaderModule shaderModule,
|
||||||
|
uint32_t perInstanceStride,
|
||||||
|
uint32_t instanceAttributeDescriptionCount,
|
||||||
|
VkVertexInputAttributeDescription * instanceAttributeDescriptions,
|
||||||
|
VkPipelineLayout * pipelineLayout,
|
||||||
|
VkPipeline * pipeline)
|
||||||
|
{
|
||||||
|
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
||||||
|
.setLayoutCount = descriptorSetLayoutCount,
|
||||||
|
.pSetLayouts = descriptorSetLayouts,
|
||||||
|
.pushConstantRangeCount = pushConstantRangeCount,
|
||||||
|
.pPushConstantRanges = pushConstantRanges
|
||||||
|
};
|
||||||
|
VK_CHECK(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, pipelineLayout));
|
||||||
|
|
||||||
|
VkPipelineInputAssemblyStateCreateInfo inputAssemblyState{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
||||||
|
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP
|
||||||
|
};
|
||||||
|
|
||||||
|
VkPipelineShaderStageCreateInfo shaderStages[2]{
|
||||||
|
{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||||
|
.stage = VK_SHADER_STAGE_VERTEX_BIT,
|
||||||
|
.module = shaderModule,
|
||||||
|
.pName = "VSMain"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||||
|
.stage = VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
|
.module = shaderModule,
|
||||||
|
.pName = "PSMain"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
VkPipelineViewportStateCreateInfo viewportState{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
||||||
|
.viewportCount = 1,
|
||||||
|
.scissorCount = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr uint32_t dynamicStateCount = 2;
|
||||||
|
VkDynamicState dynamicStates[dynamicStateCount]{
|
||||||
|
VK_DYNAMIC_STATE_VIEWPORT,
|
||||||
|
VK_DYNAMIC_STATE_SCISSOR,
|
||||||
|
};
|
||||||
|
VkPipelineDynamicStateCreateInfo dynamicState{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
|
||||||
|
.dynamicStateCount = dynamicStateCount,
|
||||||
|
.pDynamicStates = dynamicStates
|
||||||
|
};
|
||||||
|
|
||||||
|
VkPipelineDepthStencilStateCreateInfo depthStencilState{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
|
||||||
|
.depthTestEnable = VK_FALSE,
|
||||||
|
.depthWriteEnable = VK_FALSE,
|
||||||
|
.depthCompareOp = VK_COMPARE_OP_ALWAYS,
|
||||||
|
.stencilTestEnable = VK_FALSE,
|
||||||
|
.front = {
|
||||||
|
.failOp = VK_STENCIL_OP_REPLACE,
|
||||||
|
.passOp = VK_STENCIL_OP_REPLACE,
|
||||||
|
.depthFailOp = VK_STENCIL_OP_REPLACE,
|
||||||
|
.compareOp = VK_COMPARE_OP_ALWAYS,
|
||||||
|
.compareMask = 0x01,
|
||||||
|
.writeMask = 0x01,
|
||||||
|
.reference = 1,
|
||||||
|
},
|
||||||
|
.back = {
|
||||||
|
.failOp = VK_STENCIL_OP_REPLACE,
|
||||||
|
.passOp = VK_STENCIL_OP_REPLACE,
|
||||||
|
.depthFailOp = VK_STENCIL_OP_REPLACE,
|
||||||
|
.compareOp = VK_COMPARE_OP_ALWAYS,
|
||||||
|
.compareMask = 0x01,
|
||||||
|
.writeMask = 0x01,
|
||||||
|
.reference = 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
VkPipelineRenderingCreateInfo renderingCreateInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
|
||||||
|
.colorAttachmentCount = 1,
|
||||||
|
.pColorAttachmentFormats = &colorFormat,
|
||||||
|
.depthAttachmentFormat = depthFormat,
|
||||||
|
.stencilAttachmentFormat = depthFormat
|
||||||
|
};
|
||||||
|
|
||||||
|
VkPipelineColorBlendAttachmentState blendAttachment{
|
||||||
|
.blendEnable = VK_TRUE,
|
||||||
|
.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA,
|
||||||
|
.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
|
||||||
|
.colorBlendOp = VK_BLEND_OP_ADD,
|
||||||
|
.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE,
|
||||||
|
.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO,
|
||||||
|
.alphaBlendOp = VK_BLEND_OP_ADD,
|
||||||
|
.colorWriteMask = 0xF,
|
||||||
|
};
|
||||||
|
VkPipelineColorBlendStateCreateInfo colorBlendState{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
|
||||||
|
.attachmentCount = 1,
|
||||||
|
.pAttachments = &blendAttachment
|
||||||
|
};
|
||||||
|
VkPipelineRasterizationStateCreateInfo rasterizationState{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
||||||
|
//.cullMode = VK_CULL_MODE_BACK_BIT,
|
||||||
|
.cullMode = VK_CULL_MODE_NONE,
|
||||||
|
.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
|
||||||
|
.lineWidth = 1.0f
|
||||||
|
};
|
||||||
|
VkPipelineMultisampleStateCreateInfo multisampleState{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
|
||||||
|
.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr uint32_t perVertexStride = 4 * 2;
|
||||||
|
constexpr int vertexBindingDescriptionsCount = 2;
|
||||||
|
VkVertexInputBindingDescription vertexBindingDescriptions[vertexBindingDescriptionsCount]{
|
||||||
|
{
|
||||||
|
.binding = 0,
|
||||||
|
.stride = perVertexStride,
|
||||||
|
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.binding = 1,
|
||||||
|
.stride = perInstanceStride,
|
||||||
|
.inputRate = VK_VERTEX_INPUT_RATE_INSTANCE
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
uint32_t vertexAttributeDescriptionsCount = 2u + instanceAttributeDescriptionCount;
|
||||||
|
VkVertexInputAttributeDescription vertexAttributeDescriptions[vertexAttributeDescriptionsCount];
|
||||||
|
// per-vertex
|
||||||
|
vertexAttributeDescriptions[0] = { // position
|
||||||
|
.location = 0,
|
||||||
|
.binding = 0,
|
||||||
|
.format = VK_FORMAT_R16G16_SFLOAT,
|
||||||
|
.offset = 0,
|
||||||
|
};
|
||||||
|
vertexAttributeDescriptions[1] = { // texture
|
||||||
|
.location = 1,
|
||||||
|
.binding = 0,
|
||||||
|
.format = VK_FORMAT_R16G16_SFLOAT,
|
||||||
|
.offset = 4,
|
||||||
|
};
|
||||||
|
memcpy(&vertexAttributeDescriptions[2], instanceAttributeDescriptions, instanceAttributeDescriptionCount * (sizeof (VkVertexInputAttributeDescription)));
|
||||||
|
|
||||||
|
VkPipelineVertexInputStateCreateInfo vertexInputState{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
||||||
|
.vertexBindingDescriptionCount = vertexBindingDescriptionsCount,
|
||||||
|
.pVertexBindingDescriptions = vertexBindingDescriptions,
|
||||||
|
.vertexAttributeDescriptionCount = vertexAttributeDescriptionsCount,
|
||||||
|
.pVertexAttributeDescriptions = vertexAttributeDescriptions,
|
||||||
|
};
|
||||||
|
|
||||||
|
VkGraphicsPipelineCreateInfo pipelineCreateInfos[1]{
|
||||||
|
{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
||||||
|
.pNext = &renderingCreateInfo,
|
||||||
|
.stageCount = 2,
|
||||||
|
.pStages = shaderStages,
|
||||||
|
.pVertexInputState = &vertexInputState,
|
||||||
|
.pInputAssemblyState = &inputAssemblyState,
|
||||||
|
.pViewportState = &viewportState,
|
||||||
|
.pRasterizationState = &rasterizationState,
|
||||||
|
.pMultisampleState = &multisampleState,
|
||||||
|
.pDepthStencilState = &depthStencilState,
|
||||||
|
.pColorBlendState = &colorBlendState,
|
||||||
|
.pDynamicState = &dynamicState,
|
||||||
|
.layout = *pipelineLayout
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
VK_CHECK(vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, pipelineCreateInfos, nullptr, pipeline));
|
||||||
|
}
|
||||||
|
|
||||||
|
VkShaderModule loadShader(VkDevice device,
|
||||||
|
char const * const path)
|
||||||
|
{
|
||||||
|
uint32_t shaderSize;
|
||||||
|
void const * shaderStart = file::open(path, &shaderSize);
|
||||||
|
|
||||||
|
VkShaderModuleCreateInfo shaderModuleCreateInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
|
||||||
|
.codeSize = shaderSize,
|
||||||
|
.pCode = (uint32_t *)shaderStart
|
||||||
|
};
|
||||||
|
VkShaderModule shaderModule;
|
||||||
|
VK_CHECK(vkCreateShaderModule(device, &shaderModuleCreateInfo, nullptr, &shaderModule));
|
||||||
|
return shaderModule;
|
||||||
|
}
|
||||||
|
|
||||||
|
void createInstanceBuffer(VkDevice device,
|
||||||
|
VkPhysicalDeviceProperties const & physicalDeviceProperties,
|
||||||
|
VkPhysicalDeviceMemoryProperties const & physicalDeviceMemoryProperties,
|
||||||
|
VkDeviceSize bufferSize,
|
||||||
|
InstanceBuffer * instanceBuffer)
|
||||||
|
{
|
||||||
|
instanceBuffer->memorySize = bufferSize * 2;
|
||||||
|
instanceBuffer->offset[0] = bufferSize * 0;
|
||||||
|
instanceBuffer->offset[1] = bufferSize * 1;
|
||||||
|
|
||||||
|
// create buffer
|
||||||
|
VkBufferCreateInfo bufferCreateInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||||
|
.size = instanceBuffer->memorySize,
|
||||||
|
.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
|
||||||
|
.sharingMode = VK_SHARING_MODE_EXCLUSIVE
|
||||||
|
};
|
||||||
|
VK_CHECK(vkCreateBuffer(device, &bufferCreateInfo, nullptr, &instanceBuffer->buffer));
|
||||||
|
|
||||||
|
// allocate memory
|
||||||
|
|
||||||
|
VkMemoryRequirements memoryRequirements;
|
||||||
|
vkGetBufferMemoryRequirements(device, instanceBuffer->buffer, &memoryRequirements);
|
||||||
|
VkMemoryPropertyFlags memoryPropertyFlags{ VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT };
|
||||||
|
VkMemoryAllocateFlags memoryAllocateFlags{};
|
||||||
|
VkDeviceSize stride;
|
||||||
|
allocateFromMemoryRequirements(device,
|
||||||
|
physicalDeviceProperties.limits.nonCoherentAtomSize,
|
||||||
|
physicalDeviceMemoryProperties,
|
||||||
|
memoryRequirements,
|
||||||
|
memoryPropertyFlags,
|
||||||
|
memoryAllocateFlags,
|
||||||
|
1,
|
||||||
|
&instanceBuffer->memory,
|
||||||
|
&stride);
|
||||||
|
|
||||||
|
VK_CHECK(vkBindBufferMemory(device, instanceBuffer->buffer, instanceBuffer->memory, 0));
|
||||||
|
|
||||||
|
// map memory
|
||||||
|
|
||||||
|
VK_CHECK(vkMapMemory(device, instanceBuffer->memory, 0, VK_WHOLE_SIZE, 0, (void **)&instanceBuffer->mappedData));
|
||||||
|
}
|
||||||
|
|||||||
43
src/vulkan_state.cpp
Normal file
43
src/vulkan_state.cpp
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#include "vulkan_state.h"
|
||||||
|
|
||||||
|
static const _Float16 vertexData[] = {
|
||||||
|
// x y u v
|
||||||
|
(_Float16)-1.0, (_Float16)-1.0, (_Float16)0.0, (_Float16)0.0,
|
||||||
|
(_Float16)1.0, (_Float16)-1.0, (_Float16)1.0, (_Float16)0.0,
|
||||||
|
(_Float16)-1.0, (_Float16)1.0, (_Float16)0.0, (_Float16)1.0,
|
||||||
|
(_Float16)1.0, (_Float16)1.0, (_Float16)1.0, (_Float16)1.0,
|
||||||
|
};
|
||||||
|
static const uint32_t vertexSize = (sizeof (vertexData));
|
||||||
|
|
||||||
|
static const uint16_t indexData[] = {
|
||||||
|
0, 1, 2, 3,
|
||||||
|
};
|
||||||
|
static const uint32_t indexSize = (sizeof (indexData));
|
||||||
|
|
||||||
|
|
||||||
|
VulkanState::VulkanState(VkInstance instance,
|
||||||
|
VkDevice device,
|
||||||
|
VkQueue queue,
|
||||||
|
VkCommandPool commandPool,
|
||||||
|
VkPhysicalDeviceProperties const & physicalDeviceProperties,
|
||||||
|
VkPhysicalDeviceMemoryProperties const & physicalDeviceMemoryProperties,
|
||||||
|
VkFormat colorFormat,
|
||||||
|
VkFormat depthFormat)
|
||||||
|
: instance(instance)
|
||||||
|
, device(device)
|
||||||
|
, queue(queue)
|
||||||
|
, commandPool(commandPool)
|
||||||
|
, physicalDeviceProperties(physicalDeviceProperties)
|
||||||
|
, physicalDeviceMemoryProperties(physicalDeviceMemoryProperties)
|
||||||
|
, colorFormat(colorFormat)
|
||||||
|
, depthFormat(depthFormat)
|
||||||
|
{
|
||||||
|
void const * vertexStart = (void const *)vertexData;
|
||||||
|
void const * indexStart = (void const *)indexData;
|
||||||
|
|
||||||
|
quadVertexIndex = createVertexIndexBuffer(device,
|
||||||
|
physicalDeviceProperties,
|
||||||
|
physicalDeviceMemoryProperties,
|
||||||
|
vertexStart, vertexSize,
|
||||||
|
indexStart, indexSize);
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user