Skip to content
Open
Binary file added hitsounds/combobreak.wav
Binary file not shown.
2 changes: 2 additions & 0 deletions hitsounds/convert.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ ffmpeg -i soft-hitclap.wav soft-hitclap.ogg
ffmpeg -i soft-sliderslide.wav soft-sliderslide.ogg
ffmpeg -i soft-sliderwhistle.wav soft-sliderwhistle.ogg
ffmpeg -i soft-slidertick.wav soft-slidertick.ogg

ffmpeg -i combobreak.ogg combobreak.mp3
250 changes: 174 additions & 76 deletions scripts/downloader.js
Original file line number Diff line number Diff line change
@@ -1,84 +1,182 @@
// beatmap downloader

function startpreview(box) {
let volume = 1;
if (window.gamesettings) {
volume = (window.gamesettings.mastervolume/100) * (window.gamesettings.musicvolume/100);
volume = Math.min(1, Math.max(0, volume));
}
let audios = document.getElementsByTagName("audio");
for (let i=0; i<audios.length; ++i)
audios[i].softstop();
let a = document.createElement("audio");
let s = document.createElement("source");
s.src = "https://cdn.sayobot.cn:25225/preview/" + box.sid + ".mp3";
s.type = "audio/mpeg";
a.appendChild(s);
a.volume = 0;
a.play();
document.body.appendChild(a);
let fadeIn = setInterval(function(){
if (a.volume < volume)
a.volume = Math.min(volume, a.volume + 0.05*volume);
else
clearInterval(fadeIn);
}, 30);
let fadeOut = setInterval(function(){
if (a.currentTime > 9.3) // assume it's 10s long
a.volume = Math.max(0, a.volume - 0.05*volume);
if (a.volume == 0)
clearInterval(fadeOut);
}, 30);
a.softstop = function() {
let fadeOut = setInterval(function(){
a.volume = Math.max(0, a.volume - 0.05*volume);
if (a.volume == 0) {
clearInterval(fadeOut);
a.remove();
(() => {

/**
* Preview Audio
*/
class PreviewAudio {
/**
* Build a PreviewAudio object
* @param {string | number} sid Beatmap's sid
* @param {number} volume Volume of preview audio
*/
constructor(sid, volume = 1) {
const audioContext = new Audio("https://cdn.sayobot.cn:25225/preview/" + sid + ".mp3");
this._sid = sid;
this._volume = volume;
this._audioContext = audioContext;
this._playing = false;
this._ready = false;
this._fadeTimer = 0;
this._playTimer = 0;
audioContext.load();
audioContext.volume = 0;
audioContext.addEventListener('canplay', () => {
this._ready = true
if(this._playing === true){
this.play();
}
}, {once: true})
}
play() {
this._playing = true;
if(this._ready){
this._playing = true
this._audioContext.volume = 0;
this._audioContext.currentTime = 0;
this._audioContext.play();
clearInterval(this._fadeTimer);
clearTimeout(this._playTimer);
this._fadeTimer = setInterval(() => {
if (this._audioContext.volume < this._volume)
this._audioContext.volume = Math.min(this._volume, this._audioContext.volume + 0.05 * this._volume);
else
clearInterval(this._fadeTimer);
clearTimeout(this._playTimer);
}, 30);
this._playTimer = setTimeout(() => {
this._audioContext.volume = this._volume;
clearInterval(this._fadeTimer);
clearTimeout(this._playTimer);
}, 600);
}
}, 10);
}
stop() {
this._playing = false
clearInterval(this._fadeTimer);
clearTimeout(this._playTimer);
this._fadeTimer = setInterval(() => {
this._audioContext.volume = Math.max(0, this._audioContext.volume - 0.05 * this._volume);
if (this._audioContext.volume === 0) {
this._audioContext.pause();
clearInterval(this._fadeTimer);
clearTimeout(this._playTimer);
}
}, 10);
this._playTimer = setTimeout(() => {
this._audioContext.pause();
clearInterval(this._fadeTimer);
clearTimeout(this._playTimer);
}, 200);
}
set volume(value) {
this._volume = value;
}
get volume() {
return this._volume;
}
}
}

function startdownload(box) {
startpreview(box);
if (box.downloading) {
return;
}
let url = "https://txy1.sayobot.cn/beatmaps/download/mini/" + box.sid;
box.downloading = true;
box.classList.add("downloading");
let xhr = new XMLHttpRequest();
xhr.responseType = 'arraybuffer';
xhr.open("GET", url);
// create download progress bar
let container = document.createElement("div");
let title = document.createElement("div");
let bar = document.createElement("progress");
container.className = "download-progress";
title.className = "title";
title.innerText = box.setdata.title;
container.appendChild(title);
container.appendChild(bar);
// insert so that download list from recent to old
let statuslines = document.getElementById("statuslines");
statuslines.insertBefore(container, statuslines.children[3]);
bar.max = 1;
bar.value = 0;
// async part
xhr.onload = function() {
box.oszblob = new Blob([xhr.response]);
bar.className = "finished";
box.classList.remove("downloading");
class PreviewAudioManager {
/**
* Create a preview audio manager
* @param {object} [settings] Preview audio manager settings
* @param {number} [settings.volume] Audio's volume
*/
constructor(settings = {}) {
const {volume} = settings
/**
* @type {PreviewAudio}
*/
this._active = null;
this._volume = volume;
}
/**
* Play preview audio
* @param {string | number} sid Beatmap's sid
*/
play(sid) {
if(this._active){
this._active.stop();
}
this._active = new PreviewAudio(sid, this._volume);
this._active.play()
}
stop() {
if(this._active){
this._active.stop();
}
}
set volume(value) {
if(value > 1){
value = 1;
}
this._volume = value;
if(this._active) {
this._active.volume = value;
}
}
get volume() {
return this._volume;
}
}
xhr.onprogress = function(e) {
bar.value = e.loaded / e.total;

const previewAudioMgr = new PreviewAudioManager()

function startpreview(box) {
let volume = 1;
if (window.gamesettings) {
volume = (window.gamesettings.mastervolume/100) * (window.gamesettings.musicvolume/100);
volume = Math.min(1, Math.max(0, volume));
}
previewAudioMgr.volume = volume
previewAudioMgr.play(box.sid)
}
xhr.onerror = function() {
console.error("download failed");
alert("Beatmap download failed. Please retry later.")
box.downloading = false;
box.classList.remove("downloading");

function startdownload(box) {
startpreview(box);
if (box.downloading) {
return;
}
let url = "https://txy1.sayobot.cn/beatmaps/download/mini/" + box.sid;
box.downloading = true;
box.classList.add("downloading");
let xhr = new XMLHttpRequest();
xhr.responseType = 'arraybuffer';
xhr.open("GET", url);
// create download progress bar
let container = document.createElement("div");
let title = document.createElement("div");
let bar = document.createElement("progress");
container.className = "download-progress";
title.className = "title";
title.innerText = box.setdata.title;
container.appendChild(title);
container.appendChild(bar);
// insert so that download list from recent to old
let statuslines = document.getElementById("statuslines");
statuslines.insertBefore(container, statuslines.children[3]);
bar.max = 1;
bar.value = 0;
// async part
xhr.onload = function() {
box.oszblob = new Blob([xhr.response]);
bar.className = "finished";
box.classList.remove("downloading");
}
xhr.onprogress = function(e) {
bar.value = e.loaded / e.total;
}
xhr.onerror = function() {
console.error("download failed");
alert("Beatmap download failed. Please retry later.")
box.downloading = false;
box.classList.remove("downloading");
}
xhr.send();
}
xhr.send();
}

window.startdownload = startdownload
window.previewAudioMgr = previewAudioMgr
})()
41 changes: 25 additions & 16 deletions scripts/initgame.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,23 +108,32 @@ function(Osu, _, sound, Playback) {
'hitsounds/drum-slidertick.ogg',
'hitsounds/combobreak.ogg',
];
var issafariBrowser = /Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent);
if(issafariBrowser){
sample = sample.map(path => {
const pathSplited = path.split('.');
pathSplited.pop();
pathSplited.push('wav');
return pathSplited.join('.');
})
}
sounds.whenLoaded = function(){
game.sample[1].hitnormal = sounds['hitsounds/normal-hitnormal.ogg'];
game.sample[1].hitwhistle = sounds['hitsounds/normal-hitwhistle.ogg'];
game.sample[1].hitfinish = sounds['hitsounds/normal-hitfinish.ogg'];
game.sample[1].hitclap = sounds['hitsounds/normal-hitclap.ogg'];
game.sample[1].slidertick = sounds['hitsounds/normal-slidertick.ogg'];
game.sample[2].hitnormal = sounds['hitsounds/soft-hitnormal.ogg'];
game.sample[2].hitwhistle = sounds['hitsounds/soft-hitwhistle.ogg'];
game.sample[2].hitfinish = sounds['hitsounds/soft-hitfinish.ogg'];
game.sample[2].hitclap = sounds['hitsounds/soft-hitclap.ogg'];
game.sample[2].slidertick = sounds['hitsounds/soft-slidertick.ogg'];
game.sample[3].hitnormal = sounds['hitsounds/drum-hitnormal.ogg'];
game.sample[3].hitwhistle = sounds['hitsounds/drum-hitwhistle.ogg'];
game.sample[3].hitfinish = sounds['hitsounds/drum-hitfinish.ogg'];
game.sample[3].hitclap = sounds['hitsounds/drum-hitclap.ogg'];
game.sample[3].slidertick = sounds['hitsounds/drum-slidertick.ogg'];
game.sampleComboBreak = sounds['hitsounds/combobreak.ogg'];
game.sample[1].hitnormal = sounds[sample[0]];
game.sample[1].hitwhistle = sounds[sample[1]];
game.sample[1].hitfinish = sounds[sample[2]];
game.sample[1].hitclap = sounds[sample[3]];
game.sample[1].slidertick = sounds[sample[4]];
game.sample[2].hitnormal = sounds[sample[5]];
game.sample[2].hitwhistle = sounds[sample[6]];
game.sample[2].hitfinish = sounds[sample[7]];
game.sample[2].hitclap = sounds[sample[8]];
game.sample[2].slidertick = sounds[sample[9]];
game.sample[3].hitnormal = sounds[sample[10]];
game.sample[3].hitwhistle = sounds[sample[11]];
game.sample[3].hitfinish = sounds[sample[12]];
game.sample[3].hitclap = sounds[sample[13]];
game.sample[3].slidertick = sounds[sample[14]];
game.sampleComboBreak = sounds[sample[15]];
window.soundReady = true;
document.getElementById("sound-progress").classList.add("finished");
document.body.classList.add("sound-ready");
Expand Down
4 changes: 1 addition & 3 deletions scripts/launchgame.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,7 @@ function launchOSU(osu, beatmapid, version){
game.scene = playback;
playback.onload = function() {
// stop beatmap preview
let audios = document.getElementsByTagName("audio");
for (let i=0; i<audios.length; ++i)
audios[i].softstop();
previewAudioMgr.stop()
}
playback.load(); // load audio

Expand Down
18 changes: 14 additions & 4 deletions scripts/osu-audio.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,23 @@ define([], function() {
return {startoffset:offset_predict_mp3(tags)};
}

const audioContext = new AudioContext();
if (audioContext.state === "suspended") {
document.body.addEventListener("touchstart", event => {
audioContext.resume();
}, {
once: true
});
}

function OsuAudio(filename, buffer, callback) {
var self = this;
this.decoded = null;
this.source = null;
this.started = 0;
this.position = 0;
this.playing = false;
this.audio = new AudioContext();
this.audio = audioContext;
this.gain = this.audio.createGain();
this.gain.connect(this.audio.destination);
this.playbackRate = 1.0;
Expand Down Expand Up @@ -125,9 +134,11 @@ define([], function() {
};

this.play = function play(wait = 0) {
if (self.audio.state == "suspended") {
window.alert("Audio can't play. Please use Chrome or Firefox.")
if (self.audio.state === "suspended") {
console.warn("Audio suspended. Waiting for touchstart.");
self.audio.resume();
}
self.playing = true;
self.source = self.audio.createBufferSource();
self.source.playbackRate.value = self.playbackRate;
self.source.buffer = self.decoded;
Expand All @@ -140,7 +151,6 @@ define([], function() {
else {
self.source.start(0, self.position);
}
self.playing = true;
};

// return value true: success
Expand Down
Loading