home *** CD-ROM | disk | FTP | other *** search
/ Team Palmtops 7 / Palmtops_numero07.iso / Epoc / Palmtime / files / FrotzCE2_src.ZIP / FrotzCE / FrotzCESnd.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-09-11  |  6.1 KB  |  265 lines

  1. #include "stdafx.h"
  2. #include "FrotzCE.h"
  3. #include "FrotzCESnd.h"
  4. #include "FrotzCEIO.h"
  5.  
  6. #include <string.h>
  7.  
  8. extern "C"
  9. {
  10. #include "Frotz/Frotz.h"
  11. }
  12.  
  13. // Constructor
  14. CFrotzCESnd::CFrotzCESnd()
  15. {
  16.     // Initialise
  17.     m_pachSampleData = NULL;
  18.     m_nCurrentSample = 0;
  19.     m_bPlayingSound = FALSE;
  20.     memset( &m_sHeader, 0, sizeof( m_sHeader ) );
  21. }
  22.  
  23. /*
  24.  * Beep
  25.  *
  26.  * Play a beep sound. Ideally, the sound should be high- (number == 1)
  27.  * or low-pitched (nnumber == 2).
  28.  *
  29.  */
  30.  
  31. void CFrotzCESnd::Beep( int nNumber )
  32. {
  33.     if( nNumber == 2 )
  34.         MessageBeep( MB_OK );
  35.     else
  36.         MessageBeep( MB_ICONASTERISK );
  37. }
  38.  
  39. /*
  40.  * LoadSample
  41.  *
  42.  * Load the given sample from the disk.
  43.  *
  44.  */
  45.  
  46. BOOL CFrotzCESnd::LoadSample( int nNumber )
  47. {
  48.     // Loaded sample already?
  49.     if (m_nCurrentSample == nNumber)
  50.         return;
  51.  
  52.     // Find extension
  53.     int nPos;
  54.     for (nPos = strlen( FROTZCEAPP->m_achStoryFile ) - 1; 
  55.         nPos >= 0 && FROTZCEAPP->m_achStoryFile[nPos] != '.'; nPos--);
  56.  
  57.     // Get length of base sample file name
  58.     int nStubLen = strlen (FROTZCEAPP->m_achStoryFile ) - nPos;
  59.     if (nStubLen > 6) nStubLen = 6;
  60.  
  61.     // Generate sample file name
  62.     CString strSampleName;
  63.     int nDefDirLen = FROTZCEAPP->m_strDefaultDir.GetLength();
  64.     strSampleName.Format( TEXT( "%.*s\\Sound\\%.*s%02d.snd" ), 
  65.         nDefDirLen, FROTZCEAPP->m_achStoryFile, nStubLen, 
  66.         &FROTZCEAPP->m_achStoryFile[nDefDirLen+1] );
  67.  
  68.     // Open sample file
  69.     CFile cSampleFile;
  70.     if (cSampleFile.Open( strSampleName, CFile::modeRead ))
  71.     {
  72.     UINT nFileLen;
  73.     BYTE nLoByte, nHiByte;
  74.  
  75.         // Find out how long the file is for error checking later
  76.         cSampleFile.SeekToEnd();
  77.         nFileLen = cSampleFile.GetPosition();
  78.         cSampleFile.SeekToBegin();
  79.  
  80.         // If it's shorter than this, it has to be corrupt (minimum size of sound header)
  81.         if( nFileLen <= MIN_HEADER_SIZE )
  82.         {
  83.         CString strError = TEXT( "SoundFile: " );
  84.  
  85.             // Display error
  86.             strError += strSampleName;
  87.             strError += TEXT( "\nSound file too short!" );
  88.             AfxMessageBox( strError );
  89.             cSampleFile.Close();
  90.             return FALSE;
  91.         }
  92.         // Load header
  93.         // MSB is first, LSB is second
  94.         cSampleFile.Read( &nHiByte, 1 );
  95.         cSampleFile.Read( &nLoByte, 1 );
  96.         m_sHeader.nPrefix = (nHiByte << 8) + nLoByte;
  97.  
  98.         // Valid length?
  99.         if( m_sHeader.nPrefix > nFileLen )
  100.         {
  101.         CString strError = TEXT( "SoundFile: " );
  102.  
  103.             // Display error
  104.             strError += strSampleName;
  105.             strError += TEXT( "\nSound file too short!" );
  106.             AfxMessageBox( strError );
  107.             cSampleFile.Close();
  108.             return FALSE;
  109.         }
  110.  
  111.         // Read sound info
  112.         cSampleFile.Read( &m_sHeader.nRepeats, 1 );
  113.         cSampleFile.Read( &m_sHeader.nBaseNote, 1 );
  114.         cSampleFile.Read( &nHiByte, 1 );
  115.         cSampleFile.Read( &nLoByte, 1 );
  116.         m_sHeader.nFrequency= (nHiByte << 8) + nLoByte;
  117.  
  118.         // Skip the unused two bytes
  119.         cSampleFile.Read( &nHiByte, 1 );
  120.         cSampleFile.Read( &nHiByte, 1 );
  121.  
  122.         // Read sample infp
  123.         cSampleFile.Read( &nHiByte, 1 );
  124.         cSampleFile.Read( &nLoByte, 1 );
  125.         m_sHeader.nLength = ( nHiByte << 8 ) + nLoByte;
  126.  
  127.         // Allocate memory for sample data
  128.         if ((m_pachSampleData = (char *) ::LocalAlloc( LPTR, m_sHeader.nLength)) != NULL) 
  129.         {
  130.             // Read sample data
  131.             if( cSampleFile.Read( m_pachSampleData, m_sHeader.nLength ) != m_sHeader.nLength )
  132.             {
  133.             CString strError = TEXT( "SoundFile: " );
  134.  
  135.                 // Display error
  136.                 strError += strSampleName;
  137.                 strError += TEXT( "\nError reading sound data from file!" );
  138.                 AfxMessageBox( strError );
  139.                 cSampleFile.Close();
  140.                 return FALSE;
  141.             }
  142.  
  143.             // Store sample number 
  144.             m_nCurrentSample = nNumber;
  145.         } 
  146.         else 
  147.         {
  148.         CString strError = TEXT( "SoundFile: " );
  149.  
  150.             // Display error
  151.             strError += strSampleName;
  152.             strError += TEXT( "\nNot enough memory for sample!" );
  153.             AfxMessageBox( strError );
  154.             cSampleFile.Close();
  155.             return FALSE;
  156.         }
  157.  
  158.         // Close sample file
  159.         cSampleFile.Close();
  160.  
  161.         return TRUE;
  162.     }
  163.     else
  164.     {
  165.     CString strError = TEXT( "SoundFile: " );
  166.  
  167.         // Display error
  168.         strError += strSampleName;
  169.         strError += TEXT( "\nCould not open sample file!" );
  170.         AfxMessageBox( strError );
  171.         return FALSE;
  172.     }
  173. }
  174.  
  175. /*
  176.  * StartSample
  177.  *
  178.  * Play the given sample at the given volume (ranging from 1 to 8 and
  179.  * 255 meaning a default volume). The sound is played once or several
  180.  * times in the background (255 meaning forever). In Z-code 3, the
  181.  * repeats value is always 0 and the number of repeats is taken from
  182.  * the sound file itself. The end_of_sound function is called as soon
  183.  * as the sound finishes.
  184.  *
  185.  */
  186.  
  187. void CFrotzCESnd::StartSample( int nNumber, int nVolume, int nRepeats )
  188. {
  189. WAVEFORMAT EX sWaveFormat;
  190. WAVEHDR sWaveHdr;
  191.  
  192.     // Stop sample from playing
  193.     StopSample();
  194.  
  195.     // Try to load specified sample
  196.     if (!LoadSample( nNumber )) return;
  197.  
  198.     // Clear wave headers
  199.     memset( &sWaveFormat, 0, sizeof( WAVEFORMATEX ) );
  200.     memset( &sWaveHdr, 0, sizeof( WAVEHDR ) );
  201.  
  202.     // Set this up for PCM, 1 channel, 8 bits unsigned samples
  203.     sWaveFormat.wFormatTag = WAVE_FORMAT_PCM;
  204.     sWaveFormat.nChannels = 1;
  205.     sWaveFormat.nSamplesPerSec = m_sHeader.nFrequency;
  206.     sWaveFormat.nAvgBytesPerSec = m_sHeader.nFrequency;
  207.     sWaveFormat.nBlockAlign = 1;
  208.     sWaveFormat.wBitsPerSample = 8;
  209.     sWaveFormat.cbSize = 0;
  210.  
  211.     // Set up wave header
  212.     sWaveHdr.lpData = (LPSTR) m_pachSampleData;
  213.     sWaveHdr.dwBufferLength = m_sHeader.nLength;
  214.     sWaveHdr.dwLoops = m_sHeader.nRepeats;
  215.     if (sWaveHdr.dwLoops == 0) sWaveHdr.dwLoops = 255;
  216.     if (h_version >= V5) sWaveHdr.dwLoops = nRepeats;
  217.     sWaveHdr.dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP;
  218.  
  219.     // Play sound
  220.     m_bPlayingSound = sndPlaySound( sWaveHdr, SND_ASYNC | SND_MEMORY );
  221. }
  222.  
  223. /*
  224.  * StopSample
  225.  *
  226.  * Turn off the current sample.
  227.  *
  228.  */
  229.  
  230. void CFrotzCESnd::StopSample (void)
  231. {
  232.     // Playing sound?
  233.     if (m_bPlayingSound)
  234.     {
  235.         // Stop sound
  236.         sndPlaySound( NULL, 0 );
  237.         m_bPlayingSound = FALSE;
  238.     }
  239. }
  240.  
  241. /*
  242.  * ResetSound()
  243.  *
  244.  * Free resources allocated for playing samples.
  245.  *
  246.  */
  247.  
  248. void CFrotzCESnd::ResetSound()
  249. {
  250.     // Stop playing sample
  251.     StopSample();
  252.  
  253.     // Free buffer
  254.     if (m_pchSampleData) delete m_pchSampleData;
  255.     m_pchSampleData = NULL;
  256.  
  257.     m_nCurrentSample = 0;
  258. }
  259.  
  260. // Destructor
  261. CFrotzCESnd::~CFrotzCESnd()
  262. {
  263.     // Clean up
  264.     ResetSound();
  265. }