Fellow ChucKists, Yesterday I wanted to wish Dan a happy birthday on FaceBook, hoping for many more years of fun with strings and code but thought it'd be nicer to write this in ChucK. Then stuff happened and I was too late. Belated but no less sincere; emulating strings in LiSa... because we can, and because LiSa can (LiSa can actually do anything, she's just modest). We start out with a very literal implementation of Karplus-Strong at concert A4 tuning. Then we start mucking with various parameters in ways that are less traditionally Karplus-Strong for some more interesting tembral effects. Yours, Kas. /* Do copy, do share. No warranties, no refunds. Physical models can (and will!) blow up; please mind your speakers, neighbours and pets. Remixing and sharing results strongly encouraged (many parameters left....). Happy belated birthday to Dan! */ //the patch (noise or a saw plus a envelope could emulate a bow instead of a pluck) Impulse i => LiSa l => dac; //needs to be defined second => l.duration; //two voices for averaging 2 => l.maxVoices; //buffer duration = source of the pitch second / 440 => dur base_cycle; //create a looping delay //looping for both recording and playback is on by default base_cycle => l.loopEndRec; l.loopEnd (0, base_cycle); l.loopEnd (1, base_cycle); 1 => l.record; //offset the second voice by one sample //so we average between the current and the last sample value l.play (0, 1); l.playPos (1, -1 * samp); //"::" should work here but gives me a error? [BUG] l.play( 1, 1); //average between the two values. ratio sets the "filter's" effect. //make sure the two add up to unity (1.0). l.voiceGain (0, .5); l.voiceGain (1, .5); //feedback sets the tone's decay .995 => l.feedback; //off we go! 1 => i.next; 2::second => now; //tradition ends here. //fun starts l.loopEnd (1, base_cycle * .5); 1 => i.next; 2::second => now; l.loopEnd (1, base_cycle * 2); 1 => i.next; 2::second => now; l.loopEnd (1, base_cycle * .333333); 1 => i.next; 2::second => now; l.loopEnd (1, base_cycle * 1.5); 1 => i.next; 2::second => now; l.loopEndRec() * 2 => l.loopEndRec; l.loopEnd (1, base_cycle - samp); 1 => i.next; 4::second => now;