mirror of
https://github.com/jiojciojsioe3/a3cjroijsiojiorj.git
synced 2024-11-15 07:21:50 +08:00
SoundBuffer: Set song volume
- Requires a new column in the database after preview: `volume` REAL - The value is a volume multiplier, if the value is set to null or 1 there will be no change - The volume can be set in debugger - Imported TJA files are now read from disk every time the song is played, freeing some memory and making it easier to create charts - Correctly parse TJA files with alphabet notes, added "A" and "B" notes, which appear as DON (Big) and KA (Big) respectively
This commit is contained in:
parent
eb4ddb0b1f
commit
61a5d6d496
3
app.py
3
app.py
@ -142,7 +142,8 @@ def route_api_songs():
|
||||
'category': category_out,
|
||||
'type': song_type,
|
||||
'offset': song[13],
|
||||
'song_skin': song_skin_out
|
||||
'song_skin': song_skin_out,
|
||||
'volume': song[16]
|
||||
})
|
||||
|
||||
return jsonify(songs_out)
|
||||
|
@ -143,7 +143,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
var issueBody = strings.issueTemplate + "\n\n\n\n" + diag
|
||||
var issueBody = strings.about.issueTemplate + "\n\n\n\n" + diag
|
||||
this.getLink(this.linkEmail).href += "?body=" + encodeURIComponent(issueBody.replace(/\n/g, "<br>\r\n"))
|
||||
|
||||
return diag
|
||||
|
@ -21,6 +21,7 @@ class Controller{
|
||||
assets.songs.forEach(song => {
|
||||
if(song.id == this.selectedSong.folder){
|
||||
this.mainAsset = song.sound
|
||||
this.volume = song.volume || 1
|
||||
}
|
||||
})
|
||||
|
||||
@ -35,6 +36,9 @@ class Controller{
|
||||
if(syncWith){
|
||||
this.syncWith = syncWith
|
||||
}
|
||||
if(this.multiplayer !== 2){
|
||||
snd.musicGain.setVolumeMul(this.volume)
|
||||
}
|
||||
this.game.run()
|
||||
this.view.run()
|
||||
if(this.multiplayer === 1){
|
||||
@ -161,8 +165,26 @@ class Controller{
|
||||
if(this.multiplayer){
|
||||
new LoadSong(this.selectedSong, false, true, this.touchEnabled)
|
||||
}else{
|
||||
var taikoGame = new Controller(this.selectedSong, this.songData, this.autoPlayEnabled, false, this.touchEnabled)
|
||||
taikoGame.run()
|
||||
new Promise(resolve => {
|
||||
var songObj = assets.songs.find(song => song.id === this.selectedSong.folder)
|
||||
if(songObj.chart){
|
||||
var reader = new FileReader()
|
||||
var promise = pageEvents.load(reader).then(event => {
|
||||
this.songData = event.target.result.replace(/\0/g, "").split("\n")
|
||||
resolve()
|
||||
})
|
||||
if(this.selectedSong.type === "tja"){
|
||||
reader.readAsText(songObj.chart, "sjis")
|
||||
}else{
|
||||
reader.readAsText(songObj.chart)
|
||||
}
|
||||
}else{
|
||||
resolve()
|
||||
}
|
||||
}).then(() => {
|
||||
var taikoGame = new Controller(this.selectedSong, this.songData, this.autoPlayEnabled, false, this.touchEnabled)
|
||||
taikoGame.run()
|
||||
})
|
||||
}
|
||||
}
|
||||
playSound(id, time){
|
||||
@ -232,6 +254,7 @@ class Controller{
|
||||
this.stopMainLoop()
|
||||
this.keyboard.clean()
|
||||
this.view.clean()
|
||||
snd.buffer.loadSettings()
|
||||
|
||||
if(!this.multiplayer){
|
||||
debugObj.controller = null
|
||||
|
@ -16,6 +16,7 @@ class Debug{
|
||||
this.branchSelectDiv = this.byClass("branch-select")
|
||||
this.branchSelect = this.branchSelectDiv.getElementsByTagName("select")[0]
|
||||
this.branchResetBtn = this.branchSelectDiv.getElementsByClassName("reset")[0]
|
||||
this.volumeDiv = this.byClass("music-volume")
|
||||
this.restartCheckbox = this.byClass("change-restart")
|
||||
this.autoplayLabel = this.byClass("autoplay-label")
|
||||
this.autoplayCheckbox = this.byClass("autoplay")
|
||||
@ -40,6 +41,10 @@ class Debug{
|
||||
this.measureNumSlider.onchange(this.measureNumChange.bind(this))
|
||||
this.measureNumSlider.set(0)
|
||||
|
||||
this.volumeSlider = new InputSlider(this.volumeDiv, 0, 3, 2)
|
||||
this.volumeSlider.onchange(this.volumeChange.bind(this))
|
||||
this.volumeSlider.set(1)
|
||||
|
||||
this.moveTo(100, 100)
|
||||
this.restore()
|
||||
this.updateStatus()
|
||||
@ -110,10 +115,12 @@ class Debug{
|
||||
if(this.songFolder === selectedSong.folder){
|
||||
this.offsetChange(this.offsetSlider.get(), true)
|
||||
this.branchChange(null, true)
|
||||
this.volumeChange(this.volumeSlider.get(), true)
|
||||
}else{
|
||||
this.songFolder = selectedSong.folder
|
||||
this.offsetSlider.set(this.defaultOffset)
|
||||
this.branchReset(null, true)
|
||||
this.volumeSlider.set(this.controller.volume)
|
||||
}
|
||||
|
||||
var measures = this.controller.parsedSongData.measures.filter((measure, i, array) => {
|
||||
@ -176,6 +183,14 @@ class Debug{
|
||||
this.restartSong()
|
||||
}
|
||||
}
|
||||
volumeChange(value, noRestart){
|
||||
if(this.controller){
|
||||
snd.musicGain.setVolumeMul(value)
|
||||
}
|
||||
if(this.restartCheckbox.checked && !noRestart){
|
||||
this.restartSong()
|
||||
}
|
||||
}
|
||||
restartSong(){
|
||||
if(this.controller){
|
||||
this.controller.restartSong()
|
||||
@ -234,6 +249,7 @@ class Debug{
|
||||
delete this.branchSelectDiv
|
||||
delete this.branchSelect
|
||||
delete this.branchResetBtn
|
||||
delete this.volumeDiv
|
||||
delete this.restartCheckbox
|
||||
delete this.autoplayLabel
|
||||
delete this.autoplayCheckbox
|
||||
|
@ -30,6 +30,7 @@ class Game{
|
||||
this.currentTimingPoint = 0
|
||||
this.branchNames = ["normal", "advanced", "master"]
|
||||
this.resetSection()
|
||||
this.gameLagSync = !this.controller.touchEnabled && !(/Firefox/.test(navigator.userAgent))
|
||||
|
||||
assets.songs.forEach(song => {
|
||||
if(song.id == selectedSong.folder){
|
||||
@ -364,7 +365,7 @@ class Game{
|
||||
var value = {
|
||||
score: score,
|
||||
ms: circle.ms - currentTime,
|
||||
dai: typeDai ? keyDai ? 2 : 1 : 0
|
||||
dai: typeDai ? (keyDai ? 2 : 1) : 0
|
||||
}
|
||||
if((!keysDon || !typeDon) && (!keysKa || !typeKa)){
|
||||
value.reverse = true
|
||||
@ -536,7 +537,7 @@ class Game{
|
||||
this.sndTime = this.startDate - snd.buffer.getTime() * 1000
|
||||
}else if(ms < 0 || ms >= 0 && this.started){
|
||||
var currentDate = Date.now()
|
||||
if(!this.controller.touchEnabled){
|
||||
if(this.gameLagSync){
|
||||
var sndTime = currentDate - snd.buffer.getTime() * 1000
|
||||
var lag = sndTime - this.sndTime
|
||||
if(Math.abs(lag) >= 50){
|
||||
|
@ -183,7 +183,7 @@
|
||||
var songObj = {
|
||||
id: index + 1,
|
||||
type: "tja",
|
||||
chart: data,
|
||||
chart: file,
|
||||
stars: [],
|
||||
music: "muted"
|
||||
}
|
||||
@ -258,7 +258,7 @@
|
||||
var songObj = {
|
||||
id: index + 1,
|
||||
type: "osu",
|
||||
chart: data,
|
||||
chart: file,
|
||||
subtitle: osu.metadata.ArtistUnicode || osu.metadata.Artist,
|
||||
subtitle_lang: osu.metadata.Artist || osu.metadata.ArtistUnicode,
|
||||
preview: osu.generalInfo.PreviewTime / 1000,
|
||||
|
@ -196,18 +196,17 @@ class Keyboard{
|
||||
this.checkKey(keyCode, "sound", () => {
|
||||
var circles = this.controller.getCircles()
|
||||
var circle = circles[this.controller.getCurrentCircle()]
|
||||
if(
|
||||
sound === "don"
|
||||
&& circle
|
||||
&& !circle.isPlayed
|
||||
&& circle.type === "balloon"
|
||||
&& circle.requiredHits - circle.timesHit <= 1
|
||||
){
|
||||
this.controller.playSound("se_balloon")
|
||||
}else{
|
||||
this.controller.playSound("neiro_1_" + sound)
|
||||
var currentTime = this.keyTime[keyCode]
|
||||
this.keyTime[sound] = currentTime
|
||||
if(circle && !circle.isPlayed){
|
||||
if(circle.type === "balloon"){
|
||||
if(sound === "don" && circle.requiredHits - circle.timesHit <= 1){
|
||||
this.controller.playSound("se_balloon")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
this.keyTime[sound] = this.keyTime[keyCode]
|
||||
this.controller.playSound("neiro_1_" + sound)
|
||||
})
|
||||
}
|
||||
getKeys(){
|
||||
@ -242,6 +241,9 @@ class Keyboard{
|
||||
}
|
||||
}
|
||||
waitForKeyup(keyCode, type){
|
||||
if(!this.keys[keyCode]){
|
||||
return
|
||||
}
|
||||
if(type === "score"){
|
||||
this.waitKeyupScore[keyCode] = true
|
||||
}else if(type === "sound"){
|
||||
|
@ -118,6 +118,7 @@ class Loader{
|
||||
0.5
|
||||
)
|
||||
snd.sfxLoudGain.setVolume(1.2)
|
||||
snd.buffer.saveSettings()
|
||||
|
||||
this.afterJSCount = 0
|
||||
|
||||
|
@ -112,7 +112,15 @@ class LoadSong{
|
||||
}
|
||||
}))
|
||||
if(songObj.chart){
|
||||
this.songData = songObj.chart
|
||||
var reader = new FileReader()
|
||||
promises.push(pageEvents.load(reader).then(event => {
|
||||
this.songData = event.target.result.replace(/\0/g, "").split("\n")
|
||||
}))
|
||||
if(song.type === "tja"){
|
||||
reader.readAsText(songObj.chart, "sjis")
|
||||
}else{
|
||||
reader.readAsText(songObj.chart)
|
||||
}
|
||||
}else{
|
||||
promises.push(loader.ajax(this.getSongPath(song)).then(data => {
|
||||
this.songData = data.replace(/\0/g, "").split("\n")
|
||||
|
@ -69,25 +69,25 @@ class Mekadon{
|
||||
type = "don"
|
||||
}
|
||||
}
|
||||
if(type == "daiDon" && playDai){
|
||||
if(type === "daiDon" && playDai){
|
||||
this.setKey(kbd["don_l"], ms)
|
||||
this.setKey(kbd["don_r"], ms)
|
||||
this.lr = false
|
||||
keyDai = true
|
||||
}else if(type == "don" || type == "daiDon" || drumrollNotes && score !== 2){
|
||||
}else if(type === "don" || type === "daiDon" || drumrollNotes && score !== 2){
|
||||
this.setKey(this.lr ? kbd["don_l"] : kbd["don_r"], ms)
|
||||
this.lr = !this.lr
|
||||
}else if(type == "daiKa" && playDai){
|
||||
}else if(type === "daiKa" && playDai){
|
||||
this.setKey(kbd["ka_l"], ms)
|
||||
this.setKey(kbd["ka_r"], ms)
|
||||
this.lr = false
|
||||
keyDai = true
|
||||
}else if(type == "ka" || type == "daiKa" || drumrollNotes){
|
||||
}else if(type === "ka" || type === "daiKa" || drumrollNotes){
|
||||
this.setKey(this.lr ? kbd["ka_l"] : kbd["ka_r"], ms)
|
||||
this.lr = !this.lr
|
||||
}
|
||||
if(type === "balloon"){
|
||||
if(circle.requiredHits == 1){
|
||||
if(circle.requiredHits === 1){
|
||||
assets.sounds["se_balloon"].play()
|
||||
}
|
||||
this.game.checkBalloon(circle)
|
||||
|
@ -10,18 +10,20 @@
|
||||
this.difficulty = difficulty
|
||||
this.offset = (offset || 0) * -1000
|
||||
this.soundOffset = 0
|
||||
this.noteTypes = [
|
||||
{name: false, txt: false},
|
||||
{name: "don", txt: strings.note.don},
|
||||
{name: "ka", txt: strings.note.ka},
|
||||
{name: "daiDon", txt: strings.note.daiDon},
|
||||
{name: "daiKa", txt: strings.note.daiKa},
|
||||
{name: "drumroll", txt: strings.note.drumroll},
|
||||
{name: "daiDrumroll", txt: strings.note.daiDrumroll},
|
||||
{name: "balloon", txt: strings.note.balloon},
|
||||
{name: false, txt: false},
|
||||
{name: "balloon", txt: strings.note.balloon}
|
||||
]
|
||||
this.noteTypes = {
|
||||
"0": {name: false, txt: false},
|
||||
"1": {name: "don", txt: strings.note.don},
|
||||
"2": {name: "ka", txt: strings.note.ka},
|
||||
"3": {name: "daiDon", txt: strings.note.daiDon},
|
||||
"4": {name: "daiKa", txt: strings.note.daiKa},
|
||||
"5": {name: "drumroll", txt: strings.note.drumroll},
|
||||
"6": {name: "daiDrumroll", txt: strings.note.daiDrumroll},
|
||||
"7": {name: "balloon", txt: strings.note.balloon},
|
||||
"8": {name: false, txt: false},
|
||||
"9": {name: "balloon", txt: strings.note.balloon},
|
||||
"A": {name: "daiDon", txt: strings.note.daiDon},
|
||||
"B": {name: "daiKa", txt: strings.note.daiKa}
|
||||
}
|
||||
this.courseTypes = {
|
||||
"0": "easy",
|
||||
"1": "normal",
|
||||
@ -141,6 +143,7 @@
|
||||
var firstNote = true
|
||||
var circles = []
|
||||
var circleID = 0
|
||||
var regexAZ = /[A-Z]/
|
||||
|
||||
var pushMeasure = () => {
|
||||
var note = currentMeasure[0]
|
||||
@ -321,7 +324,7 @@
|
||||
|
||||
}else{
|
||||
|
||||
var string = line.split("")
|
||||
var string = line.toUpperCase().split("")
|
||||
|
||||
for(let symbol of string){
|
||||
|
||||
@ -334,7 +337,7 @@
|
||||
scroll: scroll
|
||||
})
|
||||
break
|
||||
case "1": case "2": case "3": case "4":
|
||||
case "1": case "2": case "3": case "4": case "A": case "B":
|
||||
var type = this.noteTypes[symbol]
|
||||
var circleObj = {
|
||||
type: type.name,
|
||||
@ -413,7 +416,14 @@
|
||||
currentMeasure = []
|
||||
break
|
||||
default:
|
||||
error = true
|
||||
if(regexAZ.test(symbol)){
|
||||
currentMeasure.push({
|
||||
bpm: bpm,
|
||||
scroll: scroll
|
||||
})
|
||||
}else{
|
||||
error = true
|
||||
}
|
||||
break
|
||||
|
||||
}
|
||||
|
@ -856,7 +856,7 @@ class Scoresheet{
|
||||
this.draw.clean()
|
||||
this.canvasCache.clean()
|
||||
assets.sounds["bgm_result"].stop()
|
||||
snd.musicGain.fadeIn()
|
||||
snd.buffer.loadSettings()
|
||||
this.redrawRunning = false
|
||||
pageEvents.keyRemove(this, "all")
|
||||
pageEvents.remove(this.canvas, ["mousedown", "touchstart"])
|
||||
|
@ -107,7 +107,8 @@ class SongSelect{
|
||||
type: song.type,
|
||||
offset: song.offset,
|
||||
songSkin: song.song_skin || {},
|
||||
music: song.music
|
||||
music: song.music,
|
||||
volume: song.volume
|
||||
})
|
||||
}
|
||||
this.songs.sort((a, b) => {
|
||||
@ -1741,7 +1742,7 @@ class SongSelect{
|
||||
if(!loadOnly){
|
||||
this.preview = songObj.preview_sound
|
||||
this.preview.gain = snd.previewGain
|
||||
this.previewLoaded(startLoad, songObj.preview_time)
|
||||
this.previewLoaded(startLoad, songObj.preview_time, currentSong.volume)
|
||||
}
|
||||
}else{
|
||||
songObj = {id: id}
|
||||
@ -1767,7 +1768,7 @@ class SongSelect{
|
||||
if(currentId === this.previewId){
|
||||
songObj.preview_sound = sound
|
||||
this.preview = sound
|
||||
this.previewLoaded(startLoad, songObj.preview_time)
|
||||
this.previewLoaded(startLoad, songObj.preview_time, currentSong.volume)
|
||||
|
||||
var oldPreview = this.previewList.shift()
|
||||
if(oldPreview){
|
||||
@ -1781,11 +1782,12 @@ class SongSelect{
|
||||
}
|
||||
}
|
||||
}
|
||||
previewLoaded(startLoad, prvTime){
|
||||
previewLoaded(startLoad, prvTime, volume){
|
||||
var endLoad = this.getMS()
|
||||
var difference = endLoad - startLoad
|
||||
var minDelay = 300
|
||||
var delay = minDelay - Math.min(minDelay, difference)
|
||||
snd.previewGain.setVolumeMul(volume || 1)
|
||||
this.preview.playLoop(delay / 1000, false, prvTime)
|
||||
}
|
||||
endPreview(){
|
||||
@ -1935,7 +1937,7 @@ class SongSelect{
|
||||
if(!this.bgmEnabled){
|
||||
snd.musicGain.fadeIn()
|
||||
setTimeout(() => {
|
||||
snd.musicGain.fadeIn()
|
||||
snd.buffer.loadSettings()
|
||||
}, 500)
|
||||
}
|
||||
this.redrawRunning = false
|
||||
|
@ -3,6 +3,7 @@
|
||||
var AudioContext = window.AudioContext || window.webkitAudioContext
|
||||
this.context = new AudioContext()
|
||||
pageEvents.add(window, ["click", "touchend"], this.pageClicked.bind(this))
|
||||
this.gainList = []
|
||||
}
|
||||
load(url, local, gain){
|
||||
if(local){
|
||||
@ -27,7 +28,9 @@
|
||||
})
|
||||
}
|
||||
createGain(channel){
|
||||
return new SoundGain(this, channel)
|
||||
var gain = new SoundGain(this, channel)
|
||||
this.gainList.push(gain)
|
||||
return gain
|
||||
}
|
||||
setCrossfade(gain1, gain2, median){
|
||||
if(!Array.isArray(gain1)){
|
||||
@ -60,6 +63,18 @@
|
||||
this.context.resume()
|
||||
}
|
||||
}
|
||||
saveSettings(){
|
||||
for(var i = 0; i < this.gainList.length; i++){
|
||||
var gain = this.gainList[i]
|
||||
gain.defaultVol = gain.volume
|
||||
}
|
||||
}
|
||||
loadSettings(){
|
||||
for(var i = 0; i < this.gainList.length; i++){
|
||||
var gain = this.gainList[i]
|
||||
gain.setVolume(gain.defaultVol)
|
||||
}
|
||||
}
|
||||
}
|
||||
class SoundGain{
|
||||
constructor(soundBuffer, channel){
|
||||
@ -85,6 +100,9 @@ class SoundGain{
|
||||
this.gainNode.gain.value = amount * amount
|
||||
this.volume = amount
|
||||
}
|
||||
setVolumeMul(amount){
|
||||
this.setVolume(Math.sqrt(amount * amount * this.defaultVol))
|
||||
}
|
||||
setCrossfade(amount){
|
||||
this.setVolume(Math.sqrt(Math.sin(Math.PI / 2 * amount)))
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
function StringsJa(){
|
||||
this.id = "ja"
|
||||
this.name = "日本語"
|
||||
this.regex = /^ja$/
|
||||
this.regex = /^ja$|^ja-/
|
||||
this.font = "TnT, Meiryo, sans-serif"
|
||||
|
||||
this.taikoWeb = "たいこウェブ"
|
||||
|
@ -1438,7 +1438,7 @@
|
||||
ctx.fill()
|
||||
ctx.globalAlpha = 1
|
||||
}
|
||||
if(!circle.animating){
|
||||
if(!circle.animating && circle.text){
|
||||
// Text
|
||||
var text = circle.text
|
||||
var textX = circlePos.x
|
||||
|
@ -20,6 +20,10 @@
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div>Music volume:</div>
|
||||
<div class="music-volume input-slider">
|
||||
<span class="reset">x</span><input type="text" value="" readonly><span class="minus">-</span><span class="plus">+</span>
|
||||
</div>
|
||||
<label><input class="change-restart" type="checkbox">Restart on change</label>
|
||||
<label class="autoplay-label"><input class="autoplay" type="checkbox">Auto play</label>
|
||||
<div class="bottom-btns">
|
||||
|
Loading…
Reference in New Issue
Block a user