Ticket #8851: bs1-mac-en-v4.patch

File bs1-mac-en-v4.patch, 6.0 KB (added by criezy, 15 years ago)

Update patch for r42417

  • engines/sword1/sword1.cpp

     
    145145
    146146        _systemVars.playSpeech = 1;
    147147        _mouseState = 0;
     148       
     149        // Some Mac versions use big endian for the speech files but not all of them.
     150        if (_systemVars.platform == Common::kPlatformMacintosh)
     151                _sound->checkSpeechFileEndianness();
    148152
    149153        _logic->initialize();
    150154        _objectMan->initialize();
  • engines/sword1/sound.h

     
    9595
    9696        void engine(void);
    9797
     98        void checkSpeechFileEndianness();
     99
    98100private:
    99101        uint8 _sfxVolL, _sfxVolR, _speechVolL, _speechVolR;
    100102        void playSample(QueueElement *elem);
     
    116118        uint8            _endOfQueue;
    117119        Audio::Mixer *_mixer;
    118120        ResMan *_resMan;
     121        bool _bigEndianSpeech;
    119122        char _filePath[100];
    120123        static const char _musicList[270];
    121124        static const uint16 _roomsFixedFx[TOTAL_ROOMS][TOTAL_FX_PER_ROOM];
  • engines/sword1/sound.cpp

     
    5151        strcpy(_filePath, searchPath);
    5252        _mixer = mixer;
    5353        _resMan = pResMan;
     54        _bigEndianSpeech = false;
    5455        _cowHeader = NULL;
    5556        _endOfQueue = 0;
    5657        _currentCowFile = 0;
     
    6768        closeCowSystem();
    6869}
    6970
     71void Sound::checkSpeechFileEndianness() {
     72        // Some mac versions (not all of them) use big endian waw, although
     73        // the waw header doesn't indicate it.
     74        // Use heuristic to determine endianness of speech.
     75        // The heuristic consist in computing the sum of the absolute difference for
     76        // every two consecutive samples. This is done both with a big endian and a
     77        // little endian assumption. The one with the smallest sum should be the
     78        // correct one (the sound wave is supposed to be relatively smooth).
     79        // It needs at least 1000 samples to get stable result (the code below is
     80        // using the first 2000 samples of the waw sound.
     81
     82        // Init speach file if not already done.
     83        if (!_currentCowFile) {
     84                // Open one of the speech file. It uses SwordEngine::_systemVars.currentCD
     85                // to decide which file to open, therefore if it is currently set to zero
     86                // we have to set it to either 1 or 2 (I decided to set it to 1 as this is
     87                // more likely to be the first file that will be needed).
     88                bool no_current_cd = false;
     89                if (SwordEngine::_systemVars.currentCD == 0) {
     90                        SwordEngine::_systemVars.currentCD = 1;
     91                        no_current_cd = true;
     92                }
     93                initCowSystem();
     94                if (no_current_cd) {
     95                        // In case it fails with CD1 retyr with CD2
     96                        if (!_currentCowFile) {
     97                                SwordEngine::_systemVars.currentCD = 2;
     98                                initCowSystem();
     99                        }
     100                        // Reset curentCD flag
     101                        SwordEngine::_systemVars.currentCD = 0;
     102                }
     103        }
     104
     105        // Testing for endianness makes sense only if using the nom compressed files.
     106        if (_cowHeader == NULL || (_cowMode != CowWave && _cowMode != CowDemo))
     107                return;
     108
     109        // I picked the sample to use randomly (I just made sure it is long enough so that there is
     110        // a fair change of the heuristic to have a stable result and work for every languages).
     111        int roomNo = _currentCowFile == 1 ? 1 : 129;
     112        int localNo = _currentCowFile == 1 ? 2 : 933;
     113        // Get the speech data and apply the heuristic
     114        uint32 locIndex = _cowHeader[roomNo] >> 2;
     115        uint32 sampleSize = _cowHeader[locIndex + (localNo * 2)];
     116        uint32 index = _cowHeader[locIndex + (localNo * 2) - 1];
     117        if (sampleSize) {
     118                uint32 size;
     119                double be_diff_sum = 0., le_diff_sum = 0.;
     120                _bigEndianSpeech = false;
     121                int16 *data = uncompressSpeech(index + _cowHeaderSize, sampleSize, &size);
     122                // Compute average of differecen between two consecutive samples for both BE and LE
     123                if (data) {
     124                        if (size > 4000)
     125                                size = 2000;
     126                        else
     127                                size /= 2;
     128                        int16 prev_be_value = (int16)SWAP_BYTES_16(*((uint16*)(data)));
     129                        for (uint32 i = 1 ; i < size ; ++i) {
     130                                le_diff_sum += fabs(data[i] - data[i-1]);
     131                                int16 be_value = (int16)SWAP_BYTES_16(*((uint16*)(data + i)));
     132                                be_diff_sum += fabs(be_value - prev_be_value);
     133                                prev_be_value = be_value;
     134                        }
     135                        delete [] data;
     136                }
     137                // Set the big endian flag
     138                _bigEndianSpeech = (be_diff_sum < le_diff_sum);
     139                if (_bigEndianSpeech)
     140                        debug(6, "Mac version: using big endian speech file");
     141                else
     142                        debug(6, "Mac version: using little endian speech file");
     143                debug(8, "Speech endianness heuristic: average = %f for BE and %f for LE, computed on %d samples)", be_diff_sum / (size - 1), le_diff_sum / (size - 1), size);
     144        }
     145}
     146
     147
    70148int Sound::addToQueue(int32 fxNo) {
    71149        bool alreadyInQueue = false;
    72150        for (uint8 cnt = 0; (cnt < _endOfQueue) && (!alreadyInQueue); cnt++)
     
    386464                int16 *dstData = (int16*)malloc(resSize * 2);
    387465                int32 samplesLeft = resSize;
    388466                while (srcPos < cSize && samplesLeft > 0) {
    389                         length = (int16)READ_LE_UINT16(srcData + srcPos);
     467                        length = (int16)(_bigEndianSpeech ? READ_BE_UINT16(srcData + srcPos) : READ_LE_UINT16(srcData + srcPos));
    390468                        srcPos++;
    391469                        if (length < 0) {
    392470                                length = -length;
    393471                                if (length > samplesLeft)
    394472                                        length = samplesLeft;
     473                                int16 value;
     474                                if (_bigEndianSpeech) {
     475                                        value = (int16)SWAP_BYTES_16(*((uint16*)(srcData + srcPos)));
     476                                } else {
     477                                        value = srcData[srcPos];
     478                                }
    395479                                for (uint16 cnt = 0; cnt < (uint16)length; cnt++)
    396                                         dstData[dstPos++] = srcData[srcPos];
     480                                        dstData[dstPos++] = value;
    397481                                srcPos++;
    398482                        } else {
    399483                                if (length > samplesLeft)
    400484                                        length = samplesLeft;
    401                                 memcpy(dstData + dstPos, srcData + srcPos, length * 2);
    402                                 dstPos += length;
    403                                 srcPos += length;
     485                                if (_bigEndianSpeech) {
     486                                        for (uint16 cnt = 0; cnt < (uint16)length; cnt++)
     487                                                dstData[dstPos++] = (int16)SWAP_BYTES_16(*((uint16*)(srcData + (srcPos++))));
     488                                } else {
     489                                        memcpy(dstData + dstPos, srcData + srcPos, length * 2);
     490                                        dstPos += length;
     491                                        srcPos += length;
     492                                }
    404493                        }
    405494                        samplesLeft -= length;
    406495                }