Skip to content
This repository has been archived by the owner on Sep 21, 2024. It is now read-only.

Commit

Permalink
Merge pull request #8 from maotovisk/dev
Browse files Browse the repository at this point in the history
Release 0.0.4
  • Loading branch information
maotovisk authored Jun 27, 2023
2 parents 0d4eb81 + 7d2a3ad commit ef5e1b1
Show file tree
Hide file tree
Showing 11 changed files with 91 additions and 57 deletions.
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
<p align="center"><img src="app-icon.png" alt="drawing" width="200"/></p>
<p align="center"><img src="app-icon.png" alt="logo" width="200"/></p>

# Hitsound Copier

<img align="right" src="https://github.com/maotovisk/hitsound-copier/assets/20617307/9f6e99dc-9d95-4413-b204-171ccf5bc5fd" alt="preview" width="400"/>
Cross platfrom hitsound copier for osu! standard beatmaps (for now) written in TypeScript, using osu!lazer's hitsound logic as base. It was done so we could have a hitsound copier solution that was friendly to run on Linux without the need of third party tools.

## Tools
<br/>

### Built with

- Tauri
- TypeScript
- [osu-parsers](https://github.com/kionell/osu-parsers)

<br/>

## Running

If you wish to run the project on your local machine, follow the instructions below:
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "hitsound-copier",
"private": true,
"version": "0.0.3",
"version": "0.0.4",
"type": "module",
"scripts": {
"dev": "vite",
Expand Down
2 changes: 1 addition & 1 deletion src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "hitsound-copier"
version = "0.0.3"
version = "0.0.4"
description = "A Tauri App"
authors = ["you"]
license = ""
Expand Down
2 changes: 1 addition & 1 deletion src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
},
"package": {
"productName": "hitsound-copier",
"version": "0.0.3"
"version": "0.0.4"
},
"tauri": {
"allowlist": {
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,47 +1,48 @@
import type { StandardBeatmap } from "osu-standard-stable";
import type { Options } from "src/copier/types";

import { ControlPointType } from "osu-classes";
import { ControlPointType, DifficultyPoint } from "osu-classes";
import { isMuted } from "./is-muted";

type CopyVolumesParams = {
type CopySamplePointsParams = {
originBeatmap: StandardBeatmap;
destinationBeatmap: StandardBeatmap;
options: Options;
};

export const copyVolumes = ({
export const copySamplePoints = ({
originBeatmap,
destinationBeatmap,
options,
}: CopyVolumesParams) => {
const fromBeatmapSamplePoints = originBeatmap.controlPoints.samplePoints;
let toBeatmapSamplePoints = destinationBeatmap.controlPoints.samplePoints;
}: CopySamplePointsParams) => {
const originBeatmapSamplePoints = originBeatmap.controlPoints.samplePoints;
let destinationBeatmapSamplePoints =
destinationBeatmap.controlPoints.samplePoints;

fromBeatmapSamplePoints.forEach((samplePoint) => {
originBeatmapSamplePoints.forEach((samplePoint) => {
if (!options.copySamplesetChanges) return;

if (options.removeMuting && isMuted(samplePoint.volume)) return;

const fromBeatmapSamplePoint =
const destinationBeatmapSamplePoint =
destinationBeatmap.controlPoints.samplePointAt(samplePoint.startTime);

if (!options.copyVolumes)
samplePoint.volume = fromBeatmapSamplePoint.volume;
samplePoint.volume = destinationBeatmapSamplePoint.volume;

destinationBeatmap.controlPoints
.groupAt(samplePoint.startTime)
.remove(fromBeatmapSamplePoint);
.remove(destinationBeatmapSamplePoint);

destinationBeatmap.controlPoints
.groupAt(samplePoint.startTime)
.add(samplePoint);
});

toBeatmapSamplePoints = [...fromBeatmapSamplePoints];
destinationBeatmapSamplePoints = [...originBeatmapSamplePoints];

if (options.removeMuting) {
toBeatmapSamplePoints.forEach((samplePoint) => {
destinationBeatmapSamplePoints.forEach((samplePoint) => {
if (isMuted(samplePoint.volume)) {
destinationBeatmap.controlPoints
.groupAt(samplePoint.startTime)
Expand All @@ -50,6 +51,9 @@ export const copyVolumes = ({
});
}

// This is a hack to prevent that the destination is encoded with a 0 offset
// sample point that happens before the first timing point.

const firstDestinationControlPointGroup =
destinationBeatmap.controlPoints.groups[0];
const secondDestionationControlPointGroup =
Expand Down Expand Up @@ -79,5 +83,20 @@ export const copyVolumes = ({
.add(firstDestinationControlPointGroup.controlPoints[0]);

destinationBeatmap.controlPoints.groups.shift();

const difficultyPointInSecondDestinationGroup =
secondDestionationControlPointGroup.controlPoints.find(
(controlPoint) =>
controlPoint.pointType === ControlPointType.DifficultyPoint
);

if (!difficultyPointInSecondDestinationGroup) {
const newDifficultyPoint = new DifficultyPoint();
newDifficultyPoint.sliderVelocity = 1;

destinationBeatmap.controlPoints
.groupAt(secondDestionationControlPointGroup.startTime)
.add(newDifficultyPoint);
}
}
};
4 changes: 2 additions & 2 deletions src/copier/copy-hitsounds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
copySliderHitsounds,
copySpinnerHitsounds,
} from "./hitsounds/service";
import { copyVolumes } from "./volumes/services/copy";
import { copySamplePoints } from "./control-points/services/copy";

export const copyHitsounds = (
originBeatmap: StandardBeatmap,
Expand All @@ -17,7 +17,7 @@ export const copyHitsounds = (
const hitsoundedBeatmap = destinationBeatmap;

if (options.copySamplesetChanges || options.copyVolumes) {
copyVolumes({
copySamplePoints({
originBeatmap,
destinationBeatmap,
options,
Expand Down
5 changes: 3 additions & 2 deletions src/copier/hitsounds/service/copy-slider-hitsounds.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { HitSample, HitSound } from "osu-classes";
import type { HitsoundableTimeLineObject, Options } from "src/copier/types";

import {
SliderTail,
type Slider,
StandardBeatmap,
SliderTick,
} from "osu-standard-stable";
import type { HitsoundableTimeLineObject, Options } from "src/copier/types";
import { HitSample, HitSound } from "osu-classes";
import { findNearestHitObject } from "../../utils";

export type CopySliderHitsoundsParams = {
Expand Down
79 changes: 44 additions & 35 deletions src/copier/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { HitSound, HitSample, SampleSet } from "osu-classes";
import type {
FindNearestHitObjectParams,
HitsoundableTimeLineObject,
} from "./types";

import {
Circle,
Slider,
Expand All @@ -7,10 +11,7 @@ import {
Spinner,
type StandardBeatmap,
} from "osu-standard-stable";
import type {
FindNearestHitObjectParams,
HitsoundableTimeLineObject,
} from "./types";
import { HitSound, HitSample, SampleSet } from "osu-classes";

export const calculateSampleBitwise = (samples: HitSample[]) => {
let bitwise = 0;
Expand All @@ -21,11 +22,28 @@ export const calculateSampleBitwise = (samples: HitSample[]) => {
return bitwise;
};

const resetUndefinedHitsoundSamples = (samples: HitSample[]) => {
// This is a temporary workaround for a bug with the parser library that we are using,
// which causes undefined hitsounds to be considered Normal hitsounds
// when the hit object is a slider.

if (
samples.length == 1 &&
samples[0].volume === 100 &&
samples[0].sampleSet === SampleSet[SampleSet.Normal]
) {
const newSample = new HitSample();

newSample.sampleSet = SampleSet[SampleSet.None];

samples = [newSample];
}
};

export const convertBeatmapToHitsoundableTimeLine = (
beatmap: StandardBeatmap
): HitsoundableTimeLineObject[] => {
let hitsoundableTimeLineObject = [];
console.log(beatmap.hitObjects);
const hitsoundableTimeLineObject: Array<HitsoundableTimeLineObject> = [];

beatmap.hitObjects.forEach((hitObject) => {
if (hitObject instanceof Circle) {
Expand All @@ -35,20 +53,12 @@ export const convertBeatmapToHitsoundableTimeLine = (
HitSound: hitObject.hitSound,
clickable: true,
});
} else if (hitObject instanceof Slider) {
// This is a temporary workaround for a bug with the parser library that we are using,
// which causes undefined hitsounds to be considered Normal hitsounds
// when the hit object is a slider.
if (
hitObject.samples.length == 1 &&
hitObject.samples[0].volume === 100 &&
hitObject.samples[0].sampleSet === SampleSet[SampleSet.Normal]
) {
const newSample = new HitSample();
newSample.sampleSet = SampleSet[SampleSet.None];

hitObject.samples = [newSample];
}

return;
}

if (hitObject instanceof Slider) {
resetUndefinedHitsoundSamples(hitObject.samples);

hitsoundableTimeLineObject.push({
startTime: hitObject.startTime,
Expand All @@ -62,35 +72,34 @@ export const convertBeatmapToHitsoundableTimeLine = (
);

hitObject.nodeSamples.forEach((samples, key) => {
if (
samples.length == 1 &&
samples[0].volume === 100 &&
samples[0].sampleSet === SampleSet[SampleSet.Normal]
) {
const newSample = new HitSample();
newSample.sampleSet = SampleSet[SampleSet.None];
resetUndefinedHitsoundSamples(samples);

samples = [newSample];
}
const keyStartTime = Math.round(nestedHitObjects[key].startTime);
const newHitSoundBitwise = calculateSampleBitwise(samples);

hitsoundableTimeLineObject.push({
startTime:
nestedHitObjects[key] instanceof SliderTail
? Math.round(nestedHitObjects[key].startTime) +
hitObject.legacyLastTickOffset
: Math.round(nestedHitObjects[key].startTime),
? keyStartTime + hitObject.legacyLastTickOffset
: keyStartTime,
HitSample: samples,
HitSound: calculateSampleBitwise(samples),
HitSound: newHitSoundBitwise,
clickable: true,
});
});
} else if (hitObject instanceof Spinner) {

return;
}

if (hitObject instanceof Spinner) {
hitsoundableTimeLineObject.push({
startTime: hitObject.endTime,
HitSample: hitObject.samples,
HitSound: hitObject.hitSound,
clickable: true,
});

return;
}
});

Expand Down

0 comments on commit ef5e1b1

Please sign in to comment.