The solution to this problem using js and R Shiny is to create a separate js function that stops sounds from playing. Then, each time you want to start a new sound, you first also call the sound stopping function - hence, any previously playing sound will be stopped before the new one begins.
library(shiny)
library(shinyjs)
ui <- fluidPage(
useShinyjs(),
extendShinyjs(script = "marbles.js"),
extendShinyjs(script = "birds.js"),
extendShinyjs(script = "stopper.js"),
column(10, offset = 1,
align = "center",
fluidRow(column(4,
align = "center",
column(10,
align = "center",
offset = 1,
br(),
actionButton('sound1','Sound 1', width = '100%',
style="color: #ffffff; background-color: #35467b; border-color: #2e1911"))),
column(4,
align = "center",
column(10,
align = "center",
offset = 1,
br(),
actionButton('sound2','Sound 2', width = '100%',
style="color: #ffffff; background-color: #1dbd6b; border-color: #1dbd6b"))),
column(4,
align = "center",
column(10,
align = "center",
offset = 1,
br(),
actionButton('stopper','Stop sounds', width = '100%',
style="color: #ffffff; background-color: #b73838; border-color: #b73838")))
)),
)
server <- function(input, output) {
observeEvent(input$sound1, {
js$stopper()
js$birds()
})
observeEvent(input$sound2, {
js$stopper()
js$marbles()
})
observeEvent(input$stopper, {
js$stopper()
})
}
# Run the application
shinyApp(ui = ui, server = server)
The sound stopping function is simple:
shinyjs.stopper = function() {
snd.pause();
}
Then the two sound functions would be the following, but you insert your own base64 plain text in the 'new audio' part (to convert a wav to base64, see e.g.: WAV to Base64 | Audio | Base64 Encode | Base64 Converter | Base64). All the javascript functions should be saved as js files in the same folder as your app:
shinyjs.birds = function() {
snd = new Audio("data:audio/wav;base64,blablablabla");
snd.play();
}
shinyjs.marbles = function() {
snd = new Audio("data:audio/wav;base64,blablablabla");
snd.play();
}
In short, for whatever reason, it doesn't seem to work to just call sound.pause() at the start of the function where you make a new sound start playing. Instead, make a separate function that stops the sound, and then run the new sound afterwards.