Skip to content

Instantly share code, notes, and snippets.

@m4saka
Forked from albshin/kshon
Last active May 5, 2022 14:06
Show Gist options
  • Save m4saka/a89594a17dc9422d75e01998bcfd2722 to your computer and use it in GitHub Desktop.
Save m4saka/a89594a17dc9422d75e01998bcfd2722 to your computer and use it in GitHub Desktop.
modified version of: https://bmson-spec.readthedocs.io/en/master/doc/index.html
// TODO List
// - lane swing
// - lane tilt
// - laser curves
// - BGA layer?
// top-level object
dictionary kson {
DOMString version; // kson version
KsonInfo info; // information, e.g. title, artist, ...
BarLine[]? lines; // location of bar-lines in pulses
BpmEvent[]? bpm_events; // bpm changes
StopEvent[]? stop_events; // stop events
CameraEventInfo? camera_events; // camera events
KeySound[]? key_sounds; // key sounds for chip FX & laser slams
NoteInfo[]? notes; // notes on each lane
AudioEffectDef[]? audio_effects; // audio effect definitions
AudioEffectEventInfo[]? audio_effect_events; // audio effect events on each lane
}
// header information
dictionary KsonInfo {
DOMString title; // self-explanatory
DOMString? title_translit; // transliterated title
DOMString? subtitle; // self-explanatory, can be a CD title or a music genre
DOMString artist; // self-explanatory
DOMString? artist_translit; // transliterated artist
DifficultyInfo difficulty; // self-explanatory
unsigned int level; // self-explanatory, 1-20
DOMString bpm; // self-explanatory (is this needed?)
double init_bpm; // initial bpm (needed for specifying bpm before the first tick)
// All the other metadata fields
...
unsigned long resolution = 240; // pulses per quarter note
}
// chart difficulty (or custom chart name)
dictionary DifficultyInfo {
DOMString name; // e.g. "Challenge", "Infinity", "Gravity", "Maximum", "FOUR DIMENSIONS"
DOMString? short_name; // e.g. "CH", "IN", "GRV", "MXM", "FD"
// (if not specified, it inherits the client defaults based on "index". e.g. 1=>"CH")
unsigned char index; // 0-4 e.g. "CH"=>1, "IN"/"GRV"=>3, "MXM"/"FD"=>4
}
// bar-lines
// this is for drawing bar lines, deducing time signature,
// and calculating duration of length parameters for audio effects
dictionary BarLine {
unsigned long y; // pulse number
}
// notes on each lane
dictionary NoteInfo {
BTNote[][]? bt; // bt notes (first key: lane index)
FXNote[][]? fx; // fx notes (first key: lane index)
LaserNote[][]? laser; // laser notes (first key: lane index (0: left knob, 1: right knob))
}
// BT note
dictionary BTNote {
unsigned long y; // pulse number
unsigned long l; // length (0: normal note; greater than zero (length in pulses): long note)
}
// FX note
dictionary FXNote {
unsigned char x; // lane (0-1)
unsigned long y; // pulse number
unsigned long l; // length (0: normal note; greater than zero (length in pulses): long note)
AudioEffectInfo? audio_effect; // audio effects (and parameter changes if needed)
any? key_sound; // chip sound (valid only when l == 0)
// - DOMString: preset sound name
// - unsigned long: corresponds to KeySound.id
}
// laser note
dictionary LaserNote {
unsigned char x; // lane (0: left knob, 1: right knob)
unsigned long y; // pulse number
unsigned long l; // length (0: slam; greater than zero (length in pulses): long note)
int a; // laser x-axis position (-100 - 100)
AudioEffectInfo? audio_effect; // audio effects (and parameter changes if needed)
Spin? spin; // lane spin (valid only when l == 0)
any? key_sound; // slam sound (valid only when l == 0)
// - DOMString: preset sound name
// - unsigned long: corresponds to KeySound.id
// If not specified, the default slam sound will be used.
}
// Note: Two laser notes are connected if (y == prev.y + prev.l) is satisfied.
// If the next note is not connected to the current one, it is treated as a straightforward laser note.
// lane spin
dictionary Spin {
unsigned long y; // pulse number
unsigned long duration; // spin duration
long degree; // spin in degrees (negative is left and positive is right)
}
// audio effect parameter settings
dictionary AudioEffectParamInfo {
// Custom fields per FX
//
// ex1) "type=Flanger;delay=80samples;depth=30samples-60samples" in KSH
// type: "Flanger",
// delay: ["80samples"],
// depth: ["30samples", "30samples", "60samples"]
//
// ex2) "type=TapeStop;trigger=off>on;speed=20%" in KSH
// type: "TapeStop",
// trigger: ["off", "on"],
// depth: ["20%"]
}
// audio effect definition
dictionary AudioEffectDef {
DOMString name; // name of the audio effect (e.g. "LowFlanger")
DOMString type; // name of the audio effect to inherit (e.g. "Flanger")
AudioEffectParamInfo? params;
}
// Note: Preset audio effects ("Retrigger", "Gate", "Flanger"...) are implicitly defined in default.
// If an audio effect with the same name as a preset effect, implicitly defined presets will be overwritten.
//
// FX and laser share the audio effect definition itself,
// but the instances of audio effects are created for each, and they work in parallel.
// audio effect event
dictionary AudioEffectEvent {
DOMString name; // name of the audio effect (e.g. "LowFlanger")
AudioEffectParamInfo? params; // specified if you want to change values
// (e.g. FX note with Retrigger 8th: {"waveLength":["1/8"]})
}
// audio effect events on each lane
dictionary AudioEffectEventInfo {
AudioEffectEvent[][]? fx; // audio effects for FX lanes (first key: lane index)
AudioEffectEvent[][]? laser; // audio effects for laser lanes (first key: lane index (0: left knob, 1: right knob))
}
dictionary KeySound {
unsigned long id; // id
DOMString name; // key sound filename
}
/* NEED TO DISCUSS!! (this also can be implemented as a type of camera events which controls the offset of the lane background texture...)
// hide event
// for songs like "I" where the lane hides itself
dictionary HideEvent {
unsigned long y; // pulse number
unsigned long duration; // for smoothing
}
*/
// camera events
dictionary CameraEventInfo {
CameraEvent[]? distance; // zoom_bottom
CameraEvent[]? shift_x; // zoom_side
CameraEvent[]? rotation_x; // zoom_top
}
// camera event
dictionary CameraEvent {
unsigned long y; // pulse number
unsigned long duration; // for smoothing
long value; // self-explanatory
}
// stop event
dictionary StopEvent {
unsigned long y; // pulse number
unsigned long duration; // stop duration (pulses to stop)
}
// bpm event
dictionary BpmEvent {
unsigned long y; // pulse number
double bpm; // bpm
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment