(
// Run once to convert and resample wavetable files
var paths, file, data, n, newData, outFile;

paths = PathName("/home/lcoogan/snd/wtables/AKWF").deepFiles.select { |f|
    f.extension == "wav"
};

Routine({
    paths.do { |path, i|
        var outputPath;

        // 'protect' ensures file cleanup on error
        protect {
            // Read original data
            file = SoundFile.openRead(path.fullPath);
            data = Signal.newClear(file.numFrames);
            file.readData(data);
            0.1.wait;

            // Resample to n = 4096 samples (power of 2)
            n = 4096;
            newData = data.resamp1(n).as(Signal).asWavetable;
            0.1.wait;

            // Generate output file path
            outputPath = path.fullPath ++ "_4096.wtable";

            // Write to disk
            outFile = SoundFile(outputPath)
                .headerFormat_("WAV")
                .sampleFormat_("float")
                .numChannels_(1)
                .sampleRate_(44100);

            if(outFile.openWrite.notNil) {
                outFile.writeData(newData);
                0.1.wait;
            } {
                "Couldn't write output file: %".format(outputPath).warn;
            };
        } {
            file.close;
            if(outFile.notNil) { outFile.close };
        };
    };
}).play;
)




//////////////////////////////////////////////////////////////////////////////////////////////////////////////

(
SynthDef(\wtable_vosc_dual_t_0, {| vel=1|
	var env, freq;
	var wtbufnumRange = [ ~wtbufnums.minItem, ~wtbufnums.maxItem  ];
	var sig;
	var fenv;
	var driveDB = \driveDB.kr(0);
	var direct = \direct.kr(0.5);
	// var trg = \trg.kr(1);
	// var trg = Dust.kr(2);
	var trg = Impulse.kr(1);


	env = EnvGen.ar(
		Env.adsr(
			TExpRand.kr(0.001, 0.1, trg),
			TExpRand.kr(0.001, 0.1, trg),
			TExpRand.kr(0.1, 0.6, trg),
			TExpRand.kr(1.5,4,trg),
			curve: TRand.kr(-5.0,4,trg)
		),
		gate:trg,
		doneAction:0
	).lag(0.1) * vel;


	env = XFade2.ar(env,LFDNoise3.ar(env * 20 + 1).range(0,1), env*2-1);

	// env = env * WhiteNoise.ar(MouseX.kr(0,1)!2).range(0,1.0);

	// fenv = env * LFNoise0.kr(TRand.kr(1,21, trg)).range(0.5,1.4).lag(TRand.kr(0.0001,0.1, trg));
	fenv = env * VOsc.ar(
		\fmodbufn.kr( rrand( wtbufnumRange[0],wtbufnumRange[1] ) ).lag(0.4),
		\fmodFreq.kr(11)
	).range(0.5,1.4)
	.lag(TRand.kr(0.0001,0.01, trg));


	freq = \freq.kr(111).lag(0.1);
	// freq = LFNoise0.kr(1).exprange(80,1000).lag(0.1);
	// freq = TExpRand.kr(80,1000,trg);

	sig = VOsc.ar(
		(
			VOsc.ar(\wtmodbufn.kr( rrand( wtbufnumRange[0],wtbufnumRange[1] ) ).lag(0.3), \wtmodfreq.kr(2), Rand(0,2pi), \wtmodamp.kr(1))
			+
			( env * [  Rand(0.5,1.5),  Rand(0.5,1.5) ])
			// ( env.pow(1.4) * [ LFNoise1.kr(3).range(1.5,9), LFNoise1.kr(3).range(1.5,9)] + 0.1)
			+
			\bufn.ar( rrand( wtbufnumRange[0],wtbufnumRange[1] ) )
		).lag(0.1).mod( wtbufnumRange[1] - wtbufnumRange[0] ) + wtbufnumRange[0],
		freq
	)  * env;

	sig = MoogVCF.ar(
		sig * driveDB.dbamp,
		XFade2.ar( env.pow(1.4), fenv.pow(1.4), \fmod.kr(0)) * \fltRange.kr(10000) + 50 ,
		\res.kr(0)
	);

	sig = sig * driveDB.neg.dbamp * 0.4; // compensate drive


	sig * direct;

	Out.ar(0, sig);

}).add;
)
