bool CAudioContainerSA::GetRawAudioData ( eAudioLookupIndex lookupIndex, int bankIndex, int audioIndex, uint8*& dataOut, unsigned int& lengthOut, int& iSampleRateOut )
{
    int numBanks = m_pLookupTable->CountIndex ( lookupIndex );
    if ( numBanks == 0 )
        return false;

    // Get archive file size
    std::ifstream archive ( FromUTF8( GetAudioArchiveName ( lookupIndex ) ), std::ios::binary );

    SAudioLookupEntrySA* lookupEntry = m_pLookupTable->GetEntry ( lookupIndex, bankIndex );
    if ( !lookupEntry )
        return false;

    // Read audio archive bank header (an audio archieve has multiple bank headers)
    SAudioBankHeaderSA bankHeader;

    // Seek to the bank offset and read the header
    archive.seekg ( lookupEntry->offset );
    if ( !archive.read ( reinterpret_cast<char*> ( &bankHeader ), sizeof ( SAudioBankHeaderSA ) ) )
        return false;

    // Get offsets to calculate the length
    SAudioEntrySA* audioEntry = &bankHeader.sounds[audioIndex];
    if ( !audioEntry )
        return false;

    unsigned int rawLength;
    if ( audioIndex+1 < bankHeader.numSounds ) // hacky fix: audioIndex starts at 0
    {
        SAudioEntrySA* nextAudioEntry = &bankHeader.sounds[audioIndex+1];
        if ( !nextAudioEntry )
            return false;

        rawLength = nextAudioEntry->offset - audioEntry->offset;
    }
    else if ( audioIndex+1 == bankHeader.numSounds )
    {
        rawLength = lookupEntry->length - audioEntry->offset;
    }
    else
        return false;

    // 2MB check in case of user modification errors (Max length of standard audio files is 560KB)
    if ( rawLength > 2 * 1024 * 1024 )
        return false;

    // Now we are ready to read the audio data :)
    uint8* buffer = new uint8[rawLength];

    dataOut = buffer;
    lengthOut = rawLength;
    iSampleRateOut = audioEntry->sampleRate;

    // Seek to the correct offset and read
    archive.seekg ( lookupEntry->offset + sizeof(SAudioBankHeaderSA) + audioEntry->offset ); // Or just archive.seekg ( archive.tellg() + audioEntry->offset )
    archive.read(reinterpret_cast<char*> ( buffer ), rawLength );

    return !archive.fail();
}
bool CAudioContainerSA::ValidateContainer(eAudioLookupIndex lookupIndex)
{
#ifdef MTA_DEBUG
    return true;
#endif

    // Open archive and place file pointer at the end
    std::ifstream archive(FromUTF8(GetAudioArchiveName(lookupIndex)), std::ios::binary);

    // Check if it does not exist
    if (!archive)
        return false;

    // Get the archive size divided by 10 and seek to the beginning
    archive.seekg(0, std::ios::end);
    std::streampos stepSize = archive.tellg() / 10;
    archive.seekg(0);

    // Count the zeros -> if more than 80% we assume that it has been cut (read 4KB blocks at once)
    uint8              buffer[VALIDATE_BUFFER_SIZE];
    unsigned long long numZeros = 0;
    while (archive.read(reinterpret_cast<char*>(buffer), VALIDATE_BUFFER_SIZE))
    {
        for (unsigned int i = 0; i < VALIDATE_BUFFER_SIZE; i++)
        {
            if (buffer[i] == 0)
                numZeros++;
        }

        archive.seekg(stepSize, std::ios::cur);
    }

    // Close the archive
    archive.close();

    if (static_cast<float>(numZeros) / (10 * VALIDATE_BUFFER_SIZE) >= 0.8f)
        return false;

    return true;
}