/* Example 7 - Communicating continuous values with Csound's Channel System * * This example introduces using Csound's Channel System to communicate * continuous control data (k-rate) from a host program to Csound. The * first thing to note is the RandomLine class. It takes in a base value * and a range in which to vary randomly. The reset functions calculates * a new random target value (self.end), a random duration in which to * run (self.dur, expressed as # of audio blocks to last in duration), and * calculates the increment value to apply to the current value per audio-block. * When the target is met, the Randomline will reset itself to a new target * value and duration. * * In this example, we use two RandomLine objects, one for amplitude and * another for frequency. We start a Csound instrument instance that reads * from two channels using the chnget opcode. In turn, we update the values * to the channel from the host program. In this case, because we want to * keep our values generating in sync with the audio engine, we use a * while-loop instead of a CsoundPerformanceThread. To update the channel, * we call the SetChannel method on the Csound object, passing a channel name * and value. Note: The getValue method on the RandomLine not only gets * us the current value, but also advances the internal state by the increment * and by decrementing the duration. * * In the C# object wrappers, channels are objects which are most easily used * via a software bus object as this implemetation demonstrates. */ public void Example7() { using (var c = new Csound6NetRealtime()) { c.SetOption("-odac"); // Set option for Csound c.SetOption("-m7"); // Set option for Csound 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 amp = new RandomLine(.4, .2); // create RandomLine for use with Amplitude var freq = new RandomLine(400, 80); // create RandomLine for use with Frequency var bus = c.GetSoftwareBus(); //The bus's channels can be accessed by name like a dictionary. //If they don't yet exist, they will be defined (input/output as default) bus["amp"] = amp.Value; //Create and provide and initial value for an amplitude channel bus["freq"] = freq.Value;//Create and provide and initial value for a frequency channel while (!c.PerformKsmps()) { bus["amp"] = amp.Value; bus["freq"] = freq.Value; } c.Stop(); } }
/** * 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(); } }
/* Example 7 - Communicating continuous values with Csound's Channel System * * This example introduces using Csound's Channel System to communicate * continuous control data (k-rate) from a host program to Csound. The * first thing to note is the RandomLine class. It takes in a base value * and a range in which to vary randomly. The reset functions calculates * a new random target value (self.end), a random duration in which to * run (self.dur, expressed as # of audio blocks to last in duration), and * calculates the increment value to apply to the current value per audio-block. * When the target is met, the Randomline will reset itself to a new target * value and duration. * * In this example, we use two RandomLine objects, one for amplitude and * another for frequency. We start a Csound instrument instance that reads * from two channels using the chnget opcode. In turn, we update the values * to the channel from the host program. In this case, because we want to * keep our values generating in sync with the audio engine, we use a * while-loop instead of a CsoundPerformanceThread. To update the channel, * we call the SetChannel method on the Csound object, passing a channel name * and value. Note: The getValue method on the RandomLine not only gets * us the current value, but also advances the internal state by the increment * and by decrementing the duration. * * In the C# object wrappers, channels are objects which are most easily used * via a software bus object as this implemetation demonstrates. */ public void Example7() { using (var c = new Csound6NetRealtime()) { c.SetOption("-odac"); // Set option for Csound c.SetOption("-m7"); // Set option for Csound 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 amp = new RandomLine(.4, .2); // create RandomLine for use with Amplitude var freq = new RandomLine(400, 80); // create RandomLine for use with Frequency var bus = c.GetSoftwareBus(); //The bus's channels can be accessed by name like a dictionary. //If they don't yet exist, they will be defined (input/output as default) bus["amp"] = amp.Value; //Create and provide and initial value for an amplitude channel bus["freq"] = freq.Value; //Create and provide and initial value for a frequency channel while (!c.PerformKsmps()) { bus["amp"] = amp.Value; bus["freq"] = freq.Value; } c.Stop(); } }
/** * 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(); } }
/* Example 7 - Communicating continuous values with Csound's Channel System * * This example introduces using Csound's Channel System to communicate * continuous control data (k-rate) from a host program to Csound. The * first thing to note is the RandomLine class. It takes in a base value * and a range in which to vary randomly. The reset functions calculates * a new random target value (this.End), a random duration in which to * run (this.Dur, expressed as # of audio blocks to last in duration), and * calculates the increment value to apply to the current value per audio-block. * When the target is met, the Randomline will reset itself to a new target * value and duration. * * In this example, we use two RandomLine objects, one for amplitude and * another for frequency. We start a Csound instrument instance that reads * from two channels using the chnget opcode. In turn, we update the values * to the channel from the host program. In this case, because we want to * keep our values generating in sync with the audio engine, we use a * while-loop instead of a CsoundPerformanceThread. To update the channel, * we call the SoftwareBus's channel indexer methods with new values. * * Note: The Value property on the RandomLine objects not only gets * us the current value, but also advances the internal state by the increment * and by decrementing the duration. * * In the C# object wrappers, channels are objects which are most easily used * via a software bus object as this implemetation demonstrates. */ public void Example7() { using (var c = new Csound6NetRealtime()) { c.SetOption("-odac"); // Set option for Csound c.SetOption("-m7"); // Set option for Csound 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 amp = new RandomLine(.4, .2); // create RandomLine for use with Amplitude var freq = new RandomLine(400, 80); // create RandomLine for use with Frequency var bus = c.GetSoftwareBus(); //Channels can be created explicitly: bus.AddControlChannel("amp", ChannelDirection.Input); bus["amp"] = amp.Value; //Add an initial value: Value property changes after each use //Or channels can be created implicitly just by using it: //The bus's channels can be accessed by name like a dictionary. //If they don't yet exist, they will be defined (input/output as default) bus["freq"] = freq.Value;//Create and provide and initial value in one call //Now we have our channels: update them with new RandomLine values after each ksmps cycle: while (!c.PerformKsmps()) { bus["amp"] = amp.Value; bus["freq"] = freq.Value; } c.Stop(); } }
/* Example 7 - Communicating continuous values with Csound's Channel System * * This example introduces using Csound's Channel System to communicate * continuous control data (k-rate) from a host program to Csound. The * first thing to note is the RandomLine class. It takes in a base value * and a range in which to vary randomly. The reset functions calculates * a new random target value (this.End), a random duration in which to * run (this.Dur, expressed as # of audio blocks to last in duration), and * calculates the increment value to apply to the current value per audio-block. * When the target is met, the Randomline will reset itself to a new target * value and duration. * * In this example, we use two RandomLine objects, one for amplitude and * another for frequency. We start a Csound instrument instance that reads * from two channels using the chnget opcode. In turn, we update the values * to the channel from the host program. In this case, because we want to * keep our values generating in sync with the audio engine, we use a * while-loop instead of a CsoundPerformanceThread. To update the channel, * we call the SoftwareBus's channel indexer methods with new values. * * Note: The Value property on the RandomLine objects not only gets * us the current value, but also advances the internal state by the increment * and by decrementing the duration. * * In the C# object wrappers, channels are objects which are most easily used * via a software bus object as this implemetation demonstrates. */ public void Example7() { using (var c = new Csound6NetRealtime()) { c.SetOption("-odac"); // Set option for Csound c.SetOption("-m7"); // Set option for Csound 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 amp = new RandomLine(.4, .2); // create RandomLine for use with Amplitude var freq = new RandomLine(400, 80); // create RandomLine for use with Frequency var bus = c.GetSoftwareBus(); //Channels can be created explicitly: bus.AddControlChannel("amp", ChannelDirection.Input); bus["amp"] = amp.Value; //Add an initial value: Value property changes after each use //Or channels can be created implicitly just by using it: //The bus's channels can be accessed by name like a dictionary. //If they don't yet exist, they will be defined (input/output as default) bus["freq"] = freq.Value;//Create and provide and initial value in one call //Now we have our channels: update them with new RandomLine values after each ksmps cycle: while (!c.PerformKsmps()) { bus["amp"] = amp.Value; bus["freq"] = freq.Value; } c.Stop(); } }
public void Example9() { using (var c = new Csound6NetRealtime()) { c.SetOutputDac(0); //direct sample output to sound card //SetOptions requires the knowing and using the command line flags and their arguments. //The csound API (and C# bridge) expose another way to set csounds //parameters as properties. This would suit a GUI dialog better than SetOption. var options = c.GetParameters(); //also var options = new Csound6Parameters(c); //You can read their current value: Console.Write(options.Tempo); Console.WriteLine(string.Format("Current Message Level = {0}", options.MessageLevel)); //Instead of SetOptions("-m7"), you can use: options.MessageLevel = MessageLevel.Amps | MessageLevel.Range | MessageLevel.Warnings; //=7 //Using IntelliSense, you can explore the various settings csound exposes (various command line flags). options.IsDebugMode = false; options.Tempo = 120; //will cause 10 in score to be 5 (tempo defaults to 60) 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 //That is, it contains a call to csoundGetChannelPtr internally. 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(); } }
public void Example9() { using (var c = new Csound6NetRealtime()) { c.SetOutputDac(0); //direct sample output to sound card //SetOptions requires the knowing and using the command line flags and their arguments. //The csound API (and C# bridge) expose another way to set csounds //parameters as properties. This would suit a GUI dialog better than SetOption. var options = c.GetParameters(); //also var options = new Csound6Parameters(c); //You can read their current value: Console.Write(options.Tempo); Console.WriteLine(string.Format("Current Message Level = {0}", options.MessageLevel)); //Instead of SetOptions("-m7"), you can use: options.MessageLevel = MessageLevel.Amps | MessageLevel.Range | MessageLevel.Warnings; //=7 //Using IntelliSense, you can explore the various settings csound exposes (various command line flags). options.IsDebugMode = false; options.Tempo = 120; //will cause 10 in score to be 5 (tempo defaults to 60) 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 //That is, it contains a call to csoundGetChannelPtr internally. 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(); } }
public void TestSoftwareBus() { using (var cs = new Csound6NetRealtime()) { var result = cs.Compile(new string[] { "csdFiles\\SimpleRuntime.csd" }); Assert.AreEqual(CsoundStatus.Success, result); var bus = cs.GetSoftwareBus(); Assert.IsNotNull(bus); Assert.IsTrue(bus.Count > 0); Assert.AreEqual(8, bus.Count); foreach (var channel in bus.Channels) { switch (channel.Type) { case ChannelType.Control: Assert.IsTrue(channel.Name.StartsWith("chan")); Assert.IsInstanceOfType(channel, typeof(Csound6ControlChannel)); Assert.IsInstanceOfType(channel.Value, typeof(double)); Assert.AreEqual(channel.Value, bus[channel.Name]); break; case ChannelType.String: Assert.IsInstanceOfType(channel, typeof(Csound6StringChannel)); Assert.IsInstanceOfType(channel.Value, typeof(string)); Assert.IsTrue(channel.Name.StartsWith("schan")); Assert.AreEqual(channel.Value, bus[channel.Name]); break; case ChannelType.Audio: Assert.IsInstanceOfType(channel, typeof(Csound6AudioChannel)); Assert.IsTrue(channel.Name.StartsWith("achan")); Assert.IsInstanceOfType(channel.Value, typeof(double[])); var values = channel.Value as double[]; Assert.AreEqual(cs.Ksmps, values.Length); break; case ChannelType.Pvs: Assert.Fail("PVS data type not yet supported in .net"); break; default: Assert.Fail(string.Format("Software bus has unsupported channel {0} of type: {1}", channel.Name, channel.Type)); break; } } } }
public void TestOutInCallbacks() { m_messageText = new StringBuilder(); m_count = 0; m_outval = -1; using (var cs = new Csound6NetRealtime()) { cs.OutputChannelCallback += TestOutputCallback; cs.InputChannelCallback += TestInputCallback; var result = cs.Compile(new string[] { "csdFiles\\SimpleRuntime.csd" }); Assert.AreEqual(CsoundStatus.Success, result); if (result == CsoundStatus.Success) { while (!cs.PerformKsmps()) { ; } } cs.Cleanup(); } }
public void TestPerformanceThread() { using (var cs = new Csound6NetRealtime()) { var result = cs.Compile(new string[] { "-odac0", "csdFiles\\xanadu.csd" }); Assert.AreEqual(CsoundStatus.Success, result); m_perfTheadCalledBack = false; using (var pt = new Csound6PerformanceThread(cs)) { pt.ProcessCallback += TestPerfThreadCallback; Assert.IsFalse(pt.IsRunning);//test initial state Assert.IsTrue(pt.IsPaused); Assert.IsTrue(pt.Status == CsoundStatus.Success); pt.Play(); pt.SendScoreEvent(false, ScoreEventType.Note, new double[] { 3, 0, 15, 0, 5.10, 1.4, 0.8 }); Thread.Sleep(1000); Assert.IsTrue(pt.IsRunning); Assert.IsFalse(pt.IsPaused); Assert.IsTrue(pt.Status == CsoundStatus.Success); Thread.Sleep(3000); pt.Pause(); Thread.Sleep(1000); Assert.IsTrue(pt.IsRunning); Assert.IsTrue(pt.IsPaused); pt.SetScoreOffset(44.00); pt.TogglePause(); Thread.Sleep(1000); pt.SendInputMessage("i3 0 20 0 5.10 1.4 0.8"); Thread.Sleep(18000); Assert.IsTrue(pt.IsRunning); Assert.IsFalse(pt.IsPaused); pt.Stop(); Thread.Sleep(1500); //wait for threads do settle Assert.IsTrue(m_perfTheadCalledBack); //insure that we executed the callback beyound the first ksmps Assert.IsFalse(pt.IsRunning); //flags eventually got set Assert.IsTrue(pt.Status == CsoundStatus.Completed); //finished all events Assert.IsTrue(cs.ScoreTime > 60.0); //last input message should extend past 60 seconds. } } }
/** * Example 4 - Using Csound's Performance Thread * Example 4.1 - Using Csound in a C# async/await Task for threaded execution * * In this example, we use a CsoundPerformanceThread to run Csound in * a native thread. Using a native thread is important to get the best * runtime performance for the audio engine. * CsoundPerformanceThread has some convenient methods for handling events, * but does not have features for doing regular processing at block boundaries. * In general, use CsoundPerformanceThread when the only kinds of communication you * are doing with Csound are through events, and not using channels. * * Since VS2012, C# programmers have become comfortable with the async/await Task-based * paradigm for running background processes. * Example 4.1 shows an alternative to running csound in a separate thread (really Task) * to achieve the same result as example 4. * This approach is very useful in a GUI where a cancel event and a progress dialog * would be desireable. * This example bypasses these features; later examples will use them. */ public void Example4() { using (var c = new Csound6NetRealtime()) { c.SetOutputDac(0); // Set realtime output for Csound c.CompileOrc(orc); // Compile Orchestra from String c.ReadScore("i1 0 1"); // Read in Score from String c.Start(); // When compiling from strings, this call needed before performing // Create a new CsoundPerformanceThread, passing in the Csound object var t = new Csound6PerformanceThread(c); t.Play(); // starts the thread, which is now running separately from the main thread. This // call is asynchronous and will immediately return back here to continue code // execution. t.Join(); // Join will wait for the other thread to complete. If we did not call Join(), // after t.Play() returns we would immediate move to the next line, c.Stop(). // That would stop Csound without really giving it time to run. c.Stop(); // stops Csound c.Cleanup(); // clean up Csound; this is useful if you're going to reuse a Csound instance } }
/** * Example 4 - Using Csound's Performance Thread * Example 4.1 - Using Csound in a C# async/await Task for threaded execution * * In this example, we use a CsoundPerformanceThread to run Csound in * a native thread. Using a native thread is important to get the best * runtime performance for the audio engine. * CsoundPerformanceThread has some convenient methods for handling events, * but does not have features for doing regular processing at block boundaries. * In general, use CsoundPerformanceThread when the only kinds of communication you * are doing with Csound are through events, and not using channels. * * Since VS2012, C# programmers have become comfortable with the async/await Task-based * paradigm for running background processes. * Example 4.1 shows an alternative to running csound in a separate thread (really Task) * to achieve the same result as example 4. * This approach is very useful in a GUI where a cancel event and a progress dialog * would be desireable. * This example bypasses these features; later examples will use them. */ public void Example4() { using (var c = new Csound6NetRealtime()) { c.SetOutputDac(0); // Set realtime output for Csound c.CompileOrc(orc); // Compile Orchestra from String c.ReadScore("i1 0 1"); // Read in Score from String c.Start(); // When compiling from strings, this call needed before performing // Create a new CsoundPerformanceThread, passing in the Csound object var t = new Csound6PerformanceThread(c); t.Play(); // starts the thread, which is now running separately from the main thread. This // call is asynchronous and will immediately return back here to continue code // execution. t.Join(); // Join will wait for the other thread to complete. If we did not call Join(), // after t.Play() returns we would immediate move to the next line, c.Stop(). // That would stop Csound without really giving it time to run. c.Stop(); // stops Csound c.Cleanup();// clean up Csound; this is useful if you're going to reuse a Csound instance } }
public void TestChannelDirectAccess() { using (var cs = new Csound6NetRealtime()) { var result = cs.Compile(new string[] { "csdFiles\\SimpleRuntime.csd" }); Assert.AreEqual(CsoundStatus.Success, result); if (result == CsoundStatus.Success) { var bus = cs.GetSoftwareBus(); var chan2 = bus.GetChannel("chan2") as Csound6ControlChannel; chan2.SetValueDirect(chan2.Default); double val = chan2.GetValueDirect(); Assert.AreEqual(chan2.Default, val); while (!cs.PerformKsmps()) { Assert.AreEqual(val, chan2.GetValueDirect()); chan2.SetValueDirect(++val); } } } }
/// <summary> /// Creates a threadable userdata class using the provided csound instance /// </summary> /// <param name="_csound"></param> public UserData(Csound6NetRealtime _csound) { Csound = _csound; Done = false; }
public void TestChannelDefinition() { m_messageText = new StringBuilder(); m_count = 0; using (var cs = new Csound6NetRealtime()) { cs.MessageCallback += TestMessageEvent; FileInfo csf = new FileInfo("csdFiles\\SimpleRuntime.csd"); CsoundStatus result = cs.CompileArgs(new string[] { csf.FullName }); Assert.AreEqual(CsoundStatus.Success, result); result = cs.Start(); Assert.AreEqual(CsoundStatus.Success, result); var cch = new Csound6ControlChannel("chan1", ChannelDirection.Input, cs); Assert.AreEqual(ChannelDirection.Input, cch.Direction); Assert.AreEqual(ChannelBehavior.Exponential, cch.Behavior); Assert.AreEqual(ChannelType.Control, cch.Type); Assert.AreEqual(1000.0, cch.Default); Assert.AreEqual(500.0, cch.Minimum); Assert.AreEqual(2000.0, cch.Maximum); cch.Behavior = ChannelBehavior.Integer; cch.Maximum = 2500.0; cch.Minimum = 400.0; var cch1 = new Csound6ControlChannel("chan1", ChannelDirection.Input, cs); Assert.AreEqual(cch.Name, cch1.Name); Assert.AreEqual(cch.Minimum, cch1.Minimum); Assert.AreEqual(400.0, cch1.Minimum); Assert.AreEqual(2500.0, cch.Maximum); Assert.AreEqual(cch.Maximum, cch1.Maximum); Assert.AreEqual(ChannelBehavior.Integer, cch1.Behavior); var bus = new Csound6SoftwareBus(cs); IDictionary <string, ChannelInfo> chans = cs.GetChannelList(); Assert.IsNotNull(chans); Assert.IsTrue(chans.Count > 0); foreach (string key in chans.Keys)//now in test for software bus. remove this part? { ChannelInfo info = chans[key]; var chan = bus.AddChannel(info); switch (chan.Type) { case ChannelType.String: Assert.IsInstanceOfType(chan, typeof(Csound6StringChannel)); Assert.AreEqual(256, chan.DataSize); break; case ChannelType.Audio: Assert.IsInstanceOfType(chan, typeof(Csound6AudioChannel)); Assert.AreEqual(35280, chan.DataSize); //ksmps = 4410 * sizeof(MYFLT) break; case ChannelType.Control: Assert.IsInstanceOfType(chan, typeof(Csound6ControlChannel)); Assert.AreEqual(8, chan.DataSize); if (chan.Name.Equals(cch1.Name)) { Assert.AreEqual(cch.Maximum, ((Csound6ControlChannel)chan).Maximum); Assert.AreEqual(cch.Minimum, ((Csound6ControlChannel)chan).Minimum); Assert.AreEqual(cch.Default, ((Csound6ControlChannel)chan).Default); } break; case ChannelType.Pvs: case ChannelType.Var: default: Assert.IsFalse(false, string.Format("Unsupported Channel type:{0}", chan.GetType())); break; } //end switch } //end foreach key } //end using csound string text = m_messageText.ToString(); //if need to analyze output... }
public void TestPerfTimeChannels() { m_messageText = new StringBuilder(); m_count = 0; m_outval = -1; using (var cs = new Csound6NetRealtime()) { var result = cs.Compile(new string[] { "csdFiles\\SimpleRuntime.csd" }); Assert.AreEqual(CsoundStatus.Success, result); if (result == CsoundStatus.Success) { var bus = cs.GetSoftwareBus(); while (!cs.PerformKsmps()) { double[] samps = bus["achan1"] as double[]; double[] sampInv = new double[samps.Length]; if (cs.ScoreTime <= 0.1) { foreach (double samp in samps) { Assert.IsTrue(samp == 0.0); } bool hasPvs = bus.HasChannel("0"); if (hasPvs) { object o = bus["0"]; } } else if (cs.ScoreTime == 0.2) { double prev = -1.0; for (int i = 0; i < 26; i++) { Assert.IsTrue(samps[i] > prev); prev = samps[i]; } for (int i = 26; i < 75; i++) { Assert.IsTrue(prev > samps[i]); prev = samps[i]; } for (int i = 0; i < sampInv.Length; i++) { sampInv[i] = -samps[i]; } bus["achan2"] = sampInv; } else if (cs.ScoreTime == 0.3) { double[] samp2 = bus["achan2"] as double[]; double[] samp3 = bus["achan3"] as double[]; //instrument will have put samp2 into achan3 during 0.2 second; now available in 0.3 sec for (int i = 0; i < samp3.Length; i++) { Assert.AreEqual(samp2[i], samp3[i]); } } } } cs.Cleanup(); } }