forked from csound/csoundAPI_examples
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathExample8.cs
More file actions
84 lines (76 loc) · 4.15 KB
/
Example8.cs
File metadata and controls
84 lines (76 loc) · 4.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using csound6netlib;
namespace csoundAPI_examples
{
public partial class CsoundAPI_Examples
{
/**
* Example 8 - More efficient Channel Communications (in a single threaded host)
*
* This example builds on Example 7 by replacing the calls to SetChannel
* with using GetChannelPtr. In the Csound API, using SetChannel and GetChannel
* is great for quick work, but ultimately it is slower than pre-fetching the
* actual channel pointer. This is because Set/GetChannel operates by doing a
* lookup of the Channel Pointer, then setting or getting the value. This
* happens on each call. The alternative is to use GetChannelPtr, which fetches
* the Channel Pointer and lets you directly set and get the value on the pointer.
* The approach shown here is only safe if you remain in a single thread
* such as managing channel values in between calls to PerformKsmps.
*
* The thread-safe method shown in Example6 is preferred when using events in
* a multithreaded environment such as was hinted at in Example4.
* You can use the Channel Pointer technique when using threads but you must use
* a channel lock to take care in not to creating a race condition while using
* memory shared between host and csound itself thereby causing potential glitches
* in your music. Further, since you write directly into unmanaged memory when
* using this technique, getting even one byte of data wrong can crash your program.
*
* Like other managed hosts (like python), C# provides mechanisms that attempt
* to contain your ability to do this.
* The C# version supplies Get/SetValueDirect methods for channels which use
* the channel objects declared name and direction and limits memory access to the
* actual size defined for the channel's type.
* The call to the memory pointer (GetChannelPtr) is internal and the returned pointer
* is used whenever GetValueDirect or SetValueDirect is called thereby preserving
* the speed advantage mentioned in the python example.
*
* Managing thread locks in host code is beyond the scope of this tutorial.
* Use the method shown in Example6 when using more than one thread.
*
* The code below shows how to make indirect use of the .net Csound6Channel
* object's GetChannelPtr function to touch channel memory directly.
*
*/
public void Example8()
{
using (var c = new Csound6NetRealtime())
{
c.SetOutputDac(0);
c.SetOption("-m7");
c.CompileOrc(orc3); // Compile Orchestra from String
c.ReadScore("i1 0 10\n");//Read in a score to run for 10 seconds
c.Start(); //Must call Start() explicitly when compiling from a string
var amps = new RandomLine(.4, .2); // create RandomLine for use with Amplitude
var freqs = new RandomLine(400, 80); // create RandomLine for use with Frequency
var bus = c.GetSoftwareBus();//Get bus and define the "amp" and "freq" channels of orc3
//Since orc3 instrument doesn't declare channels directly, define them here
var ampChannel = bus.AddControlChannel("amp", ChannelDirection.Input);
var freqChannel = bus.AddControlChannel("freq", ChannelDirection.Input);
//Prime with initial values accessing channel memory directly
ampChannel.SetValueDirect(amps.Value); //Use
freqChannel.SetValueDirect(freqs.Value);
while (!c.PerformKsmps())
{
//continue to update memory for the two channels directly
ampChannel.SetValueDirect(amps.Value);
freqChannel.SetValueDirect(freqs.Value);
}
c.Stop();
}
}
}
}