Skip to content

Instantly share code, notes, and snippets.

@chayleaf
Last active June 14, 2019 14:34
Show Gist options
  • Save chayleaf/33e7a196be526137e4c2ad3aacd19088 to your computer and use it in GitHub Desktop.
Save chayleaf/33e7a196be526137e4c2ad3aacd19088 to your computer and use it in GitHub Desktop.
osu! map joiner
#pls report bugs to u/pavlukivan on reddit
#dependencies (install via pip): osu; pydub.
from osu import Beatmap, SampleSet
from osu.events import BackgroundEvent
from pydub import AudioSegment
import random, os
#one file per line
bmFiles = [f for f in '''
/run/media/pavlukivan/7C6CE42C6CE3DF40/osu!/Songs/118 TRF - Survival dAnce _no no cry more_/TRF - Survival dAnce ~no no cry more~ (Echo49) [Insane].osu
/run/media/pavlukivan/7C6CE42C6CE3DF40/osu!/Songs/141 FAIRY FORE - Vivid/FAIRY FORE - Vivid (Hitoshirenu Shourai) [Insane].osu
'''.split('\n') if f]
bms = [Beatmap(f) for f in bmFiles]
newBM = bms[0]
mapID = hex(random.randint(0, 0xFFFFFFFF))[2:].zfill(8)
newBM.titleA = 'Marathon ' + mapID
newBM.titleU = newBM.titleA
newBM.artistA = 'Various artists (maybe)'
newBM.artistU = newBM.artistA
newBM.creator = ''
newBM.diffName = 'long thing'
newBM.source = ''
newBM.mapID = 0
newBM.mapsetID = 0
newBM.tags = ' '.join(b.tags for b in bms)
print('Importing HP/OD/CS/AR/SV from the first map. Edit it later if necessary.')
audio = AudioSegment.from_file(os.path.join(os.path.dirname(bms[0].filename), bms[0].audioFile))
lastObj = bms[0].audioLeadIn + bms[0].hitObjects[-1].time
if len(audio) > lastObj + 2500:
audio = audio[:lastObj + 2500].fade_out(2500)
else:
audio = audio[:len(audio)]
ofs = len(audio)
for b in bms[1:]:
tp = b.timingPoints
li = b.audioLeadIn
fadeTime = min(li, 2500)
lastObj = li + b.hitObjects[-1].time
for p in tp:
if p.time <= lastObj:
p.time += len(audio) + fadeTime
if p.hitSound.sampleSet == SampleSet.AUTO:
p.hitSound.sampleSet = b.sampleSet
newBM.timingPoints.append(p)
for o in b.hitObjects:
o.time += len(audio) + fadeTime
newBM.hitObjects.append(o)
for e in b.events:
if e.time <= lastObj and not isinstance(e, BackgroundEvent):
e.time += len(audio) + fadeTime
newBM.events.append(e)
seg = AudioSegment.from_file(os.path.join(os.path.dirname(b.filename), b.audioFile))
if len(seg) - li > lastObj + 2500:
seg = seg[:lastObj + 2500 + li].fade_out(2500)
else:
seg = seg[:len(seg)]
seg = seg[max(0, li - 2500):].fade_in(fadeTime)
audio = audio.append(seg)
newBM.audioFile = 'mix.mp3'
audio.export('mix.mp3', format='mp3', bitrate='192k')
newBM.save('map.osu')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment