home *** CD-ROM | disk | FTP | other *** search
/ Chip 2005 November / CDVD1105.ISO / Software / Freeware / programare / bass / c / synth / synth.c < prev    next >
Encoding:
C/C++ Source or Header  |  2005-09-08  |  4.8 KB  |  155 lines

  1. // BASS Simple Synth, copyright (c) 2001-2005 Ian Luck.
  2.  
  3. #include <windows.h>
  4. #include <stdio.h>
  5. #include <conio.h>
  6. #include <math.h>
  7. #include "bass.h"
  8.  
  9. /* display error messages */
  10. void Error(char *text) 
  11. {
  12.     printf("Error(%d): %s\n",BASS_ErrorGetCode(),text);
  13.     BASS_Free();
  14.     ExitProcess(0);
  15. }
  16.  
  17.  
  18. #define PI 3.14159265358979323846
  19. #define TABLESIZE 2048
  20. int sinetable[TABLESIZE];    // sine table
  21. #define KEYS 20
  22. WORD keys[KEYS]={
  23.     'Q','2','W','3','E','R','5','T','6','Y','7','U',
  24.     'I','9','O','0','P',219,187,221
  25. };
  26. #define MAXVOL    4000    // higher value = longer fadeout
  27. int vol[KEYS]={0},pos[KEYS];    // keys' volume & pos
  28.  
  29.  
  30. /* stream writer */
  31. DWORD CALLBACK WriteStream(HSTREAM handle, short *buffer, DWORD length, DWORD user)
  32. {
  33.     int n,s;
  34.     DWORD c;
  35.     float f;
  36.     memset(buffer,0,length);
  37.     for (n=0;n<KEYS;n++) {
  38.         if (!vol[n]) continue;
  39.         f=pow(2.0,(n+3)/12.0)*TABLESIZE*440.0/44100.0;
  40.         for (c=0;c<length/4 && vol[n];c++) {
  41.             s=sinetable[(int)((pos[n]++)*f)&(TABLESIZE-1)]*vol[n]/MAXVOL;
  42.             s+=(int)buffer[c*2];
  43.             if (s>32767) s=32767;
  44.             else if (s<-32768) s=-32768;
  45.             buffer[c*2+1]=buffer[c*2]=s; // left and right channels are the same
  46.             if (vol[n]<MAXVOL) vol[n]--;
  47.         }
  48.     }
  49.     return length;
  50. }
  51.  
  52. void main(int argc, char **argv)
  53. {
  54.     BASS_INFO info;
  55.     HSTREAM str;
  56.     char *fxname[9]={"CHORUS","COMPRESSOR","DISTORTION","ECHO",
  57.         "FLANGER","GARGLE","I3DL2REVERB","PARAMEQ","REVERB"};
  58.     HFX fx[9]={0}; // effect handles
  59.     INPUT_RECORD keyin;
  60.     int r;
  61.     DWORD buflen;
  62.  
  63.     printf("BASS Simple Sinewave Synth\n"
  64.             "--------------------------\n");
  65.  
  66.     /* check that BASS 2.2 was loaded */
  67.     if (BASS_GetVersion()!=MAKELONG(2,2)) {
  68.         printf("BASS version 2.2 was not loaded\n");
  69.         return;
  70.     }
  71.  
  72.     /* 10ms update period */
  73.     BASS_SetConfig(BASS_CONFIG_UPDATEPERIOD,10);
  74.  
  75.     /* setup output - get latency */
  76.     if (!BASS_Init(-1,44100,BASS_DEVICE_LATENCY,0,NULL))
  77.         Error("Can't initialize device");
  78.  
  79.     /* build sine table */
  80.     for (r=0;r<TABLESIZE;r++)
  81.         sinetable[r]=(int)(sin(2.0*PI*(double)r/TABLESIZE)*7000.0);
  82.  
  83.     BASS_GetInfo(&info);
  84.     printf("device latency: %dms\n",info.latency);
  85.     printf("device minbuf: %dms\n",info.minbuf);
  86.     printf("ds version: %d (effects %s)\n",info.dsver,info.dsver<8?"disabled":"enabled");
  87.  
  88.     /* default buffer size = update period + 'minbuf' */
  89.     buflen=BASS_SetConfig(BASS_CONFIG_BUFFER,10+info.minbuf);
  90.  
  91.     /* create a stream, stereo so that effects sound nice */
  92.     str=BASS_StreamCreate(44100,2,0,WriteStream,0);
  93.     printf("press these keys to play:\n\n"
  94.             "  2 3  5 6 7  9 0  =\n"
  95.             " Q W ER T Y UI O P[ ]\n\n"
  96.             "press -/+ to de/increase the buffer\n"
  97.             "press spacebar to quit\n\n");
  98.  
  99.     if (info.dsver>=8) // DX8 effects available
  100.         printf("press F1-F9 to toggle effects\n\n");
  101.  
  102.     printf("using a %dms buffer\r",buflen);
  103.  
  104.     BASS_ChannelPlay(str,FALSE);
  105.  
  106.     while (ReadConsoleInput(GetStdHandle(STD_INPUT_HANDLE),&keyin,1,&r)) {
  107.         int key;
  108.         if (keyin.EventType!=KEY_EVENT) continue;
  109.         if (keyin.Event.KeyEvent.wVirtualKeyCode==VK_SPACE) break;
  110.         if (keyin.Event.KeyEvent.bKeyDown && keyin.Event.KeyEvent.wVirtualKeyCode==VK_SUBTRACT) {
  111.             /* recreate stream with smaller buffer */
  112.             BASS_StreamFree(str);
  113.             buflen=BASS_SetConfig(BASS_CONFIG_BUFFER,buflen-1);
  114.             printf("using a %dms buffer\t\t\r",buflen);
  115.             str=BASS_StreamCreate(44100,2,0,WriteStream,0);
  116.             /* set effects on the new stream */
  117.             for (r=0;r<9;r++) if (fx[r]) fx[r]=BASS_ChannelSetFX(str,BASS_FX_CHORUS+r,0);
  118.             BASS_ChannelPlay(str,FALSE);
  119.         }
  120.         if (keyin.Event.KeyEvent.bKeyDown && keyin.Event.KeyEvent.wVirtualKeyCode==VK_ADD) {
  121.             /* recreate stream with larger buffer */
  122.             BASS_StreamFree(str);
  123.             buflen=BASS_SetConfig(BASS_CONFIG_BUFFER,buflen+1);
  124.             printf("using a %dms buffer\t\t\r",buflen);
  125.             str=BASS_StreamCreate(44100,2,0,WriteStream,0);
  126.             /* set effects on the new stream */
  127.             for (r=0;r<9;r++) if (fx[r]) fx[r]=BASS_ChannelSetFX(str,BASS_FX_CHORUS+r,0);
  128.             BASS_ChannelPlay(str,FALSE);
  129.         }
  130.         if (keyin.Event.KeyEvent.bKeyDown && keyin.Event.KeyEvent.wVirtualKeyCode>=VK_F1
  131.             && keyin.Event.KeyEvent.wVirtualKeyCode<=VK_F9) {
  132.             r=keyin.Event.KeyEvent.wVirtualKeyCode-VK_F1;
  133.             if (fx[r]) {
  134.                 BASS_ChannelRemoveFX(str,fx[r]);
  135.                 fx[r]=0;
  136.                 printf("effect %s = OFF\t\t\r",fxname[r]);
  137.             } else {
  138.                 /* set the effect, not bothering with parameters (use defaults) */
  139.                 if (fx[r]=BASS_ChannelSetFX(str,BASS_FX_CHORUS+r,0))
  140.                     printf("effect %s = ON\t\t\r",fxname[r]);
  141.             }
  142.         }
  143.         for (key=0;key<KEYS;key++)
  144.             if (keyin.Event.KeyEvent.wVirtualKeyCode==keys[key]) break;
  145.         if (key==KEYS) continue;
  146.         if (keyin.Event.KeyEvent.bKeyDown && vol[key]!=MAXVOL) {
  147.             pos[key]=0;
  148.             vol[key]=MAXVOL; // start key
  149.         } else if (!keyin.Event.KeyEvent.bKeyDown && vol[key])
  150.             vol[key]--; // trigger key fadeout
  151.     }
  152.  
  153.     BASS_Free();
  154. }
  155.