Sample and tabulate the values of every cable in patch for analysis

I am playing with the idea of analyzing VCV patches as networks as a fun data science exercise. It is not too difficult to recover the network structure from the JSON in the patch file, but I am unsure how to collect data on the actual information passing through the cables as the patch plays.

I want to repeatedly sample the instantaneous value of each cable in a patch every so often over some decent length of time and write the tabulated data to a file. I envision a large time series table as the output, with the time of each sample being one feature and the sampled values of all other cables (labeled with cable IDs) making up the rest of the features.

I can imagine that the sample correlation between certain pairs of cables will be quite high (imagine a VCO going into a subtle reverb or CV passing through an open attenuator) and that this could be informative / interesting when paired with the network analysis.

Of course, I expect this would slow the program down (depending on the sampling rate). I don’t need the audio to come through in real time as long as VCV renders everything accurately.

So, to those with more familiarity with C++, the VCV development environment, and real-time computing problems (I have very little experience with all of these), does this sound like a doable or reasonable project for a newbie? What are your thoughts on how I should approach this?

I don’t expect there to be a simple or easy answer to this question. Thanks for letting me think out loud!

Should be doable. The method you will want to call is

APP->scene->rack->getCompleteCables()

You can create a “logging” module that calls this inside its process method and then writes the desired information out to a file. The simplest would be to write it out to the standard log file VCV uses, by using the DEBUG command. This however will mix your output in with the regular VCV log, instead you probably want to write it out your own file, and you probably want to do it in a binary fashion, as it will perform faster. There are probably decent tutorials online on how to write binary data to a file in C++

There is two big problems you are going to run into, depending on what you use for your sampling rate.

If your sampling rate is close to the audio rate VCV is running at, it will be A lot of data. It will basically be a raw wave file PER cable. A single wave file is about 10 MB per minute at 44.1kHz with a 16 bit sample. Even if you cut that down to 8 bit samples, you are still at 5 MB per minute. If you are dealing with small patches, for a short period of time, then that is manageable, but even with 20 cables for 5 minutes, you are talking 0.5 to 1 GB.

If you sample things much less than the audio rate, you can easily quite distorted views of the underlying signals. If you are not familiar with the Nyquist-Shannon Sampling Theorem, do a little research into it. As a simple thought experiment. If you have at (261 HZ, apox C4) and you sample it 261 times a second, you will get the exact same value every time, which really doesn’t capture what is going on at the same time.

1 Like

Neat idea! A couple of other details to add to @Patheros 's very good explanation:

  • getCompleteCables is going to give you a vector of CableWidget; IIRC you’ll want to do getPort on those to get their input PortWidgets, then getPort again to get to a Port, which has various flavors of .getVoltage. (Cables just abstract the transmission of values from an output port to an input port; the ports themselves are where the values are manifested.) The VCV Rack 2 API Doxygen docs are your friend here, though the Rack source code is also commendably clear.
  • Especially if you’re interested in measuring correlation, remember that each cable in Rack adds a one-sample delay. Factoring this back out is non-trivial (in the general case) but will be an interesting problem!
1 Like

Wow. Thank you both for the in-depth guidance. I am glad that there seems to be a built in method. I need to get more familiar with the API before I can try and implement this.

  1. Yes. The dataset will be large. Good idea to write to a binary file.
  2. Yes. I wondered whether the sample rates I could achieve would still be underpowered for the correlation analysis. The Nyquist-Shannon Sampling Theorem is exactly the term I needed to investigate this issue. I wasn’t expecting to recover the full waveforms for audio cables, I just need a sample rate that will be able to differentiate dissimilar cables. Maybe this will turn out to be much more challenging than I thought. I was also thinking I could empirically test multiple sample rates on a toy patch of cables mixing pure waveforms with a series of independent noise sources.
  3. Yes. Good call on the 1-sample delay. I thought it would be easy enough to censor the first sample of the input port and the last sample of the output port (unless I am misunderstanding the delay). Also thank you for the Doxygen tip. These are exactly the docs I need to get started.
2 Likes