Supercollider: Applying FX to a group seems to affect other groups - supercollider

I have created separate groups on supercollider for each instrument so that I may apply FX, like echo, to the group and only affect one instrument rather than all instruments playing on that sc server.
On the node tree, the echo synthdef correctly appears in the required group (box) and the FX is applied to the instrument in that group, but ALSO incorrectly applying echo to the nodes in other groups on the same server.
What I have noticed is that it affects all higher number groups and not lower number groups. Applying FX (echo) to group 1 or group 2 also applies the same FX to groups 3,4,5,6,7,8, etc., but applying FX to group 8 does NOT seem to affect groups 1,2,3,4,5,6,& 7.
I have tested this on the following systems/versions....
supercollider version (1:3.10.0+repack-1ubuntu2) on ubuntu (Linux
Optiplex-3010 5.4.0-70-generic #78-Ubuntu SMP x86_64 x86_64 x86_64
GNU/Linux)
supercollider version (1:3.10.0+repack-1+rpi1) on Linux raspberrypi
4.19.75-v7l+ #1270 SMP armv7l GNU/Linux
supercollider version (1:3.8.0~repack-2) on Linux advent
5.0.0-32-generic #34~18.04.2-Ubuntu SMP 2019 i686 i686 i686 GNU/Linux
Is this a known bug? Can I make any manual changes to the supercollider code to resolve this? If not, then it will have to be a separate RPi4 for each instrument, underutilising each RPi and increasing project costs significantly.
Regards to all SCcoders,
Phil
Requested code:
(SynthDef(\echo,{|in, out, length = 1, fb = 0.6, sep = 1|
var input = In.ar(in, 2);
var feedback = LocalIn.ar(2);
var output = LeakDC.ar(feedback*fb + input);
LocalOut.ar(DelayC.ar(output, length, sep));
ReplaceOut.ar(out, output);
}).writeDefFile("/home/phil/Supercollider/syndef");)
I instigate the echo via OSC over tcp/ip, but essentially it would be called by:
/s_new s 'echo' i 1028 i 0 i 8 //in this case 1028 is the node for track 8
//and 8 is the SC group
and adjusted by:
/n_set i 1028 s 'fb' f 0.7
UPDATE: In answer to Fizz's comment about...
how I created groups, initially in the startup.scd file and then clear every time the live performance stops and create every time the live performance starts...
oscStream.Clear();
oscStream << osc::BeginBundleImmediate
<< osc::BeginMessage("/g_freeAll") << 1 << osc::EndMessage
<< osc::BeginMessage("/clearSched") << osc::EndMessage
<< osc::EndBundle;
transmitSocketMelody1.Send(oscStream.Data(),oscStream.Size());
oscStream.Clear();
oscStream << osc::BeginMessage("/g_new") << 1 << 0 << 0
<< osc::EndMessage;
transmitSocketMelody1.Send(oscStream.Data(),oscStream.Size());
oscStream.Clear();
oscStream << osc::BeginMessage("/g_new") << 2 << 0 << 0
<< osc::EndMessage;
transmitSocketMelody1.Send(oscStream.Data(),oscStream.Size());
which is the equivalent of...
s.sendMsg(\g_freeAll, 0);
s.sendMsg(\clearSched);
s.sendMsg(\g_new,1,0,0);
s.sendMsg(\g_new,2,0,0);
Order that I create synthdefs...
The echo synthdef (already shown above) is the first created via the supercollider startup.scd file.
Then the sound synthdefs are created in numerical order Piano1, Piano2, Piano3, etc... also via the supercollider startup.scd file.
s.sendMsg(\b_allocRead, 101,"piano-p-c4.wav"); //buffer 101
SynthDef.new("piano1", {|amp=1, freq|
var output,sig,sig2;
sig=PlayBuf.ar(2, 101, freq/523.25, doneAction:2);
sig=sig*amp;
sig = Splay.ar(sig);
Out.ar(0,sig!2);
}).store;
s.sendMsg(\b_allocRead, 111,"piano-p-c5.wav"); //buffer 111
SynthDef.new("piano2", {|amp=1, freq|
var sig;
sig=PlayBuf.ar(2, 111, freq/523.25, doneAction:2);
sig=sig*amp;
sig = Splay.ar(sig);
Out.ar(0,sig!2);
}).store;
The piano synthdefs are played live from the commands..
oscStream_melody1 << osc::BeginMessage("/s_new")
<< "piano1"
<< NextSCNode << 0 << 1
<< "freq" << OscFrequency[OSCOctave][OSCNote]
<< "amp" << Melody1Amplitude*Melody1Volume
<< osc::EndMessage
transmitSocketMelody1.Send(oscStream_melody1.Data(),oscStream_melody1.Size());
oscStream_melody2 << osc::BeginMessage("/s_new")
<< "piano2"
<< NextSCNode << 0 << 2
<< "freq" << OscFrequency[OSCOctave][OSCNote]
<< "amp" << Melody2Amplitude*Melody2Volume
<< osc::EndMessage;
transmitSocketMelody2.Send(oscStream_melody2.Data(),oscStream_melody2.Size());
which is the equivalent of...
s.sendMsg("/s_new","\piano1",1234, 0, 1,"freq",440,"amp", 0.8)
s.sendMsg("/s_new","\piano2",1235, 0, 2,"freq",880,"amp", 0.7)
echo is turned on, modified and off live thus...
s.sendMsg(\s_new,'echo',1001,0,X); //where X is the group to apply to
s.sendMsg(\n_set, 1001,'fb',0.5,'length',1,'sep',1);
s.sendMsg(\n_free, 1001);
but this turns on the echo for all groups with higher numbers, e.g group2, group3, group4 etc.
Whereas if reverb is set on group2 it affects group3, group4, etc but not group1.

Without seeing any code, this is hard to answer, but I wonder if you are using buses? Your instrument group should output to an echo bus and that bus should output to where you wish the sound to go next - another FX bus or to 0.
You'd want to draw a block diagram of your groups, connecting inputs and outputs. Keep in mind that any FX group can take ins from multiple places, but will only have one output. This means you may end up running the same FX synth more than once, for example, if you want echo on groups A and B, but then you want group B to go to a compressor afterwards.
Make sure to declare every bus, give it a good variable name and remember to pass it as an argument on synth creation.

Related

How to loop CSV file values using Ultimate Thread Group?

I have this links.csv file:
METHOD,HOST,PATH,HITS
GET,google.com,/,7
GET,facebook.com,/,3
I want to create a JMeter test plan using Ultimate Thread Group (UTG) that randomize the hits based on the last column in the CSV above (HITS).
When viewing the results tree, I want to see something like this:
1. google.com
2. google.com
3. facebook.com
4. google.com
5. google.com
6. google.com
7. google.com
8. google.com
9. facebook.com
10. facebook.com
Ideally, I want to set the UTG to use the following settings:
Start Threads Count = sum of all hits in the CSV file (e.g. 7 + 3)
Initial Delay = 0
Startup Time = 60
Hold Load For = 30
Shutdown Time = 0
How to achieve this? I appreciate code samples and screenshots since I'm still new to JMeter.
I can only think of generating a new CSV file out of your original one in order to:
Get the "sum" of "HITS"
Generate a line containing method, host and path per "hit"
In order to achieve this:
Add setUp Thread Group to your Test Plan
Add JSR223 Sampler to the Thread Group
Put the following code into "Script" area:
def entries = new File('/path/to/original.csv').readLines().drop(1)
def sum = 0
def newCSV = new File('/path/to/generated.csv')
newCSV << 'METHOD,HOST,PATH' << System.getProperty('line.separator')
entries.each { entry ->
def values = entry.split(',')
def hits = values[3] as int
sum += hits
1.upto(hits, {
newCSV << values[0] << ',' << values[1] << ',' << values[2] << System.getProperty('line.separator')
})
}
props.put('threads', sum as String)
Use __P() function like ${__P(threads,)} in the Ultimate Thread Group
Use the new "generated" CSV file in the CSV Data Set Config in the Ultimate Thread Group

Getting vehicle ID

I am trying to get vehicle id as follow:
mobility = TraCIMobilityAccess().get(getParentModule());
assert(mobility);
traci = mobility->getCommandInterface();
traciVehicle = mobility->getVehicleCommandInterface();
cout<< mobility->getExternalId();
But it returns an invalid vehicle id. What is wrong?
Please help me to solve this problem. Thanks.
What do you mean by an invalid vehicle id? The way you are getting the identifier is the one used by sumo. If that is the case, can you specify what do you expect as an identifier? (that of omnet which starts from [1]?)
As the id of SUMO and that one apparent in omnet are not the same (the order of creation), you may add the following to get your own id (that matches the one of omnet) :
in the ".h" file of your TraCIDemo11p, add your id:
protected:
int your_id;//added
in the ".c" file of your TraCIDemo11p, affect the index in your id:
if (stage == 0) {
...
your_id = getParentModule()->getIndex();//added
...
next, in the place you want to verify a statement, add this:
EV << "My SUMO id = " << mobility->getExternalId() << endl;
EV << "My VEINS id = " << your_id /*or just : getParentModule()->getIndex()*/<< endl;
I hope this helps.
You can try the FindModlue::findHost() in DemoBaseApplLayer::initialize(int stage) in DemoBaseApplLayer.cc:
EV << FindModule<BaseMobility*>::findHost(getParentModule())->getId() << endl;
It will first return the host module and then use the getId() function to get its id.
For better understanding:
Firstly, you can run the simulation to see the indexing of the whole simulation and it would be like this:
Simulation information in veins
As read from the figure, each objects are assigned to a number, e.g. node[0]has the id 7, besides that, each sub-modules are also assigned with id numbers, e.g.
node[0] id = 7
appl id = 8
nic id = 9
veinsmobility id = 10
All of this ids (7,8,9,10) point to the node[0], which means you can use thoese ids to identify a specific car.
In the default DemoBaseApplLayer.cc, you can find
mac = FindModule<DemoBaseApplLayerToMac1609_4Interface*>::findSubModule(getParentModule());
and
myId = mac->getMACAddress();
in the initialization function void DemoBaseApplLayer::initialize(int stage).
Therefore, you can already use the myId as the vehicle id.
By the way, the reason that you get the 18 and 20 for vehicle id, is that the returned module might just be the host module and the sub-module, e.g. 18 is for the node[*] and the 20 is for its nic sub-module.

Visual Studio 2013 SerialPort not receiving all data

I am currently working on a project that requires serial communication between PIC 24FV16KA302 and a PC software.
I have searched the Internet for the past 3 days and i cant find an answer for my problem so i decided to ask here . This is my first visual studio program so i dont have any experience with the software.
The PIC has few variables and two 8x16 tables that i need to view and modify on the PC side . The problem comes when i send the tables , all other information is received without a problem . I am using serial connection ( 38400/8-N-1 ) via uart to usb converter
FT232
When the PC send "AT+RTPM" to the PIC .
Button7.Click
SerialPort1.ReceivedBytesThreshold = 128
MachineState = MS.Receive_table
SerialPort1.Write("AT+RTPM")
End Sub
The PIC sends back 128 Bytes( the values in the table )
case read_table_pwm : // send pwm table
for (yy = 0 ; yy < 8 ; yy ++) {
for (xx = 0 ; xx < 16 ; xx++ ) {
uart_send_char(controll_by_pmw_map_lb[yy][xx]) ;
}
}
at_command = receive_state_idle ;
break ;
Which the software is suppose to get and display in a DataGrid.
Private Sub SerialPort1_DataReceived(sender As Object, e As IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
If MachineState = MS.Receive_table Then
SerialPort1.Read(Buffer_array_received_data, 0, 128)
cellpos = 0
For grid_y As Int16 = 0 To 7 Step 1
For grid_x As Int16 = 0 To 15 Step 1
DataGridView1.Rows(grid_y).Cells(grid_x).Value = Buffer_array_received_data(cellpos)
cellpos += 1
Next
Next
End Sub
The problem is that most of the time ( 99 % ) it displays only part of the dataset and zeros to the end , and when i try to do it again it display the other part and it starts from the beginning .
First request
Second request
If i try the same thing with another program i always get the full dataset
Realterm
Termite
I have tried doing it cell by cell , but it only works if i request them one very second , other wise i get the same problem .
After that i need to use a timer ( 100 ms ) to request live data from the PIC .
this work better but still some of the time i get some random data. I haven't focused on that for the moment because without the dataset everything else is useless .
Am i missing something or has anyone encountered the same problem ?
I managed to solve the problem by replacing
SerialPort1.Read(Buffer_array_received_data, 0, 128)
with
For byte_pos As Int16 = 0 To 127 Step 1
Buffer_array_received_data(byte_pos) = SerialPort1.ReadByte()
Next
But aren't they supposed to be the same ?

SDL Keyboard Handling.

SDL is a hardware abstraction layer, so it's understandable that it would map whatever the local system keys are onto a virtual keyboard.
Their wiki has this entry; https://wiki.libsdl.org/SDL_Keycode
But it never seems to take modifier keys into account when reporting the event, so that this code:
if(e.type==SDL_KEYDOWN)
{
std::cout << SDL_GetKeyName(e.key.keysym.sym) << ":" << e.key.keysym.sym << std::endl;
}
Generates this result: (UK Keyboard)
Input: 1 causes output: 1:49
Input: 2 causes output: 2:50
Input: 3 causes output: 3:51
Input: 4 causes output: 4:52
Input: Shift+1 (!) causes output: 1:49
Input: Shift+2 (") causes output: 2:50
Input: Shift+3 (£) causes output: 3:51
Input: Shift+4 ($) causes output: 4:52
Yes, I understand that I can do something like this; SDL_Keymod _keystate = SDL_GetModState(); And take each key case by case. But that would limit it to my keyboard layoyt, would be ugly code, and quite frankly would make almost everything on this page worthless; https://wiki.libsdl.org/SDL_Keycode.
So. What am I missing, it obviously isn't applying modifiers by default? Is there a way to get it do so?

Match Multiple Patterns in a String and Return Matches as Hash

I'm working with some log files, trying to extract pieces of data.
Here's an example of a file which, for the purposes of testing, I'm loading into a variable named sample. NOTE: The column layout of the log files is not guaranteed to be consistent from one file to the next.
sample = "test script result
Load for five secs: 70%/50%; one minute: 53%; five minutes: 49%
Time source is NTP, 23:25:12.829 UTC Wed Jun 11 2014
D
MAC Address IP Address MAC RxPwr Timing I
State (dBmv) Offset P
0000.955c.5a50 192.168.0.1 online(pt) 0.00 5522 N
338c.4f90.2794 10.10.0.1 online(pt) 0.00 3661 N
990a.cb24.71dc 127.0.0.1 online(pt) -0.50 4645 N
778c.4fc8.7307 192.168.1.1 online(pt) 0.00 3960 N
"
Right now, I'm just looking for IPv4 and MAC address; eventually the search will need to include more patterns. To accomplish this, I'm using two regular expressions and passing them to Regexp.union
patterns = Regexp.union(/(?<mac_address>\h{4}\.\h{4}\.\h{4})/, /(?<ip_address>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/)
As you can see, I'm using named groups to identify the matches.
The result I'm trying to achieve is a Hash. The key should equal the capture group name, and the value should equal what was matched by the regular expression.
Example:
{"mac_address"=>"0000.955c.5a50", "ip_address"=>"192.168.0.1"}
{"mac_address"=>"338c.4f90.2794", "ip_address"=>"10.10.0.1"}
{"mac_address"=>"990a.cb24.71dc", "ip_address"=>"127.0.0.1"}
{"mac_address"=>"778c.4fc8.7307", "ip_address"=>"192.168.1.1"}
Here's what I've come up with so far:
sample.split(/\r?\n/).each do |line|
hashes = []
line.split(/\s+/).each do |val|
match = val.match(patterns)
if match
hashes << Hash[match.names.zip(match.captures)].delete_if { |k,v| v.nil? }
end
end
results = hashes.reduce({}) { |r,h| h.each {|k,v| r[k] = v}; r }
puts results if results.length > 0
end
I feel like there should be a more "elegant" way to do this. My chief concern, though, is performance.

Resources