home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 February / chip_20022115.iso / amiga / chipgame / scummvm_aga.lha / ScummVM_AGA / src / sound.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2002-01-05  |  7.6 KB  |  358 lines

  1. /* ScummVM - Scumm Interpreter
  2.  * Copyright (C) 2001  Ludvig Strigeus
  3.  *
  4.  * This program is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU General Public License
  6.  * as published by the Free Software Foundation; either version 2
  7.  * of the License, or (at your option) any later version.
  8.  
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  17.  *
  18.  * $Header: /cvsroot/scummvm/scummvm/sound.cpp,v 1.5 2001/11/06 20:25:08 strigeus Exp $
  19.  *
  20.  */
  21.  
  22. #include "stdafx.h"
  23. #include "scumm.h"
  24.  
  25. #if defined(USE_IMUSE)
  26. #include "sound.h"
  27. #else
  28. struct SoundEngine {
  29.     byte **_base_sounds;
  30.     int start_sound(int sound) { return -1; }
  31.     int stop_sound(int sound) { return -1; }
  32.     int stop_all_sounds() { return -1; }
  33.     int32 do_command(int a, int b, int c, int d, int e, int f, int g, int h) { return -1; }
  34.     int get_sound_status(int sound) { return -1; }
  35.     int clear_queue() { return -1; }
  36. };
  37. #endif
  38.  
  39. void Scumm::addSoundToQueue(int sound) {
  40.     _vars[VAR_LAST_SOUND] = sound;
  41.     ensureResourceLoaded(4, sound);
  42.     addSoundToQueue2(sound);
  43. }
  44.  
  45. void Scumm::addSoundToQueue2(int sound) {
  46.     if (_soundQue2Pos < 10) {
  47.         _soundQue2[_soundQue2Pos++] = sound;
  48.     }
  49. }
  50.  
  51. void Scumm::processSoundQues() {
  52.     byte d;
  53.     int i,j;
  54.     int num;
  55.     int16 data[16];
  56.     SoundEngine *se;
  57.  
  58.     processSfxQueues();
  59.  
  60.     while (_soundQue2Pos){
  61.         d=_soundQue2[--_soundQue2Pos];
  62.         if (d)
  63.             playSound(d);
  64.     }
  65.  
  66.     for (i=0; i<_soundQuePos; ) {
  67.         num = _soundQue[i++];
  68.         if (i + num > _soundQuePos) {
  69.             warning("processSoundQues: invalid num value");
  70.             break;
  71.         }
  72.         for (j=0; j<16; j++)
  73.             data[j] = 0;
  74.         if (num>0) {
  75.             for (j=0; j<num; j++)
  76.                 data[j] = _soundQue[i+j];
  77.             i += num;
  78.  
  79.             se = (SoundEngine*)_soundDriver;
  80. #if 0
  81.             debug(1,"processSoundQues(%d,%d,%d,%d,%d,%d,%d,%d,%d)", 
  82.                 data[0]>>8,
  83.                 data[0]&0xFF,
  84.                 data[1],
  85.                 data[2],
  86.                 data[3],
  87.                 data[4],
  88.                 data[5],
  89.                 data[6],
  90.                 data[7]
  91.                 );
  92. #endif
  93.             if (se) 
  94.                 _vars[VAR_SOUNDRESULT] = se->do_command(data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[7]);
  95.         }
  96.     }
  97.     _soundQuePos = 0;
  98. }
  99.  
  100. void Scumm::playSound(int sound) {
  101.     SoundEngine *se = (SoundEngine*)_soundDriver;
  102.     if (se) {
  103.         getResourceAddress(rtSound, sound);
  104.         se->start_sound(sound);
  105.     }
  106. }
  107.  
  108. void Scumm::processSfxQueues() {
  109.     Actor *a;
  110.     int act;
  111.     bool b,finished;
  112.  
  113.     if (_talk_sound_mode != 0) {
  114.         startTalkSound(_talk_sound_a, _talk_sound_b, _talk_sound_mode);
  115.         _talk_sound_mode = 0;
  116.     }
  117.     
  118.     if (_sfxMode==2) {
  119.         act = _vars[VAR_TALK_ACTOR];
  120.         finished = isSfxFinished();
  121.  
  122.         if (act!=0 && (uint)act<0x80 && !string[0].no_talk_anim) {
  123.             a = derefActorSafe(act, "processSfxQueues");
  124.             if (a->room==_currentRoom && (finished || !_endOfMouthSync)) {
  125.                 b = true;
  126.                 if (!finished)
  127.                     b = isMouthSyncOff(_curSoundPos);
  128.                 if (_mouthSyncMode != b) {
  129.                     _mouthSyncMode = b;
  130.                     startAnimActor(a, b ? a->talkFrame2 : a->talkFrame1, a->facing);
  131.                 }
  132.             }
  133.         }
  134.         if (finished && _talkDelay==0) {
  135.             stopTalk();
  136.             _sfxMode = 0;
  137.         }
  138.     } else if (_sfxMode==1) {
  139.         if (isSfxFinished()) {
  140.             _sfxMode = 0;
  141.         }
  142.     }
  143. }
  144.  
  145. void Scumm::startTalkSound(uint32 offset, uint32 b, int mode) {
  146.     int num, i;
  147.     byte file_byte,file_byte_2;
  148.     uint16 elem;
  149.  
  150.     if (!_sfxFile) {
  151.         warning("startTalkSound: SFX file is not open");
  152.         return;
  153.     }
  154.  
  155.     fileSeek((FILE*)_sfxFile, offset + 8, SEEK_SET);
  156.     i = 0;
  157.     if (b>8) {
  158.         num = (b-8)>>1;
  159.         do {
  160.             fileRead((FILE*)_sfxFile, &file_byte, sizeof(file_byte));
  161.             fileRead((FILE*)_sfxFile, &file_byte_2, sizeof(file_byte_2));
  162.             _mouthSyncTimes[i++] = file_byte | (file_byte_2<<8);
  163.         } while (--num);
  164.     }
  165.     _mouthSyncTimes[i] = 0xFFFF;
  166.     _sfxMode = mode;
  167.     _curSoundPos = 0;
  168.     _mouthSyncMode = true;
  169.  
  170.     startSfxSound(_sfxFile);
  171. }
  172.  
  173. bool Scumm::isMouthSyncOff(uint pos) {
  174.     uint j;
  175.     bool val = true;
  176.     uint16 *ms = _mouthSyncTimes;
  177.  
  178.     _endOfMouthSync = false;
  179.     do {
  180.         val ^= 1;
  181.         j = *ms++;
  182.         if (j==0xFFFF) {
  183.             _endOfMouthSync = true;
  184.             break;
  185.         }
  186.     } while (pos > j);
  187.     return val;
  188. }
  189.  
  190.  
  191. int Scumm::isSoundRunning(int sound) {
  192.     SoundEngine *se;
  193.     int i;
  194.  
  195.     i = _soundQue2Pos;
  196.     while (i--) {
  197.         if (_soundQue2[i] == sound)
  198.             return 1;
  199.     }
  200.  
  201.     if (isSoundInQueue(sound))
  202.         return 1;
  203.  
  204.     if (!isResourceLoaded(4, sound))
  205.         return 0;
  206.  
  207.     
  208.     se = (SoundEngine*)_soundDriver;
  209.     if (!se)
  210.         return 0;
  211.     return se->get_sound_status(sound);
  212. }
  213.  
  214. bool Scumm::isSoundInQueue(int sound) {
  215.     int i = 0,j, num;
  216.     int16 table[16];
  217.  
  218.     while (i < _soundQuePos) {
  219.         num = _soundQue[i++];
  220.  
  221.         memset(table, 0, sizeof(table));
  222.  
  223.         if (num > 0) {
  224.             for (j=0; j<num; j++)
  225.                 table[j] = _soundQue[i+j];
  226.             i += num;
  227.             if (table[0] == 0x10F && table[1]==8 && table[2] == sound)
  228.                 return 1;
  229.         }
  230.     }
  231.     return 0;
  232. }
  233.  
  234. void Scumm::stopSound(int a) {
  235.     SoundEngine *se;
  236.     int i;
  237.  
  238.     se = (SoundEngine*)_soundDriver;
  239.     if (se)
  240.         se->stop_sound(a);
  241.  
  242.     for (i=0; i<10; i++)
  243.         if (_soundQue2[i] == (byte)a)
  244.             _soundQue2[i] = 0;
  245. }
  246.  
  247. void Scumm::stopAllSounds() {
  248.     SoundEngine *se = (SoundEngine*)_soundDriver;
  249.     if (se) {
  250.         se->stop_all_sounds();
  251.         se->clear_queue();
  252.     }
  253.     clearSoundQue();
  254. }
  255.  
  256. void Scumm::clearSoundQue() {
  257.     _soundQue2Pos = 0;
  258.     memset(_soundQue2, 0, sizeof(_soundQue2));
  259. }
  260.  
  261. void Scumm::soundKludge(int16 *list) {
  262.     int16 *ptr;
  263.     int i;
  264.  
  265.     if (list[0]==-1) {
  266.         processSoundQues();
  267.         return;
  268.     }
  269.     _soundQue[_soundQuePos++] = 8;
  270.  
  271.     ptr = _soundQue + _soundQuePos;
  272.     _soundQuePos += 8;
  273.  
  274.     for (i=0; i<8; i++)
  275.         *ptr++ = list[i];
  276.     if (_soundQuePos > 0x100)
  277.         error("Sound que buffer overflow");
  278. }
  279.  
  280. void Scumm::talkSound(uint32 a, uint32 b, int mode) {
  281.     _talk_sound_a = a;
  282.     _talk_sound_b = b;
  283.     _talk_sound_mode = mode;
  284. }
  285.  
  286. static const uint32 sound_tags[] = {
  287.     MKID('ADL ')
  288. };
  289.  
  290. void Scumm::setupSound() {
  291.     SoundEngine *se = (SoundEngine*)_soundDriver;
  292.     if (se) {
  293.         se->_base_sounds = res.address[4];
  294.     }
  295.     _soundTagTable = (byte*)sound_tags;
  296.     _numSoundTags = 1;
  297.     _sfxFile = openSfxFile();
  298. }
  299.  
  300. struct VOCHeader {
  301.     byte id[19];
  302.     byte extra[7];
  303. };
  304.  
  305. static const char VALID_VOC_ID[] = "Creative Voice File";
  306. static const char VALID_VOC_VERSION[] = "";
  307. void Scumm::startSfxSound(void *file) {
  308.     VOCHeader hdr;
  309.     int block_type;
  310.     byte work[8];
  311.     uint size,i;
  312.     int rate,comp;
  313.     byte *data;
  314.  
  315.     if (fread(&hdr, sizeof(hdr), 1, (FILE*)file) != 1 || 
  316.         memcmp(hdr.id, VALID_VOC_ID, sizeof(hdr.id)) != 0) {
  317.         warning("startSfxSound: invalid header");
  318.         return;
  319.     }
  320.  
  321.     block_type = fgetc( (FILE*)file );
  322.     if (block_type != 1) {
  323.         warning("startSfxSound: Expecting block_type == 1, got %d", block_type);
  324.         return;
  325.     }
  326.  
  327.     fread(work, 3, 1, (FILE*)file);
  328.  
  329.     size = ( work[0] | ( work[1] << 8 ) | ( work[2] << 16 ) ) - 2;
  330.     rate = fgetc( (FILE*)file );
  331.     comp = fgetc( (FILE*)file );
  332.  
  333.     if (comp != 0) {
  334.         warning("startSfxSound: Unsupported compression type %d", comp);
  335.         return;
  336.     }
  337.  
  338.     data = (byte*) malloc(size);
  339.     if (data==NULL) {
  340.         error("startSfxSound: out of memory");
  341.         return;
  342.     }
  343.     
  344.     if (fread(data, size, 1, (FILE*)file) != 1) {
  345.         /* no need to free the memory since error will shut down */
  346.         error("startSfxSound: cannot read %d bytes", size);
  347.         return;
  348.     }
  349.     for(i=0;i<size; i++)
  350.         data[i] ^= 0x80;
  351.  
  352.     playSfxSound(data, size, 1000000 / (256 - rate) );
  353. }
  354.  
  355. void *Scumm::openSfxFile() {
  356.     return fopen("monster.sou", "rb");
  357. }
  358.