func main() { ctx := sound.DefaultContext /* seq := sound.NewSequencer(ctx) f0 := 110.0 seq.Add(0, KarplusStrongSaw(ctx, f0*1.00, f0*1.00 * 16, 0.98)) seq.Add(time.Second*12/40, KarplusStrongSaw(ctx, f0*1.25, f0*1.25 * 16, 0.98)) seq.Add(time.Second*24/40, KarplusStrongSaw(ctx, f0*1.50, f0*1.50 * 16, 0.98)) seq.Add(time.Second*36/40, KarplusStrongSaw(ctx, f0*2.00, f0*2.00 * 16, 0.98)) seq.Add(time.Second*37/40, KarplusStrongSaw(ctx, f0*2.50, f0*2.50 * 16, 0.98)) seq.Add(time.Second*38/40, KarplusStrongSaw(ctx, f0*3.00, f0*3.00 * 16, 0.98)) seq.Add(time.Second*39/40, KarplusStrongSaw(ctx, f0*4.00, f0*4.00 * 16, 0.98)) stream := seq.Play() */ stream := KarplusStrongSaw(ctx, 100.0, 1000.0, 0.98) stream = filter.RC(ctx, stream, filter.LowPass, 300.0) stream = ctx.TakeDuration(stream, time.Second*3/2, false) stream = ctx.MulInf(stream, ctx.Const(0.1)) frontend.Main(ctx, stream) }
// input should be finite and preferably short (e.g. one cycle of a triangle wave) func KarplusStrong(ctx sound.Context, input chan float64, delaySamples uint, cutoff float64, decay float64) (output chan float64) { feedback := make(chan float64, ctx.StreamBufferSize) // Mix the input with the feedback. output = ctx.Add(input, feedback) // Fork off a copy of the output. output, outputCopy := ctx.Fork2(output) // The copy is first passed through a delay line... outputCopy = delay(ctx, outputCopy, delaySamples) // ...then filtered... //outputCopy = filter.Chebyshev(ctx, outputCopy, filter.LowPass, cutoff, 0.5, 2) outputCopy = filter.RC(ctx, outputCopy, filter.LowPass, cutoff) // ...and finally attenuated slightly. outputCopy = ctx.Mul(outputCopy, ctx.Const(decay)) // The filtered output copy is fed back into the system. go pipe(outputCopy, feedback) return output }