Digital SVF Code

Ian Fritz ijfritz at earthlink.net
Tue Mar 9 15:56:28 CET 1999


Hey Mr. Perry --

Isn't this the one you said would't work? Are you still ROFLing at us
idiots?

  Ian

Mikko Helin wrote:
> 
> Hi,
> 
> I found the code I promised to send. You can download it
> from http://www.uta.fi/~helin/ds2.zip, or in the end of this
> message (C source code).
> 
> If you want just to listen to it, there a .WAV file (130 kB)
> at http://www.uta.fi/~helin/test.wav
> 
> Code is optimized for 32-bit processor, the filter needs only
> three multiplications. I guess any 386 -> could run it real
> time. Maybe some microcontrollers like Siemens 80C188 or
> other 16 bit device with 32 bit multiplication accumulator
> register.
> 
> -Mikko
> 
> //////////////// cut here //////////// cut here //////////////
> 
> /*
>  * DOSYNTH v. 0.2
>  *
>  * DS2.C
>  *
>  * This program is based on the algorithm found in Hal Chamberlin's
>  * book "Musical Applications of Microprocessors" p. 149-151
>  * describing digital implementation of state-variable filter.
>  *
>  * Usage: DS2 <output_file> <1/Q> <level>
>  *
>  * Examples:
>  *
>  *   DS2 sine.pcm 0
>  *   DS2 sweep.pcm 200 600
>  *
>  * Output is raw PCM data, 44100 Hz/16 bit/Intel format (LSB,MSB)
>  *
>  * Copyright (c) Mikko Helin, 1999
>  *
>  */
> 
> // Include Headers
> #include <stdlib.h>
> #include <stdio.h>
> #include <string.h>
> #include <dos.h>
> 
> // EG macros; Not Much Used Here
> #define STOPPED 0
> #define ATTACK 1
> #define DECAY 2
> #define SUSTAIN 3
> #define RELEASE 4
> 
> // Some Other Constants
> #define BLOCKSIZE 2048
> 
> // Store Data Here
> static long dwSample[BLOCKSIZE];
> static int wSample[BLOCKSIZE];
> 
> // Resonance:  Less Is More = 1/Q
> static long dwQ=0x00000000;  // Zero Generates Sine Wave
> 
> // Amplitude; 12 bits
> static long dwEG2=0x0FFF;    // Amplitude Envelope; Constant Here
> 
> // DoSynth: Generates the Voice
> static void DoSynth(void);
> 
> // Main function
> /***************************************************************/
> int main(int argc, char *argv[]) {
> /***************************************************************/
>     FILE *fp=0;
>     char szFilename[32];
>     char szQ[12];
>     char szV[12];
>     int cc=0;
>     int i=0;
> 
>     if (argc>1)  // Output File Name
>         strcpy(szFilename,argv[1]);
>     else
>         strcpy(szFilename,"synth.snd");
> 
>     if (argc>2) { // Resonance Setting; 1/Q; Zero Generates SineWave
>         strcpy(szQ,argv[2]);
>         dwQ=atol(szQ);
>     }
> 
>     if (argc>3) { // Volume For DCA
>         strcpy(szV,argv[3]);
>         dwEG2=atol(szV);
>     }
> 
>     if( !(fp = fopen(szFilename, "wb")) ) {
>         printf("\t\007 Output File \"%s\" Not Created\n\n", szFilename);
>         goto exit;
>     }
> 
> 
>     printf("DS2: Generating Sound File ...");
>     for(i = 0; i < 0xFFFF/0x07FF; i++) {
>         printf(".");
>         DoSynth();
>         cc = fwrite(wSample, 2, BLOCKSIZE, fp);
>     }
>     printf("\n");
> 
>     fclose(fp);
> exit:
> 
>     return 0;
> }
> 
> /***************************************************************/
> void DoSynth() {
> /***************************************************************/
> //   DATA FORMAT: 20 bit + 12 bit fraction
>     static long dwLP=0; // LP Output
>     static long dwHP=0; // HP Output
>     static long dwBP=0; // BP Output
> //    static long dwNO=0;
>     static long dwD0=0; // Not Used
>     static long dwD1=0x00FFFFFF; // Delay 1
>     static long dwD2=0x00FFFFFF; // Delay 2
>     static long dwEG1=0;         // EG 1 Output For Filter
>     static long  dwEG=0xFFFF;    // EG 1 "Phase"
>     static unsigned int  wEG2=0xFFFF; // EG 2; not used
>     static long  dwS=0;         // VCO Output to VCA
>     static long  dwS0=0;        // "Phase"
> 
>     static int   wS=0x7FFF;     // not used
>     static unsigned int wDec=0x000F;  // not used
>     static long   dwDiff = (0x0000FFFF / (44100L/100L)); // VCO Increment
>                                                     // For 100 Hz Saw
>     static int    wDiff =  0xFFFF / (44100/100);   // not used
>     register int i;               // Loop Counter
>     static int wBufferSize=BLOCKSIZE; // Loop Size
> 
>     for (i=0; i<wBufferSize;i++) {
> 
>             //---------------------------------------------------------
>             // VCO
>             // SAW Waveform Generation (With Aliasing!!)
>             dwS0 += dwDiff;  // Generate Saw Wave Format
>             if (dwS0 > 32000)
>                 dwS0 = -32000;
>             dwS = dwS0;
> 
>             if (dwQ == 0) // For Sine Wave Generation
>                 dwS = 0;
> 
>             //---------------------------------------------------------
>             // EG1: FILTER EG
>             dwEG--;  // 0 .. FFFF  = 64 ksamples = 1.5 sec up
>             dwEG1 = dwEG >> 4;  // 16 to 12 bits
> 
>             //---------------------------------------------------------
>             // EG2: AMP; Not Used; Constant; See Main
>             //wEG2--;  // 0 .. FFFF  = 64 ksamples = 1.5 sec up
>             //dwEG2 = wEG2>>4;  // 16 to 12 bits
> 
>             //---------------------------------------------------------
>             // VCA: Amplifier
>             dwS = (dwS * dwEG2)>>12;
> 
>             //---------------------------------------------------------
>             // DSVF SECTION: Digital State Variable Filter
>             // dwEG1 := 2*pi*Fc/Fs gets values 0 (Fc=0 Hz)..1 (Fc=Fs/(2*pi))
>             // Low Pass Filter
>             dwLP = dwD2 + (dwEG1*(dwD1>>12));
> 
>             // dwQ = 1/Q gets values 0 (infinite Q) .. 2 (Q=0.5)
> 
>             // High Pass Filter
>             dwHP = ((dwS<<12) - dwLP) - (dwQ*(dwD1>>12));
> 
>             // Band Pass Filter
>             dwBP = dwEG1*(dwHP>>12) + dwD1;
> 
>             // Notch Filter; Not Used Here
>             // dwNO = dwHP + dwLP;
> 
>             // Delay Lines
>             dwD1 = dwBP;
>             dwD2 = dwLP;
> 
>             //---------------------------------------------------------
>             // OUTPUT
>             // Truncate To 20 Bits
>             dwS = dwLP >> 12;
> 
>             wSample[i] = dwS;
> 
>             // Overflow to Max/Min Values
>             if (dwS > 32767L)
>                 wSample[i] = 32767;
>             if (dwS < -32767L)
>                 wSample[i] = -32767;
> 
>     }  // Buffer Done
> } // DoSynth Done



More information about the Synth-diy mailing list