English|简体中文
An .osu ⟷ .tja converter, for Python 3.
.osu
(osu! Beatmap) is the single-difficulty chart format for the game osu!. .osz
(osu! Beatmap Archive) is the standard zipped form containing multiple .osu
files and resources for a song entry in osu!.
.tja
or TJA (unknown acronym, likely "Taiko (Tatsu)jin Another") is a Taiko chart format supported by many simulators, such as TaikoJiro, Taiko-san Daijiro, Malody, TJAPlayer3, OpenTaiko, and Project OutFox.
It contains 2 major tools: osz2tja & tja2osz.
- Python 3.x
- ffmpeg (optional, for osz2tja)
If ffmpeg is installed or placed under the same directory as osz2tja.py
, osz2tja will automatically convert the audio file into .ogg
format.
Get ffmpeg here: https://www.ffmpeg.org/download.html
After downloading, unzip it and copy bin/ffmpeg.exe
into the same directory as osz2tja.py
, and the conversion should now work.
python osz2tja.py [input_folder] [output_folder]
Example:
python osz2tja.py a_folder b_folder
[input_folder]
is where your.osz
files are located. Defaults toSongs
if omitted.[output_folder]
is where the converted.tja
files and audio files will be saved. Defaults toOutput
if omitted.
osz2tja will create a folder in [output_folder]
for each generated .tja
file.
- Batch conversion of
.osz
files to.tja
files. (@MoshirMoshir) - Automatically maps osu! difficulties (up to 5 per
.tja
file) to TJA Edit (Taiko: Inner/Ura Oni or Extra Extreme), Oni (Taiko: Extreme), Hard, Normal, and Easy difficulties. (@MoshirMoshir; improved to 5) - Beatmaps with more than 5 difficulties are split into multiple
.tja
files (e.g.,title - 1
,title - 2
). (@MoshirMoshir; improved to suffix only when necessary) - Difficulty stars are adjusted between split
.tja
files to keep higher stars for higher difficulties. (@MoshirMoshir)NOT accurate to the Taiko star ratings as the
OverallDifficulty:
(timing window strictness) is currently used for estimation. - Automatically copy and convert the audio file. (@SamLangTen; OGG conversion — @k2angel)
- Input: osu file format v4–14 (those tested; warns and continues to process for other versions) (improved)
- TJA
//
comment ignoring - TJA Headers
- Metadata Headers
- osu2tja watermark (moved to the first line of the TJA file)
-
TitleUnicode:
/Title:
→TITLE:
-
Source:
AND/ORArtistUnicode:
/Artist:
→SUBTITLE:
(@k2angel) -
AudioFilename:
→WAVE:
, with automatic file copy (@SamLangTen), with OGG conversion (@k2angel) -
PreviewTime:
→DEMOSTART:
-
Creator:
→MAKER:
(@MoshirMoshir) -
Creator:
→AUTHOR:
(for Malody) (TODO) - timing point: hitsound volume (max) →
SEVOL:
÷SONGVOL:
(TODO)
- Decoration Headers
- Background event: filename →
PREIMAGE:
(TODO) - Background event: filename →
BGIMAGE:
(TODO) - Video event: filename →
BGMOVIE:
(TODO) - Video event: start time →
MOVIEOFFSET:
(TODO) - Storyboard event → TJAPlayer3-Extended OBJ commands (not planned)
- Background event: filename →
- Sync Headers
- initial BPM →
BPM:
(for display only, rounded to 2 decimal digits), for each difficulty (new) - initial beat time position →
OFFSET:
(improved), for each difficulty (new)- The
OFFSET:
is set to the beginning time position of the last beat non-after the audio to mimic osu! behavior. It was the earliest of the first note or the timing point in delguoqing's version.
- The
- initial BPM →
- Difficulty Headers
-
Version:
&Mode:
→ TJA comment (for reference only) (new) -
Version:
→NOTEDESIGNER<n>:
(for guest difficulties) (TODO) -
Creator:
→NOTEDESIGNER<n>:
(otherwise) (TODO) - Difficulties sorted by
OverallDifficulty:
→COURSE:
(@SamLangTen; automated — @MoshirMoshir; improved to includeCOURSE:Edit
) -
OverallDifficulty:
→LEVEL:
(@SamLangTen)- TODO: Use the actual osu! star rating.
- Spinner: Time length →
BALLOON:
(improved using the official formula to account forOverallDifficulty:
(might still off by 1 or 2 hits))
-
- Metadata Headers
- TJA Commands
- Uninherited timing point: BPM →
#BPMCHANGE
- Uninherited timing point: Beats per bar →
#MEASURE
- Incomplete bar →
#MEASURE
+ optional#DELAY
(crash fixed — @delguoqing; improved to ms-level accuracy) - Inherited timing point: Slider velocity change →
#SCROLL
(uncapped range) - Timing point: Kiai time →
#GOGOSTART
&#GOGOEND
- Timing point: Omit first bar line →
#BARLINEOFF
&#BARLINEON
(TODO)
- Uninherited timing point: BPM →
- TJA Note Definition
- Timing
- relative time offset to bar start and end → beat division
- Mid-bar inter-note command insertion (improved, new)
- ms-level timing accuracy (TODO)
- Currently everything is pre-quantized to 1/96ths (1/24 beats).
- Note Symbols
- (std mode) short slider to circles (improved using the official algorithm)
- Empty →
0
(blank) - Circle, normal non-finish hitsound →
1
(regular Don) - Circle, whistle/clap non-finish hitsound →
2
(regular Katsu) - Circle, normal finish hitsound →
3
(big Don) - Circle, whistle/clap finish hitsound →
4
(big Katsu) - Slider, non-finish hitsound →
5
+8
(regular bar drumroll) - Slider, finish hitsound →
6
+8
(big bar drumroll) - Spinner, ANY hitsound →
7
+8
(regular balloon roll) - Spinner, finish hitsound →
9
+8
(special balloon roll) (TODO)
- Timing
python tja2osz.py [input_folder] [output_folder]
Example:
python tja2osz.py a_folder b_folder
[input_folder]
is where your.tja
files are located (can be in any inner directories). Defaults toSongs
if omitted.[output_folder]
is where the converted.osu
files and audio files will be saved. Defaults toOutput
if omitted.
tja2osz will create a folder in [output_folder]
for each processed .tja
file. This folder will contain converted .osu
files and audio file. tja2osz will also create an .osz
file in [output_folder]
for these .osu
files.
- Batch conversion of
.tja
files to.osz
files. (new) - Automatically split each TJA difficulty and each main branch route as a separate
.osu
difficulty file. - Automatically copy the audio file (new)
- Output: osu file format v14 (improved)
- TJA
//
comment ignoring- FIXME:
//
comments do not disable commands when splitting TJAs.
- FIXME:
- TJA Headers
- Metadata Headers
- osu2tja watermark (new)
-
TITLE:
→Title:
- FIXME: The encoding detection is usually wrong
-
SUBTITLE:
→Artist:
(TODO) (Currently defaults tounknown
) -
MAKER:
/AUTHOR:
→Creator:
(TODO) (Currently defaults tounknown
) -
SUBTITLE:
→Source:
(bug fixed)- FIXME: The encoding detection is usually wrong
- ? →
Tags:
(defaults totaiko jiro tja
) -
WAVE:
→AudioFilename:
, with automatic file copy (new) - ? →
AudioLeadIn:
(defaults to0
) (improved) -
DEMOSTART:
→PreviewTime:
(bug fixed) - ? →
CountDown:
(defaults to0
(false)) - ? →
SampleSet:
(defaults toNormal
) -
StackLeniency:0.7
(no effects) - ? →
Mode:
(defaults to1
(Taiko)) - ? →
LetterboxInBreaks:
(defaults to0
(false)) (improved) -
SEVOL:
÷SONGVOL:
→ Timing point: hitsound volume (new)
- Decoration Headers
-
PREIMAGE:
→ Background event: filename (TODO) -
BGIMAGE:
→ Background event: filename (TODO) -
BGMOVIE:
→ Video event: filename (TODO) -
MOVIEOFFSET:
→ Video event: start time (TODO) - TJAPlayer3-Extended OBJ commands → Storyboard event (not planned)
-
- Sync Headers
-
BPM:
→ initial uninherited timing point: BPM -
OFFSET:
→ initial uninherited timing point: time
-
- Difficulty Headers
-
STYLE:
→Version:
(TODO) -
COURSE:
→Version:
-
NOTESDESIGNER<n>:
→Version:<notesdesigner>'s <course>
when<notesdesigner>
isn't<maker>
/<author>
(TODO) -
COURSE:
+LEVEL:
→HPDrainRate
(TODO) (defaults to7
(roughly Taiko Oni 10 full gauge) (improved)) -
CircleSize:5
(no effects) -
ApproachRate:5
(no effects) -
COURSE:
+LEVEL:
→OverallDifficulty:
(TODO) (defaults to8.333
(Taiko Hard & Oni GREAT/GOOD window) (improved)) - ? →
SliderMultiplier:
(defaults to1.47
(AC15– note spacing)) - (Mostly-used) beat division →
SliderTickRate:
(TODO) (defaults to4
(1/16th)) -
HEADSCROLL:
→ initial inherited timing point: Slider velocity change (TODO)
-
- Metadata Headers
- TJA Commands
-
#START
→ Uninherited timing point: Large beats per bar + omit first bar line + (optional) incomplete bar (TODO) -
#START P<n>
→ Split into player-side TJA (TODO)- FIXME: When a multiple–player-side chart set has been defined for any difficulty, wrong difficulties will be notated for split difficulties.
-
#END
→ Uninherited timing point: Large beats per bar + omit first bar line (new) -
#BRANCHSTART
→ Begin branch-split section- TODO: detect and avoid impossible branch routes
-
#N
/#E
/#M
→ Split into branch TJA- FIXME: Omitting some branches causes missing bars.
-
#BRANCHEND
→ Begin branch-common section- FIXME:
#BRANCHEND
is recognized but ignored.
- FIXME:
-
#BPMCHANGE
, positive → Uninherited timing point: BPM -
#BPMCHANGE
, negative, with positive (bar length ÷ BPM) → Uninherited timing point: absolute-valued BPM (TODO) -
#MEASURE
, positive integer beats → Uninherited timing point: Beats per bar (improved), float values (new) -
#MEASURE
, positive fraction beats → Uninherited timing point: Beats per bar + incomplete bar (improved), float values (new) - Negative (bar length ÷ BPM) → Notechart events are not in completely increasing time order, re-sorted by time (TODO)
-
#DELAY
→ move time of definition cursor- FIXME: The bar line after
#DELAY
will be wrongly displayed until the next uninherited timing point generated. - FIXME: The generated events might not be in the correct increasing time order if large negative
#DELAY
s are used.
- FIXME: The bar line after
-
#SCROLL
, with positive (scroll × BPM) → Inherited timing point: Slider velocity change- FIXME: Use BPM changes to work around the slider velocity change being capped between 0.01x to 10x in osu!.
- Non-positive/complex-valued (scroll × BPM) → Inherited timing point: Absolute-valued slider velocity change (TODO)
-
#SUDDEN
, with positive stop duration → Inherited timing point: Scaled slider velocity change (TODO) -
#GOGOSTART
&#GOGOEND
→ Timing point: Kiai time -
#BARLINEOFF
&#BARLINEON
→ Timing point: Omit first bar line (new) -
#BARLINE
→ Split bars into (possibly) incomplete bars (TODO) -
#BARLINESCROLL
→ Inherited timing points: Slider velocity change for every bar line and every first note after bar line; split out a 1ms bar with omitted first bar line for notes on the original bar start (TODO)
-
- TJA Note Definition
- Timing
- Measure with no note symbols (
,
) → Full measure (new bug fix) - Sum of (bar length ÷ beat division ÷ BPM at each division) → relative time offset to bar start (bug fixed for fractional-beat bars with
#SCROLL
) - ms-level timing accuracy (TODO)
- Currently everything is pre-quantized to 1/96ths (1/24 beats).
- Measure with no note symbols (
- Note Symbols
-
0
(blank) → Empty -
1
(regular Don) → Circle, default hitsound -
2
(regular Katsu) → Circle, clap hitsound -
F
(ad-lib) → = regular Don/Katsu? (TODO) -
C
(bomb/mine) → = regular Don/Katsu? empty? (TODO) -
3
(big Don) → Circle, finish hitsound -
A
(handed big Don) → Circle, finish hitsound (TODO) -
4
(big Katsu) → Circle, clap finish hitsound -
B
(handed big Katsu) → Circle, clap finish hitsound (TODO) -
G
(Kadon) → = big Don/Katsu? (TODO) -
5
(head of regular bar drumroll) → Slider, default hitsound -
I
(head of regular/Katsu? bar drumroll) → = head of regular bar drumroll? (TODO) -
6
(head of big bar drumroll) → Slider, finish hitsound -
H
(head of big/Don? bar drumroll) → = head of big bar drumroll? (TODO) -
7
(head of regular balloon roll) → Spinner, default hitsound -
9
(head of special balloon roll) → Spinner, default hitsound- TODO: use finish hitsound to mark difference
-
D
(head of fuze balloon roll) → = regular balloon roll? (TODO) - Head of any roll-type note, after unended roll-type notes → Empty (TODO)
-
8
(explicit end of rolls), after unended roll-type notes → End of last slider/spinner - Any hit-type note, after unended roll-type notes → Forced end of last slider/spinner (TODO)
-
#END
(command), after unended roll-type notes → Forced end of last slider/spinner (TODO) -
8
, straying → Empty (TODO) - Any roll-type note, non-positive time duration → Empty (TODO)
-
- Timing