This repository has been archived on 2022-05-21. You can view files and clone it, but cannot push or open issues or pull requests.
shapes-juke/src/sj/Music.d

129 lines
2.8 KiB
D

/// License: MIT
module sj.Music;
import std.array,
std.conv,
std.exception,
std.file,
std.json,
std.path,
std.string;
import derelict.sfml2.audio,
derelict.sfml2.system;
import gl4d;
static import sjplayer;
///
class Music {
public:
///
static struct PreviewConfig {
public:
///
size_t play_offset;
///
vec4 bg_inner_color = vec4(0, 0, 0, 0);
///
vec4 bg_outer_color = vec4(0, 0, 0, 0);
}
///
static Music[] CreateFromJson(in JSONValue json, string basepath) {
auto result = appender!(Music[]);
result.reserve(json.array.length);
foreach (item; json.array) {
result ~= new Music(item, basepath);
}
return result[];
}
///
this(in JSONValue json, string basepath) {
const music_path = buildPath(basepath, json["music"].str);
name_ = json["name"].str;
bpm_ = GetNumericAsFloatFromJson(json["bpm"]);
music_ = sfMusic_createFromFile(music_path.toStringz).enforce;
script_path_ = buildPath(basepath, json["script"].str);
with (preview_) {
const preview_json = json["preview"];
play_offset = preview_json["play-offset"].integer;
bg_inner_color = GetVectorFromJson!4(preview_json["bg-inner-color"]);
bg_outer_color = GetVectorFromJson!4(preview_json["bg-outer-color"]);
}
}
~this() {
sfMusic_destroy(music_);
}
///
void PlayForGame(float offset_beat) {
sfMusic_setPlayingOffset(music_,
sfMilliseconds((offset_beat / bpm_ * 60f * 1000f).to!int));
sfMusic_play(music_);
}
///
void PlayForPreview() {
sfMusic_setPlayingOffset(
music_, sfMilliseconds(preview_.play_offset.to!int));
sfMusic_play(music_);
}
///
void StopPlaying() {
sfMusic_stop(music_);
}
///
sjplayer.Context CreatePlayerContext(
sjplayer.PostEffect posteffect, sjplayer.ProgramSet programs) const {
return sjplayer.CreateContextFromText(
script_path_.readText, posteffect, programs);
}
///
@property string name() const {
return name_;
}
///
@property ref const(PreviewConfig) preview() const {
return preview_;
}
///
@property float beat() const {
const msecs = sfMusic_getPlayingOffset(music_).microseconds * 1e-6f;
return msecs / 60f * bpm_;
}
private:
static float GetNumericAsFloatFromJson(in JSONValue json) {
return json.type == JSONType.float_? json.floating: json.integer;
}
static Vector!(float, dim) GetVectorFromJson(size_t dim)(in JSONValue json) {
(json.array.length == dim).enforce;
Vector!(float, dim) v;
static foreach (i; 0..dim) {
v.vector[i] = GetNumericAsFloatFromJson(json.array[i]);
}
return v;
}
string name_;
float bpm_;
sfMusic* music_;
string script_path_;
PreviewConfig preview_;
}