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

  1. // BASS Recording example, copyright (c) 2002-2005 Ian Luck.
  2.  
  3. #include <windows.h>
  4. #include <commctrl.h>
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7. #include "bass.h"
  8.  
  9. HWND win=NULL;
  10.  
  11. #define BUFSTEP 200000    // memory allocation unit
  12.  
  13. int input;                // current input source
  14. char *recbuf=NULL;        // recording buffer
  15. DWORD reclen;            // recording length
  16.  
  17. HRECORD rchan=0;        // recording channel
  18. HSTREAM chan=0;            // playback channel
  19.  
  20. // display error messages
  21. void Error(char *es)
  22. {
  23.     char mes[200];
  24.     sprintf(mes,"%s\n(error code: %d)",es,BASS_ErrorGetCode());
  25.     MessageBox(win,mes,"Error",0);
  26. }
  27.  
  28. // messaging macros
  29. #define MESS(id,m,w,l) SendDlgItemMessage(win,id,m,(WPARAM)w,(LPARAM)l)
  30. #define DLGITEM(id) GetDlgItem(win,id)
  31.  
  32. // buffer the recorded data
  33. BOOL CALLBACK RecordingCallback(HRECORD handle, void *buffer, DWORD length, DWORD user)
  34. {
  35.     // increase buffer size if needed
  36.     if ((reclen%BUFSTEP)+length>=BUFSTEP) {
  37.         recbuf=realloc(recbuf,((reclen+length)/BUFSTEP+1)*BUFSTEP);
  38.         if (!recbuf) {
  39.             rchan=0;
  40.             Error("Out of memory!");
  41.             MESS(10,WM_SETTEXT,0,"Record");
  42.             return FALSE; // stop recording
  43.         }
  44.     }
  45.     // buffer the data
  46.     memcpy(recbuf+reclen,buffer,length);
  47.     reclen+=length;
  48.     return TRUE; // continue recording
  49. }
  50.  
  51. void StartRecording()
  52. {
  53.     WAVEFORMATEX *wf;
  54.     if (recbuf) { // free old recording
  55.         BASS_StreamFree(chan);
  56.         chan=0;
  57.         free(recbuf);
  58.         recbuf=NULL;
  59.         EnableWindow(DLGITEM(11),FALSE);
  60.         EnableWindow(DLGITEM(12),FALSE);
  61.     }
  62.     // allocate initial buffer and make space for WAVE header
  63.     recbuf=malloc(BUFSTEP);
  64.     reclen=44;
  65.     // fill the WAVE header
  66.     memcpy(recbuf,"RIFF\0\0\0\0WAVEfmt \20\0\0\0",20);
  67.     memcpy(recbuf+36,"data\0\0\0\0",8);
  68.     wf=(WAVEFORMATEX*)(recbuf+20);
  69.     wf->wFormatTag=1;
  70.     wf->nChannels=2;
  71.     wf->wBitsPerSample=16;
  72.     wf->nSamplesPerSec=44100;
  73.     wf->nBlockAlign=wf->nChannels*wf->wBitsPerSample/8;
  74.     wf->nAvgBytesPerSec=wf->nSamplesPerSec*wf->nBlockAlign;
  75.     // start recording @ 44100hz 16-bit stereo
  76.     if (!(rchan=BASS_RecordStart(44100,2,0,&RecordingCallback,0))) {
  77.         Error("Couldn't start recording");
  78.         free(recbuf);
  79.         recbuf=0;
  80.         return;
  81.     }
  82.     MESS(10,WM_SETTEXT,0,"Stop");
  83. }
  84.  
  85. void StopRecording()
  86. {
  87.     BASS_ChannelStop(rchan);
  88.     rchan=0;
  89.     MESS(10,WM_SETTEXT,0,"Record");
  90.     // complete the WAVE header
  91.     *(DWORD*)(recbuf+4)=reclen-8;
  92.     *(DWORD*)(recbuf+40)=reclen-44;
  93.     // create a stream from the recording
  94.     if (chan=BASS_StreamCreateFile(TRUE,recbuf,0,reclen,0)) {
  95.         // enable "play" & "save" buttons
  96.         EnableWindow(DLGITEM(11),TRUE);
  97.         EnableWindow(DLGITEM(12),TRUE);
  98.     }
  99. }
  100.  
  101. // write the recorded data to disk
  102. void WriteToDisk()
  103. {
  104.     FILE *fp;
  105.     char file[MAX_PATH]="";
  106.     OPENFILENAME ofn={0};
  107.     ofn.lStructSize=sizeof(ofn);
  108.     ofn.hwndOwner=win;
  109.     ofn.nMaxFile=MAX_PATH;
  110.     ofn.lpstrFile=file;
  111.     ofn.Flags=OFN_HIDEREADONLY|OFN_EXPLORER;
  112.     ofn.lpstrFilter="WAV files\0*.wav\0All files\0*.*\0\0";
  113.     ofn.lpstrDefExt="wav";
  114.     if (!GetSaveFileName(&ofn)) return;
  115.     if (!(fp=fopen(file,"wb"))) {
  116.         Error("Can't create the file");
  117.         return;
  118.     }
  119.     fwrite(recbuf,reclen,1,fp);
  120.     fclose(fp);
  121. }
  122.  
  123. void UpdateInputInfo()
  124. {
  125.     char *type;
  126.     int it=BASS_RecordGetInput(input); // get info on the input
  127.     MESS(14,TBM_SETPOS,TRUE,LOWORD(it)); // set the level slider
  128.     switch (it&BASS_INPUT_TYPE_MASK) {
  129.         case BASS_INPUT_TYPE_DIGITAL:
  130.             type="digital";
  131.             break;
  132.         case BASS_INPUT_TYPE_LINE:
  133.             type="line-in";
  134.             break;
  135.         case BASS_INPUT_TYPE_MIC:
  136.             type="microphone";
  137.             break;
  138.         case BASS_INPUT_TYPE_SYNTH:
  139.             type="midi synth";
  140.             break;
  141.         case BASS_INPUT_TYPE_CD:
  142.             type="analog cd";
  143.             break;
  144.         case BASS_INPUT_TYPE_PHONE:
  145.             type="telephone";
  146.             break;
  147.         case BASS_INPUT_TYPE_SPEAKER:
  148.             type="pc speaker";
  149.             break;
  150.         case BASS_INPUT_TYPE_WAVE:
  151.             type="wave/pcm";
  152.             break;
  153.         case BASS_INPUT_TYPE_AUX:
  154.             type="aux";
  155.             break;
  156.         case BASS_INPUT_TYPE_ANALOG:
  157.             type="analog";
  158.             break;
  159.         default:
  160.             type="undefined";
  161.     }
  162.     MESS(15,WM_SETTEXT,0,type); // display the type
  163. }
  164.  
  165. BOOL CALLBACK dialogproc(HWND h,UINT m,WPARAM w,LPARAM l)
  166. {
  167.     switch (m) {
  168.         case WM_TIMER:
  169.             { // update the recording/playback counter
  170.                 char text[30]="";
  171.                 if (rchan) // recording
  172.                     sprintf(text,"%I64d",BASS_ChannelGetPosition(rchan));
  173.                 else if (chan) {
  174.                     if (BASS_ChannelIsActive(chan)) // playing
  175.                         sprintf(text,"%I64d / %I64d",BASS_ChannelGetPosition(chan),BASS_ChannelGetLength(chan));
  176.                     else
  177.                         sprintf(text,"%I64d",BASS_ChannelGetLength(chan));
  178.                 }
  179.                 MESS(20,WM_SETTEXT,0,text);
  180.             }
  181.             break;
  182.  
  183.         case WM_COMMAND:
  184.             switch (LOWORD(w)) {
  185.                 case IDCANCEL:
  186.                     DestroyWindow(h);
  187.                     break;
  188.                 case 10:
  189.                     if (!rchan)
  190.                         StartRecording();
  191.                     else
  192.                         StopRecording();
  193.                     break;
  194.                 case 11:
  195.                     BASS_ChannelPlay(chan,TRUE); // play the recorded data
  196.                     break;
  197.                 case 12:
  198.                     WriteToDisk();
  199.                     break;
  200.                 case 13:
  201.                     if (HIWORD(w)==CBN_SELCHANGE) { // input selection changed
  202.                         int i;
  203.                         input=MESS(13,CB_GETCURSEL,0,0); // get the selection
  204.                         // enable the selected input
  205.                         for (i=0;BASS_RecordSetInput(i,BASS_INPUT_OFF);i++) ; // 1st disable all inputs, then...
  206.                         BASS_RecordSetInput(input,BASS_INPUT_ON); // enable the selected
  207.                         UpdateInputInfo(); // update info
  208.                     }
  209.                     break;
  210.             }
  211.             break;
  212.  
  213.         case WM_HSCROLL:
  214.             if (l) { // set input source level
  215.                 int level=SendMessage((HWND)l,TBM_GETPOS,0,0);
  216.                 BASS_RecordSetInput(input,BASS_INPUT_LEVEL|level);
  217.             }
  218.             break;
  219.  
  220.         case WM_INITDIALOG:
  221.             win=h;
  222.             // setup recording and output devices (using default devices)
  223.             if (!BASS_RecordInit(-1) || !BASS_Init(-1,44100,0,win,NULL)) {
  224.                 Error("Can't initialize device");
  225.                 DestroyWindow(win);
  226.             } else { // get list of inputs
  227.                 int c;
  228.                 char *i;
  229.                 MESS(14,TBM_SETRANGE,FALSE,MAKELONG(0,100)); // initialize input level slider
  230.                 for (c=0;i=BASS_RecordGetInputName(c);c++) {
  231.                     MESS(13,CB_ADDSTRING,0,i);
  232.                     if (!(BASS_RecordGetInput(c)&BASS_INPUT_OFF)) { // this 1 is currently "on"
  233.                         input=c;
  234.                         MESS(13,CB_SETCURSEL,input,0);
  235.                         UpdateInputInfo(); // display info
  236.                     }
  237.                 }
  238.                 SetTimer(h,0,200,0); // timer to update the position display
  239.                 return 1;
  240.             }
  241.             break;
  242.  
  243.         case WM_DESTROY:
  244.             // release all BASS stuff
  245.             BASS_RecordFree();
  246.             BASS_Free();
  247.             break;
  248.     }
  249.     return 0;
  250. }
  251.  
  252. int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow)
  253. {
  254.     // check that BASS 2.2 was loaded
  255.     if (BASS_GetVersion()!=MAKELONG(2,2)) {
  256.         MessageBox(0,"BASS version 2.2 was not loaded","Incorrect BASS.DLL",0);
  257.         return 0;
  258.     }
  259.  
  260.     { // enable trackbar support (for the level control)
  261.         INITCOMMONCONTROLSEX cc={sizeof(cc),ICC_BAR_CLASSES};
  262.         InitCommonControlsEx(&cc);
  263.     }
  264.  
  265.     DialogBox(hInstance,(char*)1000,0,&dialogproc);
  266.  
  267.     return 0;
  268. }
  269.