/* ******************************************************************** * Module pour piloter la Carte sound-blaster avec Borland C++ 3.0 * * en utilisant le driver CT-VOICE.DRV. * ******************************************************************** * (C) 1992 MICRO APPLICATION * * Auteur : Axel Stolz * ******************************************************************** */ #include #include #include #include #include #include #include #ifdef TRACE #define trace(format,variable) \ { \ char format1[1000]; \ sprintf (format1, "%s(%d) %s : %s.\n", \ __FILE__, __LINE__, #variable, format); \ printf (format1, variable); \ } #else #define trace(format,variable)\ { \ char format1[1000]; \ sprintf (format1, "%s(%d) %s : %s.\n", \ __FILE__, __LINE__, #variable, format); \ } #endif #define cal(f) (((void (far *)())(f))()) #define FP_SEG(fp) (*(int *)(((char *)&(fp))+2)) #define FALSE 0 #define TRUE 1 #define DWORD unsigned long #define WORD unsigned int #define BYTE unsigned char #define VOCPTR char far* const char voctool_version[] = "v1.5"; /* Numro de version de VOCTool */ const BYTE voc_breakend = 0; /* Constante de fin de boucle */ const BYTE voc_breaknow = 1; /* Constante de fin de boucle */ WORD voc_status_word = 0; /* Variable SB status */ WORD voc_err_stat = 0; /* Variable n d'erreur driver */ char vocfile_header[] = /* Variable d'entte Format CT */ "Creative Voice File\0x1A\0x1A\0\0x0A\1\0x29\0x11\1"; BYTE voc_paused = 0; /* Flag Pause Voice */ BYTE vocdriver_installed = 0; /* Flag Driver install */ WORD vocdriver_version = 0; /* Numro de version du driver */ BYTE vocfile_headerlength = 0; /* Longueur de l'entte du format CT */ VOCPTR voc_ptr_to_driver = 0; /* Pointeur sur le Driver */ /* ************************************** * Prototype pour les fonctions cres * ************************************** */ void _print_voc_errmessage(void); VOCPTR _voc_get_buffer(char *voicefile); WORD _voc_getversion(void); void _voc_setport(WORD portnumber); void _voc_setirq(WORD irqnumber); WORD _voc_init_driver(void); void _voc_deinstall_driver(void); void _voc_set_speaker(BYTE OnOff); void _voc_output(char far *bufferaddress); void _voc_output_loop(char far *bufferaddress); void _voc_stop(void); void _voc_pause(void); void _voc_continue(void); void _voc_breakloop(WORD breakmode); int _dos_open (char *filename, int mode, int *filehandle) { if ((*filehandle = open (filename, mode)) == -1) return -1; return 0; } _dos_read (int fh, char huge *buffer, unsigned int n, unsigned int *nread) { union REGS reg; struct SREGS sreg; reg.h.ah = 0x3F; reg.x.bx = fh; reg.x.cx = n; reg.x.dx = FP_OFF(buffer); sreg.ds = FP_SEG(buffer); intdosx (®, ®, &sreg); if (reg.x.flags & 1) { *nread = 0; return reg.x.ax; } *nread = reg.x.ax; return 0; } #define _dos_close close /* #define _dos_allocmem allocmem */ int _dos_allocmem (unsigned size, unsigned *segment) { int status; status = allocmem (size, segment); if (status == -1) return 0; return -1; } #define _dos_freemem freemem void _print_voc_errmessage(void) /* * ENTRE : aucune * SORTIE : aucune * FONCTION : Affiche l'cran, sous forme texte, l'erreur SB venant de se * produire sans modifier la valeur du status. */ { switch (voc_err_stat) { case 100 : printf(" Driver CT-VOICE.DRV non trouv ");break; case 110 : printf(" Place mmoire insuffisante pour le driver ");break; case 120 : printf(" Driver incorrect ");break; case 200 : printf(" Fichier VOC non trouv ");break; case 210 : printf(" Espace mmoire insuffisant pour le fichier VOC ");break; case 220 : printf(" Le fichier n'est pas au format VOC ");break; case 300 : printf(" Erreur d'implmentation en mmoire ");break; case 400 : printf(" Carte Sound Blaster non trouve ");break; case 410 : printf(" Adresse de port incorrecte ");break; case 420 : printf(" Utilisation d'une interruption errone ");break; case 500 : printf(" Pas de boucle en cours ");break; case 510 : printf(" Aucun chantillon en cours de diffusion ");break; case 520 : printf(" Pas d'chantillon interrompu ");break; } } VOCPTR _voc_get_buffer(char *voicefile) /* * ENTRE : Nom de fichier sous forme chane de caractre * SORTIE : Pointeur sur le buffer de donnes VOC * FONCTION : Charge un fichier en mmoire, et en cas de chargement correct, retourne la valeur du pointeur sur les donnes */ { int filehandle; long filesize; WORD blocksize; WORD byte_read ; char huge *filepointer; VOCPTR bufferaddress; BYTE check; WORD segment; /* Le fichier n'a pas t trouv */ if (_dos_open(voicefile,O_RDONLY #ifndef OLD | O_BINARY #endif ,&filehandle) != 0) { voc_err_stat = 200; return(FALSE); } filesize = filelength(filehandle); blocksize = (filesize + 15L) /16; /* Espace mmoire insuffisant pour le fichier VOC */ check = _dos_allocmem(blocksize,&segment); if (check != 0) { voc_err_stat = 210; return(FALSE); } FP_SEG(bufferaddress) = segment; FP_OFF(bufferaddress) = 0; filepointer = (char huge*)bufferaddress; /* Chargement du fichier chantillon */ do { _dos_read(filehandle,filepointer,0x8000,&byte_read); filepointer += byte_read ; } while (byte_read == 0x8000); #ifdef OLD _dos_close(filehandle); #else close(filehandle); #endif /* Le Fichier n'est pas au format VOC */ if ((bufferaddress[0] != 'C') || (bufferaddress[1] != 'r')) { voc_err_stat = 220; return(FALSE); } /* Le chargement a t correctement effectu */ voc_err_stat = 0; vocfile_headerlength = (BYTE)bufferaddress[20]; return(bufferaddress); } WORD _voc_getversion(void) /* * ENTRE : aucune * SORTIE : Numro de version du driver * FONCTION : Transmet le numro de version du driver */ { WORD vdummy; #ifdef ASM asm { mov bx,0 call voc_ptr_to_driver mov vdummy, ax } #else _BX = 0; cal (voc_ptr_to_driver); vdummy = _AX; #endif return(vdummy); } void _voc_setport(WORD portnumber) /* * ENTRE : Numro de l'adresse du port * SORTIE : aucune * FONCTION : Fixe l'adresse du port avant l'initialisation */ { #ifdef ASM asm { mov bx,1 mov ax,portnumber call voc_ptr_to_driver } #else _BX = 1; _AX = portnumber; cal (voc_ptr_to_driver); #endif } void _voc_setirq(WORD irqnumber) /* * ENTRE : Numro d'interruption * SORTIE : aucune * FONCTION : Fixe le numro d'interruption avant l'initialisation */ { #ifdef ASM asm { mov bx,2 mov ax,irqnumber call voc_ptr_to_driver } #else _BX = 2; _AX = irqnumber; cal (voc_ptr_to_driver); #endif } WORD _voc_init_driver(void) /* * ENTRE : aucune * SORTIE : Numro de message d'erreur suivant le rsultat de l'initialisation * FONCTION : Initialisation du logiciel Driver */ { int filehandle; unsigned long filesize; WORD blocksize; char huge *filepointer; WORD byte_read; BYTE check; WORD segment; WORD vseg; WORD vofs; WORD vout; vocdriver_installed = FALSE; /* Driver non trouv */ if (_dos_open("CT-VOICE.DRV",O_RDONLY,&filehandle) != 0) { voc_err_stat = 100; return(FALSE); } filesize = filelength(filehandle); blocksize = (filesize + 15L) /16; /* Espace mmoire insuffisant pour le driver */ check = _dos_allocmem(blocksize,&segment); if (check != 0) { voc_err_stat = 110; return(FALSE); } FP_SEG(voc_ptr_to_driver) = segment; FP_OFF(voc_ptr_to_driver) = 0; filepointer = (char huge*)voc_ptr_to_driver; /* Chargement du driver */ do { _dos_read(filehandle,filepointer,0x8000,&byte_read); filepointer += byte_read ; } while (byte_read == 0x8000) ; _dos_close(filehandle) ; /* Driver incorrect, ne commence pas par "CT" */ if ((voc_ptr_to_driver[3] != 'C') || (voc_ptr_to_driver[4] != 'T')) { voc_err_stat = 120; return(FALSE); } /* Transmettre la version du driver */ vocdriver_version = _voc_getversion(); /* Dmarrage du Driver */ vseg = FP_SEG(&voc_status_word); vofs = FP_OFF(&voc_status_word); #ifdef ASM asm { mov bx,3 call voc_ptr_to_driver mov vout,ax mov bx,5 mov es,vseg mov di,vofs call voc_ptr_to_driver } #else _BX = 3; cal (voc_ptr_to_driver); vout = _AX; _BX = 5; _ES = vseg; _DI = vofs; cal (voc_ptr_to_driver); #endif /* Carte Sound-Blaster non trouve */ if (vout == 1) { voc_err_stat = 400; return(FALSE); } /* Utilisation d'une adresse de port incorrecte */ if (vout == 2) { voc_err_stat = 410; return(FALSE); } /* Utilisation d'un numro d'interruption incorrect */ if (vout == 3) { voc_err_stat = 420; return(FALSE); } vocdriver_installed = TRUE; return(TRUE); } void _voc_deinstall_driver(void) /* * ENTRE : aucune * SORTIE : aucune * FONCTION : Dsactivation du driver et libration de la mmoire */ { if (vocdriver_installed) { #ifdef ASM asm { mov bx,9 call voc_ptr_to_driver } #else _BX = 9; cal (voc_ptr_to_driver); #endif _dos_freemem(FP_SEG(voc_ptr_to_driver)); } } void _voc_set_speaker(BYTE on_off) /* * ENTRE : TRUE pour l'activation du haut-parleur et FALSE pour la * dsactivation * SORTIE : aucune * FONCTION : Activation/Dsactivation du haut-parleur de la carte SB */ { #ifdef ASM asm { mov bx,4 mov al,on_off call voc_ptr_to_driver } #else _BX = 4; _AL = on_off; cal (voc_ptr_to_driver); #endif } void _voc_output(VOCPTR bufferaddress) /* * ENTRE : Pointeur sur les donnes chantillonnes * SORTIE : Aucune * FONCTION Diffusion d'un chantillon */ { WORD vseg; WORD vofs; _voc_set_speaker(TRUE); vseg = FP_SEG(bufferaddress); vofs = FP_OFF(bufferaddress) + vocfile_headerlength; #ifdef ASM asm { mov bx,6 mov es,vseg mov di,vofs call voc_ptr_to_driver } #else _BX = 6; _ES = vseg; _DI = vofs; cal (voc_ptr_to_driver); #endif } void _voc_output_loop(VOCPTR bufferaddress) /* * Diffrence avec _voc_output : * Dans ce cas, le haut-parleur ne sera pas activ avant chaque dif- * fusion d'un chantillon. Cela empche le bruit rsultant sur la * plupart des cartes Sound Blaster lors de la diffusion d'une boucle. */ { WORD vseg; WORD vofs; vseg = FP_SEG(bufferaddress); vofs = FP_OFF(bufferaddress) + vocfile_headerlength; #ifdef ASM asm { mov bx,6 mov es,vseg mov di,vofs call voc_ptr_to_driver } #else trace ("calling driver %p for output...", voc_ptr_to_driver); trace ("%p", vseg); trace ("%p", vofs); /* sleep (1); */ /* { long i; for (i=0; i<100000; i++); } */ while (voc_status_word); _BX = 6; _ES = vseg; _DI = vofs; cal (voc_ptr_to_driver); trace ("driver called", 0); #endif } void _voc_stop(void) /* * ENTRE : aucune * SORTIE : aucune * FONCTION : Stoppe un chantillon */ { #ifdef ASM asm { mov bx,8 call voc_ptr_to_driver } #else _BX = 8; cal (voc_ptr_to_driver); #endif } void _voc_pause(void) /* * ENTRE : aucune * SORTIE : aucune * FONCTION : Interrompt un chantillon */ { WORD pcheck; voc_paused = TRUE; #ifdef ASM asm { mov bx,10 call voc_ptr_to_driver mov pcheck,ax } #else _BX = 10; cal (voc_ptr_to_driver); pcheck = _AX; #endif if (pcheck == 1) { voc_paused = FALSE; voc_err_stat = 510; } } void _voc_continue(void) /* * ENTRE : aucune * SORTIE : aucune * FONCTION : Reprend un chantillon interrompu */ { WORD pcheck; #ifdef ASM asm { mov bx,11 call voc_ptr_to_driver mov pcheck,ax } #else _BX = 11; cal (voc_ptr_to_driver); pcheck = _AX; #endif if (pcheck == 1) { voc_paused = FALSE; voc_err_stat = 520; } } void _voc_breakloop(WORD breakmode) /* * ENTRE : Mode d'interruption * SORTIE : aucune * FONCTION : Stoppe une boucle dans un chantillon */ { #ifdef ASM asm { mov bx,12 mov ax,breakmode call voc_ptr_to_driver mov breakmode,ax } #else _BX = 12; _AX = breakmode; cal (voc_ptr_to_driver); breakmode = _AX; #endif if (breakmode == 1) voc_err_stat = 500; } /* **************************************************************************** * Programme de dmonstration pour l'Unit VOCTOOL, (W) in Borland C++ 3.0 * * **************************************************************************** * (C) 1992 MICRO APPLICATION * * Auteur : Axel Stolz * **************************************************************************** */ /* #include #include "voctool.h" */ #include void erreur() /* * ENTRE : aucune, les donnes proviennent de la variable globale : voc_err_stat * SORTIE : aucune * FONCTION : Affiche le type d'erreur venant de se produire avec le * numro d'erreur. Termine le programme avec le niveau * d'erreur correspondant au numro. */ { printf(" Erreur # %d, ",voc_err_stat); _print_voc_errmessage(); exit(voc_err_stat); } char *create_voc (float periode, int a, int duree, int np, int flag_harmon, int flag_create); void dump (char *buffer, int n); #define TAILLE_TABLE_SIN 1000 float table_sin [TAILLE_TABLE_SIN+1]; #define PI 3.1415926 init_table () { int i; for (i=0; i<=TAILLE_TABLE_SIN; i++) table_sin[i] = sin (i * 2.0 * PI / TAILLE_TABLE_SIN); } float mysin (float x) { float y; int i; i = x * TAILLE_TABLE_SIN / (2.0 * PI); i = i % TAILLE_TABLE_SIN; if (i < 0) i += TAILLE_TABLE_SIN; y = table_sin [i]; return y; } void main (int argc, char *argv[]) { VOCPTR voc_buffer = 0; char ch; float periode; int note; init_table (); clrscr(); if (_voc_init_driver() == FALSE) erreur(); loop: gotoxy(1,1); printf("\n"); if (!init_son ()) goto end; /* Charge le fichier DEMO.VOC dans la mmoire */ /* voc_buffer = _voc_get_buffer("demo.voc"); */ voc_buffer = create_voc ((float)atoi(argv[1]), atoi(argv[2]), atoi(argv[3]), atoi(argv[4]), atoi(argv[5]), 1); loop1: trace ("loop1", 0); vocfile_headerlength = 0; trace ("%p", voc_buffer); /* Le fichier VOC n'a pas pu tre charg */ if (voc_buffer == NULL) erreur(); /* dump (voc_buffer, 120); */ /* Boucle principale du programme */ /* printf("CT-Voice-Driver Version : "); printf("%d.%02d\n",vocdriver_version >> 8, vocdriver_version % 256); printf("Voulez-vous couter le son (u)ne ou (p)lusieurs fois ?\n"); printf("Entre : "); ch = getche(); printf("\n\n"); */ ch = 'p'; switch (ch) { case 'u': printf("Frapper une touche pour interrompre"); _voc_output(voc_buffer); do {} while ((voc_status_word != 0) && (kbhit() == 0)); if (kbhit() != 0) _voc_stop(); break; case 'p': /* printf(" Appuyer sur pour quitter"); ch = ' ';*/ ch = 0; do { trace ("output %p", voc_buffer); _voc_output_loop(voc_buffer); trace ("done", 0); do { trace ("%d", voc_status_word); } while ((voc_status_word != 0) && (kbhit() == 0)); if (kbhit() != 0) { ch = getch(); trace ("0x%02X", ch); } } /*while (ch != (char)27);*/ while (!ch); trace ("stop...", 0); _voc_stop(); trace ("", 0); break; } trace ("0x%02X", ch); if (ch == '\n' || ch == '\r') goto loop; note = clavier (ch); trace ("%d", note); periode = (float) atoi(argv[1]) / pow (2.0, (float) note / 12.0); printf (" Touche '%c' 0x%02X, note %d, periode %f \n", ch, ch, note, periode); voc_buffer = create_voc (periode, atoi(argv[2]), atoi(argv[3]), atoi(argv[4]), atoi(argv[5]), 0); { int i; /* for (i=0; i<120; i++) printf ("%02X ", (unsigned char)(voc_buffer[i])); */ printf ("\n"); } goto loop1; /* Librer la mmoire occupe par le fichier VOC */ end: _dos_freemem(FP_SEG(voc_buffer)); _voc_deinstall_driver(); } /*#include */ /* #include #include */ #include /* #include #include */ #define FP_SEG(fp) (*(int *)(((char *)&(fp))+2)) #define FP_OFS(fp) ((int)(fp)) #define call(adr) (*(void (far *)())(adr))() #define PI 3.1415926 #define f sound_fn #define fonction(fx) \ float f (float x) {float y; y=0.0; {fx;} return y; } \ char def_f[] = #fx; /* fonction (y = sin(x)) */ /* fonction (int n; for (n=1; n<=18; n++) y += sin (n * x) / n;) */ float phi[50]; float ampl[50]; int nh; /* fonction (int n; for (n=1; n<=20; n++) y += sin (n * x + phi[n]) / n;) */ #if 1 fonction (int n; for (n=1; n<=nh; n++) y += sin (n * x) * ampl[n] /* / n */ ;) #else fonction (y = ampl[x]) #endif /* float f (float x) { return sin(x); } */ #define SIZE 0x4000 char buffer[SIZE]; int ptr; void dump (char *buffer, int length) { int i; for (i=0; i0); } main1 (int argc, char *argv[]) { int status; int t, i; float x, y; int driver, mode; int len; FILE *fvoc; char buf[120]; /* initgraph (HERCMONO, HERCMONOHI, ""); */ /* initgraph (EGA, EGA64LO, ""); */ #if 0 driver = EGA; mode = EGA64LO; driver = HERCMONO; mode = HERCMONOHI; initgraph (&driver, &mode, ""); status = graphresult(); if (status != grOk) printf ("Erreur initgraph %d 0x%X\n", status, status); for (i=1; i<50; i++) { phi[i] = /*0;*/ 2 * PI * (float)random(10000) / 10000.0; } for (t=0; t<1000; t++) { /* x = sin(t); y = sin(t*1.5); putpixel (100+60*x, 80+40*y, 1); */ x = t * 2 * PI / 1000; y = f(x); putpixel (10+100*x, 180-100*y, 1); } getchar(); #endif i = 1; saisie: printf ("\tHarmonique %d ? "); gets (buf); if (*buf) { sscanf (buf, "%f", &(ampl[i])); i++; goto saisie; } nh = i; printf ("Adresse: %p:%p\n", _DS, (char far *)buffer); len = vcreat (argc, argv, buffer); dump (buffer+0x1A, 250); vtest (buffer+0x1A); fvoc = fopen (argv[1], "wb"); if (fvoc == NULL) { perror(argv[1]); return (errno); } fwrite (buffer, 1, len, fvoc); fclose (fvoc); /*restorecrtmode();*/ } /* #include #include #include */ #define f voc_file FILE *f; flush () { fwrite (buffer, 1, ptr, f); ptr = 0; } put (char c) { if (ptr >= SIZE) flush(); buffer[ptr++] = c; } int vcreat (int argc, char *argv[], char *buffer) { char c; int n, i; int t, duree, periode; float a, puls; char *p; char buf[120]; ptr = 0; p = buffer; a = atoi(argv[2]); periode = atoi(argv[3]); duree = atoi(argv[4]); i = 1; saisie: printf ("\tHarmonique %d ? "); gets (buf); if (*buf) { sscanf (buf, "%f", &(ampl[i])); i++; goto saisie; } nh = i; /* f = fopen (argv[1], "wb"); if (f == NULL) { perror(argv[1]); return (errno); } */ p += sprintf (p, "Creative Voice File%c%c%c%c%c%c%c", 0x1A, 0x1A, 0, 0x0A, 0x01, 0x29, 0x11); p += sprintf (p, "%c%c%c%c%c%c", 6, 2, 0, 0, duree&0xFF, duree>>8); p += sprintf (p, "%c%c%c%c%c%c", 0x01, (periode+2)&0xFF, (periode+2)>>8, 0, 0x83, 0); for (t=0; t #define LARGEUR 600 #define HAUTEUR 200 char *create_voc (float periode_float, int a, int duree, int np, int flag_harmon, int flag_create) { char c; int n, i; int t; char *p; unsigned char buf_son[4000]; int pn; int driver, mode; int status; char buf[200]; static int flag_init = 1; int periode; trace ("create_voc", 0); periode = (int) (periode_float + 0.5); trace ("", 0); if (flag_init == 0) flag_create = 0; flag_init = 0; trace ("", 0); if (flag_create) { trace ("", 0); driver = HERCMONO; mode = HERCMONOHI; initgraph (&driver, &mode, "C:\D1"); status = graphresult (); if (status != grOk) { printf ("Erreur initgraph %d 0x%X\n", status, status); exit (status); } } trace ("", 0); ptr = 0; p = buffer; if (duree != -1) p += sprintf (p, "%c%c%c%c%c%c", 6, 2, 0, 0, duree&0xFF, duree>>8); trace ("%p", p); p += sprintf (p, "%c%c%c%c%c%c", 0x01, (int)(periode*np+2)&0xFF, (int)(periode*np+2)>>8, 0, 0x83, 0); trace ("%d", periode); for (t=0; t>8); p += sprintf (p, "%c%c%c%c", 0x02, (periode)&0xFF, (periode)>>8, 0); for (t=0; t 76) n = 76; for (i=0; i