LIBS/WAVPLAV/VOCPLAY.CPP
2021-09-08 21:26:43 +02:00

406 lines
9.4 KiB
C++
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <conio.h>
#include <alloc.h>
#include <dos.h>
#include <io.h>
#include "sb.h"
#include "dac.h"
#include "speaker.h"
#include "Wavplay.h"
#define FALSE 0
#define TRUE 1
#define ERROR_ABRIENDO 2
#define SIN_MEMORIA 3
#define FICHERO_ENORME 4
char huge *pWav, /* Puntero a la digitalizaci¢n */
huge *pMuestra; /* Puntero a la muestra que suena */
long Tamanyo, /* Tama¤o de los datos */
T_Real;
unsigned
Divisor, /* Valor del divisor del Timer 0 */
Frec=11000; /* Frecuencia de muestreo */
char FinVoz; /* Indica si la digitalizaci¢n ha terminado de sonar */
void interrupt (*Antigua8)(...); /* Antigua INT 8 */
void (*ByteAlDAC)(unsigned char); /* Puntero a la funci¢n que env¡a el byte al DAC */
char Wav_Mem = 0, Init = 0, SB_SPK = 0, Old_File[80];
int CargaWav(char *Nombre, long Pos, long Len);
void DeInitSB(void);
int InitSB(void);
int Condicion_S00(void);
int PlayWav(char far *File, long Pos, long Len );
int PlayLongWav(char far *File, long Pos, long Len);
void ProgFrec(unsigned *Frecuencia);
void interrupt Nuestra8(...);
void ProgTimer0(unsigned Divisor);
//int far TeclaPulsada(void);
/*
int main(int argc, char *argv[])
{
if (argc<2)
{
printf("Error: falta par metro necesario.\n");
printf(" Fichero Salida\n");
printf(" Salida --> 0 Speaker\n");
printf(" --> 1 SB\n");
printf(" --> 2 Dac\n");
return(1);
}
InitSB();
if ( argc == 3 ) SB_SPK = atoi(argv[2]);
if ( PlayWav(argv[1],TeclaPulsada) != 0 )
PlayLongWav(argv[1],TeclaPulsada);
return 0;
}
*/
/* *//* *//**/
/* *//* Ûßß ÜßßÜ ÛßßÜ Ûßßß ÜßßÜ Û Û ÛßßÛ Ûßß Û Û ÜßßÜ Û Û *//**/
/* *//* Û ÛÜÜÛ ÛÜÜß Û ÜÜ ÛÜÜÛ Û Û Û Û Û Û Û ÛÜÜÛ Û Û *//**/
/* *//* ÛÜÜ Û Û Û ßÜ ÛÜÜÛ Û Û ßÜß ÛÜÜÛ ÛÜÜ ÜÜÜÜ ßÜßÜß Û Û ßÜß *//**/
/* *//* JD*//**/
int CargaWav(char *Nombre, long Pos, long Len)
{
FILE *handle_sonido;
long tam = 0;
if( Wav_Mem == 1 ) { farfree( pWav ); Wav_Mem = 0; }
if((handle_sonido = fopen(Nombre, "rb"))==NULL) {
return ERROR_ABRIENDO;
}
if( (Tamanyo =
( (Len==-1) ?
filelength(fileno(handle_sonido))-32
:
Len - 32
)
) < 1 ) { T_Real = 0; return ERROR_ABRIENDO; }
fseek( handle_sonido, Pos, SEEK_SET );
T_Real = Tamanyo;
if ( (pWav = (char huge *)farmalloc(Tamanyo+32) ) == NULL ) {
fclose(handle_sonido);
return SIN_MEMORIA;
}
Wav_Mem = 1;
pMuestra = pWav;
fread(pMuestra, sizeof(char), 24, handle_sonido); // C A B E C E R A . . .
fread(&Frec, sizeof(unsigned int), 1, handle_sonido); // C A B E C E R A . . .
if ( Frec <2000 ) Frec = 11025;
fread(pMuestra, sizeof(char), 6, handle_sonido); // C A B E C E R A . . .
pMuestra = pWav;
while( tam < (Tamanyo + 1)) {
tam++; *pMuestra++ = getc(handle_sonido);
//if(pWav == pMuestra) printf("\nEl puntero esta en el origen o dio la vuelta durante la carga... %ld\n", tam);
}
pMuestra = pWav;
fclose(handle_sonido);
return 1;
}
void ProgTimer0(unsigned Divisor)
/* Programa el Timer 0 para que cuente desde Divisor hasta 0 */
{
asm CLI; /* Inhabilitamos interrupciones: secci¢n cr¡tica */
outportb(0x43,0x36); /* 00111010: Timer 0, acceso secuencial y modo cont¡nuo */
outportb(0x40,Divisor & 0xFF); /* Byte bajo del contador */
outportb(0x40,Divisor >> 8); /* Byte alto del contador */
asm STI; /* Fin de secci¢n cr¡tica */
}
void ProgFrec(unsigned *Frecuencia)
/* Programa el Timer 0 para que genere "Frecuencia" interrupciones por segundo */
{
Divisor = 1193180 / *Frecuencia;
*Frecuencia = 1193180 / Divisor;
ProgTimer0(Divisor);
}
void interrupt Nuestra8(...)
{
if (!FinVoz)
{
(*ByteAlDAC)(*pMuestra);
pMuestra++;
Tamanyo--;
if (Tamanyo<=1) FinVoz = TRUE;
}
outportb(0x20,0x20); /* Indicamos al controlador de interrupciones */
} /* que la interrupci¢n ha sido atendida */
void DeInitSB(void){
if ( Wav_Mem == 1 ) { farfree( pWav ); Wav_Mem = 0; }
}
int InitSB(void){
if ( Init == 0 )
atexit( DeInitSB );
Init = 1;
return ( ( SBDetect() != -1 ) ? ( SB_SPK = 1 ) : ( SB_SPK = 0 ) );
}
/**//* *//**/
/**//* ÛßßÜ Û ÜßßÜ Û Û Û Û ÛßßÛ Ûßß Û Û ÜßßÜ Û Û *//**/
/**//* ÛÜÜß Û ÛÜÜÛ ßÜß Û Û Û Û Û Û Û ÛÜÜÛ Û Û *//**/
/**//* Û ÛÜÜ Û Û Û ßÜß ÛÜÜÛ ÛÜÜ ÜÜÜÜ ßÜßÜß Û Û ßÜß *//**/
/**//* JD*//**/
int PlayWav(char far *File, long Pos, long Len)
{
static long Old_Pos = -1;
if( Len == -1 ) {
if ( strcmpi( File, Old_File ) != 0 || !Wav_Mem ) {
if ( CargaWav(File, Pos, Len) != 1 ) { strcpy( Old_File, "\0" ); return (-1); }
strcpy( Old_File, File );
} else {
pMuestra = pWav;
Tamanyo = T_Real;
}
} else {
if ( Old_Pos != Pos || !Wav_Mem ) {
if ( CargaWav(File, Pos, Len) != 1 ) { strcpy( Old_File, "\0" ); return (-1); }
Old_Pos = Pos;
} else {
pMuestra = pWav;
Tamanyo = T_Real;
}
}
switch ( SB_SPK ) {
case 0:
InitSpeaker();
FinVoz = TRUE;
ByteAlDAC = SpkSendByte;
break;
case 1:
FinVoz = TRUE;
ByteAlDAC = SBSendByte;
break;
case 2:
InitDAC();
FinVoz = TRUE;
ByteAlDAC = LPT1DAC;
break;
default:
return -1;
}
Antigua8 = getvect(8); /* Guardamos el puntero a la antigua INT 8 */
setvect(8,Nuestra8); /* Colocamos el puntero a nuestra rutina */
ProgFrec(&Frec);
FinVoz = FALSE;
while (!FinVoz && !Condicion_S00() );
// /* if ( !*/Condicion_S00() /*) while (!FinVoz)*/;
ProgTimer0(0);
CloseSpeaker();
setvect(8,Antigua8);
return(0);
}
int PlayLongWav(char far *File, long Pos, long Len)
{
const int Buff = 4096;
FILE *handle_sonido;
long n_lecturas, pico_lectr;
char parte=0, key;
if( Wav_Mem == 1 ) { farfree( pWav ); Wav_Mem = 0; }
if((handle_sonido = fopen(File, "rb"))==NULL) {
return ERROR_ABRIENDO;
}
if( (Tamanyo =
( (Len==-1) ?
filelength(fileno(handle_sonido))-32
:
Len - 32
)
) < 1 ) { T_Real = 0; return ERROR_ABRIENDO; }
fseek( handle_sonido, Pos, SEEK_SET );
T_Real = Tamanyo;
n_lecturas = Tamanyo / Buff;
pico_lectr = Tamanyo - ( n_lecturas * Buff );
if ( (pWav = (char huge *)farmalloc(Buff*2) ) == NULL ) {
fclose(handle_sonido);
return SIN_MEMORIA;
}
Wav_Mem = 1;
pMuestra = pWav;
// fread(pMuestra, sizeof(char), 32, handle_sonido); // C A B E C E R A . . .
fread(pMuestra, sizeof(char), 24, handle_sonido); // C A B E C E R A . . .
fread(&Frec, sizeof(unsigned int), 1, handle_sonido); // C A B E C E R A . . .
if ( Frec <2000 ) Frec = 8050;
fread(pMuestra, sizeof(char), 6, handle_sonido); // C A B E C E R A . . .
if(n_lecturas) {
fread(pWav, sizeof(char), Buff, handle_sonido);
Tamanyo = Buff;
} else {
fread(pWav, sizeof(char), pico_lectr, handle_sonido);
Tamanyo = pico_lectr;
}
switch ( SB_SPK ) {
case 0:
InitSpeaker();
FinVoz = TRUE;
ByteAlDAC = SpkSendByte;
break;
case 1:
FinVoz = TRUE;
ByteAlDAC = SBSendByte;
break;
case 2:
InitDAC();
FinVoz = TRUE;
ByteAlDAC = LPT1DAC;
break;
default:
return -1;
}
Antigua8 = getvect(8); /* Guardamos el puntero a la antigua INT 8 */
setvect(8,Nuestra8); /* Colocamos el puntero a nuestra rutina */
ProgFrec(&Frec);
FinVoz = FALSE;
parte = 1;
if ( n_lecturas > 0 ) {
while( n_lecturas > 0 ){ // Ejecutamos tantas veces con Lecturas Buff se
// puedan hacer...
n_lecturas--; // Vaya se nos fue una lectura...
if ( n_lecturas > 0 ) { // Si quedan lecturas... llenamos el Doble Buffer
if( parte ) fread( (pWav+4096), sizeof(char), Buff, handle_sonido );
else fread( (pWav ), sizeof(char), Buff, handle_sonido );
} else
if ( pico_lectr > 0) {
if( parte ) fread( (pWav+4096), sizeof(char), pico_lectr, handle_sonido );
else fread( (pWav ), sizeof(char), pico_lectr, handle_sonido );
}
while (!FinVoz && !(key = Condicion_S00() ) );
// if ( !(key = Condicion()) ) while (!FinVoz);
if ( key ) { FinVoz = TRUE; break; }
if ( (n_lecturas > 0 || pico_lectr !=0) && !key ) {
if( parte ){ parte = 0; /* Ya colocado */}
else { parte = 1; pMuestra = pWav; }
if (n_lecturas > 0) Tamanyo = Buff; else Tamanyo = pico_lectr;
FinVoz = FALSE;
}
}
while (!FinVoz && !Condicion_S00());
// if ( !(Condicion()) ) while (!FinVoz);
} else
while (!FinVoz && !Condicion_S00());
// if ( !(Condicion()) ) while (!FinVoz);
ProgTimer0(0);
CloseSpeaker();
setvect(8,Antigua8);
fclose(handle_sonido);
DeInitSB();
return(0);
}
// int far TeclaPulsada(void)
/* Esta funci¢n mira si se ha pulsado una tecla pero SIN llamadas a la BIOS,
de forma que no se inhabilitan las interrupciones en cada llamada, cosa
que bajar¡a mucho la calidad de reproducci¢n con el altavoz interno. */
// {
// return ( *(unsigned *) MK_FP(0x40,0x1A) != *(unsigned *) MK_FP(0x40,0x1C) );
// }
int Condicion_S00(void)
{
union REGS RaT;
RaT.x.ax = 3;
int86(0x33, &RaT, &RaT);
return (( *(unsigned *) MK_FP(0x40,0x1A) != *(unsigned *) MK_FP(0x40,0x1C) ) || (RaT.x.bx & 1));
}