home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 2.toast / pc / sample code / sound / sndplaydoublebuffer / _source / private_dbfffunctions.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  20.6 KB  |  624 lines

  1. /*
  2.     File:        Private_DBFFFunctions.c
  3.  
  4.     Contains:    Routines demonstrating how to set up for using SndPlayDoubleBuffer.
  5.  
  6.     Written by: Mark Cookson    
  7.  
  8.     Copyright:    Copyright © 1996-1999 by Apple Computer, Inc., All Rights Reserved.
  9.  
  10.                 You may incorporate this Apple sample source code into your program(s) without
  11.                 restriction. This Apple sample source code has been provided "AS IS" and the
  12.                 responsibility for its operation is yours. You are not permitted to redistribute
  13.                 this Apple sample source code as "Apple sample source code" after having made
  14.                 changes. If you're going to re-distribute the source, we require that you make
  15.                 it clear in the source that the code was descended from Apple sample source
  16.                 code, but that you've made changes.
  17.  
  18.     Change History (most recent first):
  19.                 8/31/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
  20.                 
  21.  
  22. */
  23. #include "MyAIFF.h"
  24. #include "Private_DBFFFunctions.h"
  25.  
  26. /********************************************************************************************
  27.         ** YOU SHOULD NEVER NEED TO CALL ANY OF THE FOLLOWING ROUTINES DIRECTLY **
  28. ********************************************************************************************/
  29.  
  30. /*    Purpose:        This sets all of local and global variables to safe values.
  31.                     This routine is called by ASoundNew, and is    called by the
  32.                     ASoundDone function after it has cleaned up to reset things.
  33.     Side Effects:    None.
  34. */
  35. /*-----------------------------------------------------------------------*/
  36.         OSErr    ASoundInit        (SoundInfoPtr theSoundInfo)
  37. /*-----------------------------------------------------------------------*/
  38. {
  39.     NumVersion    SndManagerVer;
  40.     OSErr        theErr            = noErr;
  41.  
  42.     theSoundInfo->globals.gSupports16Bit    = true;
  43.     theSoundInfo->globals.gSupportsSPDB        = true;
  44.  
  45.     theSoundInfo->signature            = kDBFFSignature;
  46.     theSoundInfo->chan                = kInit;
  47.     theSoundInfo->rateForResume        = kInit;
  48.     /* create a Universal Procedure Pointer (UPP) for our sound callback */
  49.     theSoundInfo->theSoundCallBackUPP = NewSndCallBackProc(ASoundDoneCallBack);
  50.     theSoundInfo->fileType            = kInit;
  51.     (void)ASoundSetNumBuffers        (theSoundInfo, kStart);
  52.     theSoundInfo->dataStart            = kInit;
  53.     (void)ASoundSetSoundLength        (theSoundInfo, kInit);
  54.     ASoundSetBytesCopied            (theSoundInfo, kInit);
  55.     ASoundSetCurBuffer                (theSoundInfo, kStart);
  56.     (void)ASoundSetBufferSize        (theSoundInfo, kInit);
  57.     theSoundInfo->bytesPerFrame        = kInit;
  58.     theSoundInfo->refNum            = kInit;
  59.     theSoundInfo->vRefNum            = nil;
  60.     theSoundInfo->compFactor        = kNoCompression;
  61.     theSoundInfo->paused            = false;
  62.     theSoundInfo->playing            = false;
  63.     theSoundInfo->adjusting            = false;
  64.     theSoundInfo->soundDone            = false;
  65.     theSoundInfo->backwards            = false;
  66.     theSoundInfo->hasBeenAdjusted    = false;
  67.     theSoundInfo->needsMasking        = false;
  68.     theSoundInfo->stopping            = false;
  69.  
  70.     SndManagerVer = SndSoundManagerVersion ();
  71.     theErr = InterrogateSystem (&(theSoundInfo->globals));
  72.     if (theErr == noErr) {
  73.         if (SndManagerVer.majorRev >= kMinSndMgrVer) {
  74.             if ((theSoundInfo->globals.ggestaltSoundAttr & (1 << gestaltSndPlayDoubleBuffer)) == false) {
  75.                 DebugPrint ("\pSndPlayDoubleBuffer isn't supported!");
  76.                 theSoundInfo->globals.gSupportsSPDB = false;
  77.                 theErr = kNoSPDBErr;
  78.             }
  79.             if ((theSoundInfo->globals.ggestaltSoundAttr & (1<< gestalt16BitAudioSupport)) == false) {
  80.                 DebugPrint ("\pThis machine doesn't support 16 bit audio!");
  81.                 theSoundInfo->globals.gSupports16Bit = false;
  82.                 theErr = notEnoughHardwareErr;    /* This doesn't have to be a fatal error */
  83.             }
  84.         }
  85.         else {
  86.             theErr = kOldSndMgrErr;
  87.         }
  88.     }
  89.     else {
  90.         theErr = kInitErr;
  91.     }
  92.  
  93.     return theErr;
  94. }
  95.  
  96. /*-----------------------------------------------------------------------*/
  97. Boolean            IsValid                    (SoundInfoPtr theSoundInfo)
  98. /*-----------------------------------------------------------------------*/
  99. {
  100.     return CheckValididity (theSoundInfo, false);
  101. }
  102.  
  103. /*-----------------------------------------------------------------------*/
  104. Boolean            StrictIsValid            (SoundInfoPtr theSoundInfo)
  105. /*-----------------------------------------------------------------------*/
  106. {
  107.     return CheckValididity (theSoundInfo, true);
  108. }
  109.  
  110.  
  111. /*-----------------------------------------------------------------------*/
  112. Boolean            CheckValididity            (SoundInfoPtr theSoundInfo,
  113.                                         Boolean strict)
  114. /*-----------------------------------------------------------------------*/
  115. {
  116.     Boolean        returnValue        = true;        /* Assume success */
  117.  
  118.     if (theSoundInfo == nil) {
  119.         returnValue = false;
  120.     }
  121.     else {
  122.         if (strict == true) {
  123.             if (theSoundInfo->signature != kDBFFSignature) {
  124.                 returnValue = false;
  125.                 DebugPrint ("\pStrictIsValid theSoundInfo->signature is invalid");
  126.             }
  127.             else {
  128.                 if (theSoundInfo->doubleHeader.dbhNumChannels <= kInit) {
  129.                     returnValue = false;
  130.                     DebugPrint ("\pStrictIsValid theSoundInfo->doubleHeader.dbhNumChannels is invalid");
  131.                 }
  132.                 if (theSoundInfo->doubleHeader.dbhSampleSize <= kInit) {
  133.                     returnValue = false;
  134.                     DebugPrint ("\pStrictIsValid theSoundInfo->doubleHeader.dbhSampleSize is invalid");
  135.                 }
  136.                 if (theSoundInfo->doubleHeader.dbhPacketSize < kInit) {
  137.                     returnValue = false;
  138.                     DebugPrint ("\pStrictIsValid theSoundInfo->doubleHeader.dbhPacketSize is invalid");
  139.                 }
  140.                 if (theSoundInfo->theSoundCallBackUPP == nil) {
  141.                     returnValue = false;
  142.                     DebugPrint ("\pStrictIsValid theSoundInfo->theSoundCallBackUPP is invalid");
  143.                 }
  144.                 if (theSoundInfo->rateForResume < kInit) {
  145.                     returnValue = false;
  146.                     DebugPrint ("\pStrictIsValid theSoundInfo->rateForResume is invalid");
  147.                 }
  148.                 if (theSoundInfo->numBuffers <= kInit) {
  149.                     returnValue = false;
  150.                     DebugPrint ("\pStrictIsValid theSoundInfo->numBuffers is invalid");
  151.                 }
  152.                 if (theSoundInfo->dataStart < kInit) {
  153.                     returnValue = false;
  154.                     DebugPrint ("\pStrictIsValid theSoundInfo->dataStart is invalid");
  155.                 }
  156.                 if (theSoundInfo->bytesTotal <= kInit) {
  157.                     returnValue = false;
  158.                     DebugPrint ("\pStrictIsValid theSoundInfo->bytesTotal is invalid");
  159.                 }
  160.                 if (theSoundInfo->bytesCopied <= kInit) {
  161.                     returnValue = false;
  162.                     DebugPrint ("\pStrictIsValid theSoundInfo->bytesCopied is invalid");
  163.                 }
  164.                 if (theSoundInfo->currentBuffer <= kInit) {
  165.                     returnValue = false;
  166.                     DebugPrint ("\pStrictIsValid theSoundInfo->currentBuffer is invalid");
  167.                 }
  168.                 if (theSoundInfo->doubleBufferSize <= kInit) {
  169.                     returnValue = false;
  170.                     DebugPrint ("\pStrictIsValid theSoundInfo->doubleBufferSize is invalid");
  171.                 }
  172.                 if (theSoundInfo->bytesPerFrame <= kInit) {
  173.                     returnValue = false;
  174.                     DebugPrint ("\pStrictIsValid theSoundInfo->bytesPerFrame is invalid");
  175.                 }
  176.                 if (theSoundInfo->compFactor <= kInit) {
  177.                     returnValue = false;
  178.                     DebugPrint ("\pStrictIsValid theSoundInfo->compFactor is invalid");
  179.                 }
  180.             }
  181.         }
  182.         else {
  183.             if (theSoundInfo->signature != kDBFFSignature) {
  184.                 returnValue = false;
  185.                 DebugPrint ("\pIsValid theSoundInfo->signature is invalid");
  186.             }
  187.             else {
  188.                 if (theSoundInfo->doubleHeader.dbhNumChannels < kInit) {
  189.                     returnValue = false;
  190.                     DebugPrint ("\pIsValid theSoundInfo->doubleHeader.dbhNumChannels is invalid");
  191.                 }
  192.                 if (theSoundInfo->doubleHeader.dbhSampleSize < kInit) {
  193.                     returnValue = false;
  194.                     DebugPrint ("\pIsValid theSoundInfo->doubleHeader.dbhSampleSize is invalid");
  195.                 }
  196.                 if (theSoundInfo->doubleHeader.dbhPacketSize < kInit) {
  197.                     returnValue = false;
  198.                     DebugPrint ("\pIsValid theSoundInfo->doubleHeader.dbhPacketSize is invalid");
  199.                 }
  200.                 if (theSoundInfo->theSoundCallBackUPP == nil) {
  201.                     returnValue = false;
  202.                     DebugPrint ("\pIsValid theSoundInfo->theSoundCallBackUPP is invalid");
  203.                 }
  204.                 if (theSoundInfo->rateForResume < kInit) {
  205.                     returnValue = false;
  206.                     DebugPrint ("\pIsValid theSoundInfo->rateForResume is invalid");
  207.                 }
  208.                 if (theSoundInfo->numBuffers < kInit) {
  209.                     returnValue = false;
  210.                     DebugPrint ("\pIsValid theSoundInfo->numBuffers is invalid");
  211.                 }
  212.                 if (theSoundInfo->dataStart < kInit) {
  213.                     returnValue = false;
  214.                     DebugPrint ("\pIsValid theSoundInfo->dataStart is invalid");
  215.                 }
  216.                 if (theSoundInfo->bytesTotal < kInit) {
  217.                     returnValue = false;
  218.                     DebugPrint ("\pIsValid theSoundInfo->bytesTotal is invalid");
  219.                 }
  220.                 if (theSoundInfo->bytesCopied < kInit) {
  221.                     returnValue = false;
  222.                     DebugPrint ("\pIsValid theSoundInfo->bytesCopied is invalid");
  223.                 }
  224.                 if (theSoundInfo->currentBuffer < kInit) {
  225.                     returnValue = false;
  226.                     DebugPrint ("\pIsValid theSoundInfo->currentBuffer is invalid");
  227.                 }
  228.                 if (theSoundInfo->doubleBufferSize < kInit) {
  229.                     returnValue = false;
  230.                     DebugPrint ("\pIsValid theSoundInfo->doubleBufferSize is invalid");
  231.                 }
  232.                 if (theSoundInfo->bytesPerFrame < kInit) {
  233.                     returnValue = false;
  234.                     DebugPrint ("\pIsValid theSoundInfo->bytesPerFrame is invalid");
  235.                 }
  236.                 if (theSoundInfo->compFactor < kInit) {
  237.                     returnValue = false;
  238.                     DebugPrint ("\pIsValid theSoundInfo->compFactor is invalid");
  239.                 }
  240.             }
  241.         }
  242.     }
  243.  
  244.     return returnValue;
  245. }
  246.  
  247. /*
  248.     Purpose:        Called by StandardFile for every file in a folder to
  249.                     see if we want to display that file in the open file
  250.                     dialog.  Return false (don't filter) if you want the
  251.                     file displayed, true (do filter) if you don't want
  252.                     it displayed.
  253.  
  254.                     This calls ASoundCanThisPlay() which calls the header
  255.                     parsing routines.  If we can parse the header we
  256.                     should be able to play the file.
  257.     Side Effects:    None.
  258. */
  259. /*-----------------------------------------------------------------------*/
  260. pascal Boolean    ASoundFileFilter        (CInfoPBPtr theFileInfo)
  261. /*-----------------------------------------------------------------------*/
  262. {
  263.     OSErr        theErr            = noErr;
  264.     Boolean        returnValue        = true;        /* by default don't display the file */
  265.  
  266.     theErr = ASoundCanThisPlay (theFileInfo);
  267.     if (theErr == noErr) {                    /* We can play this file. */
  268.         returnValue = false;                /* Display this file */
  269.     }
  270.  
  271.     if (theErr != noErr && theErr != kUnknownFormat) {
  272.         DebugPrint ("\pError in ASoundFileFilter");
  273.     }
  274.  
  275.     return returnValue;
  276. }
  277.  
  278. /*
  279.     Purpose:        Sets how many buffers will be needed to play the entire
  280.                     sound.
  281.     Side Effects:    None.
  282. */
  283. /*-----------------------------------------------------------------------*/
  284.         OSErr    ASoundSetNumBuffers        (SoundInfoPtr theSoundInfo,
  285.                                         long newValue)
  286. /*-----------------------------------------------------------------------*/
  287. {
  288.     OSErr        theErr    = noErr;
  289.  
  290.     if (newValue >= kInit) {
  291.         theSoundInfo->numBuffers = newValue;
  292.     }
  293.     else {
  294.         theErr = kBadValue;
  295.     }
  296.  
  297.     return theErr;
  298. }
  299.  
  300. /*
  301.     Purpose:        To install a callback command into the current sound
  302.                     channel.
  303.     Side Effects:    None.
  304. */
  305. /*-----------------------------------------------------------------------*/
  306.         OSErr    InstallCallBack            (SoundInfoPtr theSoundInfo)
  307. /*-----------------------------------------------------------------------*/
  308. {
  309.     SndCommand    mycmd    = {callBackCmd, kInit, kInit};
  310.     OSErr        theErr    = noErr;
  311.  
  312.     mycmd.param2 = SetCurrentA5();
  313.     theErr = SndDoCommand (theSoundInfo->chan, &mycmd, true);
  314.  
  315.     if (theErr != noErr) {
  316.         DebugPrint ("\pError in InstallCallBack");
  317.     }
  318.  
  319.     return theErr;
  320. }
  321.  
  322. /*
  323.     Purpose:        Gather the information needed (from the sound's header)
  324.                     to setup the structures the Sound Manager will need to
  325.                     play the sound.
  326.     Side Effects:    This will allocate memory for the sound header strucure
  327.                     that will be disposed of by ASoundDonePlaying.
  328. */
  329. /*-----------------------------------------------------------------------*/
  330.         OSErr    SetUpSoundHeader        (SoundInfoPtr theSoundInfo,
  331.                                         unsigned long bufferSize)
  332. /*-----------------------------------------------------------------------*/
  333. {
  334.     long double        sampleRate    = kInit;
  335.     long            dataStart    = kInit,
  336.                     sndLength    = kInit,
  337.                     numBuffers    = kInit;
  338.     short            remainder    = kInit;
  339.     OSErr            theErr        = noErr;
  340.  
  341.     theSoundInfo->chan->userInfo = (long)theSoundInfo;        /* So we know who we are in the SoundCompletion routines */
  342.  
  343.     switch (theSoundInfo->fileType) {
  344.         case kCompressedAIFFFile:
  345.         case kUncompressedAIFFFile:
  346.             theErr = ASoundGetAIFFHeader (theSoundInfo, &dataStart, &sndLength);
  347.             break;
  348.         case kWAVEFile:
  349.         case kWAVFile:
  350.             theErr = ASoundGetWAVEHeader (theSoundInfo, &dataStart, &sndLength);
  351.             break;
  352.         case kAUFile:
  353.             theErr = ASoundGetULAWHeader (theSoundInfo, &dataStart, &sndLength);
  354.             break;
  355.         case kSNDResource:
  356.         case kResource:
  357.             theErr = ASoundGetSNDHeader  (theSoundInfo, &dataStart, &sndLength);
  358.             break;
  359.         default:
  360.             theErr = kUnknownFormat;
  361.             break;
  362.     }
  363.  
  364.     theSoundInfo->dataStart = dataStart;
  365.     if (theErr != noErr) {
  366.         DebugPrint ("\pASoundGetAIFFHeader error!");
  367.         (void)SndDisposeChannel (theSoundInfo->chan, true);
  368.     }
  369.     else {
  370.         if ((theSoundInfo->doubleHeader.dbhSampleSize == kSixteen) && (theSoundInfo->globals.gSupports16Bit == false)) {
  371.             DebugPrint ("\pThis is a 16 bit sound, this is not a 16 bit capable machine.");
  372.             theErr = notEnoughHardwareErr;
  373.         }
  374.         else {    
  375.             theErr = ASoundSetSoundLength (theSoundInfo, sndLength);
  376.             ASoundSetBytesCopied (theSoundInfo, dataStart);                /* skip the header of the file */
  377.  
  378.             sampleRate = ASoundFixToLongDouble (theSoundInfo->doubleHeader.dbhSampleRate);
  379.  
  380.             if (bufferSize > kInit) {
  381.                 theErr = ASoundSetBufferSize (theSoundInfo, bufferSize);
  382.             }
  383.             else {
  384.                 theErr = ASoundSetBufferSize (theSoundInfo, (((theSoundInfo->doubleHeader.dbhSampleSize / kBitsPerByte) * theSoundInfo->doubleHeader.dbhNumChannels * sampleRate) / kBufLen) / theSoundInfo->compFactor);
  385.             }
  386.  
  387.             if (ASoundGetBufferSize (theSoundInfo) > kInit) {
  388.                 numBuffers = (ASoundGetNumTotalBytes (theSoundInfo) / ASoundGetBufferSize (theSoundInfo));
  389.                 remainder = (ASoundGetNumTotalBytes (theSoundInfo) % ASoundGetBufferSize (theSoundInfo));
  390.                 if (remainder != 0) {    /* Is the last buffer only a partial buffer? */
  391.                     numBuffers++;        /* Don't forget to account for it! */
  392.                 }
  393.                 theErr = ASoundSetNumBuffers (theSoundInfo, numBuffers);
  394.             }
  395.             else {
  396.                 DebugPrint ("\pThe buffer size is zero, this is bad.");
  397.                 theErr = dsZeroDivErr;
  398.             }
  399.  
  400.             theSoundInfo->doubleHeader.dbhDoubleBack = NewSndDoubleBackProc (ASoundDoubleBackProc);
  401.             theSoundInfo->doubleHeader.dbhBufferPtr[kDBBufOne] = nil;
  402.             theSoundInfo->doubleHeader.dbhBufferPtr[kDBBufTwo] = nil;
  403.         }
  404.     }
  405.  
  406.     if (theErr != noErr) {
  407.         DebugPrint ("\pError in SetUpSoundHeader");
  408.     }
  409.  
  410.     return theErr;
  411. }
  412.  
  413. /*
  414.     Purpose:        Pause the playing of the sound.
  415.     Side Effects:    None.
  416. */
  417. /*-----------------------------------------------------------------------*/
  418.         OSErr    PauseSound                (SoundInfoPtr theSoundInfo)
  419. /*-----------------------------------------------------------------------*/
  420. {
  421.     OSErr            theErr    = noErr;
  422.     UnsignedFixed    rateMul;
  423.  
  424.     rateMul = 0;
  425.     theErr = SndSetInfo (theSoundInfo->chan, siRateMultiplier, (void*)rateMul);
  426.  
  427.     if (theErr == noErr) {
  428.         theSoundInfo->paused = true;
  429.     }
  430.  
  431.     if (theErr != noErr) {
  432.         DebugPrint ("\pError in PauseSound");
  433.     }
  434.  
  435.     return theErr;
  436. }
  437.  
  438. /*
  439.     Purpose:        Resume the playing of the sound.
  440.     Side Effects:    This will reinstall the sound completion callback
  441.                     if it was removed by the ASoundPauseForAdjust function.
  442. */
  443. /*-----------------------------------------------------------------------*/
  444.         OSErr    ResumeSound                (SoundInfoPtr theSoundInfo)
  445. /*-----------------------------------------------------------------------*/
  446. {
  447.     OSErr            theErr    = noErr;
  448.     UnsignedFixed    rateMul;
  449.  
  450.     rateMul = (1<<16);
  451.     theErr = SndSetInfo (theSoundInfo->chan, siRateMultiplier, (void*)rateMul);
  452.  
  453.     if (theErr == noErr) {
  454.         theSoundInfo->paused = false;
  455.         if (theSoundInfo->hasBeenAdjusted == true) {
  456.             theErr = SndPlayDoubleBuffer (theSoundInfo->chan, (SndDoubleBufferHeaderPtr)&(theSoundInfo->doubleHeader));
  457.             theErr = InstallCallBack (theSoundInfo);
  458.             theSoundInfo->hasBeenAdjusted = false;
  459.         }
  460.     }
  461.  
  462.     if (theErr != noErr) {
  463.         DebugPrint ("\pError in ResumeSound");
  464.     }
  465.  
  466.     return theErr;
  467. }
  468.  
  469. /*-----------------------------------------------------------------------*/
  470.         OSErr    ASoundSetBufferSize        (SoundInfoPtr theSoundInfo,
  471.                                         long newValue)
  472. /*-----------------------------------------------------------------------*/
  473. {
  474.     OSErr            theErr        = noErr;
  475.  
  476.     if (newValue >= nil) {
  477.         /* Make sure the buffer is an integer multiple of the packet size,
  478.            otherwise IMA will be VERY upset, and WAVE files might not sound
  479.            too good either. */
  480.         if (theSoundInfo->doubleHeader.dbhPacketSize > kInit) {
  481.             newValue /= theSoundInfo->bytesPerFrame;
  482. //            newValue /= theSoundInfo->doubleHeader.dbhPacketSize * theSoundInfo->doubleHeader.dbhNumChannels;
  483.         }
  484.         newValue *= theSoundInfo->bytesPerFrame;
  485. //        newValue *= theSoundInfo->doubleHeader.dbhPacketSize * theSoundInfo->doubleHeader.dbhNumChannels;
  486.         theSoundInfo->doubleBufferSize = newValue;
  487.     }
  488.     else {
  489.         theSoundInfo->doubleBufferSize = kInit;
  490.         DebugPrint ("\pBad value passed to ASoundSetBufferSize");
  491.         theErr = kBadValue;
  492.     }
  493.  
  494.     if (theErr != noErr) {
  495.         DebugPrint ("\pError in ASoundSetBufferSize");
  496.     }
  497.  
  498.     return theErr;
  499. }
  500.  
  501. /*-----------------------------------------------------------------------*/
  502.         OSErr    ASoundSetSoundLength    (SoundInfoPtr theSoundInfo,
  503.                                         long newValue)
  504. /*-----------------------------------------------------------------------*/
  505. {
  506.     OSErr            theErr        = noErr;
  507.  
  508.     if (newValue >= nil) {
  509.         theSoundInfo->bytesTotal = newValue;
  510.     }
  511.     else {
  512.         theSoundInfo->bytesTotal = kInit;
  513.         theErr = kBadValue;
  514.     }
  515.  
  516.     if (theErr != noErr) {
  517.         DebugPrint ("\pError in ASoundSetSoundLength");
  518.     }
  519.  
  520.     return theErr;
  521. }
  522.  
  523. /*
  524.     Purpose:        The purpose of this routine is to fill out the
  525.                     SndDoubleBufferHeader structure with the information the
  526.                     Sound Manager will need, and to fill out the
  527.                     myParamBlockRec structure with the information the
  528.                     ASoundDoubleBackProc interrupt routine will need.  It
  529.                     then calls ASoundDoubleBackProc to fill the first two
  530.                     buffers.
  531.     Side effects:    This routine allocates two pointers as buffers for the
  532.                     sound that will be playing.
  533.                     This routine allocates two custom paramBlockRecs for
  534.                     the ASoundDoubleBackProc (interrupt routine) to use.
  535. */
  536. /*-----------------------------------------------------------------------*/
  537.         OSErr    ASoundPrimeBuffers        (SoundInfoPtr theSoundInfo)
  538. /*-----------------------------------------------------------------------*/
  539. {
  540.     myParmBlkPtr        myPB            = nil;
  541.     SndDoubleBufferPtr    doubleBuffer    = nil;
  542.     IOCompletionUPP        myIOCompletion    = nil;
  543.     OSErr                theErr            = noErr;
  544.     short                i                = kInit;
  545.  
  546.     for (i = kInit; i <= kOne; ++i) {
  547.         if (theSoundInfo->doubleHeader.dbhBufferPtr[i] == nil) {
  548.             doubleBuffer = (SndDoubleBufferPtr)NewPtrClear (sizeof(SndDoubleBuffer) + ASoundGetBufferSize (theSoundInfo));
  549.             if (doubleBuffer == nil || MemError() != noErr) {
  550.                 DebugPrint("\pNo memory for double buffers!");
  551.                 theErr = memFullErr;
  552.             }
  553.             else {
  554.                 /* Hold the memory in case VM is on, this will help to ensure that we have no sound
  555.                    drop outs caused by the paging of our buffers. */
  556.                 HoldMemory (doubleBuffer, sizeof(SndDoubleBuffer) + ASoundGetBufferSize (theSoundInfo));
  557.                 /* dbNumFrames gets set in the ASoundDoubleBackProc() routine */
  558.                 doubleBuffer->dbFlags = nil;
  559.                 doubleBuffer->dbUserInfo[kSndInfoPtr] = (long)theSoundInfo;        /* Make this point at our SoundInfo struct */
  560.                 myPB = (myParamBlockRec *)NewPtrClear(sizeof(myParamBlockRec));        /* Make one for each buffer so */
  561.                 if (myPB == nil || MemError() != noErr) {                            /* we don't reuse the same paramBlock in */
  562.                     DebugPrint("\pNo memory for a new paramBlockRec!");                /* the ioCompletion routine. */
  563.                     theErr = memFullErr;
  564.                 }
  565.                 else {
  566.                     myPB->myA5 = SetCurrentA5 ();
  567.                     myPB->theSoundInfo = theSoundInfo;
  568.                     myIOCompletion = NewIOCompletionProc (ASoundFileCallBack);
  569.                     myPB->pb.ioParam.ioCompletion = myIOCompletion;
  570.                     myPB->pb.ioParam.ioVRefNum = theSoundInfo->vRefNum;
  571.                     myPB->pb.ioParam.ioRefNum = theSoundInfo->refNum;
  572.                     myPB->pb.ioParam.ioPosMode = fsFromStart | noCacheMask;                /* Set the noCacheBit since we probably won't be reading this again */
  573.                     doubleBuffer->dbUserInfo[kPBPtr] = (long)myPB;
  574.  
  575.                     theSoundInfo->doubleHeader.dbhBufferPtr[i] = doubleBuffer;
  576.                 }
  577.             }
  578.         }
  579.         else {
  580.             doubleBuffer = theSoundInfo->doubleHeader.dbhBufferPtr[i];
  581.         }
  582.  
  583.         ASoundDoubleBackProc (theSoundInfo->chan, doubleBuffer);    /* prime the buffers */
  584.  
  585.     }
  586.  
  587.     if (theErr != noErr) {
  588.         DebugPrint ("\pError in ASoundPrimeBuffers");
  589.         for (i = kInit; i <= kOne; ++i) {
  590.             if (!theSoundInfo->doubleHeader.dbhBufferPtr[i]) {
  591.                 DisposePtr ((Ptr)myIOCompletion);
  592.                 DisposePtr ((Ptr)theSoundInfo->doubleHeader.dbhBufferPtr[i]->dbUserInfo[kSndInfoPtr]);
  593.                 DisposePtr ((Ptr)theSoundInfo->doubleHeader.dbhBufferPtr[i]);
  594.             }
  595.         }
  596.     }
  597.  
  598.     return theErr;
  599. }
  600.  
  601. /* This routine is used to calculate where to put the SFGetFile Dialog */
  602. /*-----------------------------------------------------------------------*/
  603.         Rect    GetMainScreenRect        (void)
  604. /*-----------------------------------------------------------------------*/
  605. {
  606.     GDHandle    mainDevice;
  607.     GrafPtr        mainPort;
  608.     Rect        returnRect;
  609.     long        response;
  610.     
  611.     Gestalt (gestaltQuickdrawVersion, &response);
  612.     
  613.     if (response == gestaltOriginalQD) {
  614.         GetWMgrPort (&mainPort);
  615.         returnRect = mainPort->portRect;
  616.     }
  617.     else {
  618.         mainDevice = GetMainDevice();
  619.         returnRect = (*mainDevice)->gdRect;
  620.     }
  621.  
  622.     return returnRect;
  623. }
  624.