Changing SynthDef amplitude in realtime using OSC trigger/message and UGen - osc

Sorry if this is very obvious, I'm very new to SuperCollider. I've followed a few suggestions from other threads but this application appears unique as I'm using OSC data from Max 8. I've run out of time so I'd hugely appreciate any suggestions.
I'm trying to change the amplitude of my Synth using AmpCompA. I can change the frequency in realtime using OSC messages from Max 8, however, I can't apply AmpCompA in realtime using the same trigger/message. Is this possible another way?
Here is the code:
// setup synth
(
SynthDef.new("sine", {arg out = 0, freq = 200, amp = 1.0;
var sin;
sin = SinOsc.ar(freq);
Out.ar(out, sin * amp);
}).send(s);
)
x = Synth.new("sine", [\freq, 200, \amp, 1.0]);
//test parameter setting
x.set(\freq, 400);
x.set(\amp, 0.1);
x.free;
//read from OSC message
(
f = { |msg|
if(msg[0] != '/status.reply') {
b = 1.0 * AmpCompA.kr(msg[1]);
x.set(\freq, msg[1]); //this does work when I send an OSC message from Max 8
x.set(\amp, b); //this doesn't work? Can't set a control to UGen error
}
};
thisProcess.addOSCRecvFunc(f);
)
s.sendMsg("/n_free", x);
Max 8 Screenshot
Error:
ERROR: can't set a control to a UGen
CALL STACK:
Exception:reportError
arg this =
Nil:handleError
arg this = nil
arg error =
Thread:handleError
arg this =
arg error =
Object:throw
arg this =
UGen:asControlInput
arg this =
Object:asOSCArgEmbeddedArray
arg this =
arg array = [*1]
< FunctionDef in Method SequenceableCollection:asOSCArgArray >
arg e =
ArrayedCollection:do
arg this = [*2]
arg function =
var i = 1
SequenceableCollection:asOSCArgArray
arg this = [*2]
var array = [*1]
Node:set
arg this =
arg args = [*2]
< FunctionDef in Method Collection:collectInPlace >
arg item =
arg i = 1
ArrayedCollection:do
arg this = [*2]
arg function =
var i = 1
Collection:collectInPlace
arg this = [*2]
arg function =
FunctionList:value
arg this =
arg args = [*4]
var res = nil
Main:recvOSCmessage
arg this =
arg time = 626.8060463
arg replyAddr =
arg recvPort = 57120
arg msg = [*2]
^^ The preceding error dump is for ERROR: can't set a control to a UGen

You can use the x.set to send numbers to a synthdef, but you can't use them to send functions or uGens. AmpCompA is a UGen - and therefore can only be used inside a synthdef.
You can modify your synthdef to use it:
(
SynthDef.new("sine", {arg out = 0, freq = 200, amp = 1.0;
var sin;
sin = SinOsc.ar(freq);
Out.ar(out, sin * amp * AmpCompA.kr(freq));
}).send(s);
)
Your OSC message function only would ever send the frequency:
x.set(\freq, msg[1]);
The SynthDef uses the frequency to compute the psychoacoustic amplitude change.

Related

Code not plotting - Function should be called on each calculation for consistency. It is recommended to extract the call from this scope"

I am getting this as an orange error - not sure what I have done wrong or whether this error is the reason that the code doesn't plot. I am brand new to Pine-script and any assistance would be invaluable. Many thanks in advance Alastair
//#version=5
indicator("PCY TEST4")
//Get User Inputs
fast_length = input(title="Fast Length", defval=12)
slow_length = input(title="Slow Length", defval=26)
src = input(title="Source", defval=close)
signal_length = input.int(title="Signal Smoothing", minval = 1, maxval = 50, defval = 9)
sma_source = input.string(title="Oscillator MA Type", defval="EMA", options=["SMA", "EMA"])
sma_signal = input.string(title="Signal Line MA Type", defval="EMA", options=["SMA", "EMA"])
//Variables
a = 0.33
PCY = 0.0
PCYi = 0.0
// Calculating
fast_ma = sma_source == "SMA" ? ta.sma(src, fast_length) : ta.ema(src, fast_length)
slow_ma = sma_source == "SMA" ? ta.sma(src, slow_length) : ta.ema(src, slow_length)
macd = fast_ma - slow_ma
minMacd=0.0
for i = 0 to (signal_length[1])
minMacd := ta.min(macd)
maxMacd=0.0
for i = 0 to (signal_length[1])
maxMacd := ta.max(macd)
//maxMacd = ta.min(macd)
//minMacd = ta.max(macd)
//signal = sma_signal == "SMA" ? ta.sma(macd, signal_length) : ta.ema(macd, signal_length)
//hist = macd - signal
delta = maxMacd-(fast_ma - slow_ma)/(maxMacd -minMacd)
for i = 0 to (signal_length)
PCYi := a*((delta - PCYi[1])+PCYi[1])
PCYi
//Plotting
plot(PCYi)
I think it's because you're calculating the min/max in a for loop
Those functions should (not mandatory but strongly recommended) be calculated at every candle instead
for i = 0 to (signal_length[1])
minMacd := ta.min(macd)
maxMacd=0.0
for i = 0 to (signal_length[1])
maxMacd := ta.max(macd)
If you want to calculate the min/max over a X period of time, maybe use the ta.highest/ta.lowest functions instead :)
And of course, those 2 should be called at every candle (i.e. not in a if, for,... statement)

Using zero_grad() after loss.backward(), but still receives RuntimeError: "Trying to backward through the graph a second time..."

Below is my implementation of a2c using PyTorch. Upon learning about backpropagation in PyTorch, I have known to zero_grad() the optimizer after each update iteration. However, there is still a RunTime error on second-time backpropagation.
def torchworker(number, model):
worker_env = gym.make("Taxi-v3").env
max_steps_per_episode = 2000
worker_opt = optim.Adam(lr=5e-4, params=model.parameters())
p_history = []
val_history = []
r_history = []
running_reward = 0
episode_count = 0
under = 0
start = time.time()
for i in range(2):
state = worker_env.reset()
episode_reward = 0
penalties = 0
drop = 0
print("Episode {} begins ({})".format(episode_count, number))
worker_env.render()
criterion = nn.SmoothL1Loss()
time_solve = 0
for _ in range(1, max_steps_per_episode):
#worker_env.render()
state = torch.tensor(state, dtype=torch.long)
action_probs = model.forward(state)[0]
critic_value = model.forward(state)[1]
val_history.append((state, critic_value[0]))
# Choose action
action = np.random.choice(6, p=action_probs.detach().numpy())
p_history.append(torch.log(action_probs[action]))
# Apply chosen action
state, reward, done, _ = worker_env.step(action)
r_history.append(reward)
episode_reward += reward
time_solve += 1
if reward == -10:
penalties += 1
elif reward == 20:
drop += 1
if done:
break
# Update running reward to check condition for solving
running_reward = (running_reward * (episode_count) + episode_reward) / (episode_count + 1)
# Calculate discounted returns
returns = deque(maxlen=3500)
discounted_sum = 0
for r in r_history[::-1]:
discounted_sum = r + gamma * discounted_sum
returns.appendleft(discounted_sum)
# Calculate actor losses and critic losses
loss_actor_value = 0
loss_critic_value = 0
history = zip(p_history, val_history, returns)
for log_prob, value, ret in history:
diff = ret - value[1]
loss_actor_value += -log_prob * diff
ret_tensor = torch.tensor(ret, dtype=torch.float32)
loss_critic_value += criterion(value[1], ret_tensor)
loss = loss_actor_value + 0.1 * loss_critic_value
print(loss)
# Update params
loss.backward()
worker_opt.step()
worker_opt.zero_grad()
# Log details
end = time.time()
episode_count += 1
if episode_count % 1 == 0:
worker_env.render()
if running_reward > -50: # Condition to consider the task solved
under += 1
if under > 5:
print("Solved at episode {} !".format(episode_count))
break
I believe there may be something to do with the architecture of my AC model, so I also include it here for reference.
class ActorCriticNetwork(nn.Module):
def __init__(self, num_inputs, num_hidden, num_actions):
super(ActorCriticNetwork, self).__init__()
self.embed = nn.Embedding(500, 10)
self.fc1 = nn.Linear(10, num_hidden * 2)
self.fc2 = nn.Linear(num_hidden * 2, num_hidden)
self.c = nn.Linear(num_hidden, 1)
self.fc3 = nn.Linear(num_hidden, num_hidden)
self.a = nn.Linear(num_hidden, num_actions)
def forward(self, x):
out = F.relu(self.embed(x))
out = F.relu(self.fc1(out))
out = F.relu(self.fc2(out))
critic = self.c(out)
out = F.relu(self.fc3(out.detach()))
actor = F.softmax(self.a(out), dim=-1)
return actor, critic
Would you please tell me what the mistake here is? Thank you in advance.
SOLVED: I forgot to clear the history of probabilities, action-values and rewards after iterations. It is clear why that would cause the issue, as the older elements would cause propagating through old dcgs.

Dynamic piping with FRP

Consider a problem:
split file by lines
write lines to a result file
if a result file exceeds some size create a new result file
For example, if I have a file which weights 4gb and split size is equal 1gb. The result is four files weights 1gb.
I'm looking for a solution with something like Rx*/Bacon or any other similar library in any language.
My solution in Coffee with Highland.js:
_ = require('underscore')
H = require('highland')
fs = require('fs')
debug = require('debug')
log = debug('main')
assert = require('assert')
readS = H(fs.createReadStream('walmart.dump')).map((buffer) ->
{ buffer: buffer }
)
MAX_SIZE = 10 ** 7
counter = 0
nextStream = ()->
stream = fs.createWriteStream("result/data#{counter}.txt")
wrapper = H.wrapCallback(stream.write.bind(stream))
counter += 1
return wrapper
debug('profile')('start')
s = readS.scan({
size: 0
stream: nextStream()
}, (acc, {buffer}) ->
debug('scan')(acc, buffer)
acc.size += buffer.length
acc.buffer = buffer
if acc.size > MAX_SIZE
debug('notify')(counter - 1, acc.size)
acc.size = 0
acc.stream = nextStream()
log(acc)
return acc
).filter((x)->x.buffer?)
s.parallel 4
s.flatMap((x) ->
debug('flatMap')(x)
x.stream(x.buffer)
)
.done -> debug('profile')('finish')
walmart.dump is a text file which contains 6gb of text. Splitting for 649 files takes:
profile start +0ms
profile finish +53s

Getting error from: dlen = uint32(0) ;

I don't know why but I am getting this error:
Error in mr_lsbpex (line 3)
dlen = uint32(0) ;
Output argument "a" (and maybe others) not assigned during call to "E:\path\mr_lsbpex.m>mr_lsbpex"
I have tested "dlen = uint32(0) ;" in matlab enviorment (outside of this function) and everything was OK. Here is my code:
function a = mr_lsbpex ( r, p )
% extract from an array
dlen = uint32(0) ;
s = size (r) ;
rnd = rand (s(1),s(2)) ;
rd = 32 ;
rl = s(2) ;
for i=1:s(2)
if rnd(1,i)<rd/rl
d = bitget (round(r(1,i)/p),1);
dlen = bitset (dlen,rd,d);
rd = rd -1 ;
end
rl = rl -1 ;
end
if (dlen > 10000000 )
clear a ;
return ;
end
a = uint8(zeros(dlen,1)) ;
rd = double(dlen * 8) ;
rl = double(s(1)*s(2)-s(2)) ;
for i=2:s(1)
for j=1:s(2)
if rnd(i,j)<rd/rl
d = bitget (round(r(i,j)/p) ,1) ;
a = z_set_bit (a,rd,d) ;
rd = rd - 1 ;
end
rl = rl - 1 ;
end
end
Remember: a needs to be returned ALLWAYS!
The error is not in that specific line, but in the "whole" function itself.
Your problem is that Matlab thinks that a its not going to be created. And actually in some case it may not be created.
The following line in the beginning of your function should do the trick
a=0; % well, or a=NaN; or whatever you want to return
Additionally, don't clear a in if (dlen > 10000000 ).

This code kills the page

I have a function
makeMarks: (first, nextIncrement, classifier) ->
results = new Array()
t = first(#minT)
while t<=#maxT
mark =
t: t
x: this.tToX(t)
class: classifier(t)
results.push(mark)
t = nextIncrement(t)
results
this function works great with the following two functions as parameters
# parameters for hour tickmarks
#firstHour = (t) ->
msPerHour = 1000*60*60
Math.floor(t / msPerHour) * msPerHour
#nextHour = (currentHour) ->
msPerHour = 1000*60*60
currentHour + msPerHour
when called as such
marks = markMaker.makeMarks( #firstMonth, #nextMonth, #classifier)
Now to the problem:
# parameters for month tickmarks
#firstMonth = (minT) ->
msPerDay = 1000*60*60*24
t = Math.floor(minT/msPerDay) * msPerDay
d = new Date(t)
while(d.getDate() isnt 0)
t += msPerDay
d.setTime(t)
t
#nextMonth = (currentMonth) ->
msPerDay = 1000*60*60*24
t = currentMonth + msPerDay
d = new Date(t)
while(d.getDate() isnt 0)
t += msPerDay
d.setTime(t)
t
The hour code works fine, but the month code doesn't seem to terminate.
The getDate function never returns 0. Its minimum value is 1 and it's maximum value is 31. If you're looking for anything outside that range, that's a long wait for a train that don't come.