Thread: Sound card interrupt problems

  1. #1
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607

    Sound card interrupt problems

    My main problem is quite strange. My code does play RAW files and it works perfect, until the file size is larger than my buffer.

    In a DOS shell this code works to perfection. In true DOS it does not. The first two blocks play fine, that is the sound card does generate the interrupt once. After the first interrupt when it comes to the end of the next block, the interrupt is not generated.
    Since I'm in single cycle DMA, the sound stops. The DMA is not reprogrammed nor is the DSP, the offset is not incremented, and everything hangs. Since I've hooked an interrupt and not unhooked it properly (since the code never comes to the end of the sound) the system is hosed and I must reboot to reset all the chips and to regenerate the interrupt vector table.


    Two questions:
    [ist][*]Why does the sound card only generate 1 interrupt? If I'm acknowleding all hanging ints and the PIC, it should continue to generate interrupts until the sound is done playing. It only works correctly in a Windows DOS box and I cannot figure out why.
    [*]How do you rewrite a Ctrl-C handler? I know you can rewrite these handlers using signal(), but the syntax of the function is so cluttered(and the example code does not work) I cannot figure out how to do it. It is signal(SIGINT,(void)(*near)(int)) or something like that. If I can do this, then on CTRL-C I would uninstall my handler - thus I might not have to reboot every time.[/list]

    If I can get this working, then I've finally written an SB16 module that works and can play very long samples. The sample I tested in the Windows DOS box was 800kb in length and it played flawlessly (except for clicking which I know how to fix). Once this works in real-mode, it's on to DJGPP and PM.

    Some of this is directly from Ethan Brodsky's code so he deserves the credit

    Code:
    void interrupt newhandler(...)   
    {
      //Check if sound is done - not the best/safest way to do it
      if (done==1) exit(EXIT_SUCCESS);   
    
      //Increment offset into file - globals again
      //ChunkSize is 32000 bytes
      fileoffset+=ChunkSize;   
    
      //Load data and get chunk size
      //Will be less than 32000 when near the end of the sound file
      unsigned int size=LoadData(fileoffset); 
    
      //Reprogram the DSP and DMA for next block and start playing
      PlayBuffer(size);       
    
      //Acknowledge SB - for 8 bit sound
      inp(DSPREADBUF);   
    
      //Acknowledge pic for int<8
      outp(0x20,0x20);    
    }
    
    void Shutdown(void)
    {
      //Acknowledge PIC since caller could be an interrupt handler
      outp(0x20,0x20);   
    
      //Stop current sound - none should be playing at this point
      WriteDSP(0xD0);    
    
      //Restore the old handler to clean up the vector table  
      if(handlerinstalled==TRUE) UninstallHandler();  //Clean up
    
      //Reset the DSP for future use
      ResetDSP();
    
      //Close the file
      close(handle);        
    }
    
    void InstallHandler(void)
    {
      //Disable interrupts (CLI)
      disable();
      
      //Mask the interrupt 
      outp(picmaskport, (inp(picmaskport)|irqstopmask));
      
      //Save the old handler for later restoration of vector table
      oldhandler=getvect(intvector);   //intvector is global for now
      
      //Install our handler
      setvect(intvector,newhandler);    
      
      //Unmask the interrupt
      outp(picmaskport,(inp(picmaskport)&irqstartmask));
      
      //Handler is installed
      handlerinstalled=TRUE;
      
      //Re-enable interrupts (STI)
      enable();
    }
    
    void UninstallHandler(void)
    {
      //Disable interrupts (CLI)
      disable();
      
      //Mask
      outp(picmaskport,(inp(picmaskport)|irqstartmask));
      
      //Restore old handler
      setvect(intvector,oldhandler); 
      
      //Set flag to reflect change
      handlerinstalled=FALSE;
      
      //Enable interrupts (STI)
      enable();
    }
    
    unsigned int LoadData(unsigned long offset)
    {
      //Check for end of sound file
      if (offset+32000L>filelength(handle) done=1;  
      
      //Get next chunk size
      unsigned long size=filelength(handle)-offset;
    
      //if larger than buffer size - clamp to buffer size
      if (size>32000L) size=32000;
      
      //read in size bytes
      read(handle,(int *)buffer,size);
    
    return size;
    }

    This should be enough code to see what I'm doing. If not, I'll post my whole source later. Again, some variables are global and are not evident or declared in this snippet.

  2. #2
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    I downloaded all of the old legacy docs from Creative's website last night as well as several docs on the DMA itself. Seems my transfer length is causing the problem.

  3. #3
    Linguistic Engineer... doubleanti's Avatar
    Join Date
    Aug 2001
    Location
    CA
    Posts
    2,459
    first -> what is your sound card? in a pure dos environment, many programs come supplied with sb compatible external drivers that do the works for you... and if under the shell it's just being rerouted to the correct windows installed drivers, this may cause problems in pure dos since you don't have that automated redirection...

    secondly -> don't know it offhand, but check your RBIL... i know you've got it... and i'm sure it tells you which interrupt to chain into for that...
    hasafraggin shizigishin oppashigger...

  4. #4
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Actually RBIL failed me on this one. They don't specify which SB interrupts are there, and I know why.

    Basic idea for the DSP and PICS is that if your interrupt is below 8 then the actual interrupt is 0x08+SBinterrupt. Then to acknowledge the PIC you only have to outp(0x20,0x20). For interrupts larger than 8 the actual interrupt is 0x70 +(SBinterrupt-0x08) and you have to acknowledge both PICs outp(0x20,0x20) and outp(0xa0,0x20).

    The reason for the PICS is that there are two in the system. The second PIC is chained to the first one so when the interrupt is larger than 8, PIC 1 responds first and realizes that he cannot control that interrupt line so he passes the interrupt on to PIC 2. But, since both have, in effect, handled the interrupt you must signal both of them with EOI.

    RBIL does not get into this because it really relates to just knowing how to use the PICS which is beyond the scope or the function of the RBIL.

    I'm transferring two many bytes into the DMA transfer buffer. Supposed to transfer (length/2)-1 bytes (for 8 bit sound) per transfer. Then send the next portion of the buffer to the DMA and refill the portion that was just sent.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Need to interact with sound card
    By SubtleAphex in forum C Programming
    Replies: 14
    Last Post: 03-21-2009, 10:28 AM
  2. brace-enclosed error
    By jdc18 in forum C++ Programming
    Replies: 53
    Last Post: 05-03-2007, 05:49 PM
  3. New Hardware install kills sound (card?)
    By lightatdawn in forum Tech Board
    Replies: 4
    Last Post: 06-22-2005, 03:30 PM
  4. any sound card recomendations
    By eats only heads in forum Tech Board
    Replies: 7
    Last Post: 12-13-2002, 10:43 PM
  5. mixer to sound card problem, need help ASAP
    By Waldo2k2 in forum Tech Board
    Replies: 0
    Last Post: 12-09-2002, 05:02 PM