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
make PDJE object
call SearchTrack
call InitPlayer
use player. this is handler.
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:
-
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.
-
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
-
enumerator COMPRESSOR
-
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:
-
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:
trueif the editor was initialized successfully,falseotherwise.
-
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:
trueif the configuration was successful,falseotherwise.
-
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:
trueif the rendering was successful,falseotherwise.
-
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:
trueif the push was successful,falseotherwise.
-
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:
trueif the push was successful,falseotherwise.
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
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()