Code Monkey home page Code Monkey logo

infinitebeatsaber's Introduction

Infinite Beat Saber

A Beat Saber for PC mod that generates never-ending and ever changing variations of existing Beat Saber levels. Play your favorite songs for as long as you want — they never end!

This mod is both inspired by the The Infinite Jukebox and leverages some of its source code. See the Credits section for details.

How to Play

  1. Install the Infinite Beat Saber mod using ModAssistant or a mechanism of your choosing. If you haven't installed any Beat Saber mods before, you might want to check out the PC Modding page on the Beat Saber Modding Group Wiki. (If you prefer manual installation, see the Manual Installation doc.)
  2. Launch Beat Saber.
  3. Press the "Solo" button.
  4. Select one of the 42 currently supported levels. Only the Standard, One Saber, and No Arrows modes are currently supported.
  5. Press the button with the infinity symbol on it — (1) in the screenshot.
  6. Play the song for as long as you like — it never ends!

Here's a screenshot highlighting the relevant UI:

Screenshot highlighting the Custom Levels and infinity buttons

If the infinity button is disabled, it means one of these things:

  1. The selected level isn't currently supported.
  2. The selected mode isn't currently supported — only the Standard, One Saber, and No Arrows modes are currently supported.

If you hover over the infinity button, it'll pop up some text describing which case it is.

Currently Supported Levels

All but 3 built-in levels are supported (excluding DLC). In other words, these level packs are supported:

  • Original Soundtrack Volumes 1 through 5
  • Extras
  • Camellia Music Pack

These are the 3 unsupported levels:

  • I Wanna Be A Machine by The Living Tombstone. Mapped by ConnorJC (Issue #1)
  • One Hope ft. David Binney by KNOWER (Issue #2)
  • Light it up by Camellia (Issue #3)

Additionally, these custom levels are supported:

How to Add Additional Levels

See the How to Add Additional Levels doc.

How It Works

For songs in Spotify's catalog, Spotify's audio analysis web API provides information about their structure and musical content including rhythm, pitch, and timbre. The Infinite Jukebox algorithm (see InfiniteJukeboxAlgorithm/) uses this information to figure out which sections of the song are so similar that it can jump the song from one section to the other without the listener noticing a seam in the music. The result is a never-ending list of song sections — play this section, then this section, then this section, etc.

Based on this never-ending list of song sections, Infinite Beat Saber slices up the audio and beatmap which results in a never-ending Beat Saber level.

If you're interested in understanding the code, InfiniteBeatSaberMode.cs would be a good place to start. It brings together all of the pieces so it contains the big picture. From there, you can jump into any of the pieces that interest you.

Credits

This mod is inspired by The Infinite Jukebox and leverages its algorithm.

The original implementation of The Infinite Jukebox is by Paul Lamere.

The code for the Infinite Jukebox algorithm in this repo is derived from The Eternal Jukebox by UnderMybrella, a rework of the original project.

I published my extraction of the Infinite Jukebox algorithm to its own repo to make it easier for anyone that wants to make use of the algorithm in their own projects.

Development Blog

If you want to hear about my experience working on this project, check out the Infinite Beat Saber Development Blog. Here are some highlights:

Support My Work

If you'd like to support my work, consider buying me a coffee on ko-fi.

License

MIT

infinitebeatsaber's People

Contributors

rigdern avatar

Stargazers

Davi Rodrigues avatar  avatar A.s. avatar Ryan Govostes avatar

Watchers

 avatar  avatar

Forkers

joerkig

infinitebeatsaber's Issues

Explore a better alignment for LudicrousPlus

I was running commit 3421722 with a SystemRandom seed of 342932250. The first jump has a noticeable seam. Here's an idea for a technique for investigating a better alignment:

  • Set up the game to do a 2 second loop around the first jump and try different values for shiftTimestampsSeconds. Maybe such a loop would enable a rapid testing of jump quality and could be a good technique to find the right alignment for a song.

Support adding songs without recompiling the mod

Adding a song requires 3 pieces of information:

  • The song ID
  • The Spotify analysis file for the song
  • ShiftTimestampsSeconds. The number of seconds by which to shift the Spotify analysis timestamps so that they're aligned with those of the Beat Saber song.

Potential solutions

  • To add a song, create a JSON file called <song-id.json> in InfiniteBeatSaber/songs. It has these keys:
    • shiftTimestampsSeconds
    • spotifyAnalysis: The value should be the contents of the Spotify analysis file (for example Spotify analysis files, see SpotifyAnalyses/)

Other notes

  • Modifying a song's Info.dat changes its hash and, consequently, ID. This is used by Beat Saver when submitting scores to the leaderboard.
  • I'm not sure if adding new files to a song's folder would have any unintentional effects. I don't think it affects the song's hash/ID. It would be good to double check.

See also

Replace Spotify’s audio analysis with one that can be run on any song

The major constraint with Spotify’s audio analysis web API is that the data is only available for Spotify’s audio files. Implications:

  • Songs don’t work with Infinite Beat Saber when:
    • They aren’t on Spotify
    • They are on Spotify but the audio file we have is too different from Spotify’s (e.g. OneHope)
  • Even when a song is on Spotify and is nearly identical to our audio file, it still takes 10 minutes or so to align the audio files (i.e. determine shiftTimestampsSeconds in RemixableSongs.cs)

For these reasons, it’d be great to have a replacement for Spotify’s audio analysis that we can use with any audio file we want. It would enable Infinite Beat Saber to work with any song and it’d remove some of the manual effort required to add a song to Infinite Beat Saber.

Resources

These resources may be helpful. I found them in spotify/web-api#209 (comment).

BeatmapRemixer: Consider heuristics for eliminating “impossible” player movements when joining 2 sections of a beatmap together

BeatmapRemixer's job is to generate a remix of the beatmap. This involves joining beatmap sections that weren’t originally joined. This can result in boundaries of beatmap sections that are nearly impossible for the player to hit. Examples:

  • Two notes of the same color that appear on sequential beats (or close to it) and are on completely different parts of the screen. For example, imagine trying to hit a red note in the top left corner on one beat and a red note in the bottom right corner on the next beat.
  • A note that is blocked by a wall (because the note is on the beat immediately after the wall (or close to it)).
  • Two notes of the same color that appear on sequential beats (or close to it) that are in the same spot and have the same cut direction. For example, imagine having to swing down to hit a red note on one beat and having to swing down again to hit a red note on the next beat.
  • A note sequence that results in a handclap (the player smashing their controllers together). For example, a red note pointing right and, on the next beat, a blue note pointing left.
  • See the “Pattern Best Practices” section of the Beat Saber Modding Group Wiki’s Basic Mapping page for more ideas on the kinds of things BeatmapRemixer should avoid.

Possible solutions:

  • Here’s a straightforward solution. When joining two beatmap sections, ensure the boundary doesn’t have any beatmap items that are within X seconds of each other (X to be determined). If there are, delete some of these beatmap items so that there’s at least X seconds of free space at the boundary. This would have to be tested to see how good the resulting beatmap remixes feel.
  • A more complicated solution would be to manually implement heuristics for eliminating undesirable beatmap patterns at section boundaries. For example, there could be a heuristic that checks for notes that are immediately behind walls. If there are, the wall is removed.

Support Beat Saber version 1.32.0

When mod support becomes available for Beat Saber 1.32.0 we'll need to:

  • Update the manifest's gameVersion
  • Potentially update the versions of other dependencies we're using.
  • Test Infinite Beat Saber running in Beat Saber 1.32.0.
  • Submit to BeatMods.

Investigate supporting built-in level: OneHope

This level is currently unsupported because the Beat Saber & Spotify songs are too different. Notes:

  • The Spotify song (4:01) is significantly longer than the Beat Saber song (2:52) so there will be differences.
  • The 2nd instrument starts at the same timestamp in the Spotify & Beat Saber songs (~3.3).
  • But at 2:30 Spotify has a horn solo & Beat Saber has singing.
  • So the Spotify & Beat Saber songs might be too different to use Spotify's audio analysis data.

If more time is spent comparing the Beat Saber & Spotify songs, we might discover that the songs are sufficiently similar that we can make use of Spotify's audio analysis data.

Investigate impact of Beat Saber & Spotify BPM difference in INeedYou

These are the BPMs:

  • Beat Saber: 128
  • Spotify: 192.076 (as seen in the Spotify analysis file)

Spotify’s BPM is 1.5x that of the Beat Saber one. It’s not an integer multiple. Questions:

  • Does it make sense that the BPM could be interpreted to be 192.076? Or is it a bug in Spotify’s analysis data?
  • When we generate a remix, does this result in noticeable seams when the audio jumps from one beat to another?
    • InfiniteRemix.BeatAlignedObject shifts slices such that every slice starts and ends on a beat (using Beat Saber’s BPM). Is this problematic? Does it result in noticeable seams when the audio jumps from one beat to another? Should we be using Spotify’s BPM instead? But then could we end up with weird results when using Spotify’s BPM to slice the beatmap (which the author designed with Beat Saber’s BPM, not Spotify’s)?

Consider better implementation for chains

I went with the most straightforward implementation. It just omits any chains that don't fully fit into the song slice.

Improvement ideas:

  • If a chain doesn't fully fit into a slice, it could be truncated to the portion that does fit into the slice. Would this benefit be worth the implementation cost?

  • Whenever we omit a SliderData that represents a chain (i.e. its sliderType is Burst) then we should also omit the item representing the head of the chain (the head of the chain is a NoteData with type: BurstSliderHead).

    For now, we leave the head of the chain alone because it results in the simplest implementation. Leaving it in doesn't result in any undesirable side effects in the game, as far as I know.

    A good question is: is there any noticeable impact of our current implementation of omitting the SliderData but not NoteData, type: BurstSliderHead? If not, perhaps it’s not worth the implementation cost of doing anything fancier than we’re currently doing.

Investigate supporting built-in level: LightItUp

This level is currently unsupported because aligning the Beat Saber & Spotify songs requires more investigation. I tried 3 reference points but they all had quite different shifts between the Beat Saber & Spotify songs:

  • Initial drum (shiftTimestampsSeconds: 1.6 secs)
    • Spotify: 0:01.2
    • Beat Saber: 0:02.8
  • Vocals (shiftTimestampsSeconds: 2.9 secs)
    • Spotify: 4:01.2
    • Beat Saber: 4:04.1
  • Final clap (shiftTimestampsSeconds: 3.7 secs)
    • Spotify: 6:02.9
    • Beat Saber: 6:06.6

Did I make any mistakes?

Is the Spotify version of the song too different from the Beat Saber one for the Spotify audio analysis data to be usable?

Support a field for specifying Spotify analysis file path in Info.plist of custom maps

Currently Infinite Beat Saber only looks for Spotify analysis data in its own DLL. In addition, we should allow maps to ship with Spotify analysis data. Thoughts:

  • The map’s Info.plist can contain custom keys for:
    • The path to the Spotify analysis data file
    • The value of shiftTimestampsSeconds (name taken from RemixableSongs.cs)
  • The map can include the Spotify analysis data file somewhere in its directory (like it includes a beatmap file for each difficulty it supports).

Notes

  • Modifying a song's Info.dat changes its hash and, consequently, ID. This is used by Beat Saver when submitting scores to the leaderboard.
  • I'm not sure if adding new files to a song's folder would have any unintentional effects. I don't think it affects the song's hash/ID. It would be good to double check.
  • Maybe it'd be better to have an infiniteBeatSaber.json file in the song's directory if it's the case that this information could be added and updated without affecting the song's hash/ID.

See also

Investigate impact of beats in RumNBass & AngelVoices that have a length other than 1

Some songs have Spotify analysis files with beats that have a length other than 1 beat. Here’s what I’m wondering:

  • Why isn’t each beat’s duration 1 beat? Is it a bug in Spotify’s analysis data?
  • When we generate a remix, does this result in noticeable seams when the audio jumps from one beat to another?
    • InfiniteRemix.BeatAlignedObject shifts slices such that every slice starts and ends on a beat. Is this problematic? Does it result in noticeable seams when the audio jumps from one beat to another?
  • When loading a Spotify analysis file, should we consider filtering out the beats that have a duration that isn’t 1?

RumNBass

Below is the list of beats in RumNBass that have a duration that isn’t 1. It was generated by EvalProgram.GenerateSongCatalogCompatibilityReport.

Table of RumNBass beats that have a length other than 1.
Timestamp (seconds) Beat duration (in beats)
0.39489 1.313511913
0.99176 1.316482813
1.58998 1.317671173
2.18875 1.314106093
2.78588 1.315294453
3.38356 1.326627887
3.98639 1.334968413
4.59301 1.336156773
5.20017 1.333780053
5.80625 1.330192967
6.4107 1.333163867
7.01649 1.335540587
7.62337 1.33433022
8.2297 1.33433022
8.83603 1.3349244
9.44263 1.337279113
10.0503 1.3408662
10.6596 1.337279113
11.26727 1.331909487
11.8725 1.3342642
12.4788 1.335430553
13.08563 1.33300982
13.69137 1.332371627
14.29681 1.330523067
14.90141 1.32984086
15.5057 1.33452828
16.11212 1.335606607
16.71903 1.334902393
17.32561 1.33716908
17.93324 1.334704333
18.53974 1.33267972
19.14532 1.33697102
19.75285 1.333978113
20.35902 1.330413033
20.96357 1.3316234
21.56867 1.329884873
22.17297 1.329928887
22.7773 1.331931493
23.38254 1.33241564
23.98799 1.334836373
24.59455 1.334880387
25.20113 1.333758047
25.8072 1.333824067
26.4133 1.33505644
27.01996 1.336288813
27.62719 1.332173567
28.23253 1.332195573
28.8379 1.335804667
29.4449 1.335232493
30.05164 1.33406614
30.65785 1.334704333
31.26435 1.33532052
31.87113 1.337719247
32.479 1.337675233
33.08685 1.334044133
33.69305 1.332173567
34.29841 1.335804667
34.9054 1.335958713
35.51247 1.331909487
36.1177 1.331931493
36.72294 1.333163867
37.32874 1.335606607
37.93566 1.338049347
38.54368 1.3355846
39.15058 1.333626007
39.75659 1.335870687
40.36361 1.336266807
40.97082 1.335958713
41.5779 1.338071353
42.18592 1.339567807
42.79463 1.336905
43.40213 1.334242193
44.00843 1.333383933
44.61433 1.33089718
45.2191 1.329730827
45.82334 1.326187753
46.42597 1.323855047
47.02754 1.3293127
47.63158 1.331777447
48.23675 1.32951076
48.84089 1.337983327
49.44888 1.341108273
50.05829 1.33769724
50.66615 1.33664092
51.27353 1.331997513
51.8788 1.3332739
52.48464 1.3398759
53.09349 1.333978113
53.69967 1.326891967
54.30261 1.331117247
54.90748 1.335364533
55.51428 1.337257107
56.12194 1.3355846
56.72884 1.332723733
57.33444 1.330457047
57.93901 1.334154167
58.54526 1.337257107
59.15292 1.33380206
59.75901 1.331513367
60.36405 1.33340594
60.96997 1.33175544
61.57512 1.33307584
62.18088 1.336156773
62.78805 1.332657713
63.39361 1.330919187
63.99839 1.330391027
64.60293 1.329818853
65.20721 1.33578266
65.8142 1.3375652
66.42201 1.33281176
67.02764 1.334572293
67.63408 1.336949013
68.2416 1.337521187
68.84938 1.34047008
69.4585 1.337477173
70.06626 1.333890087
70.67239 1.335672627
71.27934 1.333317913
71.88521 1.330391027
72.48976 1.334638313
73.09623 1.3359147
73.70328 1.33300982
74.30901 1.33367002
74.91504 1.3319535
75.52029 1.3296428
76.12449 1.33446226
76.73088 1.335078447
77.33755 1.329136647
77.94152 1.329158653
78.5455 1.328564473
79.14921 1.327376113
79.75238 1.329158653
80.35636 1.328564473
80.96007 1.32878454
81.56388 1.263732833
82.13812 1.19865912

AngelVoices

Below is the list of beats in AngelVoices that have a duration that isn’t 1. It was generated by EvalProgram.GenerateSongCatalogCompatibilityReport:

Table of AngelVoices beats that have a length other than 1.
Timestamp (seconds) Beat duration (in beats)
144.76611 1.19977719
145.19972 1.301185907
145.66998 1.402566955
146.17688 1.503948003
146.72041 1.505331478
147.26447 1.500074273
147.8066 1.496145204
148.34732 1.505663512
148.8915 1.512497879
149.43811 1.51797644
149.98672 1.499271858
150.52856 1.47647219
151.06218 1.491275372
151.60115 1.496698594
152.14207 1.488674439
152.68008 1.483334226
153.21619 1.480484267
153.75124 1.485464777
154.2881 1.510588683
154.83405 1.522292882
155.38422 1.532585936
155.9381 1.510644022
156.48405 1.50743436
157.02887 1.503090249
157.57208 1.509592581
158.11768 1.509426564
158.6632 1.484966726
159.19987 1.471242654
159.73158 1.485713803
160.26855 1.493350585
160.80826 1.499659231
161.35025 1.497777705
161.89156 1.47312418
162.42397 1.465736424
162.95369 1.446395443
163.47643 1.433501456
163.9945 1.427497175
164.51042 1.423789462
165.02498 1.433639804
165.5431 1.451043919
166.06754 1.460617566
166.59541 1.480567276
167.1305 1.500710672
167.67288 1.503200927
168.21614 1.507046987
168.7608 1.490971008
169.29964 1.471325663
169.83139 1.44769591
170.3546 1.428188912
170.87076 1.432505354
171.38847 1.430402472
171.90544 1.427248149
172.42126 1.436019381
172.94025 1.459510786
173.46774 1.490887999
174.00656 1.519774957
174.55582 1.516814321
175.104 1.510118302
175.64978 1.508707157
176.19504 1.50466741
176.73885 1.500655333
177.28119 1.492575839
177.82063 1.481895412
178.35619 1.480511937
178.89127 1.493654949
179.43109 1.490943338
179.96992 1.494817068
180.51018 1.500046604
181.0523 1.49747334
181.5935 1.500489316
182.13579 1.495757831
182.67638 1.498967493
183.21811 1.491773423
183.75725 1.507102326
184.30194 1.500129612
184.8441 1.502426181
185.38708 1.513826015
185.9342 1.511778472
186.48058 1.500572324
187.02289 1.510367327
187.56876 1.499078171
188.11053 1.500766011
188.65292 1.396036953
189.15746 1.295707346
189.62575 1.195405409

Consider better implementation for `ColorBoostBeatmapEventData`

I went with the easiest implementation. My understanding is that ColorBoostBeatmapEventData enables the map to switch between two different color schemes. I'm not sure exactly what colors are affected. Maybe just lights & lasers? This video has some info: Boost Colors | Beat Saber Explained - YouTube

Currently, for each map segment, there's no guarantee that we preserve that segment's original boost setting. We should consider preserving it. The problem is that the boost color setting is stateful so a segment receives the boost color setting of the most recent ColorBoostBeatmapEventData event.

Support levels that have BPM changes

This issue is about supporting levels that change their BPM during the song (via the BPMChangeBeatmapEventData event).

This issue affects these levels:

  • IWannaBeAMachine

For example, IWannaBeAMachine has these BPM changes via the event BPMChangeBeatmapEventData:

Timestamp (seconds) BPM
-100 128
0 128.2381
3.743039 127.9312
33.75918 127.9747
48.76215 128.0574
78.7487 128.0454
108.7381 128.0485
138.7267 127.8375
166.8875 104.7496
169.1786 105.1153
205.7099 66.65743

Consider hooking up unit tests

  • We could run EvalProgram.GenerateSongCatalogCompatibilityReport or some subset of it.
  • Would we launch Beat Saber?
    • Or just link against its DLL?
    • Or test stuff that doesn’t require Beat Saber (e.g. validating Spotify analysis files)?
    • Or load Beat Saber data from disk rather than via runtime APIs?

Explore improving the remixing implementation

Jumps in SpinEternally often seem more noticeable than those in other songs. So SpinEternally seems like a good song to study to identify weaknesses in the remix implementation and how to improve it. Things to explore:

  • Is shiftTimestampsSeconds (in RemixableSongs.cs) close enough?
  • Is QueueBasedAudioRemixer.cs doing a good job of scheduling the audio?
  • Is InfiniteRemix.cs producing song slices with bad timestamps (e.g. maybe BeatAlignedObject is flawed and is messing up the timestamps).
  • Is InfiniteJukeboxAlgorithm/ doing a good job of identifying similar beats in the song?
    • Maybe its implementation or its parameter values should be tweaked to improve SpinEternally.
    • Maybe it’s being too lenient on SpinEternally and suggesting jumps between beats that aren’t similar enough.
  • Are there any issues with the analysis data provided by Spotify's audio analysis web API?

Related

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.