⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 delay.c

📁 大量的汇编程序源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -------------------------------------------------------------------------- */
/*                                                                            */
/* (C) Copyright Creative Technology Ltd 1994-1996. All right reserved        */
/*                                                                            */
/* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY      */
/* KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE        */
/* IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR      */
/* PURPOSE.                                                                   */
/*                                                                            */
/* You have a royalty-free right to use, modify, reproduce and                */
/* distribute the Sample Files (and/or any modified version) in               */
/* any way you find useful, provided that you agree that                      */
/* Creative has no warranty obligations or liability for any Sample Files.    */
/*                                                                            */
/*----------------------------------------------------------------------------*/

/* DELAY.C
 *
 * D. Kaden 6/22/94
 *
 * Copyright (c) 1993, 1994 Creative Labs, Inc.
 *
 * This program records and plays simultaneously using two Sound Blaster
 * cards.
 *
 * In addition to the normal BLASTER environment variable, you should also
 * have a BLASTER2 environment variable for the second Sound Blaster card.
 *
 * For example, your environment should look something like this:
 *
 *    BLASTER=A220 I5 D1 H5 P330 T6
 *    BLASTER2=A240 I7 D3 H6 P330 T6
 *
 * The first card (BLASTER) does the recording.  The second (BLASTER2) does
 * the playback.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <conio.h>
#include <dos.h>
#include <mem.h>
#include <fcntl.h>
#include "mydefs.h"
#include "sbdefs.h"

#define FILENAME "delay.raw"


// Structure for storing data associated with each SB card.
typedef struct {
   int base,                         // SB card base I/O address
    MixerAddr, MixerData,            // mixer chip addresses
    Reset, WrBuf,                    // DSP addresses
    DataAvail, ReadData,             // DSP addresses
    irq,                             // IRQ number
    dma8,                            // 8-bit DMA channel
    dma16,                           // 16-bit DMA channel
    midi,                            // midi port
    cardtype;                        // card type number from environment
    void interrupt (*intvecsave)();  // previous interrupt vector
    int intrnum;                     // interrupt number
    int intrmask;                    // interrupt mask
   } cardinfo;


// Structure for retrieving DMA controller register port addresses.
typedef struct {
   unsigned char addr, count, page, mask, mode, FF;
   } dmaportstruct;


// Constant array that defines port addresses for DMA controller registers.
const dmaportstruct dmaportarray[8] = {
    {0x0,  0x1,  0x87, 0xA,  0xB,  0xC},   // chan 0
    {0x2,  0x3,  0x83, 0xA,  0xB,  0xC},   // chan 1
    {0x4,  0x5,  0x81, 0xA,  0xB,  0xC},   // chan 2  DON'T USE
    {0x6,  0x7,  0x82, 0xA,  0xB,  0xC},   // chan 3
    {0x0,  0x0,  0x00, 0xD4, 0xD6, 0xD8},  // chan 4  DON'T USE
    {0xC4, 0xC6, 0x8B, 0xD4, 0xD6, 0xD8},  // chan 5
    {0xC8, 0xCA, 0x89, 0xD4, 0xD6, 0xD8},  // chan 6
    {0xCC, 0xCE, 0x8A, 0xD4, 0xD6, 0xD8}   // chan 7
   };




#define BUFSIZE (8*1024)      // size of the DMA buffer
#define NUMBUFS 2
#define TIMECONST 165         // 165 = approx 11.5 KHz sample rate


cardinfo      card1, card2;

              // It would be better to dynamically allocate the DMA buffers
              // to guarantee that they don't cross a DMA page boundary.
              // This is quick and dirty, but it usually works.
unsigned char recbuf[BUFSIZE],         // recording DMA buffer
              playbuf[BUFSIZE];        // playback DMA buffer

unsigned int  inpage,   outpage,       // DMA pages for input and output buffers
              inoffset, outoffset,     // offsets for DMA input and output buffers
              count = BUFSIZE;         // size of the DMA buffers

char          *inbuffers[NUMBUFS];     // Input (recording) buffers to
                                       //  transfer data from DMA buffer
                                       //  to disk.
char          *outbuffers[NUMBUFS];    // Output (playback) buffers to
                                       //  transfer data from disk to DMA
                                       //  buffer.

int           NumFilledInBufs   = 0,   // number of filled input buffers
              NumFilledOutBufs  = 0,   // number of filled output buffers
              NumRecBufToFill   = 0,   // next input buffer to fill from DMA buffer
              NumRecBufToEmpty  = 0,   // next input buffer to copy to disk
              NumPlayBufToFill  = 0,   // next output buffer to fill from disk
              NumPlayBufToEmpty = 0,   // next output buffer to copy to DMA buffer
              HalfBufToEmpty    = 0,   // which half of input DMA buffer to empty
              HalfBufToFill     = 0,   // which half of output DMA buffer to fill
              NumBufsWritten    = 0;   // number of buffers written to disk



int base16(char **str, int *val)
/* Takes a double pointer to a string, interprets the characters as a
 * base-16 number, and advances the pointer.
 * Returns 0 if successful, 1 if not.
 */
{
   char c;
   int digit;
   *val = 0;

   while ((**str != ' ') && (**str != '\0')) {
      c = toupper(**str);
      if (c >= '0' && c <= '9')
         digit = c - '0';
      else if (c >= 'A' && c <= 'F')
         digit = c - 'A'  + 10;
      else
         return 1;          // error in string

      *val = *val * 16 + digit;
      (*str)++;
   }
   return 0;
}



int base10(char **str, int *val)
/* Takes a double pointer to a string, interprets the characters as a
 * base-10 number, and advances the pointer.
 * Returns 0 if successful, 1 if not.
 */
{
   char c;
   int digit;
   *val = 0;

   while ((**str != ' ') && (**str != '\0')) {
      c = toupper(**str);
      if (c >= '0' && c <= '9')
         digit = c - '0';
      else
         return 1;          // error in string

      *val = *val * 10 + digit;
      (*str)++;
   }
   return 0;
}



int ReadBlasterEnv(char *name, int *port, int *irq, int *dma8, int *dma16,
 int *midi, int *cardtype)
/* Gets the Blaster environment statement and stores the values in the
 * variables whose addresses were passed to it.
 *
 * Input:
 *   name  - environment name to get, usually "BLASTER"
 *
 * Returns:
 *   0  if successful
 *   1  if there was an error reading the port address.
 *   2  if there was an error reading the IRQ number.
 *   3  if there was an error reading the 8-bit DMA channel.
 *   4  if there was an error reading the 16-bit DMA channel.
 *   5  if there was an error reading the MIDI address.
 *   6  if there was an error reading the card type number.
 */
{
   char     *env;
   unsigned val;
   int      digit;

   env = getenv(name);

   if (!env)
      return 7;   // if there was no environment entry for name.

   while (*env) {
      switch(toupper( *(env++) )) {
         case 'A':
            if (base16(&env, port))
               return 1;
            break;
         case 'I':
            if (base10(&env, irq))
               return 2;
            break;
         case 'D':
            if (base10(&env, dma8))
               return 3;
            break;
         case 'H':
            if (base10(&env, dma16))
               return 4;
            break;
         case 'P':
            if (base16(&env, midi))
               return 5;
            break;
         case 'T':
            if (base10(&env, cardtype))
               return 6;
            break;
         default:
            break;
      }
   }

   return 0;
}



void SegToPhys(unsigned char far *ptr, unsigned long size, unsigned long *physaddr, unsigned long *endaddr)
// Converts a segmented address to a physical memory address.
{
   *physaddr=(unsigned long)(((unsigned long)FP_SEG(ptr) << 4) + FP_OFF(ptr));
   *endaddr = *physaddr+size-1;
}



unsigned int PhysToPage(unsigned long physaddr, unsigned long endaddr, unsigned int *page, unsigned int *offset)
/* Converts a physical memory address to a DMA-page address.  Returns the
 * number of bytes in this block of memory that aren't in a different DMA
 * page.
 *  INPUT:
 *   physaddr - a physical (not segmented) address specifying the start
 *              of the DMA buffer.
 *   endaddr  - a physical address specifying the last byte of the DMA
 *              buffer.
 *  OUTPUT:
 *   page     - the DMA page of the buffer.
 *   offset   - the offset of the buffer.
 *  RETURN VALUE:
 *   The minimum of (endaddr-physaddr+1, number of bytes in this page
 *   starting at physaddr).
 */
{
   unsigned int remaining;
   *page=physaddr >> 16;
   *offset=physaddr & 0xFFFF;

   remaining=0xFFFF - *offset + 1;   /* bytes remaining in page */
   if (remaining>endaddr-physaddr)   /* if more bytes left in page than in buffer */
      return endaddr-physaddr+1;     /* return number of bytes in buffer */
   else return remaining;            /* else return number of bytes left in page */
}



void dspout(cardinfo *card, unsigned int val)
// Output a byte to the Sound Blaster Digital Sound Processor.
{
   while (inp(card->WrBuf) & 0x80)
      ;
   outp(card->WrBuf, val);
}



boolean dspin(cardinfo *card, unsigned int *val)
// Read a byte from the Digital Sound Processor.
{
   while (!(inp(card->DataAvail) & 0x80)) {
      ;
   }
   *val=inp(card->ReadData);

   return true;    // used to be meaningful
}



void SetupDMA(int dmachan, unsigned short page, unsigned short ofs,
 unsigned short DMAcount, unsigned char dmacmd)
// This programs the DMA controller.
// NOTE:  This function supports 8-bit DMA channels ONLY (because this pro-
// gram only uses 8-bit voice mode.  The SetupDMA function in the program
// DELAY2.C supports both 8- and 16-bit DMA channels.
{
   dmaportstruct dmaports;

/**** There MUST be parens around the values to be output, or the compiler
 **** will convert them to unsigned chars BEFORE it does the operations
 **** on them.
 ****/
   dmaports = dmaportarray[dmachan];

   outp(dmaports.mask, 4 | dmachan);            // mask off dma channel
   outp(dmaports.FF, 0);                        // clear flip-flop
/* This next value to DMAC is different between auto-init and non-auto-init.
 * (0x58 vs. 0x48) */
   outp(dmaports.mode , dmacmd | dmachan);      // set mode
   outp(dmaports.addr, (ofs & 0xFF));           // low byte base addr
   outp(dmaports.addr, (ofs >> 8));             // high byte base addr
   outp(dmaports.page, page);                   // physical page number
   outp(dmaports.count,((DMAcount-1) & 0xFF));  // count low byte
   outp(dmaports.count,((DMAcount-1) >> 8));    // count high byte
   outp(dmaports.mask, dmachan);                // enable dma channel
}



void SetupDSP(cardinfo *card, unsigned char dspcmd, unsigned short DSPcount,
 unsigned char tc)
// Programs the Sound Blaster card.
{
   // Program the time constant.
   dspout(card, dspcmdTimeConst);
   dspout(card, tc);

   // Program the DMA buffer size.
   dspout(card, dspcmdBlockSize);
   dspout(card, (DSPcount-1) & 0xFF);
   dspout(card, (DSPcount-1) >> 8);

   // Send the play or record command.
   dspout(card, dspcmd);
}



void SetupInputDMA(unsigned int page, unsigned int ofs, int count,
 unsigned char tc)
// Program the DMA Controller and Sound Blaster for DMA input.
{
   SetupDMA(card1.dma8, page, ofs, count, DMAMODEWRITE);
   SetupDSP(&card1, dspcmdAUTODMAADC, count/2, tc);
}



void SetupOutputDMA(unsigned int page, unsigned int ofs, int count,
 unsigned char tc)
// Program the DMA Controller and Sound Blaster for DMA output.
{
   SetupDMA(card2.dma8, page, ofs, count, DMAMODEREAD);
   SetupDSP(&card2, dspcmdAUTODMADAC, count/2, tc);
}



void SetMixer(cardinfo *card1, cardinfo *card2)
// Resets the SB cards and selects the proper input.
{

   unsigned int val;

   /* reset sb card #1 */
   outp(card1->Reset,1);
   delay(1);
   outp(card1->Reset,0);
   if (dspin(card1, &val))
      if (val!=dspReady)
         printf("Sound Blaster card #1 not ready.");

   switch (card1->cardtype) {
      case 2:
      case 4:     // SBPRO
         outp(card1->MixerAddr, ADCSELECT);
         outp(card1->MixerData, 0);             // select microphone
         dspout(card1, 0xD3);                   // turn speaker off
         break;
      case 6:     // SB16
         outp(card1->MixerAddr, SB16INPUTL);
         outp(card1->MixerData, 1);             // select microphone
         outp(card1->MixerAddr, SB16INPUTR);
         outp(card1->MixerData, 1);             // select microphone
         break;
   }

   /* reset sb card #2 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -