Skip to content

Commit

Permalink
update osu assets, add more effects
Browse files Browse the repository at this point in the history
  • Loading branch information
konekowo committed Jun 28, 2024
1 parent 7761688 commit 1102cbe
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 33 deletions.
20 changes: 12 additions & 8 deletions src/Audio/Audio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ export class Audio {
if (!this.source){
throw new Error("Source not created yet!");
}
this.source.connect(node);
this.nodes.push(node);
}

Expand All @@ -36,7 +35,7 @@ export class Audio {
}
}

public ConnectToContext(audioContext: AudioContext) {
public ConnectToContext(audioContext: AudioContext, howToConnectFunction?: (nodes: AudioNode[], source: AudioBufferSourceNode) => void) {
if (!this.source){
throw new Error("Source not created yet!");
}
Expand All @@ -45,12 +44,17 @@ export class Audio {
}
this._connectedToContext = true;
if (this.nodes.length > 0){
this.nodes.forEach((node, index) => {
this.source!.connect(node);
if (!(node instanceof AnalyserNode)) {
node.connect(audioContext.destination);
}
});
if (howToConnectFunction){
howToConnectFunction(this.nodes, this.source);
}
else {
this.nodes.forEach((node, index) => {
this.source!.connect(node);
if (!(node instanceof AnalyserNode)) {
node.connect(audioContext.destination);
}
});
}
}
else {
this.source.connect(audioContext.destination);
Expand Down
26 changes: 24 additions & 2 deletions src/Audio/AudioEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,32 @@ export class AudioEngine {
let gain = this.audioContext.createGain();
gain.gain.value = 0;
let analyzer = this.audioContext.createAnalyser();
analyzer.fftSize = 256;
analyzer.fftSize = 1024;
let lowpassFilter = this.audioContext.createBiquadFilter();
lowpassFilter.type = 'lowpass';
lowpassFilter.frequency.value = 75; // Set cutoff frequency to 200 Hz
lowpassFilter.Q.value = 1;
audio.AddAudioNode(analyzer);
audio.AddAudioNode(gain);
audio.ConnectToContext(this.audioContext);
audio.AddAudioNode(lowpassFilter);
audio.ConnectToContext(this.audioContext, (nodes, source) => {
let analyzerNode: AnalyserNode;
nodes.forEach((node) => {
if (node instanceof GainNode) {
source.connect(node);
node.connect(this.audioContext.destination);
}
if (node instanceof AnalyserNode) {
analyzerNode = node;
}
});
nodes.forEach((node) => {
if (node instanceof BiquadFilterNode) {
source.connect(node);
node.connect(analyzerNode);
}
});
});
audio.Play();
if (audio.playingCallback){
audio.playingCallback();
Expand Down
55 changes: 46 additions & 9 deletions src/Elements/AudioVisualizers/LogoVisualizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {MapAudio} from "../../Audio/Audio";
import * as PIXI from "pixi.js";
import {data} from "browserslist";
import {MathUtil} from "../../Util/MathUtil";
import {UniformData} from "pixi.js";

export class LogoVisualizer extends PIXI.Container {

Expand All @@ -12,7 +13,7 @@ export class LogoVisualizer extends PIXI.Container {
private readonly index_change = 5;

// The maximum length of each bar in the visualiser. Will be reduced when kiai is not activated.
private readonly bar_length = 2;
private readonly bar_length = 5;

// The number of bars in one rotation of the visualiser.
private bars_per_visualiser = 200;
Expand All @@ -29,36 +30,74 @@ export class LogoVisualizer extends PIXI.Container {
// The minimum amplitude to show a bar.
private readonly amplitude_dead_zone = 1 / this.bar_length;

public alphaMultiplier = 1;



protected audio!: MapAudio;
protected analyzer!: AnalyserNode;
protected bufferLength!: number;
protected audioData!: Uint8Array
protected amplitudes!: Uint8Array

protected temporalAmplitudes: Uint8Array = new Uint8Array(256);
protected frequencyAmplitudes: Uint8Array = new Uint8Array(256);
public audioData: Uint8Array = new Uint8Array(256);

protected graphics: PIXI.Graphics = new PIXI.Graphics();

private indexOffset = 0;

public start() {
Main.AudioEngine.addMusicChangeEventListener(() => this.initVisualizer());
this.graphics.blendMode = "add";
this.addChild(this.graphics);
this.graphics.eventMode = "none";
this.eventMode = "none";
setInterval(() => {this.updateAmplitudes()}, this.time_between_updates);

}

public initVisualizer() {
private updateAmplitudes() {
let half = this.amplitudes.length/2;
this.amplitudes.slice(100, half+100);
for (let i = 3; i < this.amplitudes.length; i++) {
this.temporalAmplitudes[i] = this.amplitudes[i];
}
for (let i = 0; i < this.bars_per_visualiser; i++) {
let targetAmplitude = (this.temporalAmplitudes[(i + this.indexOffset) % this.bars_per_visualiser]) * 0.5;
if (targetAmplitude > this.frequencyAmplitudes[i]) {
this.frequencyAmplitudes[i] = targetAmplitude;
}
}
this.indexOffset = (this.indexOffset + this.index_change) % this.bars_per_visualiser;
}

private initVisualizer() {
this.audio = Main.AudioEngine.GetCurrentPlayingMusic();
const analyzerNodes = this.audio.GetNode(AnalyserNode);
if (analyzerNodes == null) {
throw new Error("Couldn't find any AnalyzerNode on Audio Object!");
}
this.analyzer = analyzerNodes[0];
this.bufferLength = this.analyzer.frequencyBinCount;
this.bufferLength = 256;
this.bars_per_visualiser = this.bufferLength;
this.audioData = new Uint8Array(this.bufferLength);
this.amplitudes = new Uint8Array(this.bufferLength);

}

public draw(ticker: PIXI.Ticker) {
this.graphics.clear();
this.analyzer.getByteFrequencyData(this.audioData);
this.analyzer.getByteFrequencyData(this.amplitudes);
let decayFactor = ticker.deltaMS * this.decay_per_millisecond;
for (let i = 0; i < this.bars_per_visualiser; i++) {
//3% of extra bar length to make it a little faster when bar is almost at it's minimum
this.frequencyAmplitudes[i] -= decayFactor * (this.frequencyAmplitudes[i] + 0.03);
if (this.frequencyAmplitudes[i] < 0) {
this.frequencyAmplitudes[i] = 0;
}
}
this.audioData = new Uint8Array(this.frequencyAmplitudes);

for (let j = 0; j < this.visualiser_rounds; j++){
for (let i = 0; i < this.bars_per_visualiser; i++){
if (this.audioData[i] < this.amplitude_dead_zone){
Expand All @@ -75,14 +114,12 @@ export class LogoVisualizer extends PIXI.Container {
x: LogoVisualizer.size * Math.sqrt(2 * (1 - Math.cos(MathUtil.DegreesToRadians(360 / this.bars_per_visualiser)))) / 2,
y: this.bar_length * this.audioData[i]
};
// The distance between the position and the sides of the bar.
let bottomOffset = {x: -rotationSin * barSize.x / 2, y: rotationCos * barSize.x / 2};
// The distance between the bottom side of the bar and the top side.
let amplitudeOffset = {x: rotationCos * barSize.y, y: rotationSin * barSize.y};

this.graphics.moveTo(barPosition.x, barPosition.y);
this.graphics.lineTo(barPosition.x + amplitudeOffset.x, barPosition.y + amplitudeOffset.y);
this.graphics.stroke({color: "rgba(255, 255, 255, 0.2)", width: 10});
this.graphics.stroke({color: "rgba(255, 255, 255, "+0.2 * this.alphaMultiplier+")", width: 10});
}
}

Expand Down
30 changes: 30 additions & 0 deletions src/Elements/MainMenu/OsuCircle/OsuCircle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export class OsuCircle extends PIXI.Container {
private readonly parallaxContainer: PIXI.Container = new PIXI.Container();
private readonly menu: Menu = new Menu();
private isBeingHovered = false;
private readonly defaultVisualizerAlpha = 0.5;

public constructor() {
super();
Expand All @@ -30,6 +31,7 @@ export class OsuCircle extends PIXI.Container {
let scale = 0.6;
this.visualizer.position.set(-LogoVisualizer.size/3.35, -LogoVisualizer.size/3.35);
this.visualizer.scale.set(scale);
this.visualizer.alphaMultiplier = this.defaultVisualizerAlpha;
this.beatContainer.addChild(this.visualizer);

let mask = PIXI.Sprite.from("mainMenu.logoMask");
Expand Down Expand Up @@ -137,9 +139,37 @@ export class OsuCircle extends PIXI.Container {
}
});

setInterval(() => {this.onNewBeat()}, 375)
}

private onNewBeat() {
let beatLength = 375;
let maxAmplitude = 0;
this.visualizer.audioData.forEach((num) => {
if (maxAmplitude < num) {
maxAmplitude = num;
}
});
let amplitudeAdjust = Math.min(1, 0.4 + maxAmplitude);
ease.add(this.beatContainer, {scale: 1 - 0.02 * amplitudeAdjust}, {ease: "linear", duration: 60}).once("complete",
() => {
ease.add(this.beatContainer, {scale: 1}, {ease: "easeOutQuint", duration: beatLength*2});
});
ease.add(this.triangles.flash, {alpha: 0.2*amplitudeAdjust}, {duration: 60, ease:"linear"}).once("complete",
() => {
ease.add(this.triangles.flash, {alpha: 0}, {duration: beatLength})
});
let dummy = new PIXI.Container();
let visualizerEase = ease.add(dummy, {alpha: this.defaultVisualizerAlpha * 1.8 * amplitudeAdjust},
{duration: 60, ease: "linear"}).on("each", () => {this.visualizer.alphaMultiplier = dummy.alpha});
visualizerEase.once("complete", () => {
ease.add(dummy, {alpha: this.defaultVisualizerAlpha}, {duration: beatLength, ease: "linear"}).on("each", () => {
this.visualizer.alphaMultiplier = dummy.alpha
});
});
}


public onResize() {
this.menu.onResize();
}
Expand Down
15 changes: 1 addition & 14 deletions src/Elements/MainMenu/OsuCircle/Triangles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ export class Triangles extends PIXI.Container{
private triangles: Triangle[] = [];
private triangleGenInterval: NodeJS.Timeout;
private graphics: PIXI.Graphics = new PIXI.Graphics();
private pulseAnimation: EaseOutSine;
private pulseAnimationFlash: EaseOutSine;
private flash: PIXI.Sprite;
public flash: PIXI.Sprite;

public constructor() {
super();
Expand Down Expand Up @@ -53,25 +51,14 @@ export class Triangles extends PIXI.Container{
this.flash.blendMode = "add";

this.addChild(this.flash);
this.pulseAnimation = new EaseOutSine(0, true, 0);
this.pulseAnimationFlash = new EaseOutSine(0, true, 0);
let playingAudio = Main.AudioEngine.GetCurrentPlayingMusic();
if (playingAudio != null) {
this.pulseAnimation = new EaseOutSine(375, true, playingAudio.timeStarted);
this.pulseAnimationFlash = new EaseOutSine(375, true, playingAudio.timeStarted);
}

}

public destroy(options?: PIXI.DestroyOptions) {
super.destroy(options);
}

public draw(ticker: PIXI.Ticker) {
this.pulseAnimation.update();
this.pulseAnimationFlash.update();
if (!this.destroyed){
this.flash.alpha = this.pulseAnimationFlash.getValue()/7;
if (document.hasFocus()){
this.graphics.clear();
this.graphics.rect(0, 0, 1024, 1024);
Expand Down

0 comments on commit 1102cbe

Please sign in to comment.