Message Boards Message Boards

What scoping construct to use with "Play" (audio)?

GROUPS:
functionForm[hz_] := Cos[2 Pi hz seconds]
    expressionForm = Cos[2 Pi hz seconds]

This works:

Play[functionForm[300], {seconds, 0, 2}]

None of these works:

With[{hz = 300}, Play[expressionForm, {seconds, 0, 2}]]

Module[{hz = 300}, Play[expressionForm, {seconds, 0, 2}]]

Block[{hz = 300}, Play[expressionForm, {seconds, 0, 2}]]

(I was expecting "Block" to work.) How can I do this with scoping-constructs, rather than functions?

POSTED BY: Joe Donaldson
Answer
8 months ago

Joe,

Play[expressionForm /. hz -> 300, {seconds, 0, 2}]

Works. Note that if you replace Play with an arbitrary function, what you are trying will not work:

In[18]:= With[{hz = 300}, f[expressionForm, {seconds, 0, 2}]]

Out[18]= f[Cos[2 hz \[Pi] seconds], {seconds, 0, 2}]

While this does work:

In[21]:= With[{hz = 300}, f[Cos[2 Pi hz seconds], {seconds, 0, 2}]]

Out[21]= f[Cos[600 \[Pi] seconds], {seconds, 0, 2}]

The hz is not replaced because expressionForm does not have hz in it until it is evaluated (which is too late because the With tried to replace the value first)

You can always do this if you need it in a block/module/with type construct:

With[{withhz = 300}, 
 Play[expressionForm /. hz -> withhz, {seconds, 0, 2}]]
POSTED BY: Neil Singer
Answer
8 months ago

Thanks for your clear response.

Your solution with "/." is good for my specific example, but I'm left curious why Block doesn't work in my attempt (as an exercise while I'm trying to learn the Wolfram language.) Block does work with an arbitrary function in place of Play:

In[9]:= Block[{hz = 300}, f[expressionForm, {seconds, 0, 2}]]

Out[9]= f[Cos[600 \[Pi] seconds], {seconds, 0, 2}]

Block also works with the function-operator Integrate:

In[11]:= Block[{hz = 300}, Integrate[expressionForm, seconds]]

Out[11]= Sin[600 \[Pi] seconds]/(600 \[Pi])

My previous success using Block is why I was surprised when it didn't work with Play. Ideally I'd like to be able to predict ahead of time when I need to use "/." instead of Block, but I haven't yet grasped the principle at play here.

POSTED BY: Joe Donaldson
Answer
8 months ago

Joe,

The problem is that Play has the attribute of HoldAll. It will not evaluate expressionForm unless you force it to.

Block[{hz = 300}, Play[Evaluate[expressionForm], {seconds, 0, 2}]]

Will work. Lookup the documentation on HoldAll and Evaluation Control to learn more.

Regards,

Neil

POSTED BY: Neil Singer
Answer
8 months ago

Thanks very much for the references and the example.

POSTED BY: Joe Donaldson
Answer
8 months ago

HoldAll cannot be the whole story, because the following works:

expressionForm = Cos[2 Pi hz seconds];
Block[{hz = 800}, Table[expressionForm, {seconds, 0, 2}]]
Block[{hz = 800}, Plot[expressionForm, {seconds, 0, 2}]]

although Table and Plot both have the HoldAll attribute.

POSTED BY: Gianluca Gorni
Answer
8 months ago

Group Abstract Group Abstract