Core_Engine

Before Playback

Before Playback Step-1: initialize PDJE core engine

class PDJE

the main Interface of this Engine PDJE gets music data and track data from database. from that datas, you can activate music player and you can get a music player handler. with this player handler, you can control music’s mixing in real time.

to-use

  1. make PDJE object

  2. call SearchTrack

  3. call InitPlayer

  4. use player. this is handler.

digraph PDJE_Interface_Tree{ PDJE -> Search_Tools; PDJE -> Player; Player -> Player_ON_OFF; Player -> FXController; Player -> MusicController; FXController -> FX_ON_OFF; FXController -> FX_arg_setter; FX_arg_setter -> change_FX_value; MusicController -> Load_Music; MusicController -> Unload_Music; MusicController -> ON_OFF_Music; MusicController -> Cue_Music; MusicController -> FXController; }

auto engine = new PDJE("database/path");
PDJE engine = new PDJE("database/path");
import pdje_POLYGLOT as pypdje
engine = pypdje.PDJE("database/path")
var engine:PDJE_Wrapper = PDJE_Wrapper.new()
engine.InitEngine("res://database/path")

Before Playback Step-2: Search Music & Track

MUS_VEC PDJE::SearchMusic(const UNSANITIZED &Title, const UNSANITIZED &composer, const double bpm = -1)

searches musics and metadatas from database. if you don’t need to filter, send “” to the values

Parameters:
  • Title – the title of the music

  • composer – the composer of the music

  • bpm – the bpm of the music. send under zero to skip filter

Returns:

MUS_VEC

TRACK_VEC PDJE::SearchTrack(const UNSANITIZED &Title)

searches track the track contains the note data, mix data and included music lists.

Parameters:

Title – the title of the track. send “” to skip filter

Returns:

TRACK_VEC the array of the track_data. find what you want

trackdata td = engine->SearchTrack("Track name").front();
musdata md = engine->SearchMusic("music title", "composer name", -1.0).front();
//-1.0 means ignore bpm
TRACK_VEC tdvec = engine.SearchTrack("Track name");
MUS_VEC mdvec = engine.SearchMusic("music title", "composer name", -1.0);
//-1.0 means ignore bpm
import pdje_POLYGLOT as pypdje
from pdje_POLYGLOT import TRACK_VEC
from pdje_POLYGLOT import MUS_VEC

tdvec:TRACK_VEC = engine.SearchTrack("track name")
mdvec:MUS_VEC = engine.SearchMusic("music title", "composer name", -1.0)
#-1.0 means ignore bpm
var tdlist = engine.SearchTrack("track name")
var mdlist = engine.SearchMusic("music name", "composer name", -1.0)
#-1.0 means ignore bpm

Before Playback Step-3: Init, Activate & Deactivate Audio Player

bool PDJE::InitPlayer(PLAY_MODE mode, trackdata &td, const unsigned int FrameBufferSize)

this inits the music handler. the music handler called a “player” it initializes the player

Parameters:
  • mode – the play modes. you can choose “FULL_PRE_RENDER”, “HYBRID_RENDER”, “FULL_MANUAL_RENDER”

  • td – the track data. you can get this from SearchTrack()

  • FrameBufferSize – the buffersize. in this project, it uses 48000 samplerate. if you use 48 as a value, in theory, it calls mixing function 1000 times per second.

Returns:

true no error

Returns:

false error

bool audioPlayer::Activate()

Plays music.

inline void PDJE::ResetPlayer()

Reset the Player object.

bool audioPlayer::Deactivate()

Stops music.

bool player_OK = engine->InitPlayer(PLAY_MODE::HYBRID_RENDER, td, 48);
//render mode, trackdata, sample buffer

engine->ResetPlayer();
//reset player

bool activate_OK = engine->player->Activate();
//start playback

bool deactivate_OK = engine->player->Deactivate();
//stop playback
bool player_OK = engine.InitPlayer(PLAY_MODE.HYBRID_RENDER, tdvec[0], 48);
//render mode, trackdata, sample buffer

var AudioP = engine.GetPlayerObject();
//get player object

engine.ResetPlayer();
//reset player object.
//WARNING: after reset, AudioP becomes unavailable.

bool activate_OK = AudioP.Activate();
//start playback

bool deactivate_OK = AudioP.Deactivate();
//stop playback
from pdje_POLYGLOT import audioPlayer

player_OK = engine.InitPlayer(pyPDJE.HYBRID_RENDER, tdvec[0], 48)
#render mode, trackdata, sample buffer

AudioP:audioPlayer = engine.GetPlayerObject()
#get player object

engine.ResetPlayer()
#reset player object.
#WARNING: after reset, AudioP becomes unavailable.

activate_OK = AudioP.Activate()
#start playback

deactivate_OK = AudioP.Deactivate()
#stop playback
var player_OK = engine.InitPlayer(PDJE_Wrapper.HYBRID_RENDER, tdlist[0], 48)
#render mode, trackdata, sample buffer

var AudioP:PlayerWrapper = engine.GetPlayer()
#get player object

engine.ResetPlayer()
#reset player object.
#WARNING: after reset, AudioP becomes unavailable.

var activate_OK = AudioP.Activate()
#start playback

var deactivate_OK = AudioP.Deactivate()
#stop playback

On Playback

On Playback Step-1: Get & Use FX Controller Panel

FXControlPanel *audioPlayer::GetFXControlPanel(const UNSANITIZED &title = "__PDJE__MAIN__")

fx controller getter this returns the fx controller. with this, you can control the fx in realtime manually.

Parameters:

title – the music to control. “__PDJE__MAIN__” means the prerendered music.

Returns:

FXControlPanel* but the “title” doesn’t exists, it returns nullptr.

void FXControlPanel::FX_ON_OFF(FXList fx, bool onoff)

activate/deactivate FX

Parameters:
  • fx – the fx type

  • onoff – activate / deactivate

enum FXList

the usable fx list

Values:

enumerator COMPRESSOR
enumerator DISTORTION
enumerator ECHO
enumerator EQ
enumerator FILTER
enumerator FLANGER
enumerator OCSFILTER
enumerator PANNER
enumerator PHASER
enumerator ROBOT
enumerator ROLL
enumerator TRANCE
enumerator VOL
ARGSETTER FXControlPanel::GetArgSetter(FXList fx)

Get the Arg Setter object.

Parameters:

fx – the fx type

Returns:

ARGSETTER the FX arg handler

bool FXControlPanel::checkSomethingOn()

check any FX is activated

Returns:

true , something is activated

Returns:

false , nothing activated.

to see Available args, See: FX_ARGS

FXControlPanel* fx_panel = engine->player->GetFXControlPanel("title");
//get music's fx controller.

fx_panel = engine->player->GetFXControlPanel();
//or get mixed track's fx controller like this.

bool TurnON = true;
fx_panel->FX_ON_OFF(FXList::EQ, TurnON);
//turn on EQ effect

auto argsetter = fx_panel->GetArgSetter(FXList::EQ);
for(auto& i : argsetter){
    std::cout << "fx key: " << i.first << std::endl;
}
// get argument setter for EQ
// you can check configurable (settable) arg keys like this

argsetter["EQSelect"](1);
argsetter["EQPower"](-32);
// change FX args by key
//for details, see FXArgs document
FXControlPanel fx_panel = AudioP.GetFXControlPanel("title");
//get music's fx controller

fx_panel = AudioP.GetFXControlPanel();
//or get mixed track's fx controller like this.

bool TurnON = true;
fx_panel.FX_ON_OFF(FXList.EQ, TurnON);
//turn on EQ effect

ARGSETTER_WRAPPER argsetter = new ARGSETTER_WRAPPER(fx_panel);
KEY_VEC keylist = argsetter.GetFXArgKeys(FXList.EQ);
foreach(var keys in keylist){
    Console.WriteLine(keys);
}
//get argument setter wrapper and get configurable arg keys like this.

argsetter.SetFXArg(FXList.EQ, "EQSelect", 1);
argsetter.SetFXArg(FXList.EQ, "EQPower", -32);

//change FX args by key
//for details, see FXArgs document
import pdje_POLYGLOT as pypdje
from pdje_POLYGLOT import FXControlPanel
from pdje_POLYGLOT import ARGSETTER_WRAPPER
from pdje_POLYGLOT import KEY_VEC

#...

fx_panel:FXControlPanel = AudioP.GetFXControlPanel("title")
#get music's fx controller
fx_panel = AudioP.GetFXControlPanel()
#or get mixed track's fx controller like this.
TurnON:bool = True
fx_panel.FX_ON_OFF(pypdje.EQ, TurnON)
#turn on EQ effect
argsetter = ARGSETTER_WRAPPER(fx_panel)
keylist:KEY_VEC = argsetter.GetFXArgKeys(pypdje.EQ)

for i in keylist:
    print("key: ", i)
#get argument setter wrapper and get configurable arg keys like this.

argsetter.SetFXArg(pypdje.EQ, "EQSelect", 1)
argsetter.SetFXArg(pypdje.EQ, "EQPower", -32)
#change FX args by key
#for details, see FXArgs document
var fx_panel:FXControlPanel = AudioP.GetFXControlPanel()
#get mixed track's fx controller

var TurnON = true
fx_panel.FX_ON_OFF(EnumWrapper.EQ, TurnON)
#turn on EQ effect

var argsetter:FXArgWrapper = fx_panel.GetArgSetter()
print(argsetter.GetFXArgKeys(EnumWrapper.EQ))

#get argument setter wrapper and get configurable arg keys like this.

argsetter.SetFXArg(EnumWrapper.EQ, "EQSelect", 1)
argsetter.SetFXArg(EnumWrapper.EQ, "EQPower", -32)
#change FX args by key
#for details, see FXArgs document

On Playback Step-2: Get & Use Music Controller Panel

class MusicControlPanel

Music handler for manual mode.

MusicControlPanel *audioPlayer::GetMusicControlPanel()

music controller getter this returns the music controller. with this, you can load music, stop music in realtime manually.

Returns:

MusicControlPanel* if something wrong, it returns nullptr.

bool MusicControlPanel::LoadMusic(litedb &ROOTDB, const musdata &Mus)

loads music to the deck. doesn’t play music

Parameters:

Mus – Searched music

Returns:

int, miniaudio Error code.

bool MusicControlPanel::SetMusic(const UNSANITIZED &title, const bool onOff)

turn on, off the music

Parameters:
  • title – the music title

  • onOff – True is on, False is off

Returns:

true

Returns:

false

bool MusicControlPanel::CueMusic(const UNSANITIZED &title, const unsigned long long newPos)

Change playback position of the music.

Parameters:
  • title – the music title

  • newPos – the new playback position of the music

Returns:

true

Returns:

false

LOADED_LIST MusicControlPanel::GetLoadedMusicList()

get music list on the deck

Returns:

LOADED_LIST

FXControlPanel *MusicControlPanel::getFXHandle(const UNSANITIZED &title)

gets FX handler

Parameters:

title – the title of the music

Returns:

FXControlPanel*, the handler pointer

auto musPanel = engine->player->GetMusicControlPanel();

auto musicFound = engine->SearchMusic("title", "composer");
//find music to playback manually

bool load_OK = musPanel->LoadMusic(*(engine->DBROOT), musicFound.front());
// load found music to deck. music won't playback in here

bool unload_OK = musPanel->UnloadMusic("title");
// unload music from deck. don't forget for the memory space.
// the deck always contains loaded music before calling musPanel.UnloadMusic or engine.ResetPlayer

bool onoff_OK = musPanel->SetMusic("title", true);
// turn on the music. now music playbacks

unsigned long long second = 15;
unsigned long long PCMFrame_position = 15 * 48000;
//PCMFrame_position = second X SampleRate

bool cue_OK = musPanel->CueMusic("title", PCMFrame_position);
//set playback position of the music.

std::vector<std::string> loaded_list = musPanel->GetLoadedMusicList();
//get loaded music list.

FXControlPanel* Fxhandle = musPanel->getFXHandle("title");
//get music's fx handle
MusicControlPanel musPanel = AudioP.GetMusicControlPanel();

var musicFound = engine.SearchMusic("title", "composer");
//find music to playback manually

bool load_OK = musPanel.LoadMusic(engine.DBROOT, musicFound[0]);
// load found music to deck. music won't playback in here

bool unload_OK = musPanel.UnloadMusic("title");
// unload music from deck. don't forget for the memory space.
// the deck always contains loaded music before calling musPanel.UnloadMusic or engine.ResetPlayer

bool onoff_OK = musPanel.SetMusic("title", true);
// turn on the music. now music playbacks

ulong second = 15;
ulong PCMFrame_position = 15 * 48000;
//PCMFrame_position = second X SampleRate

bool cue_OK = musPanel.CueMusic("title", PCMFrame_position);
//set playback position of the music.

KEY_VEC loaded_list = musPanel.GetLoadedMusicList();
//get loaded music list.

FXControlPanel Fxhandle = musPanel.getFXHandle("title");
//get music's fx handle
import pdje_POLYGLOT as pyPDJE
from pdje_POLYGLOT import MusicControlPanel
from pdje_POLYGLOT import FXControlPanel
from pdje_POLYGLOT import audioPlayer
from pdje_POLYGLOT import MUS_VEC

musPanel:MusicControlPanel = engine.player.GetMusicControlPanel()

musicFound:MUS_VEC = engine.SearchMusic("title", "composer")
#find music to playback manually

load_OK = musPanel.LoadMusic(engine.DBROOT, musicFound[0])
# load found music to deck. music won't playback in here

unload_OK = musPanel.UnloadMusic("title")
# unload music from deck. don't forget for the memory space.
# the deck always contains loaded music before calling musPanel.UnloadMusic or engine.ResetPlayer

onoff_OK = musPanel.SetMusic("title", True)
# turn on the music. now music playbacks

second:int = 15
PCMFrame_position:int = 15 * 48000
#PCMFrame_position = second X SampleRate

cue_OK = musPanel.CueMusic("title", PCMFrame_position)
#set playback position of the music.

loaded_list = musPanel.GetLoadedMusicList()
#get loaded music list.

Fxhandle:FXControlPanel = musPanel.getFXHandle("title")
#get music's fx handle
var musPanel:MusPanelWrapper = AudioP.GetMusicControlPanel()

var musicFound = engine.SearchMusic("title", "composer", -1.0)
#find music to playback manually

var load_OK = musPanel.LoadMusic("title", "composer", -1.0)
# load found music to deck. music won't playback in here

var unload_OK = musPanel.UnloadMusic("title")
# unload music from deck. don't forget for the memory space.
# the deck always contains loaded music before calling musPanel.UnloadMusic or engine.ResetPlayer

var onoff_OK = musPanel.SetMusic("title", true)
# turn on the music. now music playbacks

var second = 15
var PCMFrame_position = 15 * 48000
#PCMFrame_position = second X SampleRate

var cue_OK = musPanel.CueMusic("title", PCMFrame_position)
#set playback position of the music.

var loaded_list = musPanel.GetLoadedMusicList()
#get loaded music list.

var Fxhandle:FXWrapper = musPanel.getFXHandle("title")
#get music's fx handle

Editor API

The PDJE editor provides only an API and does not include a built-in graphical user interface (GUI).

With the editor API, you can:

  • Add audio files to the PDJE database (DB) and generate metadata

  • Create and edit mix sets (combinations of multiple tracks) using the registered music in the DB

  • Create and edit note data that can be used in rhythm games

Editor Step-1: Create & Manage DB

bool PDJE::InitEditor(const DONT_SANITIZE &auth_name, const DONT_SANITIZE &auth_email, const DONT_SANITIZE &projectRoot)

Initializes the editor.

Parameters:
  • auth_name – The author’s name for Git commits.

  • auth_email – The author’s email for Git commits.

  • projectRoot – The root directory of the editor project.

Returns:

true if the editor was initialized successfully, false otherwise.

inline void PDJE::CloseEditor()

Close the Editor object.

inline std::shared_ptr<editorObject> PDJE::GetEditorObject()

editor handler getter api for binded codes. this function gives you a editor handler.

Returns:

editorObject* the editor object. check nullptr before use.

DONT_SANITIZE editorObject::DESTROY_PROJECT()

Destroys the entire project.

Warning

This operation is irreversible.

Returns:

A string indicating the result of the operation.

bool initRes = engine->InitEditor("my name", "my@email, no need to fill", "ProjectRoot");
auto editor = engine->GetEditorObject();
std::string destroyRes = editor->DESTROY_PROJECT();
engine->CloseEditor();
bool initRes = engine.InitEditor("my name", "my@email, no need to fill", "ProjectRoot");
var editor = engine.GetEditorObject();
var destroyRes = engine.DESTROY_PROJECT();
engine.CloseEditor();
init_res = engine.InitEditor("my name", "my@email, no need to fill", "ProjectRoot")
editor:editorObject = engine.GetEditorObject()
destroy_res = editor.DESTROY_PROJECT()
engine.CloseEditor()
var init_res = engine.InitEditor("my name", "my@email, no need to fill", "ProjectRoot")
var editor = engine.GetEditor()
editor.DESTROY_PROJECT()
engine.CloseEditor()

Editor Step-2: Editing Control & History view

To see all functions, check Class editorObject

Undo

// Undo Mix
bool undoRes = editor->Undo<EDIT_ARG_MIX>();

// Undo Note
undoRes = editor->Undo<EDIT_ARG_NOTE>();

// Undo KV
undoRes = editor->Undo<EDIT_ARG_KEY_VALUE>();

// Undo Music
undoRes = editor->Undo<EDIT_ARG_MUSIC>();
bool undoRes = editor->UndoNote();
undoRes = editor->UndoMix();
undoRes = editor->UndoKV();
undoRes = editor->UndoMusic();
import pdje_POLYGLOT as pypdje
from pdje_POLYGLOT import editorObject
undoRes = editor.UndoNote()
undoRes = editor.UndoKV()
undoRes = editor.UndoMix()
undoRes = editor.UndoMusic()
var undoRes = editor.Undo(editor.NOTE, "")
undoRes = editor.Undo(editor.MUSIC, "music name")
undoRes = editor.Undo(editor.MIX, "")
undoRes = editor.Undo(editor.KV, "")

Redo

// Redo Mix
bool RedoRes = editor->Redo<EDIT_ARG_MIX>();

// Redo Note
RedoRes = editor->Redo<EDIT_ARG_NOTE>();

// Redo KV
RedoRes = editor->Redo<EDIT_ARG_KEY_VALUE>();

// Redo Music
RedoRes = editor->Redo<EDIT_ARG_MUSIC>();
bool RedoRes = editor->RedoNote();
RedoRes = editor->RedoMix();
RedoRes = editor->RedoKV();
RedoRes = editor->RedoMusic();
import pdje_POLYGLOT as pypdje
from pdje_POLYGLOT import editorObject
RedoRes = editor.RedoNote()
RedoRes = editor.RedoKV()
RedoRes = editor.RedoMix()
RedoRes = editor.RedoMusic()
var RedoRes = editor.Redo(editor.NOTE, "")
RedoRes = editor.Redo(editor.MUSIC, "music name")
RedoRes = editor.Redo(editor.MIX, "")
RedoRes = editor.Redo(editor.KV, "")

Time travel

To get necessary args, See Get edit logs

//get note edit logs
std::string logs = editor->GetLogWithJSONGraph<EDIT_ARG_NOTE>();
// std::string logs = editor->GetLogWithJSONGraph<EDIT_ARG_MIX>();
// std::string logs = editor->GetLogWithJSONGraph<EDIT_ARG_KEY_VALUE>();
// std::string logs = editor->GetLogWithJSONGraph<EDIT_ARG_MUSIC>("music name"); // this is the only difference

//parse json. try print them.
auto jj = nlohmann::json::parse(logs);

//the "BRANCH" has branch lists. this is json array.
std::string branchName = jj["BRANCH"].at(0)["NAME"];
std::string branch_head_oid = jj["BRANCH"].at(0)["OID"];
// "BRANCH" is an array of { "NAME": "...", "OID": "..." }
//it has two keys. "NAME", "OID". the oid means the head commit oid of the branch.

bool GoRes = editor->Go<EDIT_ARG_NOTE>(branchName, branch_head_oid);
//bool GoRes = editor->Go<EDIT_ARG_MIX>(branchName, branch_head_oid);
//bool GoRes = editor->Go<EDIT_ARG_KEY_VALUE>(branchName, branch_head_oid);
//bool GoRes = editor->Go<EDIT_ARG_MUSIC>(branchName, branch_head_oid);
//get logs
string logs = editor.GetLogMixJSON();
//string logs = editor.GetLogNoteJSON();
//string logs = editor.GetLogMusicJSON("music name");
//string logs = editor.GetLogKVJSON();

//get branch name, oid from logs

// editor.GoNote(name, oid);
editor.GoMix(name, oid);
// editor.GoKV(name, oid);
// editor.GoMusic(name, oid);
import pdje_POLYGLOT as pypdje
from pdje_POLYGLOT import editorObject

#...

logs = editor.GetLogMixJSON()
# logs = editor.GetLogKVJSON()
# logs = editor.GetLogMusicJSON("music name")
# logs = editor.GetLogNoteJSON()

# get branch name, oid from logs

# editor.GoKV(name, oid)
# editor.GoNote(name, oid)
# editor.GoMusic(name, oid)
editor.GoMix(name, oid)
var logs = editor.GetLogWithJSONGraph(editor.NOTE, "")
# var logs = editor.GetLogWithJSONGraph(editor.MUSIC, "music name")
# var logs = editor.GetLogWithJSONGraph(editor.KV, "")
# var logs = editor.GetLogWithJSONGraph(editor.MIX, "")

#get branch name, oid from logs

editor.Go(editor.NOTE, name, oid)
# editor.Go(editor.MUSIC, name, oid)
# editor.Go(editor.MIX, name, oid)
# editor.Go(editor.KV, name, oid)

Add line

See Mix Data first.

EDIT_ARG_MIX mixs;

mixs.type = TypeEnum::FILTER; //Filter
mixs.details = DetailEnum::LOW; //Low pass

mixs.ID = 1; //Deck number. access music with this.

mixs.first = ITPL_ENUM::ITPL_COSINE; // first arg
mixs.second = "5000,1000,2000,3000,4000,5000,5500,6000"; // second arg, eight point values
// mixs.first = ITPL_ENUM::ITPL_FLAT; // if no need interpolation
// mixs.second = "5000"; // just one value

mixs.third = "NONE"; // third arg

mixs.beat = 0;
mixs.subBeat = 0;
mixs.separate = 0;
//"start_position" = beat + (subBeat / separate)

mixs.Ebeat = 16;//end beat
mixs.EsubBeat = 2;//end subBeat
mixs.Eseparate = 4;//end separate
//"end_position" = ebeat + (esubBeat / eseparate)

//summation: add low pass filter from "start_position" to "end_position" with interpolation

editor->AddLine(mixs);//add mix data

// EDIT_ARG_NOTE data;
// EDIT_ARG_KEY_VALUE data;
// EDIT_ARG_MUSIC data;

// editor->AddLine(data);

// editor->AddLine("music name", "48000") // this changes the music's first beat position
EDIT_ARG_MIX mixs = new EDIT_ARG_MIX();

mixs.type = TypeEnum.FILTER; //Filter
mixs.details = DetailEnum.LOW; //Low pass

mixs.ID = 1; //Deck number. access music with this.

mixs.first = ITPL_ENUM.ITPL_COSINE.ToString(); // first arg
mixs.second = "5000,1000,2000,3000,4000,5000,5500,6000"; // second arg, eight point values
// mixs.first = ITPL_ENUM.ITPL_FLAT.ToString(); // if no need interpolation
// mixs.second = "5000"; // just one value

mixs.third = "NONE"; // third arg

mixs.beat = 0;
mixs.subBeat = 0;
mixs.separate = 0;
//"start_position" = beat + (subBeat / separate)

mixs.Ebeat = 16;//end beat
mixs.EsubBeat = 2;//end subBeat
mixs.Eseparate = 4;//end separate
//"end_position" = ebeat + (esubBeat / eseparate)

//summation: add low pass filter from "start_position" to "end_position" with interpolation

engine.editor.AddLineMix(mixs);//add mix data
// EDIT_ARG_NOTE data;
// editor.AddLineNote(data);

// EDIT_ARG_KEY_VALUE data;
// editor.AddLineKV(data);

// EDIT_ARG_MUSIC data;
// editor.AddLineMusic(data);

// editor.AddLine("music name", "48000"); // this changes the music's first beat position.
import pdje_POLYGLOT as pypdje

from pdje_POLYGLOT import EDIT_ARG_MIX
from pdje_POLYGLOT import EDIT_ARG_MUSIC
from pdje_POLYGLOT import EDIT_ARG_KEY_VALUE

from pdje_POLYGLOT import EDIT_ARG_NOTE
from pdje_POLYGLOT import editorObject

mixs = EDIT_ARG_MIX()

mixs.type = pypdje.TypeEnum_FILTER #Filter
mixs.details = pypdje.DetailEnum_LOW #Low pass

mixs.ID = 1 #Deck number. access music with this.

mixs.first = pypdje.ITPL_COSINE.ToString() # first arg
mixs.second = "5000,1000,2000,3000,4000,5000,5500,6000" # second arg, eight point values
# mixs.first = pypdje.ITPL_FLAT.ToString() # if no need interpolation
# mixs.second = "5000" # just one value

mixs.third = "NONE" # third arg

mixs.beat = 0
mixs.subBeat = 0
mixs.separate = 0
#"start_position" = beat + (subBeat / separate)

mixs.Ebeat = 16#end beat
mixs.EsubBeat = 2#end subBeat
mixs.Eseparate = 4#end separate
#"end_position" = ebeat + (esubBeat / eseparate)

#summation: add low pass filter from "start_position" to "end_position" with interpolation

editor.AddLineMix(mixs)#add mix data
# data = EDIT_ARG_NOTE()
# editor.AddLineNote(data)

# data = EDIT_ARG_KEY_VALUE()
# editor.AddLineKV(data)

# data = EDIT_ARG_MUSIC()
# editor.AddLineMusic(data)

# editor.AddLine("music name", "48000") # this changes the music's first beat position.
var mixs = PDJE_EDITOR_ARG.new()
mixs.InitMixArg(
    PDJE_EDITOR_ARG.EDITOR_TYPE_LIST.FILTER,
    PDJE_EDITOR_ARG.EDITOR_DETAIL_LIST.LOW,
    1,
    "1",
    "5000,1000,2000,3000,4000,5000,5500,6000",
    "NONE",
    16,
    0,
    0,
    32,
    0,
    0)
#"start_position" = beat + (subBeat / separate)
#"end_position" = ebeat + (esubBeat / eseparate)
#summation: add low pass filter from "start_position" to "end_position" with interpolation
editor.AddLine(mixs)#add mix data

var data = PDJE_EDITOR_ARG.new()
data.InitKeyValueArg("", "")
editor.AddLine(data) #add key-value args

data = PDJE_EDITOR_ARG.new()
data.InitNoteArg(
    "something. ex- tap note",
    "something. ex- color red",
    "something. ex- line number",
    "something. ex- tap sound",
    "something. ex- ??",
    4,0,0,
    4,0,0)
editor.AddLine(data)#add custom simple red tap note data on music's 4th beat

data = PDJE_EDITOR_ARG.new()
data.InitMusicArg("temp music title", "120", 0, 0, 0)
editor.AddLine(data)#music starts with 120 bpm
var data2 = PDJE_EDITOR_ARG.new()
data2.InitMusicArg("temp music title", "240", 64, 0, 0)
editor.AddLine(data2)#music starts with 120 bpm and it changes into 240 bpm in 64th beat

Get all lines

std::vector<EDIT_ARG_MIX> mixFound;
editor->getAll([&mixFound](const EDIT_ARG_MIX& mix_arg){//single threaded. will add multithreaded , faster getter soon.
    if(mix_arg.beat < 50){
        mixFound.push_back();
    }
});

// std::vector<EDIT_ARG_NOTE> Found;
// editor->getAll([&Found](const EDIT_ARG_NOTE& arg);

// std::vector<EDIT_ARG_KEY_VALUE> Found;
// editor->getAll([&Found](const EDIT_ARG_KEY_VALUE& arg);

// std::vector<EDIT_ARG_MUSIC> Found;
// editor->getAll([&Found](const EDIT_ARG_MUSIC& arg);
MixCall caller = new MixCall();

editor.GetAllMixes(caller);

// editor.GetAllKeyValues(caller);
// editor.GetAllMusics(caller);
// editor.GetAllNotes(caller);

public class MixCall : MixVisitor { // MusicVisitor, NoteVisitor, KVVisitor
    public List<EDIT_ARG_MIX> mixs = new List<EDIT_ARG_MIX>();
    public override void on_item(EDIT_ARG_MIX o)// override this function
    {
        if (o.beat > 50)
        {
            mixs.Add(o);
        }
    }
};// Just change MIX into NOTE, KEY_VALUE, MUSIC
import pdje_POLYGLOT as pypdje

class MixCall(pypdje.MixVisitor):# MusicVisitor, NoteVisitor, KVVisitor
    def __init__(self):
        super().__init__()
        self.mixs = []

    def on_item(self, o:EDIT_ARG_MIX):# def this function
        if o.beat > 50:
            self.mixs.append(o)

caller = MixCall()

editor.GetAllMixes(caller)

# editor.GetAllKeyValues(caller)
# editor.GetAllMusics(caller)
# editor.GetAllNotes(caller)

for i in caller.mixs:
    print(i)
var edited_data:Dictionary = editor.getAll()

Delete line

std::vector<EDIT_ARG_NOTE> noteFound;

//find delete targets with getAll function.

for(const auto& delete_target : noteFound){
    editor->deleteLine(delete_target);
}

std::vector<EDIT_ARG_MIX> mixFound;

//find delete targets with getAll function.

bool skipType = true;
bool skipDetail = false;
for(const auto& delete_target : mixFound){
    editor->deleteLine(delete_target, skipType, skipDetail); //mix arg is special.
}
MixCall caller = new MixCall();

editor.GetAllMixes(caller);
bool skipType = true;
bool skipDetail = false;
foreach (var target in caller.mixs)
{
    editor.deleteLine(target, skipType, skipDetail);
    // editor.deleteLineKV(target);
    // editor.deleteLineMusic(target);
    // editor.deleteLineNote(target);
}
class MixCall(pypdje.MixVisitor):
    def __init__(self):
        super().__init__()
        self.mixs = []

    def on_item(self, o:EDIT_ARG_MIX):
        if o.beat > 50:
            self.mixs.append(o)

caller = MixCall()

editor.GetAllMixes(caller)

skip_type = False
skip_detail = True

for i in caller.mixs:
    editor.deleteLine(i, skip_type, skip_detail)
    # editor.deleteLineKV(i)
    # editor.deleteLineMusic(i)
    # editor.deleteLineNote(i)
var edited_data:Dictionary = editor.getAll()
for delete_target in edited_data["noteDatas"]:
    var target = PDJE_EDITOR_ARG.new()
    target.InitNoteArg(
        delete_target["note_type"],
        delete_target["note_detail"],
        delete_target["first"],
        delete_target["second"],
        delete_target["third"],
        delete_target["beat"],
        delete_target["subBeat"],
        delete_target["separate"],
        delete_target["e_beat"],
        delete_target["e_subBeat"],
        delete_target["e_separate"],
        delete_target["rail_id"],
        )
    editor.deleteLine(target, false, false)

Get edit logs

/*
JSON structure produced:

{
"BRANCH": [                          // branch head list
    {
    "NAME": string,                  // branch name (e.g., "main")
    "OID":  string                   // head commit oid (40-hex from git_oid_tostr_s)
    },
    ...
],
"COMMIT": [                          // commit metadata list
    {
    "OID":      string,              // commit oid (40-hex)
    "EMAIL":    string,              // author email
    "NAME":     string,              // author name
    "PARENTID": string               // parent commit oid (may be empty/zero for initial)
    },
    ...
]
}
*/
std::string mix_json_graph = editor->GetLogWithJSONGraph<EDIT_ARG_MIX>();
std::string key_value_json_graph = editor->GetLogWithJSONGraph<EDIT_ARG_KEY_VALUE>();
std::string note_json_graph = editor->GetLogWithJSONGraph<EDIT_ARG_NOTE>();
std::string music_json_graph = editor->GetLogWithJSONGraph<EDIT_ARG_MUSIC>("music name");
/*
JSON structure produced:

{
"BRANCH": [                          // branch head list
    {
    "NAME": string,                  // branch name (e.g., "main")
    "OID":  string                   // head commit oid (40-hex from git_oid_tostr_s)
    },
    ...
],
"COMMIT": [                          // commit metadata list
    {
    "OID":      string,              // commit oid (40-hex)
    "EMAIL":    string,              // author email
    "NAME":     string,              // author name
    "PARENTID": string               // parent commit oid (may be empty/zero for initial)
    },
    ...
]
}
*/
string KV_json_graph = editor.GetLogKVJSON();
string Mix_json_graph = editor.GetLogMixJSON();
string Music_json_graph = editor.GetLogMusicJSON("music name");
string Note_json_graph = editor.GetLogNoteJSON();
"""
JSON structure produced:

{
"BRANCH": [                          // branch head list
    {
    "NAME": string,                  // branch name (e.g., "main")
    "OID":  string                   // head commit oid (40-hex from git_oid_tostr_s)
    },
    ...
],
"COMMIT": [                          // commit metadata list
    {
    "OID":      string,              // commit oid (40-hex)
    "EMAIL":    string,              // author email
    "NAME":     string,              // author name
    "PARENTID": string               // parent commit oid (may be empty/zero for initial)
    },
    ...
]
}
"""
KV_json_graph = editor.GetLogKVJSON()
Mix_json_graph = editor.GetLogMixJSON()
Music_json_graph = editor.GetLogMusicJSON("music name")
Note_json_graph = editor.GetLogNoteJSON()
"""
JSON structure produced:

{
"BRANCH": [                          // branch head list
    {
    "NAME": string,                  // branch name (e.g., "main")
    "OID":  string                   // head commit oid (40-hex from git_oid_tostr_s)
    },
    ...
],
"COMMIT": [                          // commit metadata list
    {
    "OID":      string,              // commit oid (40-hex)
    "EMAIL":    string,              // author email
    "NAME":     string,              // author name
    "PARENTID": string               // parent commit oid (may be empty/zero for initial)
    },
    ...
]
}
"""
editor.GetLogWithJSONGraph(EditorWrapper.MIX, "")

Update edit logs

bool updateRes = false;
updateRes = editor->UpdateLog<EDIT_ARG_MIX>();
updateRes = editor->UpdateLog<EDIT_ARG_MIX>("branch name");
// updateRes = editor->UpdateLog<EDIT_ARG_KEY_VALUE>();
// updateRes = editor->UpdateLog<EDIT_ARG_KEY_VALUE>("branch name");
// updateRes = editor->UpdateLog<EDIT_ARG_MUSIC>();
// updateRes = editor->UpdateLog<EDIT_ARG_MUSIC>("music name");
// updateRes = editor->UpdateLog<EDIT_ARG_NOTE>();
// updateRes = editor->UpdateLog<EDIT_ARG_NOTE>("branch name");
bool updateRes = false;
updateRes = editor.UpdateLogMix();
updateRes = editor.UpdateLogMixOn("branch name");
// updateRes = editor.UpdateLogKV();
// updateRes = editor.UpdateLogKVOn("branch name");
// updateRes = editor.UpdateLogMusic();
// updateRes = editor.UpdateLogMusicOn("music name");
// updateRes = editor.UpdateLogNote();
// updateRes = editor.UpdateLogNoteOn("branch name");
import pdje_POLYGLOT as pypdje

updateRes = editor.UpdateLogMix();
updateRes = editor.UpdateLogMixOn("branch name");
# updateRes = editor.UpdateLogKV();
# updateRes = editor.UpdateLogKVOn("branch name");
# updateRes = editor.UpdateLogMusic();
# updateRes = editor.UpdateLogMusicOn("music name");
# updateRes = editor.UpdateLogNote();
# updateRes = editor.UpdateLogNoteOn("branch name");
editor.UpdateLog(EditorWrapper.MIX,"")
editor.UpdateLog(EditorWrapper.MUSIC,"music title")
editor.UpdateLog(EditorWrapper.NOTE,"")
editor.UpdateLog(EditorWrapper.KV,"")

Editor Step-3: Config new Music & Render & apply to root db

bool editorObject::ConfigNewMusic(const UNSANITIZED &NewMusicName, const UNSANITIZED &composer, const fs::path &musicPath, const DONT_SANITIZE &firstBeat = "0")

Configures a new music entry.

Parameters:
  • NewMusicName – The unsanitized name of the new music.

  • composer – The unsanitized composer of the new music.

  • musicPath – The path to the music file.

  • firstBeat – The first Beat of the music (defaults to “0”).

Returns:

true if the configuration was successful, false otherwise.

bool editorObject::render(const UNSANITIZED &trackTitle, litedb &ROOTDB, UNSANITIZED &lint_msg)

Renders the project data to the root database.

Parameters:
  • trackTitle – The unsanitized title of the track to render.

  • ROOTDB – The root database to render to.

Returns:

true if the rendering was successful, false otherwise.

bool editorObject::pushToRootDB(litedb &ROOTDB, const UNSANITIZED &trackTitleToPush)

Pushes a track to the root database.

Parameters:
  • ROOTDB – The root database to push to.

  • trackTitleToPush – The unsanitized title of the track to push.

Returns:

true if the push was successful, false otherwise.

bool editorObject::pushToRootDB(litedb &ROOTDB, const UNSANITIZED &musicTitle, const UNSANITIZED &musicComposer)

Pushes a music entry to the root database.

Parameters:
  • ROOTDB – The root database to push to.

  • musicTitle – The unsanitized title of the music.

  • musicComposer – The unsanitized composer of the music.

Returns:

true if the push was successful, false otherwise.

editor->ConfigNewMusic("music name", "composer name", "C://path.wav", "4800");
//configure new music meta data. the 4800 means the music's first beat is on (4800 / 48000)second after begin of the music.
std::string linter_message;
editor->render("track name", *(engine->DBROOT), linter_message);
//renders track. builds track and music binary data from editor data.
//if you want to add just musics, you don't need to edit or add track data. doesn't need to care about track name
//track or music data must contain bpm data on 0beat, 0subBeat position.

editor->pushToRootDB(*engine->DBROOT, "track title");
//push rendered binary track data to Root DB.
//all related musics will be pushed too.

editor->pushToRootDB(*engine->DBROOT, "music name", "composer name");
//just push rendered binary music data to Root DB.

//you should render before pushing music or track data.
editor.ConfigNewMusic("music name", "composer name", "C://path.wav", "4800");
//configure new music meta data. the 4800 means the music's first beat is on (4800 / 48000)second after begin of the music.
var linter_msg = "";
editor.render("track name", (engine.DBROOT), linter_msg);
//renders track. builds track and music binary data from editor data.
//if you want to add just musics, you don't need to edit or add track data. doesn't need to care about track name
//track or music data must contain bpm data on 0beat, 0subBeat position.

editor.pushToRootDB(engine.DBROOT, "track title");
//push rendered binary track data to Root DB.
//all related musics will be pushed too.

editor.pushToRootDB(engine.DBROOT, "music name", "composer name");
//just push rendered binary music data to Root DB.

//you should render before pushing music or track data.
import pdje_POLYGLOT as pypdje
editor.ConfigNewMusic("music name", "composer name", "C://path.wav", "4800")
#configure new music meta data. the 4800 means the music's first beat is on (4800 / 48000)second after begin of the music.

linter_msg = ""
editor.render("track name", (engine.DBROOT), linter_msg)
#renders track. builds track and music binary data from editor data.
#if you want to add just musics, you don't need to edit or add track data. doesn't need to care about track name
#track or music data must contain bpm data on 0beat, 0subBeat position.

editor.pushToRootDB(engine.DBROOT, "track title")
#push rendered binary track data to Root DB.
#all related musics will be pushed too.

editor.pushToRootDB(engine.DBROOT, "music name", "composer name")
#just push rendered binary music data to Root DB.

#you should render before pushing music or track data.
editor.ConfigNewMusic("music name", "composer name", "C://path.wav", "4800");
#configure new music meta data. the 4800 means the music's first beat is on (4800 / 48000)second after begin of the music.
var linter_msg = editor.render("track name");
#renders track. builds track and music binary data from editor data.
#if you want to add just musics, you don't need to edit or add track data. doesn't need to care about track name
#track or music data must contain bpm data on 0beat, 0subBeat position.

editor.pushTrackToRootDB("track title")
#push rendered binary track data to Root DB.
#all related musics will be pushed too.

editor.pushToRootDB("music name","composer name")
#just push rendered binary music data to Root DB.

#you should render before pushing music or track data.

Editor Step-4: playback editing project

void editorObject::demoPlayInit(std::shared_ptr<audioPlayer> &player, unsigned int frameBufferSize, const UNSANITIZED &trackTitle)

Initializes a demo player for a given track.

Parameters:
  • player[out] A shared pointer to the audio player to initialize.

  • frameBufferSize – The frame buffer size for the player.

  • trackTitle – The unsanitized title of the track to play.

std::shared_ptr<audioPlayer> demoplayer;
editor->demoPlayInit(demoplayer, 48, "track title");
demoplayer->Activate();
audioPlayer demoplayer = new audioPlayer(48);
editor.demoPlayInit(demoplayer, 48, "track title");
demoplayer.Activate();
import pdje_POLYGLOT as pypdje
from pdje_POLYGLOT import audioPlayer
demoplayer:audioPlayer = audioPlayer(48)
editor.demoPlayInit(demoplayer, 48, "track title")
demoplayer.Activate()
editor.demoPlayInit(48, "track title")
var demoplayer = engine.GetPlayerdd()
demoplayer.Activate()