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

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

Updated with heuristic to make the decision

  • engines/sword1/sound.cpp

    diff -ruN scummvm-20090228-orig/engines/sword1/sound.cpp scummvm-20090228/engines/sword1/sound.cpp
    old new  
    5050        strcpy(_filePath, searchPath);
    5151        _mixer = mixer;
    5252        _resMan = pResMan;
     53        _bigEndianSpeech = false;
    5354        _cowHeader = NULL;
    5455        _endOfQueue = 0;
    5556        _currentCowFile = 0;
     
    6667        closeCowSystem();
    6768}
    6869
     70void Sound::checkSpeechFileEndianness() {
     71        // Some mac versions (not all of them) use big endian waw, although
     72        // the waw header doesn't indicate it.
     73        // Use heuristic to determine endianness of speech.
     74        // The heuristic consist in computing the sum of the absolute difference for
     75        // every two consecutive samples. This is done both with a big endian and a
     76        // little endian assumption. The one with the smallest sum should be the
     77        // correct one (the sound wave is supposed to be relatively smooth).
     78        // It needs at least 1000 samples to get stable result (the code below is
     79        // using the first 2000 samples of the waw sound.
     80       
     81        // Init speach file if not already done.
     82        if (!_currentCowFile) {
     83                // Open one of the speech file. It uses SwordEngine::_systemVars.currentCD
     84                // to decide which file to open, therefore if it is currently set to zero
     85                // we have to set it to either 1 or 2 (I decided to set it to 1 as this is
     86                // more likely to be the first file that will be needed).
     87                bool no_current_cd = false;
     88                if (SwordEngine::_systemVars.currentCD == 0) {
     89                        SwordEngine::_systemVars.currentCD = 1;
     90                        no_current_cd = true;
     91                }
     92                initCowSystem();
     93                if (no_current_cd) {
     94                        // In case it fails with CD1 retyr with CD2
     95                        if (!_currentCowFile) {
     96                                SwordEngine::_systemVars.currentCD = 2;
     97                                initCowSystem();
     98                        }
     99                        // Reset curentCD flag
     100                        SwordEngine::_systemVars.currentCD = 0;
     101                }
     102        }
     103
     104        // Testing for endianness makes sense only if using the nom compressed files.
     105        if (_cowHeader == NULL || (_cowMode != CowWave && _cowMode != CowDemo))
     106                return;
     107
     108        // I picked the sample to use randomly (I just made sure it is long enough so that there is
     109        // a fair change of the heuristic to have a stable result and work for every languages).
     110        int roomNo = _currentCowFile == 1 ? 1 : 129;
     111        int localNo = _currentCowFile == 1 ? 2 : 933;
     112        // Get the speech data and apply the heuristic
     113        uint32 locIndex = _cowHeader[roomNo] >> 2;
     114        uint32 sampleSize = _cowHeader[locIndex + (localNo * 2)];
     115        uint32 index = _cowHeader[locIndex + (localNo * 2) - 1];
     116        if (sampleSize) {
     117                uint32 size;
     118                double be_diff_sum = 0., le_diff_sum = 0.;
     119                _bigEndianSpeech = false;
     120                int16 *data = uncompressSpeech(index + _cowHeaderSize, sampleSize, &size);
     121                // Compute average of differecen between two consecutive samples for both BE and LE
     122                if (data) {
     123                        if (size > 4000)
     124                                size = 2000;
     125                        else
     126                                size /= 2;
     127                        int16 prev_be_value = (int16)SWAP_BYTES_16(*((uint16*)(data)));
     128                        for (uint32 i = 1 ; i < size ; ++i) {
     129                                le_diff_sum += fabs(data[i] - data[i-1]);
     130                                int16 be_value = (int16)SWAP_BYTES_16(*((uint16*)(data + i)));
     131                                be_diff_sum += fabs(be_value - prev_be_value);
     132                                prev_be_value = be_value;
     133                        }
     134                        delete [] data;
     135                }
     136                // Set the big endian flag
     137                _bigEndianSpeech = (be_diff_sum < le_diff_sum);
     138                if (_bigEndianSpeech)
     139                        debug(6, "Mac version: using big endian speech file");
     140                else
     141                        debug(6, "Mac version: using little endian speech file");
     142                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);
     143        }
     144}
     145
    69146int Sound::addToQueue(int32 fxNo) {
    70147        bool alreadyInQueue = false;
    71148        for (uint8 cnt = 0; (cnt < _endOfQueue) && (!alreadyInQueue); cnt++)
     
    310387                int16 *dstData = (int16*)malloc(resSize * 2);
    311388                int32 samplesLeft = resSize;
    312389                while (srcPos < cSize && samplesLeft > 0) {
    313                         length = (int16)READ_LE_UINT16(srcData + srcPos);
     390                        length = (int16)(_bigEndianSpeech ? READ_BE_UINT16(srcData + srcPos) : READ_LE_UINT16(srcData + srcPos));
    314391                        srcPos++;
    315392                        if (length < 0) {
    316393                                length = -length;
    317394                                if (length > samplesLeft)
    318395                                        length = samplesLeft;
     396
     397                                int16 value;
     398                                if (_bigEndianSpeech) {
     399                                        value = (int16)SWAP_BYTES_16(*((uint16*)(srcData + srcPos)));
     400                                } else {
     401                                        value = srcData[srcPos];
     402                                }
     403
    319404                                for (uint16 cnt = 0; cnt < (uint16)length; cnt++)
    320                                         dstData[dstPos++] = srcData[srcPos];
     405                                        dstData[dstPos++] = value;
     406
    321407                                srcPos++;
    322408                        } else {
    323409                                if (length > samplesLeft)
    324410                                        length = samplesLeft;
    325                                 memcpy(dstData + dstPos, srcData + srcPos, length * 2);
    326                                 dstPos += length;
    327                                 srcPos += length;
     411
     412                                if (_bigEndianSpeech) {
     413                                        for (uint16 cnt = 0; cnt < (uint16)length; cnt++)
     414                                                dstData[dstPos++] = (int16)SWAP_BYTES_16(*((uint16*)(srcData + (srcPos++))));
     415                                } else {
     416                                        memcpy(dstData + dstPos, srcData + srcPos, length * 2);
     417                                        dstPos += length;
     418                                        srcPos += length;
     419                                }
    328420                        }
    329421                        samplesLeft -= length;
    330422                }
  • engines/sword1/sound.h

    diff -ruN scummvm-20090228-orig/engines/sword1/sound.h scummvm-20090228/engines/sword1/sound.h
    old new  
    9393        int addToQueue(int32 fxNo);
    9494
    9595        void engine(void);
     96       
     97        void checkSpeechFileEndianness();
    9698
    9799private:
    98100        uint8 _sfxVolL, _sfxVolR, _speechVolL, _speechVolR;
     
    115117        uint8            _endOfQueue;
    116118        Audio::Mixer *_mixer;
    117119        ResMan *_resMan;
     120        bool _bigEndianSpeech;
    118121        char _filePath[100];
    119122        static const char _musicList[270];
    120123        static const uint16 _roomsFixedFx[TOTAL_ROOMS][TOTAL_FX_PER_ROOM];
  • engines/sword1/sword1.cpp

    diff -ruN scummvm-20090228-orig/engines/sword1/sword1.cpp scummvm-20090228/engines/sword1/sword1.cpp
    old new  
    137137
    138138        _systemVars.playSpeech = 1;
    139139        _mouseState = 0;
     140       
     141        // Some Mac versions use big endian for the speech files but not all of them.
     142        if (SwordEngine::_systemVars.isMac)
     143                _sound->checkSpeechFileEndianness();
    140144
    141145        _logic->initialize();
    142146        _objectMan->initialize();