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