Skip to content

Commit

Permalink
Queue filters export
Browse files Browse the repository at this point in the history
  • Loading branch information
ileukocyte committed Aug 16, 2022
1 parent 2a18cdf commit 5eb616d
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 29 deletions.
10 changes: 6 additions & 4 deletions src/main/kotlin/io/ileukocyte/hibernum/audio/TrackScheduler.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.ileukocyte.hibernum.audio

import com.google.common.util.concurrent.AtomicDouble

import com.sedmelluq.discord.lavaplayer.player.AudioPlayer
import com.sedmelluq.discord.lavaplayer.player.event.AudioEventAdapter
import com.sedmelluq.discord.lavaplayer.track.AudioTrack
Expand All @@ -12,6 +13,7 @@ import io.ileukocyte.hibernum.extensions.*

import java.util.concurrent.ConcurrentLinkedQueue
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicInteger

import kotlin.time.Duration.Companion.minutes

Expand All @@ -25,8 +27,8 @@ import net.dv8tion.jda.api.interactions.InteractionType
class TrackScheduler(private val player: AudioPlayer) : AudioEventAdapter() {
var queue = ConcurrentLinkedQueue<AudioTrack>()
var loopMode = LoopMode.DISABLED
var pitchOffset = AtomicDouble(0.0)
var speed = AtomicDouble(1.0)
var pitchOffset = AtomicInteger(0)
var speedRate = AtomicDouble(1.0)

operator fun plusAssign(track: AudioTrack) {
if (!player.startTrack(track, true)) {
Expand Down Expand Up @@ -76,8 +78,8 @@ class TrackScheduler(private val player: AudioPlayer) : AudioEventAdapter() {
if (track.info.isStream) {
player.setFilterFactory(null)

pitchOffset.set(0.0)
speed.set(1.0)
pitchOffset.set(0)
speedRate.set(1.0)
}

val userData = track.customUserData
Expand Down
6 changes: 4 additions & 2 deletions src/main/kotlin/io/ileukocyte/hibernum/audio/music.kt
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ fun GuildMusicManager.stop() {
player.volume = 100
player.setFilterFactory(null)
scheduler.loopMode = LoopMode.DISABLED
scheduler.pitchOffset.set(0.0)
scheduler.speed.set(1.0)
scheduler.pitchOffset.set(0)
scheduler.speedRate.set(1.0)

scheduler.queue.clear()
}
Expand Down Expand Up @@ -162,6 +162,8 @@ fun GuildMusicManager.exportQueueAsJson(
fun exportPlayerAsJson() = JsonObject(mutableMapOf(
"is_paused" to JsonPrimitive(player.isPaused),
"looping_mode" to JsonPrimitive(scheduler.loopMode.name.lowercase()),
"speed_rate" to JsonPrimitive(scheduler.speedRate.get()),
"pitch_offset" to JsonPrimitive(scheduler.pitchOffset.get()),
).apply {
if (includePlayerVolume) {
this["volume"] = JsonPrimitive(player.volume)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ import io.ileukocyte.hibernum.commands.GenericCommand.StaleComponentHandling
import io.ileukocyte.hibernum.commands.TextCommand
import io.ileukocyte.hibernum.commands.music.LoopCommand.Companion.getButton
import io.ileukocyte.hibernum.commands.music.LoopCommand.Companion.getNext
import io.ileukocyte.hibernum.extensions.bold
import io.ileukocyte.hibernum.extensions.maskedLink
import io.ileukocyte.hibernum.extensions.replyConfirmation
import io.ileukocyte.hibernum.extensions.*
import io.ileukocyte.hibernum.handlers.CommandHandler
import io.ileukocyte.hibernum.utils.asDuration

Expand Down Expand Up @@ -227,14 +225,32 @@ class NowPlayingCommand : TextCommand {
}

field {
title = "Looping Mode"
description = musicManager.scheduler.loopMode.toString()
title = "Volume"
description = "${musicManager.player.volume}%"
isInline = true
}

field {
title = "Volume"
description = "${musicManager.player.volume}%"
title = "Pitch Offset"
description = musicManager.scheduler.pitchOffset.get().let {
if (it == 0) {
"0 semitones"
} else {
"${it.toDecimalFormat("+#;-#")} semitone".singularOrPlural(it)
}
}
isInline = true
}

field {
title = "Speed Rate"
description = musicManager.scheduler.speedRate.get().toDecimalFormat("0.##x")
isInline = true
}

field {
title = "Looping Mode"
description = musicManager.scheduler.loopMode.toString()
isInline = true
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.ileukocyte.hibernum.commands.music

import com.github.natanbc.lavadsp.timescale.TimescalePcmAudioFilter

import com.sedmelluq.discord.lavaplayer.tools.FriendlyException
import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist
import com.sedmelluq.discord.lavaplayer.track.AudioTrack
Expand Down Expand Up @@ -93,6 +95,18 @@ class PlayCommand : TextCommand {
musicManager.player.isPaused = player.isPaused
//musicManager.player.volume = player.volume
musicManager.scheduler.loopMode = player.loopMode

if (!musicManager.player.playingTrack.info.isStream
&& (player.pitchOffset != 0 || player.speedRate != 1.0)) {
musicManager.player.setFilterFactory { _, format, output ->
val filter = TimescalePcmAudioFilter(output, format.channelCount, format.sampleRate)

filter.speed = player.speedRate
filter.setPitchSemiTones(player.pitchOffset.toDouble())

listOf(filter)
}
}
}

if (queue.tracks.size > 1) {
Expand Down Expand Up @@ -256,6 +270,18 @@ class PlayCommand : TextCommand {
musicManager.player.isPaused = player.isPaused
//musicManager.player.volume = player.volume
musicManager.scheduler.loopMode = player.loopMode

if (!musicManager.player.playingTrack.info.isStream
&& (player.pitchOffset != 0 || player.speedRate != 1.0)) {
musicManager.player.setFilterFactory { _, format, output ->
val filter = TimescalePcmAudioFilter(output, format.channelCount, format.sampleRate)

filter.speed = player.speedRate
filter.setPitchSemiTones(player.pitchOffset.toDouble())

listOf(filter)
}
}
}

if (queue.tracks.size > 1) {
Expand Down Expand Up @@ -401,6 +427,12 @@ class PlayCommand : TextCommand {
null
}
} ?: LoopMode.DISABLED
val speedRate = player["speed_rate"]?.jsonPrimitive?.doubleOrNull?.takeIf {
it in setOf(0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0)
} ?: 1.0
val pitchOffset = player["pitch_offset"]?.jsonPrimitive?.intOrNull?.takeIf {
it in -12..12
} ?: 0

suspend fun handleTrack(json: JsonObject) = HibernumTrack(
json["url"]?.jsonPrimitive?.content ?: throw exception,
Expand All @@ -422,7 +454,7 @@ class PlayCommand : TextCommand {
handleTrack(current),
*queue.map { handleTrack(it.jsonObject) }.toTypedArray(),
),
HibernumPlayer(isPaused, loopMode),
HibernumPlayer(isPaused, loopMode, speedRate, pitchOffset),
)
}

Expand All @@ -441,5 +473,7 @@ class PlayCommand : TextCommand {
val isPaused: Boolean,
//val volume: Int,
val loopMode: LoopMode,
val speedRate: Double,
val pitchOffset: Int,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,30 @@ class QueueCommand : TextCommand {
.takeUnless { track.info.isStream } ?: "(LIVE)")
}

field {
title = "Volume"
description = "${musicManager.player.volume}%"
isInline = true
}

field {
title = "Pitch Offset"
description = musicManager.scheduler.pitchOffset.get().let {
if (it == 0) {
"0 semitones"
} else {
"${it.toDecimalFormat("+#;-#")} semitone".singularOrPlural(it)
}
}
isInline = true
}

field {
title = "Speed Rate"
description = musicManager.scheduler.speedRate.get().toDecimalFormat("0.##x")
isInline = true
}

if (queueIsNotEmpty) {
field {
val tracks = musicManager.scheduler.queue + track
Expand All @@ -453,11 +477,5 @@ class QueueCommand : TextCommand {
description = musicManager.scheduler.loopMode.toString()
isInline = true
}

field {
title = "Volume"
description = "${musicManager.player.volume}%"
isInline = true
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class SpeedCommand : SlashOnlyCommand {
override val name = "speed"
override val description = "Enables the speed and pitch filters on the player"
override val fullDescription = "$description (or resets them in case no options are provided)"
override val aliases = setOf("pitch")
override val category = CommandCategory.BETA
override val options = setOf(
OptionData(OptionType.NUMBER, "speed", "The speed multiplier")
Expand All @@ -27,6 +28,7 @@ class SpeedCommand : SlashOnlyCommand {
.addChoice("1x", 1.0)
.addChoice("1.25x", 1.25)
.addChoice("1.5x", 1.5)
.addChoice("1.75x", 1.75)
.addChoice("2x", 2.0),
OptionData(
OptionType.INTEGER,
Expand All @@ -49,8 +51,8 @@ class SpeedCommand : SlashOnlyCommand {
val pitch = event.getOption("pitch")?.asInt

if (speed === null && pitch === null) {
audioPlayer.scheduler.pitchOffset.set(0.0)
audioPlayer.scheduler.speed.set(1.0)
audioPlayer.scheduler.pitchOffset.set(0)
audioPlayer.scheduler.speedRate.set(1.0)

audioPlayer.player.setFilterFactory(null)

Expand All @@ -60,32 +62,32 @@ class SpeedCommand : SlashOnlyCommand {
}

if (speed !== null) {
audioPlayer.scheduler.speed.set(speed)
audioPlayer.scheduler.speedRate.set(speed)
}

if (pitch !== null) {
audioPlayer.scheduler.pitchOffset.set(pitch.toDouble())
audioPlayer.scheduler.pitchOffset.set(pitch)
}

audioPlayer.player.setFilterFactory { _, format, output ->
val filter = TimescalePcmAudioFilter(output, format.channelCount, format.sampleRate)

filter.speed = audioPlayer.scheduler.speed.get()
filter.setPitchSemiTones(audioPlayer.scheduler.pitchOffset.get())
filter.speed = audioPlayer.scheduler.speedRate.get()
filter.setPitchSemiTones(audioPlayer.scheduler.pitchOffset.get().toDouble())

listOf(filter)
}

val pitchFormat = audioPlayer.scheduler.pitchOffset.get().let {
if (it.toInt() == 0) {
if (it == 0) {
"0 semitones"
} else {
"${it.toDecimalFormat("+#;-#")} semitone".singularOrPlural(it.toInt())
"${it.toDecimalFormat("+#;-#")} semitone".singularOrPlural(it)
}
}

event.replySuccess(
"The speed has been set to ${audioPlayer.scheduler.speed.get().toDecimalFormat("0.##x")} " +
"The speed has been set to ${audioPlayer.scheduler.speedRate.get().toDecimalFormat("0.##x")} " +
"and the pitch offset has been set to $pitchFormat!"
).queue()
} else {
Expand Down

0 comments on commit 5eb616d

Please sign in to comment.