Hiya @CircadianSound! I’ve put together a demo for you that embeds a 44,100 Hz sample as code into a VCV Rack module!
Here’s the code:
#include "kick.hpp"
#define KICK_SAMPLE_LENGTH 22820
struct Circadian : Module
{
dsp::SchmittTrigger playback_trigger;
float left_audio = 0;
float right_audio = 0;
bool playback = false;
double playback_position = 0;
enum ParamIds {
PLAYBACK_BUTTON,
NUM_PARAMS
};
enum InputIds {
NUM_INPUTS
};
enum OutputIds {
AUDIO_OUTPUT_LEFT,
AUDIO_OUTPUT_RIGHT,
NUM_OUTPUTS
};
Circadian()
{
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
}
void process(const ProcessArgs &args) override
{
if(playback_trigger.process(params[PLAYBACK_BUTTON].getValue()))
{
// reset sample playback position
playback_position = 0;
// Set playback flag. The sample will playback while this is true
playback = true;
}
if(playback)
{
// 44100 is the sample rate of the recorded sample
float step_amount = 44100 / args.sampleRate;
// Step the playback position forward.
playback_position = playback_position + step_amount;
// convert float to integer
unsigned int sample_position = playback_position;
// If the playback position is past the playback length, end sample playback
if(sample_position >= KICK_SAMPLE_LENGTH)
{
playback_position = 0;
playback = false;
}
else
{
left_audio = kick_drum[sample_position][0];
right_audio = kick_drum[sample_position][1];
outputs[AUDIO_OUTPUT_LEFT].setVoltage(left_audio);
outputs[AUDIO_OUTPUT_RIGHT].setVoltage(right_audio);
}
}
}
};
struct CircadianWidget : ModuleWidget
{
CircadianWidget(Circadian* module)
{
setModule(module);
setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/looper_front_panel.svg")));
// Add output jacks
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(7.560, 35.0)), module, Circadian::AUDIO_OUTPUT_LEFT));
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(7.560, 40.0)), module, Circadian::AUDIO_OUTPUT_RIGHT));
// Add playback input
addParam(createParamCentered<LEDButton>(mm2px(Vec(7.560, 5)), module, Circadian::PLAYBACK_BUTTON));
}
};
You’ll notice that the only include is kick.hpp. It’s a bit long to paste here, but here’s a sample of what it contains…
float kick_drum[][2] = {
{ -0.000030,-0.000061 },
{ -0.000030,-0.000030 },
{ 0.000000,-0.000091 },
{ 0.000000,-0.000091 },
{ -0.000031,-0.000061 }, // etc...
Here’s how I generated the sample data. First, I used Wavosaur to export a kick drum as text.
This left me with a pretty awful file to work with that looked like:
-0.000030 -0.000061
-0.000030 -0.000030
0.000000 -0.000091
0.000000 -0.000091
-0.000031 -0.000061
I wrote a quick PHP program to get this closer to what I needed:
<?PHP
/*
For prepping samples for vcvrack embed
*/
$input_data = file_get_contents("circadian.txt");
$lines = explode("\r\n",$input_data);
$output_text = "{";
$pair_count = 0;
foreach($lines as $line)
{
$pair_count ++;
list($left_audio, $right_audio) = explode(" ", $line);
$output_text .= "{ $left_audio,$right_audio },";
}
$output_text .= "}";
file_put_contents("output.text", $output_text);
print("pair count: $pair_count");
?>
The resulting output is essentially what I used in kick.hpp, but I had to remove a trailing comma that I was too lazy to fix in the PHP code.
Here’s the code on GitHub:
Here’s a video of it in action. I borrowed a module’s front panel and didn’t spend any time on customizing it: