Karplus–Strong algoritm

Audio software developers forum.
Forum rules
If you require help using Audacity, please post on the forum board relevant to your operating system:
Windows
Mac OS X
GNU/Linux and Unix-like
Post Reply
btb4198
Posts: 16
Joined: Fri Sep 26, 2014 12:31 pm
Operating System: Please select

Karplus–Strong algoritm

Post by btb4198 » Wed Oct 29, 2014 3:35 am

http://en.wikipedia.org/wiki/Karplus%E2 ... _synthesis

ok I just want to make sure I understand how this works.
you have N with = fs/fo .
fs is sampling rate = 44100Hz
Fo is the note you want to play like 440hz

then you make an array of N sizes and full it up with random value between 0.5 and -0.5
then you outputs the array from 0 to N then after N you do this

output = the 1st value of Array and the second value of the Array / by 2 * 0.995

and you keep doing this until output is 0?
is that right ?

this is mt class :

Code: Select all

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NAudio.Wave;

namespace test
{
    class Guitar : WaveStream
    {
        public Guitar()
        {
            Frequency = 0;
            n2 = 0;
            n3 = 0;
            n4 = 0;
            rnd1 = new System.Random();
            t = 0;
            decay = 0.995;
        }
        public double Frequency { get; set; }
        public double Amplitude { get; set; }
        static int n2;
        static int n3;
        static int n4;
        public long Bufferlength { get; set; }
        private long position;
        float[] X;
        float[] temp;
        public override long Length { get { return Bufferlength; } }
        public override WaveFormat WaveFormat { get { return WaveFormat.CreateIeeeFloatWaveFormat(44100, 2); } }
        Random rnd1;
        static int t;
        double decay;

        public override long Position
        {
            get
            {
                // we'll just return the number of bytes read so far
                return position;
            }
            set
            {
                position = value;
            }
        }

        // buffer size is 52920 and so is sampleCount
        // oddset is 0
        public override int Read(byte[] buffer, int offset, int sampleCount)
        {
            // Bufferlength set to the min I want the sound to play for

            int N = (int)(44100D / Frequency); // size of buffer for the karplus-strong algorithm
            float sum;// temp holding place
            // below only happens once 
            // it make the karplus-strong algorithm buffer
            if (n2 == 0) // flag
            {
                X = new float[N];
                temp = new float[N + 1];
                for (int i = 0; i < N; i++)
                {
                    X[i] = (float)(0.1 * rnd1.Next(-5, 5)) + (float)(0.5 * Math.Sin(i * Frequency * Math.PI / 44100D));// random number from -0.5 - 0.5
                  //  X[i] = (float)(0.5 * Math.Sin(i * Frequency * Math.PI / 44100D));
                }
                n2 = 1; // flag  
            }
            // karplus-strong algorithm low pass filer
            for (int r = 0; r < sampleCount / 4; r++)
            {
                if (t == (N - 1))
                {
                    t = 0;
                    n4 = 1;
                }
                if (n3 >= Bufferlength && t == 0)
                {
                //    Dispose(); // stop playing
                  //  return 0; // stop playing
                }
                if (n4 == 0)
                {
                    sum = X[t];
                    temp[t] = sum;
                }
                else
                {
                    sum = (float)(X[t] + ((temp[t] + temp[t + 1]) * 0.5 * decay));// low pass filter and decay factor of 0,996
                    temp[t] = sum;

                }
                t++; // counter this is a  static  counter
                decay = decay - 0.00009;
                // send sum to the butter that so it can be played later
                byte[] bytes = BitConverter.GetBytes(sum);
                buffer[r * 4 + 0] = bytes[0];
                buffer[r * 4 + 1] = bytes[1];
                buffer[r * 4 + 2] = bytes[2];
                buffer[r * 4 + 3] = bytes[3];
                n3++;
            }
            return sampleCount;// end of Read sound start playing now
        }

    }
}

My sound does not stop
it get to a point where the number in the buffer just repeat...
that is wrong right ?

steve
Site Admin
Posts: 81609
Joined: Sat Dec 01, 2007 11:43 am
Operating System: Linux *buntu

Re: Karplus–Strong algoritm

Post by steve » Tue Nov 04, 2014 11:00 pm

btb4198 wrote:that is wrong right ?
Yes that's wrong.

The expected behaviour for Karplus–Strong synthesis is that the sound decays. For that to work, the overall gain must be less than 1.
Sorry, I've no idea about your code, but there is an implementation of Karplus-Strong algorithm in "Nyquist" code here, if that is any use to you:

Code: Select all

;;; Simple KARPLUS-STRONG
;;; coded by Pedro Jose Morales
;;; [email protected]


; NYQUIST code for simple Karplus-Strong algorithm

(setf *pmorales-path* (current-path))
(load (strcat *pmorales-path* "pjmg.lsp"))


(setf ks-class
 (send class :new '(cnt total-cnt z-1output output delay-line len total-len)))

(send ks-class :answer :isnew '(pitch dur)
  '((setf len (round (/ *sound-srate* (step-to-hz pitch))))
    (setf total-len (* *sound-srate* dur))
    (setf delay-line (snd-samples (noise (/ (step-to-hz pitch))) len))
    (setf cnt 0)
    (setf total-cnt 0)
    (setf z-1output 0.0)
    (setf output 0.0)))

(send ks-class :answer :next '()
  '((setf output (aref delay-line cnt))
    (setf (aref delay-line cnt) (/ (+ output z-1output) 2.0))
    (setf z-1output output)
    (setf cnt (if (= (1- len) cnt) 0 (1+ cnt)))
    (setf total-cnt (1+ total-cnt))
    (if (= total-cnt total-len) NIL output)))

(defun ks (pitch dur)
  (let (obj (d (get-duration dur)))
    (setf obj (send ks-class :new pitch d))
    (snd-fromobject *rslt* *sound-srate* obj)))

(defun ks-env (pitch dur)
  (mult (pwe dur 0.064)
        (ks pitch dur)))

;(ss (seq (ks a4 1.0) (ks b4 1.0) (ks c5 3.0)))

(ss (seq (ks-env a3 1.0) (ks-env b3 1.0)))
(example taken from the CMU Nyquist documentation)
9/10 questions are answered in the FREQUENTLY ASKED QUESTIONS (FAQ)

Post Reply