2
$\begingroup$

I am trying to create a simple audio player but I am stuck at designing the seek bar. I am using the AudioStream framework.

After loading music in a variable stream, I can access its position using stream["Position"]. However, this returns the current position of the track as a Quantity instead of a Real number.

So when I put this in a slider, I cannot control the position of the audio

Slider[
    Dynamic[QuantityMagnitude@UnitConvert[stream["Position"], "Seconds"]],
    {0, stream["Duration"]}
 ]

This results in the error

Set::write: Tag QuantityMagnitude in QuantityMagnitude[0.s] is Protected.

Can anyone suggest a workaround for this?

$\endgroup$

1 Answer 1

3
$\begingroup$

Maybe something like this will get you started?

stream = AudioStream[ExampleData[{"Audio", "ChurchBell"}]]
{Slider[
   Dynamic[
     QuantityMagnitude@stream["Position"], 
     (stream["Position"] = Quantity[#, "Seconds"]) &
   ], 
   {0., stream["Duration"]}
 ], 
 Dynamic[stream["Position"]]}
AudioPlay[stream]

The problem with your code is that by default Dynamic tries to assign the current value to whatever the first argument is. So it sees something like QuantityMagnitude@UnitConvert[stream["Position"], "Seconds"] = somenewvalue and it's saying that you cannot use Set on QuantityMagnitude.

My solution avoids this by making use of the second argument of Dynamic. So the value that is actually being tracked by the slider is QuantityMagnitude@stream["Position"], basically the same as what you had. You can add your UnitConvert back in if you need it, but I didn't need it since my sample audio was short. But we don't want Dynamic to actually try to assign to that value. Instead, using the second argument, I tell it to convert the current raw value to seconds, and then assign that value to stream["Position"].

You can see that as the audio plays, the position of the slider as well as the number afterwards changes.

I did notice that if you grab the slider while the audio is playing, it doesn't seem to want to play again. You could probably remedy this by having pause and play buttons using stream["Status"] = "Paused", or making the Dynamic pause the audio whenever you click the slider.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.