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

📄 delay.c

📁 大量的汇编程序源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
   outp(card2->Reset,1);
   delay(1);
   outp(card2->Reset,0);
   if (dspin(card2,&val))
      if (val!=dspReady)
         printf("Sound Blaster card #2 not ready.");

   switch (card2->cardtype) {
      case 2:
      case 4:     // SBPRO
         dspout(card2,0xD1);        // turn speaker on
         break;
      case 6:
         outp(card2->MixerAddr, SB16INPUTL);
         outp(card2->MixerData, 0);             // select nothing
         outp(card2->MixerAddr, SB16INPUTR);
         outp(card2->MixerData, 0);             // select nothing
         break;
   }
}



void InitScreen(void)
{
   clrscr();
   printf("Two Sound Blaster Delay program.\nPress any key to stop.\n");
}



void DrainInputBuffer(void)
// Copies half the DMA buffer to one of the record buffers.
{
   // Copy data from current half of DMA buffer to next input buffer. 
   memcpy(inbuffers[NumRecBufToFill], recbuf + HalfBufToEmpty*BUFSIZE/2, BUFSIZE/2);

   // Make next buffer current
   ++NumRecBufToFill;
   if (NumRecBufToFill >= NUMBUFS)
      NumRecBufToFill =  0;

   // Increment count of filled input buffers.
   ++NumFilledInBufs;

   // Next time use other half of DMA buffer.
   HalfBufToEmpty ^= 1;

}


void FillOutputBuffer(void)
// Copies one of the output buffers to half the DMA buffer.
{
   // Copy data from next output buffer to current half of DMA buffer.
   memcpy(playbuf + HalfBufToFill*BUFSIZE/2, outbuffers[NumPlayBufToEmpty], BUFSIZE/2);

   // Make next buffer current
   ++NumPlayBufToEmpty;
   if (NumPlayBufToEmpty >= NUMBUFS)
      NumPlayBufToEmpty =  0;

   // Decrement count of filled output buffers.
   --NumFilledOutBufs;

   // Next time use other half of DMA buffer.
   HalfBufToFill ^= 1;
}



void interrupt InputSBISR(void)
// Service interrupts from SB doing input.
{
   // Make sure this wasn't a spurious interrupt.
   if (card1.irq == 7) {
      outp(PIC1MODE, 0xB);                // select In Service Register
      if ((inp(PIC1MODE) & 0x80) == 0)    // if bit 7 == 0, spurious interrupt
         return;
   }

   inp(card1.DataAvail);                  // acknowledge interrupt

   DrainInputBuffer();

   if (card1.irq > 8)                     // If irq 10, send EOI to second PIC.
      outp(PIC2MODE, PICEOI);
   outp(PIC1MODE,PICEOI);                 // Send EOI to first PIC.
}



void interrupt OutputSBISR(void)
// Service interrupts from SB doing output.
{
   // Make sure this wasn't a spurious interrupt.
   if (card2.irq == 7) {
      outp(PIC1MODE, 0xB);                // select In Service Register
      if ((inp(PIC1MODE) & 0x80) == 0)    // if bit 7 == 0, spurious interrupt
         return;
   }

   inp(card2.DataAvail);                  // acknowledge interrupt

   FillOutputBuffer();

   if (card2.irq > 8)                     // If irq 10, send EOI to second PIC.
      outp(PIC2MODE, PICEOI);
   outp(PIC1MODE,PICEOI);                 // Send EOI to first PIC.
}





int GetCardInfo(char *name, cardinfo *card)
// Read a blaster environment string.
{
   int result;
   int dummy;

   result=ReadBlasterEnv(name, &card->base, &card->irq, &card->dma8, &dummy,
    &dummy, &card->cardtype);

   if (result != 0) {
      switch (result) {
         case 1:
            printf("Error in %s port address.\n",name);
            break;
         case 2:
            printf("Error in %s IRQ number.\n",name);
            break;
         case 3:
            printf("Error in %s 8-bit DMA channel.\n",name);
            break;
         case 4:
            printf("Error in %s 16-bit DMA channel.\n",name);
            break;
         case 5:
            printf("Error in %s MIDI address.\n",name);
            break;
         case 6:
            printf("Error in %s card type number.\n",name);
            break;
         case 7:
            printf("Error:  %s environment variable not set.\n",name);
            break;
      }
   }

   card->WrBuf     = card->base + dspoffsetWrBuf;
   card->Reset     = card->base + dspoffsetReset;
   card->ReadData  = card->base + dspoffsetReadData;
   card->DataAvail = card->base + dspoffsetDataAvail;
   card->MixerAddr = card->base + dspoffsetMixerAddr;
   card->MixerData = card->base + dspoffsetMixerData;

   return result;
}



void EnableCardInterrupt(cardinfo *card, void interrupt (*newvect)())
{
   int intrmask;

   // calculate interrupt number for IRQ
   if (card->irq < 8)
      card->intrnum = card->irq + 8;          // IRQs 0-7 map to interrupts 8-15.
   else
      card->intrnum = card->irq - 8 + 0x70;   // IRQs 8-15 map to interrupts 70H-78H.

   // generate 16-bit mask for IRQ
   card->intrmask = 1 << card->irq;

   card->intvecsave = getvect(card->intrnum); // save previous interrupt vector

   setvect(card->intrnum, newvect);           // set new interrupt vector

   // enable interrupts at interrupt controllers
   intrmask = card->intrmask;
   outp(PIC1MASK, inp(PIC1MASK) & ~intrmask);
   intrmask >>= 8;
   outp(PIC2MASK, inp(PIC2MASK) & ~intrmask);
}



void DisableCardInterrupt(cardinfo *card)
{
   int intrmask;

   // disable interrupts at interrupt controllers
   intrmask = card->intrmask;
   outp(PIC1MASK, inp(PIC1MASK) | intrmask);
   intrmask >>= 8;
   outp(PIC2MASK, inp(PIC2MASK) | intrmask);

   // Restore previous vector
   setvect(card->intrnum, card->intvecsave);
}



int CompareCards(cardinfo *card1, cardinfo *card2)
// Make sure the two SB cards don't have the same settings.
{
   int result = 0;

   if (card1->base == card2->base) {
      printf("Error:  Cards are at the same I/O address: %X\n",card1->base);
      result |= 1;
   }

   if (card1->irq == card2->irq) {
      printf("Error:  Cards are using the same interrupt: %d\n",card1->irq);
      result |= 2;
   }

   if (card1->dma8 == card2->dma8) {
      printf("Error:  Cards are using the same DMA channel: %d\n",card1->dma8);
      result |= 4;
   }

   return result;
}


void WriteBufsToDisk(int handle)
// Writes all the record buffers that have data to the disk.
{
   unsigned nread;

   // While there are input buffers with data, write them to disk
   while (NumFilledInBufs > 0) {
      _dos_write(handle, inbuffers[NumRecBufToEmpty], BUFSIZE/2, &nread);
      ++NumBufsWritten;

      --NumFilledInBufs;

      ++NumRecBufToEmpty;
      if (NumRecBufToEmpty >= NUMBUFS)
         NumRecBufToEmpty = 0;
   }
}



void ReadBufsFromDisk(int handle)
// Fills all empty playback buffers from disk.
{
   unsigned nread;

   // While some output buffers are empty, fill them from disk
   while (NumFilledOutBufs < NUMBUFS) {
      _dos_read(handle, outbuffers[NumPlayBufToFill], BUFSIZE/2, &nread);

      ++NumFilledOutBufs;

      ++NumPlayBufToFill;
      if (NumPlayBufToFill >= NUMBUFS)
         NumPlayBufToFill = 0;
   }
}





void main(void)
{
   int i,b,c;
   unsigned long physaddr,endaddr;
   boolean done=false;
   int result;
   int rech, playh;       // file handles for recording and playing
   char fname[] = FILENAME;

   result=GetCardInfo("BLASTER", &card1);
   if (result != 0)
      return;

   result=GetCardInfo("BLASTER2", &card2);
   if (result != 0)
      return;

   if (CompareCards(&card1, &card2))
      return;

   SegToPhys(recbuf,BUFSIZE,&physaddr,&endaddr);
   if (PhysToPage(physaddr,endaddr,&inpage,&inoffset) < BUFSIZE) {
      printf("The DMA buffer crossed a page boundary.  Sorry, I didn't write the program\n");
      printf("to deal with this.  See comments in program.  Terminating.\n");
      return;
      /*
       * The program should dynamically allocate buffers until a buffer is
       * found that doesn't cross a DMA page boundary.  I took a short cut
       * here by just using an array, which usually works if it's much less
       * than 64K bytes.
       */
   }

   SegToPhys(playbuf,BUFSIZE,&physaddr,&endaddr);
   if (PhysToPage(physaddr,endaddr,&outpage,&outoffset) < BUFSIZE) {
      printf("The DMA buffer crossed a page boundary.  Sorry, I didn't write the program\n");
      printf("to deal with this.  See comments in program.  Terminating.\n");
      return;
   }


   InitScreen();


   // allocate buffers to transfer data between DMA buffer and disk
   for (i=0; i<NUMBUFS; i++) {
      inbuffers[i] = malloc(BUFSIZE/2);
      if (!inbuffers[i]) {
         printf("Error:  memory couldn't be allocated.\n");
         return;
      }
      outbuffers[i] = malloc(BUFSIZE/2);
      if (!outbuffers[i]) {
         printf("Error:  memory couldn't be allocated.\n");
         return;
      }
   }

   if (_dos_creat(fname, 0, &rech)) {
      printf("Couldn't open file %s for writing.\n",fname);
      return;
   }

   if (_dos_open(fname, O_RDONLY, &playh)) {
      printf("Couldn't open file %s for reading.\n",fname);
      return;
   }

   SetMixer(&card1, &card2);

   EnableCardInterrupt(&card1, InputSBISR);
   EnableCardInterrupt(&card2, OutputSBISR);


   // Fill playback buffers with silence and mark them as filled so the
   // playback of the actual file will start delayed by 2+NUMBUFS buffers.
   for (b=0; b<NUMBUFS; b++)
      for (i=0; i<BUFSIZE/2; ++i) {
         *((char *)outbuffers[b] + i) = 0x80;
      }
   NumFilledOutBufs = NUMBUFS;

   // fill both halves of output DMA buffer
   FillOutputBuffer();
   FillOutputBuffer();


   // Start recording
   SetupInputDMA(inpage,inoffset,count,TIMECONST);

   // Wait until several buffers have been written to disk before starting
   // playback.  This gives the recording section a head start.  This is
   // necessary because the playback section tries to fill all of its buffers,
   // so there must be that much data already on the disk.
   do {
      WriteBufsToDisk(rech);
   } while (NumBufsWritten < NUMBUFS);


   // Now start playing.
   SetupOutputDMA(outpage,outoffset,count,TIMECONST);


   while (!done) {
      WriteBufsToDisk(rech);     // write all full input buffers
      ReadBufsFromDisk(playh);   // fill all empty output buffers

      gotoxy(1,3);
      printf("Number of buffers written to disk: %5d\n",NumBufsWritten);

      if (kbhit()) {
         c=getch();
         switch (c) {
            case ESC:
               done=true;
               break;
            // Used to have other stuff here in a previous program.
            default:
               done=true;
         }
      }
   }

   // Stop recording and playing.
   dspout(&card1,dspcmdHaltDMA8);
   dspout(&card2,dspcmdHaltDMA8);

   DisableCardInterrupt(&card1);
   DisableCardInterrupt(&card2);
}

⌨️ 快捷键说明

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