java and csoundapi question
Date | 2015-06-23 00:55 |
From | peiman khosravi |
Subject | java and csoundapi question |
Attachments | None None |
Can someone provide a very simple example of how audio signals might be passed on form csound to java? Many Thanks Peiman
|
Date | 2015-06-23 02:09 |
From | Hlöðver Sigurðsson |
Subject | Re: java and csoundapi question |
Attachments | None None |
2015-06-22 23:55 GMT+00:00 peiman khosravi <peimankhosravi@gmail.com>:
|
Date | 2015-06-23 08:55 |
From | peiman khosravi |
Subject | Re: java and csoundapi question |
Attachments | None None |
Yes I have and that's how I'm learning about it. But as far as I can see there examples only deal with messages and data but no actual audio signal is passed between the programmes. I can see that Steven calls... csnd6.csoundInitialize(csnd6.CSOUNDINIT_NO_ATEXIT | csnd6.CSOUNDINIT_NO_SIGNAL_HANDLER); ...which I'm guessing disables the signal processing stuff within java? Thanks Peiman On 23 June 2015 at 02:09, Hlöðver Sigurðsson <hlolli@gmail.com> wrote:
|
Date | 2015-06-23 11:27 |
From | Rory Walsh |
Subject | Re: java and csoundapi question |
Attachments | None None |
I've never done with this Java. In C one can use GetChannelPtr() with CSOUND_AUDIO_CHANNEL. Perhaps somthing like this would work? CsoundMYFLTArray audioData = new CsoundMYFLTArray(1); ccsd.GetChannelPtr(audioData.GetPtr(), "audio", controlChannelType.CSOUND_AUDIO_CHANNEL.swigValue() | controlChannelType.CSOUND_INPUT_CHANNEL.swigValue()); I've never used the CsoundMYFLTArray class so I've no idea if can be used for audio signals too. Why not I suppose. On 23 June 2015 at 08:55, peiman khosravi <peimankhosravi@gmail.com> wrote:
|
Date | 2015-06-23 13:34 |
From | peiman khosravi |
Subject | Re: java and csoundapi question |
Attachments | None None |
Thanks Rory, I'm getting closer in that the code seems to compile without error but still no sound. I have a couple of basic questions: 1- can I simply call the Perform() method or do I need to use GetKsmps() for this? 2- if using GetKsmps(), how do I format the sample values into arrays of N float. The second question is relevant because I'm trying to pass the signal on to MaxMSP. MSP expects a vector sized array of floats, whereas in the code snippet below csound is constructing an array of ksmps size doubles. Or [very possibly] have I missed something?? Many Thanks Peiman public void event(String sco) { SWIGTYPE_p_p_double pdata1 = data1.GetPtr(); SWIGTYPE_p_p_double pdata2 = data2.GetPtr(); c.GetChannelPtr(pdata1, "ach1", controlChannelType.CSOUND_AUDIO_CHANNEL.swigValue() | controlChannelType.CSOUND_INPUT_CHANNEL.swigValue()); c.GetChannelPtr(pdata2, "ach2", controlChannelType.CSOUND_AUDIO_CHANNEL.swigValue() | controlChannelType.CSOUND_INPUT_CHANNEL.swigValue()); while (c.PerformKsmps() == 0) { for (int i = 0; i < ksmps; i++) { double d1 = data1.GetValue(i); double d2 = data2.GetValue(i); output[i] = d1+d2; } } c.ReadScore(sco); } On 23 June 2015 at 11:27, Rory Walsh <rorywalsh@ear.ie> wrote:
|
Date | 2015-06-23 13:59 |
From | Francois PINOT |
Subject | Re: java and csoundapi question |
Attachments | None None |
Hello Peiman, the CSOUNDINIT_NO_ATEXIT constant is used to tell csound to not set an atexit() callback funtion. Similarly, the CSOUNDINIT_NO_SIGNAL_HANDLER constant tells csound to not set signal handlers. Here signal means unix signal, used for inter-process communication: nothing to do with signal processing.The Csound API offers different functions to yield audio signals: csoundGetSpin, csoundAddSpinSample, csoundGetSpout give access to the audio working buffers (ksmps frames in each buffer, to use before of after calling csoundPerformKsmps). csoundGetInputBuffer, csoundGetInputBufferSize, csoundGetOutputBuffer, csoundGetOutputBufferSize give acces to the audio input or output buffers whose size is fixed by the command flag -b, to use before of after calling csoundPerformBuffer). csoundGetChannelPtr, csoundGetAudioChannel and csoundSetAudioChannel deal with software buses that you can use with the chnget/chnset opcodes. To see how this is wrapped in csnd6.jar, you can look at the cs_glue files in the sources (csound/interfaces). You can also decompress the csnd6.jar file in a directory and then disassemble the different classes with the javap utility. or even better, use a java decompiler. Best regards Francois 2015-06-23 9:55 GMT+02:00 peiman khosravi <peimankhosravi@gmail.com>:
|
Date | 2015-06-23 14:30 |
From | peiman khosravi |
Subject | Re: java and csoundapi question |
Attachments | None None |
Thanks very much Francois. This is really great information. I'm going to learn about decompressing right away. In the mean time, I'm looked into the different methods that you've mentioned. That all makes sense with one exception: What is the data type 'SWIGTYPE_p_double' that a method like csoundGetOutputBuffer appears to be returning, and how does one go about converting this to a float array? Apologies if I'm making stupid assumptions in my question. Many Thanks Peiman On 23 June 2015 at 13:59, Francois PINOT <fggpinot@gmail.com> wrote:
|
Date | 2015-06-23 15:04 |
From | peiman khosravi |
Subject | Re: java and csoundapi question |
Attachments | None None |
To give you a better idea of where I am with this. Below is my code. As you can see in the last part of the code, I've no idea what to do with 'c.GetOutputBuffer();', where I really want it to output a float arrays for each buffer frame. Many Thanks Peiman import com.cycling74.max.*; import com.cycling74.msp.*; import csnd6.*; public class csound extends MSPPerformer { Csound c = new Csound(); String filename = null; int ksmps = c.GetKsmps(); float output[] = new float[ksmps]; public csound(Atom[] csd) { csnd6.csoundInitialize( csnd6.CSOUNDINIT_NO_ATEXIT | csnd6.CSOUNDINIT_NO_SIGNAL_HANDLER); declareInlets(new int[]{SIGNAL}); declareOutlets(new int[]{SIGNAL}); filename = csd[0].toString(); Thread t = new Thread(){ public void run() { c.SetOption("-odac"); c.SetOption("-b 512" ); c.Compile(filename); c.PerformBuffer(); c.Stop(); c.Cleanup(); } }; t.start(); } public void event(String sco) { c.ReadScore(sco); } public void perform(MSPSignal[] ins, MSPSignal[] outs){ c.GetOutputBuffer(); } } On 23 June 2015 at 14:30, peiman khosravi <peimankhosravi@gmail.com> wrote:
|
Date | 2015-06-23 15:54 |
From | Francois PINOT |
Subject | Re: java and csoundapi question |
Attachments | None None |
csnd6.SWIGTYPE_p_double is a class generated by SWIG (the tool which generates the java wrapper to the Csound API). This class encapsulates a C pointer to the double type. I'm not using Java myself but I think a typical sequence would be: Csound csound; csound = new Csound(); CsoundMYFLTArray myBuffer;myBuffer = new CsoundMYFLTBuffer(); myBuffer.SetPtr(csound.CsoundGetOutputBuffer());double val; int myBufferSize = CsoundGetOutputBufferSize(); for (i = 0; i < myBufferSize; i++) { val = myBuffer.GetValue(i); ... } Beware, it seems that the Java wrapper is intended for Csound built with double. Francois 2015-06-23 15:30 GMT+02:00 peiman khosravi <peimankhosravi@gmail.com>:
|
Date | 2015-06-23 16:25 |
From | peiman khosravi |
Subject | Re: java and csoundapi question |
Attachments | None None |
Thanks very much. I feel I'm getting closer, still no sound! import com.cycling74.max.*; import com.cycling74.msp.*; import csnd6.*; public class csound extends MSPPerformer { Csound c = new Csound(); String filename = null; public csound(Atom[] csd) { csnd6.csoundInitialize( csnd6.CSOUNDINIT_NO_ATEXIT | csnd6.CSOUNDINIT_NO_SIGNAL_HANDLER); declareInlets(new int[]{SIGNAL}); declareOutlets(new int[]{SIGNAL}); filename = csd[0].toString(); Thread t = new Thread(){ public void run() { c.SetOption("-odac"); c.SetOption("-b 512" ); c.Compile(filename); c.PerformBuffer(); c.Stop(); c.Cleanup(); } }; t.start(); } public void event(String sco) { c.ReadScore(sco); } public void perform(MSPSignal[] ins, MSPSignal[] outs){ float[] in = ins[0].vec; float[] out = outs[0].vec; CsoundMYFLTArray myBuffer = new CsoundMYFLTArray(); myBuffer.SetPtr(c.GetOutputBuffer()); int myBufferSize = c.GetOutputBufferSize(); double val; int i; for (i = 0; i < myBufferSize; i++) { val = myBuffer.GetValue(i); float floatVal = (float) val; out[i] = floatVal; } } } On 23 June 2015 at 15:54, Francois PINOT <fggpinot@gmail.com> wrote:
|
Date | 2015-06-23 16:54 |
From | Francois PINOT |
Subject | Re: java and csoundapi question |
Attachments | None None |
the PerformBuffer method will yield (-b) samples (one single buffer). It should be used in a loop: while (c.PerformBuffer() == 0) {for (i = 0; i < myBufferSize; i++) { val = myBuffer.GetValue(i); float floatVal = (float) val; out[i] = floatVal; } } This loop should be placed in your execution thread. Remember that if your csound output is stereo, the samples will be interlaced in the buffer: L R L R etc. 2015-06-23 17:25 GMT+02:00 peiman khosravi <peimankhosravi@gmail.com>:
|
Date | 2015-06-23 17:22 |
From | peiman khosravi |
Subject | Re: java and csoundapi question |
Attachments | None None |
Thanks, that makes sense. I've added this. Java compiles fine but now the audio signal in maxmsp freezes and I get this error in the console: Max[14058]: ad_spin: looks like audio callbacks have stopped Perhaps reading from buffer is not the best way to get samples out of csound... On 23 June 2015 at 16:54, Francois PINOT <fggpinot@gmail.com> wrote:
|
Date | 2015-06-23 17:35 |
From | peiman khosravi |
Subject | Re: java and csoundapi question |
Attachments | None None |
OK I move the performance loop and it's not not crashing but weirdly I'm getting audio coming directly out of Csound (not through java/maxmsp), even though I'm not calling csoundPerform(). import com.cycling74.max.*; import com.cycling74.msp.*; import csnd6.*; public class csound extends MSPPerformer { Csound c = new Csound(); String filename = null; float[] globalOut = new float[512]; public csound(Atom[] csd) { csnd6.csoundInitialize( csnd6.CSOUNDINIT_NO_ATEXIT | csnd6.CSOUNDINIT_NO_SIGNAL_HANDLER); declareInlets(new int[]{SIGNAL}); declareOutlets(new int[]{SIGNAL}); filename = csd[0].toString(); Thread t = new Thread(){ public void run() { c.SetOption("-odac"); c.SetOption("-b 512" ); c.Compile(filename); CsoundMYFLTArray myBuffer = new CsoundMYFLTArray(); myBuffer.SetPtr(c.GetOutputBuffer()); int myBufferSize = c.GetOutputBufferSize(); while (c.PerformBuffer() == 0) { double val; int i; for (i = 0; i < myBufferSize; i++) { val = myBuffer.GetValue(i); float floatVal = (float) val; globalOut[i] = floatVal; } } c.Stop(); c.Cleanup(); } }; t.start(); } public void event(String sco) { c.ReadScore(sco); } public void perform(MSPSignal[] ins, MSPSignal[] outs) { int i; float[] in = ins[0].vec; float[] out = outs[0].vec; for(i = 0; i < in.length;i++) { /*do something*/ out[i] = globalOut[i]; } } } On 23 June 2015 at 17:22, peiman khosravi <peimankhosravi@gmail.com> wrote:
|
Date | 2015-06-23 19:47 |
From | Francois PINOT |
Subject | Re: java and csoundapi question |
Attachments | None None |
I think there's a problem using globalOut inside the Thread t and outside this Thread without any protection and sync mechanism (a mutex ?). Maybe you should not use a Thread. I mean have an init method to start csound and then have the perfomBuffer loop or the performKsmps loop in your perform method. Generally speaking, if you need threading you should prefer to use the csound threading system, through the CsoundPerformanceThread class for example.2015-06-23 18:35 GMT+02:00 peiman khosravi <peimankhosravi@gmail.com>:
|
Date | 2015-06-23 20:22 |
From | Michael Gogins |
Subject | Re: java and csoundapi question |
Attachments | None None |
I have taken both approaches in my projects: loop over performKsmps and handle other things before or after the performKsmps code, or run performKsmps inside a separate thread, using either the Csound performance thread class, or my own thread routines. Both approaches can work fine. They have pros and cons. If you don't have a lot of stuff that the host application needs to do, don't run a separate thread. If the host application is also doing a lot of processing or has time-critical stuff like many GUI event callbacks, you will need a separate thread. If you do have a separate thread, you will need to create a Csound message callback that enqueues messages in a thread-safe FIFO, and then in your host thread, dequeue these messages and display them. The Csound performance thread class already encapsulates this behavior. But it's not hard to reproduce this behavior with less code by using boost::lockfree::queue, see the csound/frontends/nwjs/jscsound.cpp class for an example. Regards, Mike ----------------------------------------------------- Michael GoginsIrreducible Productions http://michaelgogins.tumblr.com Michael dot Gogins at gmail dot com On Tue, Jun 23, 2015 at 2:47 PM, Francois PINOT <fggpinot@gmail.com> wrote:
|
Date | 2015-06-23 21:25 |
From | peiman khosravi |
Subject | Re: java and csoundapi question |
Attachments | None None |
Thanks both. So to check this in the simplest possible form (below) I've got rid of the threading part. Still, max audio seems to freeze after turning DSP on. I think there is something fishy going on with the final writing of the array into the msp float array. P import com.cycling74.max.*; import com.cycling74.msp.*; import csnd6.*; public class csound extends MSPPerformer { Csound c = new Csound(); String filename = null; public csound(Atom[] csd) { csnd6.csoundInitialize( csnd6.CSOUNDINIT_NO_ATEXIT | csnd6.CSOUNDINIT_NO_SIGNAL_HANDLER); declareInlets(new int[]{SIGNAL}); declareOutlets(new int[]{SIGNAL}); filename = csd[0].toString(); c.SetOption("-odac"); c.SetOption("-b 512" ); c.Compile(filename); c.Stop(); c.Cleanup(); } public void event(String sco) { c.ReadScore(sco); } public void perform(MSPSignal[] ins, MSPSignal[] outs){ float[] in = ins[0].vec; float[] out = outs[0].vec; CsoundMYFLTArray myBuffer = new CsoundMYFLTArray(); myBuffer.SetPtr(c.GetOutputBuffer()); int myBufferSize = c.GetOutputBufferSize(); double val; int i; while (c.PerformBuffer() == 0) { for (i = 0; i < myBufferSize; i++) { val = myBuffer.GetValue(i); float floatVal = (float) val; out[i] = floatVal; } } } } On 23 June 2015 at 20:22, Michael Gogins <michael.gogins@gmail.com> wrote:
|
Date | 2015-06-23 21:43 |
From | Victor Lazzarini |
Subject | Re: java and csoundapi question |
Attachments | None None |
What is the size of the out array? Are you assuming it is the same size as the Csound buffer? Where does it say that? Victor Lazzarini Dean of Arts, Celtic Studies, and Philosophy Maynooth University Ireland
|
Date | 2015-06-23 21:49 |
From | peiman khosravi |
Subject | Re: java and csoundapi question |
Attachments | None None |
Hi Victor, I've set vector size in max's DSP settings to 512 samples and I'm setting the csound -b flag to the same, so hopefully they should be the same. I was thinking that once I've got it working I'll make a generic method for automatically synching these up. But... On further reflection I have a feeling that this is a timing issue. According to the msp java manual,
MSP is repeatedly calling the perform() method for each sample vector
package (in my case 512 samples). I suppose this means that putting the CsoundPerformBuffer loop inside this
method is potentially going to cause timing problems. I need to figure
out a way of syncing msp timing with csound. Mhh this may well be over
my head but I'll keep banging my head against that wall! P On 23 June 2015 at 21:43, Victor Lazzarini <Victor.Lazzarini@nuim.ie> wrote:
|
Date | 2015-06-23 22:28 |
From | Victor Lazzarini |
Subject | Re: java and csoundapi question |
Attachments | None None |
If that is the case, you don't put performBuffer in the loop, but outside it, then just use the loop to fill it. Also check that the size of the Csound buffer is reported in frames, not samples (can't remember or check right now). If you look in the csound tilde source code, you will have a better idea how this is done, and the case is very similar. Also, I would say you should use performKsmps() and spout/spin, because then you can run Csound more tightly, closer to a realistic blocksize for Max Victor Lazzarini Dean of Arts, Celtic Studies, and Philosophy Maynooth University Ireland
|
Date | 2015-06-23 23:22 |
From | Michael Gogins |
Subject | Re: java and csoundapi question |
Attachments | None None |
The thread runs the csound performance loop, that's what it is for. Specify no audio output and you can still get the audio from the csound buffers. Regards, On Jun 23, 2015 12:37 PM, "peiman khosravi" <peimankhosravi@gmail.com> wrote:
|
Date | 2015-06-23 23:43 |
From | peiman khosravi |
Subject | Re: java and csoundapi question |
Thanks so much. These are really useful tips. I'm going to have another crack at this tomorrow. All the best, Peiman www.peimankhosravi.co.uk || RSS Feed || Concert News On 23 June 2015 at 23:22, Michael Gogins |
Date | 2015-06-24 21:49 |
From | peiman khosravi |
Subject | Re: java and csoundapi question |
I'm getting there. I'm finally getting a signal coming into max. It sounds quite ring modulated though (buffering issue). Still messing around with it. Will pot more info soon. Thanks Peiman www.peimankhosravi.co.uk || RSS Feed || Concert News On 23 June 2015 at 23:43, peiman khosravi |
Date | 2015-06-24 22:23 |
From | peiman khosravi |
Subject | Re: java and csoundapi question |
Why is it that just running the code below returns sound directly from Csound itself? I'd like to bypass that and pass the signal to MSP, which is sort of working now but I get a double signal. public void run() { c.SetOption("-odac"); c.SetOption("-b 512" ); c.Compile(filename); post("csoundcompiled"); CsoundMYFLTArray myBuffer = new CsoundMYFLTArray(); myBuffer.SetPtr(c.GetOutputBuffer()); int myBufferSize = c.GetOutputBufferSize(); double val; float floatval; int i; while (c.PerformBuffer() == 0) { for (i = 0; i < myBufferSize; i++) { val = myBuffer.GetValue(i); floatval = (float) val; csoundOutput[i] = floatval; } } } www.peimankhosravi.co.uk || RSS Feed || Concert News On 24 June 2015 at 21:49, peiman khosravi |
Date | 2015-06-24 22:30 |
From | Victor Lazzarini |
Subject | Re: java and csoundapi question |
Because csound is loading and using the audio output module. Just running performksmps() will do it. Check the API docs for the function to turn it off. You can also use -n to shut it up. But then you will need to get audio from the spout buffer. Victor Lazzarini Dean of Arts, Celtic Studies, and Philosophy Maynooth University Ireland > On 24 Jun 2015, at 22:23, peiman khosravi |
Date | 2015-06-24 22:32 |
From | peiman khosravi |
Subject | Re: java and csoundapi question |
OK I got it. I had to call csoundSetHostImplementedAudioIO. Getting there! www.peimankhosravi.co.uk || RSS Feed || Concert News On 24 June 2015 at 22:23, peiman khosravi |
Date | 2015-06-24 22:35 |
From | peiman khosravi |
Subject | Re: java and csoundapi question |
Thanks Victor. Yes I'm just about to look at performksmps() now. I think that's the way forward. I'm on to it now! Best, Peiman www.peimankhosravi.co.uk || RSS Feed || Concert News On 24 June 2015 at 22:30, Victor Lazzarini |
Date | 2015-06-24 23:22 |
From | peiman khosravi |
Subject | Re: java and csoundapi question |
I've found the relevant method in the csound~ sourcecode. Trying to make sense of it at the moment but I think I can figure it out if I stare at it for long enough! It's using [I think] PD's vector size and ksmps together to get the correct output. static t_int *csoundapi_perform(t_int *w) { t_csoundapi *x = (t_csoundapi *) w[1]; t_int size = x->vsize; t_int pos = x->pos; t_int posn = pos; t_float scal = csoundGet0dBFS(x->csound); t_int pksmps = x->pksmps; t_int numlets = x->numlets; t_int chans = x->chans, samps; t_sample *out[CS_MAX_CHANS], *in[CS_MAX_CHANS]; t_int i, n, end = x->end, run = x->run; MYFLT *csout, *csin; csout = csoundGetSpout(x->csound); csin = csoundGetSpin(x->csound); for (i = 0; i < numlets; i++) { in[i] = x->ins[i]; out[i] = x->outs[i]; } samps = pksmps * chans; for (i = 0; i < size; i++) { if (run && end == 0) { if (pos == samps) { if ((end = csoundPerformKsmps(x->csound)) != 0) outlet_bang(x->bangout); pos = 0; posn = 0; } for (n = 0; n < numlets; n++) { if (n < chans) csin[posn] = (MYFLT) in[n][i] * scal; posn++; } for (n = 0; n < numlets; n++) { out[n][i] = (t_float) (n < chans ? csout[pos] / scal : 0.0); pos++; } } else for (n = 0; n < numlets; n++) out[n][i] = 0.f; } x->end = end; x->pos = pos; return (t_int *) (w + 2); } www.peimankhosravi.co.uk || RSS Feed || Concert News On 24 June 2015 at 22:35, peiman khosravi |
Date | 2015-06-25 00:44 |
From | Rory Walsh |
Subject | Re: java and csoundapi question |
Attachments | None None |
You could try looking at the source for the csladspa and csoundapi~ frontends too. They all use similar processing methods. Sounds like you're getting close! On 24 Jun 2015 23:24, "peiman khosravi" <peimankhosravi@gmail.com> wrote:
I've found the relevant method in the csound~ sourcecode. Trying to |
Date | 2015-06-25 07:33 |
From | peiman khosravi |
Subject | Re: java and csoundapi question |
Yes sorry the code I quoted was from csoundapi~ not csound~. My mistake. I can't make sense of the csound~ code as there are so many files! www.peimankhosravi.co.uk || RSS Feed || Concert News On 25 June 2015 at 00:44, Rory Walsh |
Date | 2015-06-25 09:29 |
From | peiman khosravi |
Subject | Re: java and csoundapi question |
I think I have something that [should] work. Please see the java code below. It compiles fine but doesn't seem to make any noise at all. A couple of observations: 1- The MSP side seems to be working fine because if I replace o[i] = (float) csoundOutput[i]; (at the end of the code) with o[i] = (float) 0.5; I get a constant of 0.5 coming out of the MSP external. So it seems that Csound is not filling the csoundOutput array and I can't think why. 2- I need to run csound in a different thread. All java methods are executed in the same thread as max, one defines a separate java thread. If I run csound in the same thread as max then it will freeze max's GUI until the performance is over. My question is, is what I'm doing correct? It seems to work when I output the could directly out of csound but the array not filling correctly could have something to do with this?? I would really appreciate any 'pointers' (with or without pun!). Many Thanks Peiman import com.cycling74.max.*; import com.cycling74.msp.*; import csnd6.*; public class csound extends MSPPerformer { Csound c = new Csound(); String filename = null; double[] csoundOutput; int vec_size; double sampleValue; public csound(Atom[] csd) { filename = csd[0].toString(); declareInlets(new int[]{SIGNAL}); declareOutlets(new int[]{SIGNAL}); } public void dspsetup(MSPSignal[] in, MSPSignal[] out) { post("dspsetup was called."); vec_size = in[0].n; csoundOutput = new double[vec_size]; } public void compile() { Thread t = new Thread(){ public void run() { csnd6.csoundInitialize( csnd6.CSOUNDINIT_NO_ATEXIT | csnd6.CSOUNDINIT_NO_SIGNAL_HANDLER); //c.SetHostImplementedAudioIO(1, 512); c.SetOption("-odac"); c.SetOption("-b 512" ); c.Compile(filename); int ksmps = c.GetKsmps(); post("csound compiled"); post("ksmps is " + Integer.toString(ksmps)); CsoundMYFLTArray myBuffer = new CsoundMYFLTArray(); myBuffer.SetPtr(c.GetSpout()); int i; int j; while (c.PerformKsmps() == 0) { for(i = 0;i < 512; i++) { for(j = 0;j < 100; i++) { sampleValue = myBuffer.GetValue(j); } csoundOutput[i] = sampleValue; } } } }; t.start(); } public void stop(){ c.Stop(); c.Cleanup(); post("performance terminated"); } public void perform(MSPSignal[] in, MSPSignal[] out) { float[] o = out[0].vec; int i; for(i = 0;i < vec_size;i++) { o[i] = (float) csoundOutput[i]; } } } www.peimankhosravi.co.uk || RSS Feed || Concert News On 25 June 2015 at 07:33, peiman khosravi |
Date | 2015-06-25 09:30 |
From | peiman khosravi |
Subject | Re: java and csoundapi question |
typo: "All java methods are executed in the same thread as max, UNLESS one defines a separate java thread" www.peimankhosravi.co.uk || RSS Feed || Concert News On 25 June 2015 at 09:29, peiman khosravi |
Date | 2015-06-25 10:20 |
From | Jacques Leplat |
Subject | Re: java and csoundapi question |
Attachments | None None |
Hello, I’ve been comparing your code to a Java Swing based app I write/use from time to time. I think you are correct about threading, I run the performKsmps() in a separate thread loop, otherwise the UI freezes. I did notice you are not checking the compile return value. It returns 0 if compilation was OK, another number otherwise. Maybe try something like: int result = csound.Compile(arguments.argc(), arguments.argv()); if (result == 0) { // additional csound setup work… ... // all setup, perform the scd while (result == 0 && isPlaying) { synchronized (csound) { result = csound.PerformKsmps(); } Thread.yield(); } } else { // report compile error } I’m not sure why I have the trhead.yield() in there, I wrote the code a good few years back, it’s probable that there is a reason for the yield. If you are still stuck, I suggest running the code oustide of MSP, and see if you get sound. Once that works, try plugging it into msp As to CSound and Java, I can’t think of many API examples out there. I believe Blue is written in Java, It has a lot of code/files. but it is likely that it makes extensive use of CSound API’s. Worth a look, if you have the time. All the best, Jacques
|
Date | 2015-06-25 10:52 |
From | peiman khosravi |
Subject | Re: java and csoundapi question |
Thanks Jacques. That's reassuring! I'll into the yield method to see what's its function. Best, Peiman www.peimankhosravi.co.uk || RSS Feed || Concert News On 25 June 2015 at 10:20, Jacques Leplat |
Date | 2015-06-25 13:12 |
From | peiman khosravi |
Subject | Re: java and csoundapi question |
I've done many tests, and basically it all works (and csound makes a noise directly) when I comment out this loop: while (c.PerformKsmps() == 0) { for(i = 0;i < vec_size; i++) { for(j = 0;j < ksmps; i++) { sampleValue = myBuffer.GetValue(j); } csoundOutput[i] = 0.5; } } BUT I'm still unable to pass audio to msp. I think I might be misunderstanding something. Am I correct that in the lines below we're first declaring the myBuffer array and then filling it with the values of the pointer? So that myBuffer ends up being an array of ksmps samples? CsoundMYFLTArray myBuffer = new CsoundMYFLTArray(); myBuffer.SetPtr(c.GetSpout()); www.peimankhosravi.co.uk || RSS Feed || Concert News On 25 June 2015 at 10:52, peiman khosravi |
Date | 2015-06-25 16:29 |
From | Jacques Leplat |
Subject | Re: java and csoundapi question |
Attachments | None None |
Hello again, It is strange that you get sound with the loop commented out. The c.performKsmps() is what causes CSound to make noise. For example, in my loop I tried putting a Thread.sleep(250), and that means I only get a little splutter every few seconds. Without the Thread.sleep() it plays fine. Are you really commenting out the c.PerformKsmps()? while (result == 0 && isPlaying) { synchronized (csound) { result = csound.PerformKsmps(); } try { Thread.sleep(250); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } Thread.yield(); } The Thread.yield() is for my own use, all my calls to CSound are synchronised, because I’m not sure CSound is thread safe. Putting the yield() livens up the Swing UI a bit (I have been working on a VU Level meter using CSound channels). ALl the best, Jacques
|
Date | 2015-06-25 16:30 |
From | Francois PINOT |
Subject | Re: java and csoundapi question |
Attachments | None None |
When created, myBuffer is an java object which owns a pointer to nothing. myBuffer.SetPtr(c.GetSpout()); makes this pointer point to the output working buffer of Csound. I don't understand your inner loop (j index).2015-06-25 14:12 GMT+02:00 peiman khosravi <peimankhosravi@gmail.com>: I've done many tests, and basically it all works (and csound makes a |
Date | 2015-06-25 16:38 |
From | peiman khosravi |
Subject | Re: java and csoundapi question |
Thanks, ok that makes sense. I'll try and explain the logic for the inner loop but I'm probably really wrong! I need to read each individual sample held in myBuffer for each kontrol period. That's why I've got a loop reading ksmps number of indices. Then I need to write these to the msp vector which has (for instance) 512 samples (an array with 512 indices). But now that I think about it, neither of those loops do the job because I need to read myBuffer iteratively on each control period and I think I'm only reading the first frame now. Is that right?? Thanks P www.peimankhosravi.co.uk || RSS Feed || Concert News On 25 June 2015 at 16:30, Francois PINOT |
Date | 2015-06-25 16:48 |
From | Francois PINOT |
Subject | Re: java and csoundapi question |
Attachments | None None |
Right. spout contains ksmps frames (a frame contains one sample in mono, two samples in stereo, four samples in quadro, etc). So the inner loop should iterate ksmps times to read all the frames. 2015-06-25 17:38 GMT+02:00 peiman khosravi <peimankhosravi@gmail.com>: Thanks, ok that makes sense. |
Date | 2015-06-25 16:57 |
From | peiman khosravi |
Subject | Re: java and csoundapi question |
But once I've read through ksmps frames within spout then I need to reset the index number to zero and read through the frames again? And continue to do this iteratively in order to update the 'buffer'? www.peimankhosravi.co.uk || RSS Feed || Concert News On 25 June 2015 at 16:48, Francois PINOT |
Date | 2015-06-25 17:06 |
From | peiman khosravi |
Subject | Re: java and csoundapi question |
Sorry I should have been more accurate in my email. I get sound when I comment out everything in the middle: while (c.PerformKsmps() == 0) { // for(i = 0;i < vec_size; i++) { // for(j = 0;j < ksmps; i++) { // sampleValue = myBuffer.GetValue(j); // } // csoundOutput[i] = sampleValue; // } } In fact, I'm getting some kind of signal coming into msp too. But it isn't what it should be. It appears to be at a very low sample rate. So I must be doing something wrong with the buffering. Here's what I have. Note that the content of csoundOutput array is then read by msp on every vector period. It could be a syncing issue. I have no idea... //c.SetHostImplementedAudioIO(1, 512); c.SetOption("-odac"); c.SetOption("-b 512" ); int result = c.Compile(filename); int ksmps = c.GetKsmps(); post("csound compiled"); post("ksmps is " + Integer.toString(ksmps)); CsoundMYFLTArray myBuffer = new CsoundMYFLTArray(); myBuffer.SetPtr(c.GetSpout()); int i; int j; while (c.PerformKsmps() == 0) { for (i = 0; i < vec_size; i++) { if (i == vec_size) { i = 0; } for(j = 0;j < ksmps; j++) { sampleValue = myBuffer.GetValue(j); if (j == ksmps) { j = 0; } } csoundOutput[i] = sampleValue; } www.peimankhosravi.co.uk || RSS Feed || Concert News On 25 June 2015 at 16:29, Jacques Leplat |
Date | 2015-06-25 17:19 |
From | Francois PINOT |
Subject | Re: java and csoundapi question |
Attachments | None None |
What is vec_size? 2015-06-25 17:57 GMT+02:00 peiman khosravi <peimankhosravi@gmail.com>: But once I've read through ksmps frames within spout then I need to |
Date | 2015-06-25 17:24 |
From | peiman khosravi |
Subject | Re: java and csoundapi question |
It's the vector size of msp. currently 512 sampels. MSP outputs and inputs all audio signals in packages of N samples. In order to pass any signal to msp I need to write csound's frames into packages of N samples defined by vector size. Then msp, through its perform() method, iteratively reads the array and sends it's content 'out'. www.peimankhosravi.co.uk || RSS Feed || Concert News On 25 June 2015 at 17:19, Francois PINOT |
Date | 2015-06-25 17:53 |
From | jpff |
Subject | Re: java and csoundapi question |
I do not read Java but the loops look wrong to me. You loop on i and for a fixed i your read many j values. Looks like a strang form of down sampling Try replacing the ad from spout by j, and observe the output.... But as I said Java is beyond me. ==John ------------------------------------------------------------------------------ Monitor 25 network devices or servers for free with OpManager! OpManager is web-based network management software that monitors network devices and physical & virtual servers, alerts via email & sms for fault. Monitor 25 devices for free with no restriction. Download now http://ad.doubleclick.net/ddm/clk/292181274;119417398;o _______________________________________________ Csound-users mailing list Csound-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/csound-users Send bugs reports to https://github.com/csound/csound/issues Discussions of bugs and features can be posted here |
Date | 2015-06-25 18:01 |
From | peiman khosravi |
Subject | Re: java and csoundapi question |
Thanks John, yes you're right. What I was trying to do was to have two parallel loops, one indexing from 0 to 99 and the other 0-511. But by nesting the loops I've messed it all up. www.peimankhosravi.co.uk || RSS Feed || Concert News On 25 June 2015 at 17:53, jpff |
Date | 2015-06-25 18:37 |
From | Francois PINOT |
Subject | Re: java and csoundapi question |
Attachments | None None |
Maybe something like that? for(i = 0; i < vec_size; i++) {j =0; while (c.PerformKsmps() == 0) {
sampleValue = myBuffer.GetValue(j); csoundOutput[i] = sampleValue; j++; if (j >= c.GetKsmps()) { j = 0; break; // exiting the for loop to stay synchronized } } } 2015-06-25 18:24 GMT+02:00 peiman khosravi <peimankhosravi@gmail.com>: It's the vector size of msp. currently 512 sampels. |
Date | 2015-06-25 18:57 |
From | peiman khosravi |
Subject | Re: java and csoundapi question |
Thanks very much. This looks like it should work but I'm getting really weird signals coming out of msp... The thing is that I'm not sure GetSpout is giving me the right sample values and I can't figure out how to test this. www.peimankhosravi.co.uk || RSS Feed || Concert News On 25 June 2015 at 18:01, peiman khosravi |
Date | 2015-06-25 19:18 |
From | Francois PINOT |
Subject | Re: java and csoundapi question |
Attachments | None None |
Try to record the samples in a raw file and then open that file in Audacity. 2015-06-25 19:57 GMT+02:00 peiman khosravi <peimankhosravi@gmail.com>: Thanks very much. |
Date | 2015-06-25 19:27 |
From | peiman khosravi |
Subject | Re: java and csoundapi question |
Do you mean to record them in java? That's a good idea! www.peimankhosravi.co.uk || RSS Feed || Concert News On 25 June 2015 at 19:18, Francois PINOT |
Date | 2015-06-25 19:32 |
From | jpff |
Subject | Re: java and csoundapi question |
I would generate a very simple signal in csound, like 0 to 1 in 1 second. or in 1024 samples, and then either watch the signal in msp or dump it. One should recognise the correct value, or ven understand a false.erroneous one But I never got the Java APPI to work with aidio and we abandoned the project (twice!) On Thu, 25 Jun 2015, peiman khosravi wrote: > Thanks very much. > > This looks like it should work but I'm getting really weird signals > coming out of msp... The thing is that I'm not sure GetSpout is giving > me the right sample values and I can't figure out how to test this. > ------------------------------------------------------------------------------ Monitor 25 network devices or servers for free with OpManager! OpManager is web-based network management software that monitors network devices and physical & virtual servers, alerts via email & sms for fault. Monitor 25 devices for free with no restriction. Download now http://ad.doubleclick.net/ddm/clk/292181274;119417398;o _______________________________________________ Csound-users mailing list Csound-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/csound-users Send bugs reports to https://github.com/csound/csound/issues Discussions of bugs and features can be posted here |
Date | 2015-06-25 20:25 |
From | peiman khosravi |
Subject | Re: java and csoundapi question |
Thanks for the advice. I'll work on generating a test signal tomorrow! Cheers, Peiman www.peimankhosravi.co.uk || RSS Feed || Concert News On 25 June 2015 at 19:32, jpff |
Date | 2015-06-26 08:12 |
From | peiman khosravi |
Subject | Re: java and csoundapi question |
Attachments | None None |
I think I've found the culprit. I've bypassed the msp signal chain and 'poked' the spout frame values to a short circular buffer. I've also simplified my csd so that it's only outputting a 0-1 ramp in one second after which the performance should terminate. Looking at the way the buffer is being filled is pointing to the problem. Spout is outputting at least around 100 (ksmps N) frames per iteration but it doesn't look like that each frame is a single sample value that corresponds to the sequence in which samples are outputed by the out opcode. I'm assuming that I get strictly one sample per frame because I have set nchnls to 1. (See csd below.) Furthermore, when I print out the value of PerformKsmps() it looks like the performance isn't terminating after one second. It takes over a minute for the performance to terminate! I also think CPU is maxing out. But only when I try to access the data (not when I simply playback the csd in java). I'm sure the issue isn't threading because when I comment out the code in the 'while (c.PerformKsmps() == 0) {}' loop, csound outputs the right stuff. So either my loop is dodgy or I'm missing something about the format of Spout. Or there is something fishy going out with the format. Here's the relevant commented part of the code followed by my csd. public void run() { csnd6.csoundInitialize( csnd6.CSOUNDINIT_NO_ATEXIT | csnd6.CSOUNDINIT_NO_SIGNAL_HANDLER); //c.SetHostImplementedAudioIO(1, 512); c.SetOption("-odac"); c.SetOption("-b 512" ); int result = c.Compile(filename); int ksmps = c.GetKsmps(); post("csound compiled"); post("ksmps is " + Integer.toString(ksmps)); CsoundMYFLTArray myBuffer = new CsoundMYFLTArray(); myBuffer.SetPtr(c.GetSpout()); int i; int j; j = 0; while (c.PerformKsmps() == 0) { for(i = 0; i < 44100; i++) { //44100 is the sample rate, correspondig with 1 second of audio sampleValue = (float) myBuffer.GetValue(j); //csoundOutput[i] = sampleValue; MSPBuffer.poke(bufname, 0, i, sampleValue); //writes the result of each iteration to an index in the table (MSP buffer) j++; if (j == ksmps) { //when j reaches the last index reset it back to 0 and start over... j = 0; } } } //post(Integer.toString(c.PerformKsmps())); c.Cleanup(); c.Reset(); } <CsoundSynthesizer> <CsOptions> -d -odac </CsOptions> <CsInstruments> sr = 44100 ksmps = 100 nchnls = 1 0dbfs = 1.0 instr 1 asig line 0, p3, 1 out asig endin </CsInstruments> <CsScore> i1 0 1 </CsScore> </CsoundSynthesizer> On 25 June 2015 at 20:25, peiman khosravi <peimankhosravi@gmail.com> wrote: Thanks for the advice. I'll work on generating a test signal tomorrow! |
Date | 2015-06-26 08:19 |
From | peiman khosravi |
Subject | Re: java and csoundapi question |
Attachments | None None |
To sum up. The buffer is receiving the correct value but it's filling up very very slowly. On 26 June 2015 at 08:12, peiman khosravi <peimankhosravi@gmail.com> wrote:
|
Date | 2015-06-26 10:45 |
From | Rory Walsh |
Subject | Re: java and csoundapi question |
Attachments | None None |
Hi Peiman. I've only been able to follow this thread loosely as I'm currently away from the land of the living. Personally, I would stay away from threads and just use the perform method to call Csound. I've taken a look at the java documentation for writing externals in Max and here is what I think you should be doing. Note that I'm just rearranging and adding to parts of your code. I donät have access to a compiler so I canät check it. you'll also notice that I donät have access to a spell checker, so please excuse the state of the text!. c.PerformKsmps() is called inside the perform method after every ksmps samples has been output. Each time it is called it should fill your myBuffer with a new block of samples. You can then access those samples and write them to the out array. Doing it this way means the vector size in max and the ksmps size in Csound do not have to be the same.
public class csound extends MSPPerformer { Csound c = new Csound(); String filename = null; double[] csoundOutput; int vec_size; int csdIndex= csound->GetKsmps(); double sampleValue; CsoundMYFLTArray myBuffer; public csound(Atom[] csd) { filename = csd[0].toString(); declareInlets(new int[]{SIGNAL}); declareOutlets(new int[]{SIGNAL}); } public void dspsetup(MSPSignal[] in, MSPSignal[] out) { post("dspsetup was called."); vec_size = in[0].n; csoundOutput = new double[vec_size]; csnd6.csoundInitialize( csnd6.CSOUNDINIT_NO_ATEXIT | csnd6.CSOUNDINIT_NO_SIGNAL_HANDLER); c.SetOption("-n"); c.SetOption("-b 512" ); c.Compile(filename); int ksmps = c.GetKsmps(); post("csound compiled"); post("ksmps is " + Integer.toString(ksmps)); myBuffer = new CsoundMYFLTArray(); myBuffer.SetPtr(c.GetSpout()); } public void perform(MSPSignal[] ins, MSPSignal[] outs){ float[] in = ins[0].vec; float[] out = outs[0].vec; int vec_size = in[0].n; for(int i = 0; i < vec_size ;i++, csdindex++) { if(csndIndex == csound->GetKsmps()) { c.PerformKsmps(); csdIndex=0; } out[i] = myBuffer[csdIndex]; } } } |
Date | 2015-06-26 11:20 |
From | peiman khosravi |
Subject | Re: java and csoundapi question |
Attachments | None None |
Rory, I don't know what to say. Other than that you're a genius!! There were just a few typos and one omission in your code which I've amended, other than that it's working!!! Wow, this is really cool and it seems to work well!! I think we have a new way of max->csound communication. The nice this is that it is completely cross platform and doesn't require any building and it's only native max and Csound... The only thing is that I can't get rid of the direct audio output of csound any more, even with 'SetHostImplementedAudioIO()' I'll spend some time on it now. I also need to figure out a way of terminating the performance. Wow, really I don't know how to thank you enough! Cheers, Peiman On 26 June 2015 at 10:45, Rory Walsh <rorywalsh@ear.ie> wrote:
|
Date | 2015-06-26 11:21 |
From | peiman khosravi |
Subject | Re: java and csoundapi question |
Attachments | None None |
Here's your amended code Rory: import com.cycling74.max.*; import com.cycling74.msp.*; import csnd6.*; public class csound extends MSPPerformer { Csound c = new Csound(); String filename = null; double[] csoundOutput; int vec_size; int csdindex = c.GetKsmps(); float sampleValue; CsoundMYFLTArray myBuffer; public csound(Atom[] csd) { filename = csd[0].toString(); declareInlets(new int[]{SIGNAL}); declareOutlets(new int[]{SIGNAL}); } public void dspsetup(MSPSignal[] in, MSPSignal[] out) { post("dspsetup was called."); vec_size = in[0].n; csoundOutput = new double[vec_size]; csnd6.csoundInitialize( csnd6.CSOUNDINIT_NO_ATEXIT | csnd6.CSOUNDINIT_NO_SIGNAL_HANDLER); c.SetOption("-n"); c.SetOption("-b 512" ); c.Compile(filename); int ksmps = c.GetKsmps(); post("csound compiled"); post("ksmps is " + Integer.toString(ksmps)); myBuffer = new CsoundMYFLTArray(); myBuffer.SetPtr(c.GetSpout()); } public void perform(MSPSignal[] ins, MSPSignal[] outs){ float[] in = ins[0].vec; float[] out = outs[0].vec; int vec_size = ins[0].n; for(int i = 0; i < vec_size ;i++, csdindex++) { if(csdindex == c.GetKsmps()) { c.SetHostImplementedAudioIO(1, 512); c.PerformKsmps(); csdindex=0; } sampleValue = (float) myBuffer.GetValue(csdindex); out[i] = sampleValue; } } } On 26 June 2015 at 11:20, peiman khosravi <peimankhosravi@gmail.com> wrote:
|
Date | 2015-06-26 11:29 |
From | Rory Walsh |
Subject | Re: java and csoundapi question |
Attachments | None None |
Glad to help. Strange that you still here csound direct output. Try adding -+rtaudio=NULL or -n to your CsOptions in the csd file. On 26 Jun 2015 12:22, "peiman khosravi" <peimankhosravi@gmail.com> wrote:
|
Date | 2015-06-26 11:31 |
From | Rory Walsh |
Subject | Re: java and csoundapi question |
Attachments | None None |
Btw, that code is set up for mono. You'll need to take care of multi channel stuff. On 26 Jun 2015 12:29, "Rory Walsh" <rorywalsh@ear.ie> wrote:
|
Date | 2015-06-26 11:33 |
From | peiman khosravi |
Subject | Re: java and csoundapi question |
Attachments | None None |
I move the SetHostImplementedAudioIO line around a bit and now it works. I think it had tom come before Compile(). Amazing!! On 26 June 2015 at 11:29, Rory Walsh <rorywalsh@ear.ie> wrote:
|
Date | 2015-06-26 11:35 |
From | peiman khosravi |
Subject | Re: java and csoundapi question |
Attachments | None None |
Yes, I thought so. I'm going to get it working in mc, as well as adding bus access. No doubt you'll hear from me again! Thanks again. P On 26 June 2015 at 11:31, Rory Walsh <rorywalsh@ear.ie> wrote:
|
Date | 2015-06-27 07:56 |
From | peiman khosravi |
Subject | Re: java and csoundapi question |
Attachments | None None |
Hello, So I now attempting to add input to the object. I think i have it set up correctly: First these are declared: double inputSampleValue; CsoundMYFLTArray myInputBuffer; myInputBuffer = new CsoundMYFLTArray(); Then I'm calling SetValue in the perform method: inputSampleValue = (double) in[i]; myInputBuffer.SetValue(csdindex,inputSampleValue); But nothing happens (although there is no error). And of course I'm still getting output. Do I need to add any more options? Many Thanks Peiman On 26 June 2015 at 11:35, peiman khosravi <peimankhosravi@gmail.com> wrote:
|
Date | 2015-06-27 09:42 |
From | peiman khosravi |
Subject | Re: java and csoundapi question |
Attachments | None None |
Must have been a typo, it's now working!! Here's the code so far. mono Input/output and control busses. import com.cycling74.max.*; import com.cycling74.msp.*; import csnd6.*; public class csound extends MSPPerformer { String filename = null; double[] csoundOutput; int csdindex; int compiled; int vec_size; Csound c = new Csound(); float outputSampleValue; double inputSampleValue; CsoundMYFLTArray myOutputBuffer; CsoundMYFLTArray myInputBuffer; public csound(Atom[] csd) { declareInlets(new int[]{SIGNAL}); declareOutlets(new int[]{SIGNAL}); filename = csd[0].toString(); csnd6.csoundInitialize( csnd6.CSOUNDINIT_NO_ATEXIT | csnd6.CSOUNDINIT_NO_SIGNAL_HANDLER); c.SetHostImplementedAudioIO(1, 0); c.SetOption("-n"); c.Compile(filename); int ksmps = c.GetKsmps(); myOutputBuffer = new CsoundMYFLTArray(); myInputBuffer = new CsoundMYFLTArray(); myOutputBuffer.SetPtr(c.GetSpout()); myInputBuffer.SetPtr(c.GetSpin());; } public void dspsetup(MSPSignal[] ins, MSPSignal[] outs) { float[] output = outs[0].vec; vec_size = output.length; } public void event(String sco) { c.ReadScore(sco); } public void chn_k(Atom[] args) { Atom a; Atom b; String aa; float bb; a = args[0]; b = args[1]; aa = a.getString(); bb = b.getFloat(); CsoundMYFLTArray bus = new CsoundMYFLTArray(1); c.GetChannelPtr(bus.GetPtr(),aa, controlChannelType.CSOUND_CONTROL_CHANNEL.swigValue() | controlChannelType.CSOUND_INPUT_CHANNEL.swigValue()); bus.SetValue(0, bb); } public void perform(MSPSignal[] ins, MSPSignal[] outs){ float[] in = ins[0].vec; float[] out = outs[0].vec; for(int i = 0; i < vec_size ;i++, csdindex++) { if(csdindex == c.GetKsmps()) { c.PerformKsmps(); csdindex = 0; } if(compiled==0) { inputSampleValue = (double) in[i]; myInputBuffer.SetValue(csdindex,inputSampleValue); //write spin outputSampleValue = (float) myOutputBuffer.GetValue(csdindex); //read spout out[i] = (float) outputSampleValue; } else { out[i] = 0; } } } } On 27 June 2015 at 07:56, peiman khosravi <peimankhosravi@gmail.com> wrote:
|