<commit_before>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "txdb.h"
#include "main.h"

using namespace std;

void static BatchWriteCoins(CLevelDBBatch &batch, const uint256 &hash, const CCoins &coins) {
    if (coins.IsPruned())
        batch.Erase(make_pair('c', hash));
    else
        batch.Write(make_pair('c', hash), coins);
}

void static BatchWriteHashBestChain(CLevelDBBatch &batch, const uint256 &hash) {
    batch.Write('B', hash);
}

CCoinsViewDB::CCoinsViewDB(bool fMemory) : db(GetDataDir() / "coins", fMemory) {
}

bool CCoinsViewDB::GetCoins(uint256 txid, CCoins &coins) {
    return db.Read(make_pair('c', txid), coins);
}

bool CCoinsViewDB::SetCoins(uint256 txid, const CCoins &coins) {
    CLevelDBBatch batch;
    BatchWriteCoins(batch, txid, coins);
    return db.WriteBatch(batch);
}

bool CCoinsViewDB::HaveCoins(uint256 txid) {
    return db.Exists(make_pair('c', txid));
}

CBlockIndex *CCoinsViewDB::GetBestBlock() {
    uint256 hashBestChain;
    if (!db.Read('B', hashBestChain))
        return NULL;
    std::map<uint256, CBlockIndex*>::iterator it = mapBlockIndex.find(hashBestChain);
    if (it == mapBlockIndex.end())
        return NULL;
    return it->second;
}

bool CCoinsViewDB::SetBestBlock(CBlockIndex *pindex) {
    CLevelDBBatch batch;
    BatchWriteHashBestChain(batch, pindex->GetBlockHash());
    return db.WriteBatch(batch);
}

bool CCoinsViewDB::BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex) {
    printf("Committing %u changed transactions to coin database...\n", (unsigned int)mapCoins.size());

    CLevelDBBatch batch;
    for (std::map<uint256, CCoins>::const_iterator it = mapCoins.begin(); it != mapCoins.end(); it++)
        BatchWriteCoins(batch, it->first, it->second);
    BatchWriteHashBestChain(batch, pindex->GetBlockHash());

    return db.WriteBatch(batch);
}

CBlockTreeDB::CBlockTreeDB(bool fMemory) : CLevelDB(GetDataDir() / "blktree", fMemory) {
}

bool CBlockTreeDB::WriteBlockIndex(const CDiskBlockIndex& blockindex)
{
    return Write(make_pair('b', blockindex.GetBlockHash()), blockindex);
}

bool CBlockTreeDB::ReadBestInvalidWork(CBigNum& bnBestInvalidWork)
{
    return Read('I', bnBestInvalidWork);
}

bool CBlockTreeDB::WriteBestInvalidWork(const CBigNum& bnBestInvalidWork)
{
    return Write('I', bnBestInvalidWork);
}

bool CBlockTreeDB::WriteBlockFileInfo(int nFile, const CBlockFileInfo &info) {
    return Write(make_pair('f', nFile), info);
}

bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) {
    return Read(make_pair('f', nFile), info);
}

bool CBlockTreeDB::WriteLastBlockFile(int nFile) {
    return Write('l', nFile);
}

bool CBlockTreeDB::ReadLastBlockFile(int &nFile) {
    return Read('l', nFile);
}

bool CCoinsViewDB::GetStats(CCoinsStats &stats) {
    leveldb::Iterator *pcursor = db.NewIterator();
    pcursor->SeekToFirst();

    while (pcursor->Valid()) {
        try {
            leveldb::Slice slKey = pcursor->key();
            CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
            char chType;
            ssKey >> chType;
            if (chType == 'c' && !fRequestShutdown) {
                leveldb::Slice slValue = pcursor->value();
                CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
                CCoins coins;
                ssValue >> coins;
                uint256 txhash;
                ssKey >> txhash;

                stats.nTransactions++;
                BOOST_FOREACH(const CTxOut &out, coins.vout) {
                    if (!out.IsNull())
                        stats.nTransactionOutputs++;
                }
                stats.nSerializedSize += 32 + slValue.size();
            }
            pcursor->Next();
        } catch (std::exception &e) {
            return error("%s() : deserialize error", __PRETTY_FUNCTION__);
        }
    }
    delete pcursor;
    stats.nHeight = GetBestBlock()->nHeight;
    return true;
}

bool CBlockTreeDB::LoadBlockIndexGuts()
{
    leveldb::Iterator *pcursor = NewIterator();

    CDataStream ssKeySet(SER_DISK, CLIENT_VERSION);
    ssKeySet << make_pair('b', uint256(0));
    pcursor->Seek(ssKeySet.str());

    // Load mapBlockIndex
    while (pcursor->Valid()) {
        try {
            leveldb::Slice slKey = pcursor->key();
            CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
            char chType;
            ssKey >> chType;
            if (chType == 'b' && !fRequestShutdown) {
                leveldb::Slice slValue = pcursor->value();
                CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
                CDiskBlockIndex diskindex;
                ssValue >> diskindex;

                // Construct block index object
                CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash());
                pindexNew->pprev          = InsertBlockIndex(diskindex.hashPrev);
                pindexNew->nHeight        = diskindex.nHeight;
                pindexNew->nFile          = diskindex.nFile;
                pindexNew->nDataPos       = diskindex.nDataPos;
                pindexNew->nUndoPos       = diskindex.nUndoPos;
                pindexNew->nVersion       = diskindex.nVersion;
                pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
                pindexNew->nTime          = diskindex.nTime;
                pindexNew->nBits          = diskindex.nBits;
                pindexNew->nNonce         = diskindex.nNonce;
                pindexNew->nStatus        = diskindex.nStatus;
                pindexNew->nTx            = diskindex.nTx;

                // Watch for genesis block
                if (pindexGenesisBlock == NULL && diskindex.GetBlockHash() == hashGenesisBlock)
                    pindexGenesisBlock = pindexNew;

                if (!pindexNew->CheckIndex())
                    return error("LoadBlockIndex() : CheckIndex failed: %s", pindexNew->ToString().c_str());

                pcursor->Next();
            } else {
                break; // if shutdown requested or finished loading block index
            }
        } catch (std::exception &e) {
            return error("%s() : deserialize error", __PRETTY_FUNCTION__);
        }
    }
    delete pcursor;

    return true;
}
<commit_msg>Bugfix: don't crash by trying to write unchanged best block<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "txdb.h"
#include "main.h"

using namespace std;

void static BatchWriteCoins(CLevelDBBatch &batch, const uint256 &hash, const CCoins &coins) {
    if (coins.IsPruned())
        batch.Erase(make_pair('c', hash));
    else
        batch.Write(make_pair('c', hash), coins);
}

void static BatchWriteHashBestChain(CLevelDBBatch &batch, const uint256 &hash) {
    batch.Write('B', hash);
}

CCoinsViewDB::CCoinsViewDB(bool fMemory) : db(GetDataDir() / "coins", fMemory) {
}

bool CCoinsViewDB::GetCoins(uint256 txid, CCoins &coins) {
    return db.Read(make_pair('c', txid), coins);
}

bool CCoinsViewDB::SetCoins(uint256 txid, const CCoins &coins) {
    CLevelDBBatch batch;
    BatchWriteCoins(batch, txid, coins);
    return db.WriteBatch(batch);
}

bool CCoinsViewDB::HaveCoins(uint256 txid) {
    return db.Exists(make_pair('c', txid));
}

CBlockIndex *CCoinsViewDB::GetBestBlock() {
    uint256 hashBestChain;
    if (!db.Read('B', hashBestChain))
        return NULL;
    std::map<uint256, CBlockIndex*>::iterator it = mapBlockIndex.find(hashBestChain);
    if (it == mapBlockIndex.end())
        return NULL;
    return it->second;
}

bool CCoinsViewDB::SetBestBlock(CBlockIndex *pindex) {
    CLevelDBBatch batch;
    BatchWriteHashBestChain(batch, pindex->GetBlockHash());
    return db.WriteBatch(batch);
}

bool CCoinsViewDB::BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex) {
    printf("Committing %u changed transactions to coin database...\n", (unsigned int)mapCoins.size());

    CLevelDBBatch batch;
    for (std::map<uint256, CCoins>::const_iterator it = mapCoins.begin(); it != mapCoins.end(); it++)
        BatchWriteCoins(batch, it->first, it->second);
    if (pindex)
        BatchWriteHashBestChain(batch, pindex->GetBlockHash());

    return db.WriteBatch(batch);
}

CBlockTreeDB::CBlockTreeDB(bool fMemory) : CLevelDB(GetDataDir() / "blktree", fMemory) {
}

bool CBlockTreeDB::WriteBlockIndex(const CDiskBlockIndex& blockindex)
{
    return Write(make_pair('b', blockindex.GetBlockHash()), blockindex);
}

bool CBlockTreeDB::ReadBestInvalidWork(CBigNum& bnBestInvalidWork)
{
    return Read('I', bnBestInvalidWork);
}

bool CBlockTreeDB::WriteBestInvalidWork(const CBigNum& bnBestInvalidWork)
{
    return Write('I', bnBestInvalidWork);
}

bool CBlockTreeDB::WriteBlockFileInfo(int nFile, const CBlockFileInfo &info) {
    return Write(make_pair('f', nFile), info);
}

bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) {
    return Read(make_pair('f', nFile), info);
}

bool CBlockTreeDB::WriteLastBlockFile(int nFile) {
    return Write('l', nFile);
}

bool CBlockTreeDB::ReadLastBlockFile(int &nFile) {
    return Read('l', nFile);
}

bool CCoinsViewDB::GetStats(CCoinsStats &stats) {
    leveldb::Iterator *pcursor = db.NewIterator();
    pcursor->SeekToFirst();

    while (pcursor->Valid()) {
        try {
            leveldb::Slice slKey = pcursor->key();
            CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
            char chType;
            ssKey >> chType;
            if (chType == 'c' && !fRequestShutdown) {
                leveldb::Slice slValue = pcursor->value();
                CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
                CCoins coins;
                ssValue >> coins;
                uint256 txhash;
                ssKey >> txhash;

                stats.nTransactions++;
                BOOST_FOREACH(const CTxOut &out, coins.vout) {
                    if (!out.IsNull())
                        stats.nTransactionOutputs++;
                }
                stats.nSerializedSize += 32 + slValue.size();
            }
            pcursor->Next();
        } catch (std::exception &e) {
            return error("%s() : deserialize error", __PRETTY_FUNCTION__);
        }
    }
    delete pcursor;
    stats.nHeight = GetBestBlock()->nHeight;
    return true;
}

bool CBlockTreeDB::LoadBlockIndexGuts()
{
    leveldb::Iterator *pcursor = NewIterator();

    CDataStream ssKeySet(SER_DISK, CLIENT_VERSION);
    ssKeySet << make_pair('b', uint256(0));
    pcursor->Seek(ssKeySet.str());

    // Load mapBlockIndex
    while (pcursor->Valid()) {
        try {
            leveldb::Slice slKey = pcursor->key();
            CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
            char chType;
            ssKey >> chType;
            if (chType == 'b' && !fRequestShutdown) {
                leveldb::Slice slValue = pcursor->value();
                CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
                CDiskBlockIndex diskindex;
                ssValue >> diskindex;

                // Construct block index object
                CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash());
                pindexNew->pprev          = InsertBlockIndex(diskindex.hashPrev);
                pindexNew->nHeight        = diskindex.nHeight;
                pindexNew->nFile          = diskindex.nFile;
                pindexNew->nDataPos       = diskindex.nDataPos;
                pindexNew->nUndoPos       = diskindex.nUndoPos;
                pindexNew->nVersion       = diskindex.nVersion;
                pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
                pindexNew->nTime          = diskindex.nTime;
                pindexNew->nBits          = diskindex.nBits;
                pindexNew->nNonce         = diskindex.nNonce;
                pindexNew->nStatus        = diskindex.nStatus;
                pindexNew->nTx            = diskindex.nTx;

                // Watch for genesis block
                if (pindexGenesisBlock == NULL && diskindex.GetBlockHash() == hashGenesisBlock)
                    pindexGenesisBlock = pindexNew;

                if (!pindexNew->CheckIndex())
                    return error("LoadBlockIndex() : CheckIndex failed: %s", pindexNew->ToString().c_str());

                pcursor->Next();
            } else {
                break; // if shutdown requested or finished loading block index
            }
        } catch (std::exception &e) {
            return error("%s() : deserialize error", __PRETTY_FUNCTION__);
        }
    }
    delete pcursor;

    return true;
}
<|endoftext|>


<commit_before>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Syscoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "txdb.h"

#include "chain.h"
#include "chainparams.h"
#include "hash.h"
#include "main.h"
#include "pow.h"
#include "uint256.h"

#include <stdint.h>

#include <boost/thread.hpp>

using namespace std;

static const char DB_COINS = 'c';
static const char DB_BLOCK_FILES = 'f';
static const char DB_TXINDEX = 't';
static const char DB_BLOCK_INDEX = 'b';

static const char DB_BEST_BLOCK = 'B';
static const char DB_FLAG = 'F';
static const char DB_REINDEX_FLAG = 'R';
static const char DB_LAST_BLOCK = 'l';

CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / "chainstate", nCacheSize, fMemory, fWipe, true)
{
}

bool CCoinsViewDB::GetCoins(const uint256 &txid, CCoins &coins) const {
    return db.Read(make_pair(DB_COINS, txid), coins);
}

bool CCoinsViewDB::HaveCoins(const uint256 &txid) const {
    return db.Exists(make_pair(DB_COINS, txid));
}

uint256 CCoinsViewDB::GetBestBlock() const {
    uint256 hashBestChain;
    if (!db.Read(DB_BEST_BLOCK, hashBestChain))
        return uint256();
    return hashBestChain;
}

bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) {
    CDBBatch batch(&db.GetObfuscateKey());
    size_t count = 0;
    size_t changed = 0;
    for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) {
        if (it->second.flags & CCoinsCacheEntry::DIRTY) {
            if (it->second.coins.IsPruned())
                batch.Erase(make_pair(DB_COINS, it->first));
            else
                batch.Write(make_pair(DB_COINS, it->first), it->second.coins);
            changed++;
        }
        count++;
        CCoinsMap::iterator itOld = it++;
        mapCoins.erase(itOld);
    }
    if (!hashBlock.IsNull())
        batch.Write(DB_BEST_BLOCK, hashBlock);

    LogPrint("coindb", "Committing %u changed transactions (out of %u) to coin database...\n", (unsigned int)changed, (unsigned int)count);
    return db.WriteBatch(batch);
}

CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe) {
}

bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) {
    return Read(make_pair(DB_BLOCK_FILES, nFile), info);
}

bool CBlockTreeDB::WriteReindexing(bool fReindexing) {
    if (fReindexing)
        return Write(DB_REINDEX_FLAG, '1');
    else
        return Erase(DB_REINDEX_FLAG);
}

bool CBlockTreeDB::ReadReindexing(bool &fReindexing) {
    fReindexing = Exists(DB_REINDEX_FLAG);
    return true;
}

bool CBlockTreeDB::ReadLastBlockFile(int &nFile) {
    return Read(DB_LAST_BLOCK, nFile);
}

bool CCoinsViewDB::GetStats(CCoinsStats &stats) const {
    /* It seems that there are no "const iterators" for LevelDB.  Since we
       only need read operations on it, use a const-cast to get around
       that restriction.  */
    boost::scoped_ptr<CDBIterator> pcursor(const_cast<CDBWrapper*>(&db)->NewIterator());
    pcursor->Seek(DB_COINS);

    CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
    stats.hashBlock = GetBestBlock();
    ss << stats.hashBlock;
    CAmount nTotalAmount = 0;
    while (pcursor->Valid()) {
        boost::this_thread::interruption_point();
        std::pair<char, uint256> key;
        CCoins coins;
        if (pcursor->GetKey(key) && key.first == DB_COINS) {
            if (pcursor->GetValue(coins)) {
                stats.nTransactions++;
                for (unsigned int i=0; i<coins.vout.size(); i++) {
                    const CTxOut &out = coins.vout[i];
                    if (!out.IsNull()) {
                        stats.nTransactionOutputs++;
                        ss << VARINT(i+1);
                        ss << out;
                        nTotalAmount += out.nValue;
                    }
                }
                stats.nSerializedSize += 32 + pcursor->GetValueSize();
                ss << VARINT(0);
            } else {
                return error("CCoinsViewDB::GetStats() : unable to read value");
            }
        } else {
            break;
        }
        pcursor->Next();
    }
    {
        LOCK(cs_main);
        stats.nHeight = mapBlockIndex.find(stats.hashBlock)->second->nHeight;
    }
    stats.hashSerialized = ss.GetHash();
    stats.nTotalAmount = nTotalAmount;
    return true;
}

bool CBlockTreeDB::WriteBatchSync(const std::vector<std::pair<int, const CBlockFileInfo*> >& fileInfo, int nLastFile, const std::vector<const CBlockIndex*>& blockinfo) {
    CDBBatch batch(&GetObfuscateKey());
    for (std::vector<std::pair<int, const CBlockFileInfo*> >::const_iterator it=fileInfo.begin(); it != fileInfo.end(); it++) {
        batch.Write(make_pair(DB_BLOCK_FILES, it->first), *it->second);
    }
    batch.Write(DB_LAST_BLOCK, nLastFile);
    for (std::vector<const CBlockIndex*>::const_iterator it=blockinfo.begin(); it != blockinfo.end(); it++) {
        batch.Write(make_pair(DB_BLOCK_INDEX, (*it)->GetBlockHash()), CDiskBlockIndex(*it));
    }
    return WriteBatch(batch, true);
}

bool CBlockTreeDB::ReadTxIndex(const uint256 &txid, CDiskTxPos &pos) {
    return Read(make_pair(DB_TXINDEX, txid), pos);
}

bool CBlockTreeDB::WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> >&vect) {
    CDBBatch batch(&GetObfuscateKey());
    for (std::vector<std::pair<uint256,CDiskTxPos> >::const_iterator it=vect.begin(); it!=vect.end(); it++)
        batch.Write(make_pair(DB_TXINDEX, it->first), it->second);
    return WriteBatch(batch);
}

bool CBlockTreeDB::WriteFlag(const std::string &name, bool fValue) {
    return Write(std::make_pair(DB_FLAG, name), fValue ? '1' : '0');
}

bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) {
    char ch;
    if (!Read(std::make_pair(DB_FLAG, name), ch))
        return false;
    fValue = ch == '1';
    return true;
}

bool CBlockTreeDB::LoadBlockIndexGuts()
{
    boost::scoped_ptr<CDBIterator> pcursor(NewIterator());

    pcursor->Seek(make_pair(DB_BLOCK_INDEX, uint256()));

    // Load mapBlockIndex
    while (pcursor->Valid()) {
        boost::this_thread::interruption_point();
        std::pair<char, uint256> key;
        if (pcursor->GetKey(key) && key.first == DB_BLOCK_INDEX) {
            CDiskBlockIndex diskindex;
            if (pcursor->GetValue(diskindex)) {
                // Construct block index object
                CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash());
				pindexNew->pauxpow        = diskindex.pauxpow;
                pindexNew->pprev          = InsertBlockIndex(diskindex.hashPrev);
                pindexNew->nHeight        = diskindex.nHeight;
                pindexNew->nFile          = diskindex.nFile;
                pindexNew->nDataPos       = diskindex.nDataPos;
                pindexNew->nUndoPos       = diskindex.nUndoPos;
                pindexNew->nVersion       = diskindex.nVersion;
                pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
                pindexNew->nTime          = diskindex.nTime;
                pindexNew->nBits          = diskindex.nBits;
                pindexNew->nNonce         = diskindex.nNonce;
                pindexNew->nStatus        = diskindex.nStatus;
                pindexNew->nTx            = diskindex.nTx;
				// SYSCOIN disk auxpow check
                if (pindexNew->nVersion.IsAuxpow()) {
                    if (!diskindex.pauxpow->check(diskindex.GetBlockHash(), pindexNew->nVersion.GetChainId(), Params().GetConsensus(pindexNew->nHeight))) {
                        return error("LoadBlockIndex(): CheckProofOfWork failed: %s", pindexNew->ToString());
                    }
                } else {
                    if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits, Params().GetConsensus(pindexNew->nHeight)))
                        return error("LoadBlockIndex(): CheckProofOfWork failed: %s", pindexNew->ToString());
                }
                pcursor->Next();
            } else {
                return error("LoadBlockIndex() : failed to read value");
            }
        } else {
            break;
        }
    }

    return true;
}
<commit_msg>fix getconsensus<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Syscoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "txdb.h"

#include "chain.h"
#include "chainparams.h"
#include "hash.h"
#include "main.h"
#include "pow.h"
#include "uint256.h"

#include <stdint.h>

#include <boost/thread.hpp>

using namespace std;

static const char DB_COINS = 'c';
static const char DB_BLOCK_FILES = 'f';
static const char DB_TXINDEX = 't';
static const char DB_BLOCK_INDEX = 'b';

static const char DB_BEST_BLOCK = 'B';
static const char DB_FLAG = 'F';
static const char DB_REINDEX_FLAG = 'R';
static const char DB_LAST_BLOCK = 'l';

CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / "chainstate", nCacheSize, fMemory, fWipe, true)
{
}

bool CCoinsViewDB::GetCoins(const uint256 &txid, CCoins &coins) const {
    return db.Read(make_pair(DB_COINS, txid), coins);
}

bool CCoinsViewDB::HaveCoins(const uint256 &txid) const {
    return db.Exists(make_pair(DB_COINS, txid));
}

uint256 CCoinsViewDB::GetBestBlock() const {
    uint256 hashBestChain;
    if (!db.Read(DB_BEST_BLOCK, hashBestChain))
        return uint256();
    return hashBestChain;
}

bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) {
    CDBBatch batch(&db.GetObfuscateKey());
    size_t count = 0;
    size_t changed = 0;
    for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) {
        if (it->second.flags & CCoinsCacheEntry::DIRTY) {
            if (it->second.coins.IsPruned())
                batch.Erase(make_pair(DB_COINS, it->first));
            else
                batch.Write(make_pair(DB_COINS, it->first), it->second.coins);
            changed++;
        }
        count++;
        CCoinsMap::iterator itOld = it++;
        mapCoins.erase(itOld);
    }
    if (!hashBlock.IsNull())
        batch.Write(DB_BEST_BLOCK, hashBlock);

    LogPrint("coindb", "Committing %u changed transactions (out of %u) to coin database...\n", (unsigned int)changed, (unsigned int)count);
    return db.WriteBatch(batch);
}

CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe) {
}

bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) {
    return Read(make_pair(DB_BLOCK_FILES, nFile), info);
}

bool CBlockTreeDB::WriteReindexing(bool fReindexing) {
    if (fReindexing)
        return Write(DB_REINDEX_FLAG, '1');
    else
        return Erase(DB_REINDEX_FLAG);
}

bool CBlockTreeDB::ReadReindexing(bool &fReindexing) {
    fReindexing = Exists(DB_REINDEX_FLAG);
    return true;
}

bool CBlockTreeDB::ReadLastBlockFile(int &nFile) {
    return Read(DB_LAST_BLOCK, nFile);
}

bool CCoinsViewDB::GetStats(CCoinsStats &stats) const {
    /* It seems that there are no "const iterators" for LevelDB.  Since we
       only need read operations on it, use a const-cast to get around
       that restriction.  */
    boost::scoped_ptr<CDBIterator> pcursor(const_cast<CDBWrapper*>(&db)->NewIterator());
    pcursor->Seek(DB_COINS);

    CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
    stats.hashBlock = GetBestBlock();
    ss << stats.hashBlock;
    CAmount nTotalAmount = 0;
    while (pcursor->Valid()) {
        boost::this_thread::interruption_point();
        std::pair<char, uint256> key;
        CCoins coins;
        if (pcursor->GetKey(key) && key.first == DB_COINS) {
            if (pcursor->GetValue(coins)) {
                stats.nTransactions++;
                for (unsigned int i=0; i<coins.vout.size(); i++) {
                    const CTxOut &out = coins.vout[i];
                    if (!out.IsNull()) {
                        stats.nTransactionOutputs++;
                        ss << VARINT(i+1);
                        ss << out;
                        nTotalAmount += out.nValue;
                    }
                }
                stats.nSerializedSize += 32 + pcursor->GetValueSize();
                ss << VARINT(0);
            } else {
                return error("CCoinsViewDB::GetStats() : unable to read value");
            }
        } else {
            break;
        }
        pcursor->Next();
    }
    {
        LOCK(cs_main);
        stats.nHeight = mapBlockIndex.find(stats.hashBlock)->second->nHeight;
    }
    stats.hashSerialized = ss.GetHash();
    stats.nTotalAmount = nTotalAmount;
    return true;
}

bool CBlockTreeDB::WriteBatchSync(const std::vector<std::pair<int, const CBlockFileInfo*> >& fileInfo, int nLastFile, const std::vector<const CBlockIndex*>& blockinfo) {
    CDBBatch batch(&GetObfuscateKey());
    for (std::vector<std::pair<int, const CBlockFileInfo*> >::const_iterator it=fileInfo.begin(); it != fileInfo.end(); it++) {
        batch.Write(make_pair(DB_BLOCK_FILES, it->first), *it->second);
    }
    batch.Write(DB_LAST_BLOCK, nLastFile);
    for (std::vector<const CBlockIndex*>::const_iterator it=blockinfo.begin(); it != blockinfo.end(); it++) {
        batch.Write(make_pair(DB_BLOCK_INDEX, (*it)->GetBlockHash()), CDiskBlockIndex(*it));
    }
    return WriteBatch(batch, true);
}

bool CBlockTreeDB::ReadTxIndex(const uint256 &txid, CDiskTxPos &pos) {
    return Read(make_pair(DB_TXINDEX, txid), pos);
}

bool CBlockTreeDB::WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> >&vect) {
    CDBBatch batch(&GetObfuscateKey());
    for (std::vector<std::pair<uint256,CDiskTxPos> >::const_iterator it=vect.begin(); it!=vect.end(); it++)
        batch.Write(make_pair(DB_TXINDEX, it->first), it->second);
    return WriteBatch(batch);
}

bool CBlockTreeDB::WriteFlag(const std::string &name, bool fValue) {
    return Write(std::make_pair(DB_FLAG, name), fValue ? '1' : '0');
}

bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) {
    char ch;
    if (!Read(std::make_pair(DB_FLAG, name), ch))
        return false;
    fValue = ch == '1';
    return true;
}

bool CBlockTreeDB::LoadBlockIndexGuts()
{
    boost::scoped_ptr<CDBIterator> pcursor(NewIterator());

    pcursor->Seek(make_pair(DB_BLOCK_INDEX, uint256()));

    // Load mapBlockIndex
    while (pcursor->Valid()) {
        boost::this_thread::interruption_point();
        std::pair<char, uint256> key;
        if (pcursor->GetKey(key) && key.first == DB_BLOCK_INDEX) {
            CDiskBlockIndex diskindex;
            if (pcursor->GetValue(diskindex)) {
                // Construct block index object
                CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash());
				pindexNew->pauxpow        = diskindex.pauxpow;
                pindexNew->pprev          = InsertBlockIndex(diskindex.hashPrev);
                pindexNew->nHeight        = diskindex.nHeight;
                pindexNew->nFile          = diskindex.nFile;
                pindexNew->nDataPos       = diskindex.nDataPos;
                pindexNew->nUndoPos       = diskindex.nUndoPos;
                pindexNew->nVersion       = diskindex.nVersion;
                pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
                pindexNew->nTime          = diskindex.nTime;
                pindexNew->nBits          = diskindex.nBits;
                pindexNew->nNonce         = diskindex.nNonce;
                pindexNew->nStatus        = diskindex.nStatus;
                pindexNew->nTx            = diskindex.nTx;
				// SYSCOIN disk auxpow check
                if (pindexNew->nVersion.IsAuxpow()) {
                    if (!diskindex.pauxpow->check(diskindex.GetBlockHash(), pindexNew->nVersion.GetChainId(), Params().GetConsensus())) {
                        return error("LoadBlockIndex(): CheckProofOfWork failed: %s", pindexNew->ToString());
                    }
                } else {
                    if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits, Params().GetConsensus()))
                        return error("LoadBlockIndex(): CheckProofOfWork failed: %s", pindexNew->ToString());
                }
                pcursor->Next();
            } else {
                return error("LoadBlockIndex() : failed to read value");
            }
        } else {
            break;
        }
    }

    return true;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: XMLElementPropertyContext.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 10:49:18 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_xmloff.hxx"

#ifndef _XMLOFF_XMLELEMENTPROPERTYCONTEXT_HXX
#include "XMLElementPropertyContext.hxx"
#endif

using namespace ::rtl;

TYPEINIT1( XMLElementPropertyContext , SvXMLImportContext );

XMLElementPropertyContext::XMLElementPropertyContext (
                                SvXMLImport& rImport, sal_uInt16 nPrfx,
                                const OUString& rLName,
                                const XMLPropertyState& rProp,
                                 ::std::vector< XMLPropertyState > &rProps ) :
    SvXMLImportContext( rImport, nPrfx, rLName ),
    bInsert( sal_False ),
      rProperties( rProps ),
    aProp( rProp )
{
}

XMLElementPropertyContext::~XMLElementPropertyContext()
{
}

void XMLElementPropertyContext::EndElement( )
{
    if( bInsert )
        rProperties.push_back( aProp );
}

<commit_msg>INTEGRATION: CWS impresstables2 (1.4.80); FILE MERGED 2007/07/27 09:09:53 cl 1.4.80.1: fixed build issues due to pch and namespace ::rtl<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: XMLElementPropertyContext.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2008-03-12 10:46:26 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_xmloff.hxx"

#ifndef _XMLOFF_XMLELEMENTPROPERTYCONTEXT_HXX
#include "XMLElementPropertyContext.hxx"
#endif

using ::rtl::OUString;

TYPEINIT1( XMLElementPropertyContext , SvXMLImportContext );

XMLElementPropertyContext::XMLElementPropertyContext (
                                SvXMLImport& rImport, sal_uInt16 nPrfx,
                                const OUString& rLName,
                                const XMLPropertyState& rProp,
                                 ::std::vector< XMLPropertyState > &rProps ) :
    SvXMLImportContext( rImport, nPrfx, rLName ),
    bInsert( sal_False ),
      rProperties( rProps ),
    aProp( rProp )
{
}

XMLElementPropertyContext::~XMLElementPropertyContext()
{
}

void XMLElementPropertyContext::EndElement( )
{
    if( bInsert )
        rProperties.push_back( aProp );
}

<|endoftext|>


<commit_before>#include <cassert>

#include <exodus/program.h>
programinit()

function main() {
	printl("test_greg says 'Hello World!'");

	assert(oconv(date(),"D") == "5 APR 2021");

	printl("Test passed");

	return 0;
}

programexit()

<commit_msg>remove new test<commit_after><|endoftext|>


<commit_before>

#include "TTadsr.h"

TTAdsr::TTAdsr(TTUInt8 newMaxNumChannels)
	: TTAudioObject("audio.adsr", newMaxNumChannels), output(0.), output_db(NOISE_FLOOR),
	eg_state(k_eg_inactive), trigger(false), attrMode(TT("linear"))
{
	registerAttribute(TT("attack"), kTypeFloat64, &attack_ms, (TTSetterMethod)&TTAdsr::setAttack);
	registerAttribute(TT("decay"), kTypeFloat64, &decay_ms, (TTSetterMethod)&TTAdsr::setDecay);
	registerAttribute(TT("release"), kTypeFloat64, &release_ms, (TTSetterMethod)&TTAdsr::setRelease);
	registerAttribute(TT("sustain"), kTypeFloat64, &sustain_amp, (TTSetterMethod)&TTAdsr::setSustainAmp);
	registerAttribute(TT("sustain_db"), kTypeFloat64, NULL, (TTGetterMethod)&TTAdsr::getSustainDb, (TTSetterMethod)&TTAdsr::setSustainDb);
	registerAttribute(TT("trigger"), kTypeBoolean, &trigger);
	registerAttribute(TT("mode"), kTypeSymbol, &attrMode, (TTSetterMethod)&TTAdsr::setMode);

	setAttributeValue(TT("attack"), 50.);
	setAttributeValue(TT("decay"), 100.);
	setAttributeValue(TT("sustain_db"), -6.);
	setAttributeValue(TT("release"), 500.);
	setAttributeValue(TT("mode"), TT("linear"));	// <-- sets the process method
}

TTAdsr::~TTAdsr()
{
	;
}

#ifdef USE_MACRO_ACCESSORS
/** Defines a setter function, the first parameter creates a function prefixed with the word set
 * in front of it.  The second parameter is the prefix for the variable that has been defined in the class */
#define DEFINE_SETPARAM(functionName, prefix)	TTErr TTAdsr::set ## functionName (const TTAttribute&, const TTValue& newValue) { \
	prefix ## _ms = TTClip<TTFloat64>( prefix ## _ms, 1., 60000.); \
	prefix ## _samples = long(( prefix ## _ms / 1000.) * sr); \
	prefix ## _step = 1.0 / prefix ## _samples; \
	prefix ## _step_db = -(double(NOISE_FLOOR) / prefix ## _samples); \
	return kTTErrNone; \
	}

/** Defines a getter function, the first parameter creates a function prefixed with the word get
 * in front of it.  The second parameter is the prefix for the variable that has been defined in the class */
#define DEFINE_GETPARAM(functionName, prefix)	TTErr TTAdsr::get ## functionName (const TTAttribute&, TTValue& value) { \
	value = prefix ## _ms; \
	return kTTErrNone; \
	}

/** Define a setter and getter function */
#define DEFINE_PARAM(functionName, prefix) DEFINE_SETPARAM(functionName, prefix) \
	DEFINE_GETPARAM(functionName, prefix)

DEFINE_PARAM(Attack, attack);
DEFINE_PARAM(Decay, decay);
DEFINE_PARAM(Release, release);

#else // using old fashioned not-generated-by-a-macro accessors

TTErr TTAdsr::setAttack(const TTAttribute&, const TTValue& newValue)
{
	attack_ms = TTClip((TTFloat64)newValue, 1.0, 60000.0);
	attack_samples = long((attack_ms / 1000.0) * sr);
	attack_step = 1.0 / attack_samples;
	attack_step_db = -(double(NOISE_FLOOR) / attack_samples);
	return kTTErrNone;
}

TTErr TTAdsr::setDecay(const TTAttribute&, const TTValue& newValue)
{
	decay_ms = TTClip((TTFloat64)newValue, 1.0, 60000.0);
	decay_samples = long((decay_ms / 1000.0) * sr);
	decay_step = 1.0 / decay_samples;
	decay_step_db = -(double(NOISE_FLOOR) / decay_samples);
	return kTTErrNone;
}

TTErr TTAdsr::setRelease(const TTAttribute&, const TTValue& newValue)
{
	release_ms = TTClip((TTFloat64)newValue, 1.0, 60000.0);
	release_samples = long((release_ms / 1000.0) * sr);
	release_step = 1.0 / release_samples;
	release_step_db = -(double(NOISE_FLOOR) / release_samples);
	return kTTErrNone;
}

#endif

TTErr TTAdsr::setSustainAmp(const TTAttribute&, const TTValue& newValue)
{
	sustain_amp = newValue;
	sustain_db = linearToDb(sustain_amp);
	return kTTErrNone;
}

/*
TTErr TTAdsr::getSustainAmp(const TTAttribute&, TTValue& value)
{
	value = sustain_amp;
	return kTTErrNone;
}
*/

TTErr TTAdsr::setSustainDb(const TTAttribute&, const TTValue& newValue)
{
	sustain_db = newValue;
	sustain_amp = dbToLinear(sustain_db);
	return kTTErrNone;
}

TTErr TTAdsr::getSustainDb(const TTAttribute&, TTValue& value)
{
	value = linearToDb(sustain_amp);
	return kTTErrNone;
}

TTErr TTAdsr::setMode(const TTAttribute&, const TTValue& newValue)
{
	attrMode = newValue;
	if(attrMode == TT("exponential"))
		setProcess((TTProcessMethod)&TTAdsr::processAudioExponential);
	else
		setProcess((TTProcessMethod)&TTAdsr::processAudioLinear);
	return kTTErrNone;
}

/*
TTErr TTAdsr::processAudio(TTAudioSignal& out)
{
	TTSampleValue *outSample;
	short vs = out.vs;

	while(vs--) {

		if(trigger) {
			if(eg_state == k_eg_inactive || eg_state == k_eg_release)
				eg_state = k_eg_attack;
		} else {
			if(eg_state != k_eg_inactive && eg_state != k_eg_release)
				eg_state = k_eg_release;
		}

		switch(eg_state) {
			case k_eg_attack:
				output += attack_step;
				if(output >= 1.) {
					output = 1.;
					eg_state = k_eg_decay;
				}
				break;
			case k_eg_decay:
				output -= decay_step;
				if(output <= sustain_amp) {
					eg_state = k_eg_sustain;
					output = sustain_amp;
				}
				break;
			case k_eg_sustain:

				break;

			case k_eg_release:
				output -= release_step;
				if(output <= 0.) {
					eg_state = k_eg_inactive;
					output = 0.;
				}
				break;
		}
		*outSample++ = output;
	}

	return kTTErrNone;
}
*/

TTErr TTAdsr::processAudioLinear(TTAudioSignal& in, TTAudioSignal& out)
{
	TTSampleValue*	inSample;
	TTSampleValue*	outSample;
	TTUInt16		vs = in.getVectorSize();
	bool			checkAudioTrigger = false;

	// If the two signals are the same instance, then we know that only an output signal has been passed
	// So in that case we use the control-rate trigger instead of an audio-rate trigger.
	// TODO: Is there a decent way to do this without having to check this every single vector?
	if(&in != &out)
		checkAudioTrigger = true;

	inSample = in.sampleVectors[0];
	outSample = out.sampleVectors[0];

	while(vs--) {
		if(checkAudioTrigger)
			trigger = (TTBoolean)(*inSample++ > 0.5);

		if(trigger) {
			if(eg_state == k_eg_inactive || eg_state == k_eg_release)
				eg_state = k_eg_attack;
		} else {
			if(eg_state != k_eg_inactive && eg_state != k_eg_release)
				eg_state = k_eg_release;
		}

		switch(eg_state) {
			case k_eg_attack:
				output += attack_step;
				if(output >= 1.) {
					output = 1.;
					eg_state = k_eg_decay;
				}
				break;
			case k_eg_decay:
				output -= decay_step;
				if(output <= sustain_amp) {
					eg_state = k_eg_sustain;
					output = sustain_amp;
				}
				break;
			case k_eg_sustain:

				break;

			case k_eg_release:
				output -= release_step;
				if(output <= 0.) {
					eg_state = k_eg_inactive;
					output = 0.;
				}
				break;
		}
		*outSample++ = output;
	}

	return kTTErrNone;
}

TTErr TTAdsr::processAudioExponential(TTAudioSignal& in, TTAudioSignal& out)
{
	TTSampleValue*	inSample;
	TTSampleValue*	outSample;
	TTUInt16		vs = in.getVectorSize();
	bool			checkAudioTrigger = false;

	// If the two signals are the same instance, then we know that only an output signal has been passed
	// So in that case we use the control-rate trigger instead of an audio-rate trigger.
	// TODO: Is there a decent way to do this without having to check this every single vector?
	if(&in != &out)
		checkAudioTrigger = true;

	inSample = in.sampleVectors[0];
	outSample = out.sampleVectors[0];

	while(vs--) {
		if(checkAudioTrigger)
			trigger = (TTBoolean)(*inSample++ > 0.5);

		if(trigger) {
			if(eg_state == k_eg_inactive || eg_state == k_eg_release)
				eg_state = k_eg_attack;
		} else {
			if(eg_state != k_eg_inactive && eg_state != k_eg_release)
				eg_state = k_eg_release;
		}

		switch(eg_state){
			case k_eg_attack:						// ATTACK
				output_db += attack_step_db;			// Increment the output
				if (output_db >= 0.0){						// If we've hit the top of the attack,
					eg_state = k_eg_decay;				// start the decay stage
					output = 1.0;						// Make sure we didn't go over 1.0
				}
				else
					output = dbToLinear(output_db);
				break;
			case k_eg_decay:						// DECAY
				output_db -= decay_step_db;
				output = dbToLinear(output_db);	// Decrement the output
				if (output <= sustain_amp){				// If we've hit the bottom of the decay,
					eg_state = k_eg_sustain;			// start the sustain stage
					output = sustain_amp;				// Lock in the sustain value
				}
				break;
			case k_eg_sustain:						// SUSTAIN
				break;									// leave it alone

			case k_eg_release:						// RELEASE
				output_db -= release_step_db;
				if (output_db <= NOISE_FLOOR){						// If we've hit the basement,
					eg_state = k_eg_inactive;			// deactivate the eg
					output = 0.0;						// Make sure we didn't dip too low
				}
				else
					output = dbToLinear(output_db);		// Decrement the output
				break;
		}
		*outSample++ = output;
	}

	return kTTErrNone;
}

<commit_msg>Fixes for when someone changes the sample rate so that TTAdsr is updated.  <commit_after>

#include "TTadsr.h"

TTAdsr::TTAdsr(TTUInt8 newMaxNumChannels)
	: TTAudioObject("audio.adsr", newMaxNumChannels), output(0.), output_db(NOISE_FLOOR),
	eg_state(k_eg_inactive), trigger(false), attrMode(TT("linear"))
{
	registerAttribute(TT("attack"), kTypeFloat64, &attack_ms, (TTSetterMethod)&TTAdsr::setAttack);
	registerAttribute(TT("decay"), kTypeFloat64, &decay_ms, (TTSetterMethod)&TTAdsr::setDecay);
	registerAttribute(TT("release"), kTypeFloat64, &release_ms, (TTSetterMethod)&TTAdsr::setRelease);
	registerAttribute(TT("sustain"), kTypeFloat64, &sustain_amp, (TTSetterMethod)&TTAdsr::setSustainAmp);
	registerAttribute(TT("sustain_db"), kTypeFloat64, NULL, (TTGetterMethod)&TTAdsr::getSustainDb, (TTSetterMethod)&TTAdsr::setSustainDb);
	registerAttribute(TT("trigger"), kTypeBoolean, &trigger);
	registerAttribute(TT("mode"), kTypeSymbol, &attrMode, (TTSetterMethod)&TTAdsr::setMode);

	// register for notifications from the parent class so we can recalculate coefficients as required
	registerMessage(TT("updateSr"),	(TTMethod)&TTAdsr::updateSr);

	setAttributeValue(TT("attack"), 50.);
	setAttributeValue(TT("decay"), 100.);
	setAttributeValue(TT("sustain_db"), -6.);
	setAttributeValue(TT("release"), 500.);
	setAttributeValue(TT("mode"), TT("linear"));	// <-- sets the process method
}

TTAdsr::~TTAdsr()
{
	;
}

TTErr TTAdsr::updateSr()
{
	TTValue	v;

	v = attack_ms;
	setAttack(TTATTR, v);

	v = decay_ms;
	setDecay(TTATTR, v);

	v = release_ms;
	setRelease(TTATTR, v);

	return kTTErrNone;
}

#ifdef USE_MACRO_ACCESSORS
/** Defines a setter function, the first parameter creates a function prefixed with the word set
 * in front of it.  The second parameter is the prefix for the variable that has been defined in the class */
#define DEFINE_SETPARAM(functionName, prefix)	TTErr TTAdsr::set ## functionName (const TTAttribute&, const TTValue& newValue) { \
	prefix ## _ms = TTClip<TTFloat64>( prefix ## _ms, 1., 60000.); \
	prefix ## _samples = long(( prefix ## _ms / 1000.) * sr); \
	prefix ## _step = 1.0 / prefix ## _samples; \
	prefix ## _step_db = -(double(NOISE_FLOOR) / prefix ## _samples); \
	return kTTErrNone; \
	}

/** Defines a getter function, the first parameter creates a function prefixed with the word get
 * in front of it.  The second parameter is the prefix for the variable that has been defined in the class */
#define DEFINE_GETPARAM(functionName, prefix)	TTErr TTAdsr::get ## functionName (const TTAttribute&, TTValue& value) { \
	value = prefix ## _ms; \
	return kTTErrNone; \
	}

/** Define a setter and getter function */
#define DEFINE_PARAM(functionName, prefix) DEFINE_SETPARAM(functionName, prefix) \
	DEFINE_GETPARAM(functionName, prefix)

DEFINE_PARAM(Attack, attack);
DEFINE_PARAM(Decay, decay);
DEFINE_PARAM(Release, release);

#else // using old fashioned not-generated-by-a-macro accessors

TTErr TTAdsr::setAttack(const TTAttribute&, const TTValue& newValue)
{
	attack_ms = TTClip((TTFloat64)newValue, 1.0, 60000.0);
	attack_samples = long((attack_ms / 1000.0) * sr);
	attack_step = 1.0 / attack_samples;
	attack_step_db = -(double(NOISE_FLOOR) / attack_samples);
	return kTTErrNone;
}

TTErr TTAdsr::setDecay(const TTAttribute&, const TTValue& newValue)
{
	decay_ms = TTClip((TTFloat64)newValue, 1.0, 60000.0);
	decay_samples = long((decay_ms / 1000.0) * sr);
	decay_step = 1.0 / decay_samples;
	decay_step_db = -(double(NOISE_FLOOR) / decay_samples);
	return kTTErrNone;
}

TTErr TTAdsr::setRelease(const TTAttribute&, const TTValue& newValue)
{
	release_ms = TTClip((TTFloat64)newValue, 1.0, 60000.0);
	release_samples = long((release_ms / 1000.0) * sr);
	release_step = 1.0 / release_samples;
	release_step_db = -(double(NOISE_FLOOR) / release_samples);
	return kTTErrNone;
}

#endif

TTErr TTAdsr::setSustainAmp(const TTAttribute&, const TTValue& newValue)
{
	sustain_amp = newValue;
	sustain_db = linearToDb(sustain_amp);
	return kTTErrNone;
}

/*
TTErr TTAdsr::getSustainAmp(const TTAttribute&, TTValue& value)
{
	value = sustain_amp;
	return kTTErrNone;
}
*/

TTErr TTAdsr::setSustainDb(const TTAttribute&, const TTValue& newValue)
{
	sustain_db = newValue;
	sustain_amp = dbToLinear(sustain_db);
	return kTTErrNone;
}

TTErr TTAdsr::getSustainDb(const TTAttribute&, TTValue& value)
{
	value = linearToDb(sustain_amp);
	return kTTErrNone;
}

TTErr TTAdsr::setMode(const TTAttribute&, const TTValue& newValue)
{
	attrMode = newValue;
	if(attrMode == TT("exponential"))
		setProcess((TTProcessMethod)&TTAdsr::processAudioExponential);
	else
		setProcess((TTProcessMethod)&TTAdsr::processAudioLinear);
	return kTTErrNone;
}

/*
TTErr TTAdsr::processAudio(TTAudioSignal& out)
{
	TTSampleValue *outSample;
	short vs = out.vs;

	while(vs--) {

		if(trigger) {
			if(eg_state == k_eg_inactive || eg_state == k_eg_release)
				eg_state = k_eg_attack;
		} else {
			if(eg_state != k_eg_inactive && eg_state != k_eg_release)
				eg_state = k_eg_release;
		}

		switch(eg_state) {
			case k_eg_attack:
				output += attack_step;
				if(output >= 1.) {
					output = 1.;
					eg_state = k_eg_decay;
				}
				break;
			case k_eg_decay:
				output -= decay_step;
				if(output <= sustain_amp) {
					eg_state = k_eg_sustain;
					output = sustain_amp;
				}
				break;
			case k_eg_sustain:

				break;

			case k_eg_release:
				output -= release_step;
				if(output <= 0.) {
					eg_state = k_eg_inactive;
					output = 0.;
				}
				break;
		}
		*outSample++ = output;
	}

	return kTTErrNone;
}
*/

TTErr TTAdsr::processAudioLinear(TTAudioSignal& in, TTAudioSignal& out)
{
	TTSampleValue*	inSample;
	TTSampleValue*	outSample;
	TTUInt16		vs = in.getVectorSize();
	bool			checkAudioTrigger = false;

	// If the two signals are the same instance, then we know that only an output signal has been passed
	// So in that case we use the control-rate trigger instead of an audio-rate trigger.
	// TODO: Is there a decent way to do this without having to check this every single vector?
	if(&in != &out)
		checkAudioTrigger = true;

	inSample = in.sampleVectors[0];
	outSample = out.sampleVectors[0];

	while(vs--) {
		if(checkAudioTrigger)
			trigger = (TTBoolean)(*inSample++ > 0.5);

		if(trigger) {
			if(eg_state == k_eg_inactive || eg_state == k_eg_release)
				eg_state = k_eg_attack;
		} else {
			if(eg_state != k_eg_inactive && eg_state != k_eg_release)
				eg_state = k_eg_release;
		}

		switch(eg_state) {
			case k_eg_attack:
				output += attack_step;
				if(output >= 1.) {
					output = 1.;
					eg_state = k_eg_decay;
				}
				break;
			case k_eg_decay:
				output -= decay_step;
				if(output <= sustain_amp) {
					eg_state = k_eg_sustain;
					output = sustain_amp;
				}
				break;
			case k_eg_sustain:

				break;

			case k_eg_release:
				output -= release_step;
				if(output <= 0.) {
					eg_state = k_eg_inactive;
					output = 0.;
				}
				break;
		}
		*outSample++ = output;
	}

	return kTTErrNone;
}

TTErr TTAdsr::processAudioExponential(TTAudioSignal& in, TTAudioSignal& out)
{
	TTSampleValue*	inSample;
	TTSampleValue*	outSample;
	TTUInt16		vs = in.getVectorSize();
	bool			checkAudioTrigger = false;

	// If the two signals are the same instance, then we know that only an output signal has been passed
	// So in that case we use the control-rate trigger instead of an audio-rate trigger.
	// TODO: Is there a decent way to do this without having to check this every single vector?
	if(&in != &out)
		checkAudioTrigger = true;

	inSample = in.sampleVectors[0];
	outSample = out.sampleVectors[0];

	while(vs--) {
		if(checkAudioTrigger)
			trigger = (TTBoolean)(*inSample++ > 0.5);

		if(trigger) {
			if(eg_state == k_eg_inactive || eg_state == k_eg_release)
				eg_state = k_eg_attack;
		} else {
			if(eg_state != k_eg_inactive && eg_state != k_eg_release)
				eg_state = k_eg_release;
		}

		switch(eg_state){
			case k_eg_attack:						// ATTACK
				output_db += attack_step_db;			// Increment the output
				if (output_db >= 0.0){						// If we've hit the top of the attack,
					eg_state = k_eg_decay;				// start the decay stage
					output = 1.0;						// Make sure we didn't go over 1.0
				}
				else
					output = dbToLinear(output_db);
				break;
			case k_eg_decay:						// DECAY
				output_db -= decay_step_db;
				output = dbToLinear(output_db);	// Decrement the output
				if (output <= sustain_amp){				// If we've hit the bottom of the decay,
					eg_state = k_eg_sustain;			// start the sustain stage
					output = sustain_amp;				// Lock in the sustain value
				}
				break;
			case k_eg_sustain:						// SUSTAIN
				break;									// leave it alone

			case k_eg_release:						// RELEASE
				output_db -= release_step_db;
				if (output_db <= NOISE_FLOOR){						// If we've hit the basement,
					eg_state = k_eg_inactive;			// deactivate the eg
					output = 0.0;						// Make sure we didn't dip too low
				}
				else
					output = dbToLinear(output_db);		// Decrement the output
				break;
		}
		*outSample++ = output;
	}

	return kTTErrNone;
}

<|endoftext|>


<commit_before><commit_msg>Common: extend linear interpolation to support negative values as well<commit_after><|endoftext|>


<commit_before>#include "core/featuredata.h"

#include "core/exception.h"
#include "ts/ts.h"

using namespace std;
using namespace cv;
using namespace sem;

namespace {

/**
 * @brief Test FeatureData class
 * @todo define guards around PCL dependent tests
 */
class FeatureDataTest : public ::testing::Test
{
protected:
    virtual void SetUp()
    {
        mat_ = Mat_f(4, 3);
        randn(mat_, 0.f, 100.f);

        cld_ = Mat2PointCloud(mat_.clone());
        mat_ = PointCloud2Mat(cld_).clone();
    }

    Mat_f mat_;
    CloudXYZ::Ptr cld_;
};

/**
 * @brief Initialize test object with Cloud object, then call getters.
 */
TEST_F(FeatureDataTest, Init_Cloud)
{
    FeatureData to(cld_);

    Mat_f m = to.get<Mat_f>();
    CloudXYZ::Ptr cld = to.get<CloudXYZ::Ptr>();

    EXPECT_MAT_EQ(m, mat_);
    EXPECT_MAT_EQ(PointCloud2Mat(cld), mat_);
}

/**
 * @brief Initialize test object with Mat object, then call getters.
 */
TEST_F(FeatureDataTest, Init_Mat_f)
{
    FeatureData to(mat_);

    Mat_f m = to.get<Mat_f>();
    CloudXYZ::Ptr cld = to.get<CloudXYZ::Ptr>();

    EXPECT_MAT_EQ(m, mat_);
    EXPECT_MAT_EQ(PointCloud2Mat(cld), mat_);
}

/**
 * @brief Verify initializing with Mat and getting a mat only involves a shared copy
 */
TEST_F(FeatureDataTest, Same_Mat)
{
    FeatureData to(mat_);

    Mat_f m = to.get<Mat_f>();
    EXPECT_MAT_EQ(m, mat_);
    EXPECT_EQ(m.data, mat_.data) << "Both Mats are not pointing to the same memory location.";
    ASSERT_NE(m.clone().data, mat_.data) << "Cannot still be pointing to the same memory chunk after cloning.";
}

/**
 * @brief Test caching of cloud reference
 * by comparing what the pointers are pointing at and verifying the use count increased by 1 after calling get
 */
TEST_F(FeatureDataTest, Cached_Cloud)
{
    FeatureData to(mat_);

    CloudXYZ::Ptr cld = to.get<CloudXYZ::Ptr>();
    EXPECT_NE(cld, cld_);
    long old_cld_use_count = cld.use_count();

    CloudXYZ::Ptr cld2 = to.get<CloudXYZ::Ptr>();
    EXPECT_NE(cld2, cld_);
    EXPECT_EQ(cld2, cld);

    // check use count increased
    EXPECT_EQ(cld2.use_count(), cld.use_count());
    EXPECT_EQ(cld2.use_count(), old_cld_use_count+1);
}

/**
 * @brief Type-Parameterized tests around FeatureData class with POD typed feature data
 */
template <class T>
class FeatureDataPOD_Test : public ::testing::Test
{
protected:
};
typedef ::testing::Types<float, int, uchar> PODTypes;
TYPED_TEST_CASE(FeatureDataPOD_Test, PODTypes);

TYPED_TEST(FeatureDataPOD_Test, FromMat_Invalid)
{
    // empty
    EXPECT_THROW(FeatureData(Mat_f()).get<TypeParam >(), ExceptionBadDims);
    EXPECT_THROW(FeatureData(Mat_f(0, 0)).get<TypeParam >(), ExceptionBadDims);
    EXPECT_THROW(FeatureData(Mat_f(1, 0)).get<TypeParam >(), ExceptionBadDims);
    EXPECT_THROW(FeatureData(Mat_f(0, 1)).get<TypeParam >(), ExceptionBadDims);

    // multiple elements
    EXPECT_THROW(FeatureData(Mat_f(2, 1)).get<TypeParam >(), ExceptionBadDims);
    EXPECT_THROW(FeatureData(Mat_f(1, 2)).get<TypeParam >(), ExceptionBadDims);
    EXPECT_THROW(FeatureData(Mat_f(2, 2)).get<TypeParam >(), ExceptionBadDims);

    // multiple elements + initialized with scalar
    EXPECT_THROW(FeatureData(Mat_f(2, 1, 1.f)).get<TypeParam >(), ExceptionBadDims);
    EXPECT_THROW(FeatureData(Mat_f(1, 2, 0.f)).get<TypeParam >(), ExceptionBadDims);
    EXPECT_THROW(FeatureData(Mat_f(2, 2, 3.f)).get<TypeParam >(), ExceptionBadDims);
}

TYPED_TEST(FeatureDataPOD_Test, FromMat)
{
    float _v = 256; // to cover a range of values common between all of our PODs
    while(--_v >= 0) {

        FeatureData to(Mat1f(1, 1, _v));
        EXPECT_EQ(static_cast<TypeParam >(_v), to.get<TypeParam >()) << "Value mismatch.";
    }
}

/**
 * @todo: anyway to make this less manual?
 */
TYPED_TEST(FeatureDataPOD_Test, FromPOD)
{
    float vf = 256.f; // to cover a range of values common between all of our PODs
    TypeParam _v = static_cast<TypeParam >(vf); // to cover a range of values common between all of our PODs
    while(--vf >= 0.f) {

        FeatureData to(--_v);
        EXPECT_EQ( static_cast<float >(_v),  to.get<float>() )  << "Value mismatch while getting float.";
        EXPECT_EQ( static_cast<int >(_v),    to.get<int>()   )  << "Value mismatch while getting int.";
        EXPECT_EQ( static_cast<uchar >(_v),  to.get<uchar>() )  << "Value mismatch while getting uchar.";

        EXPECT_MAT_EQ( Mat_f(1, 1, static_cast<float >(_v)), to.get<Mat_f >()) << "Value mismatch while getting Mat_f.";

#ifdef __WITH_PCL
        EXPECT_THROW( to.get<CloudXYZ::Ptr >(), ExceptionTypeError );

        {
            VecVertices vv = to.get<VecVertices >();
            EXPECT_SIZE(1, vv);
            EXPECT_SIZE(1, vv[0].vertices);

            EXPECT_EQ(static_cast<uint32_t>(_v), vv[0].vertices[0]);
        }
#endif // __WITH_PCL
    }
}

#ifdef __WITH_PCL // PCL support required for these tests

TYPED_TEST(FeatureDataPOD_Test, Invalid_Cloud)
{
    // empty
    CloudXYZ::Ptr cld(new CloudXYZ);
    EXPECT_THROW(FeatureData(cld).get<TypeParam >(), ExceptionTypeError);

    // multi-row, 3-col
    cld = Mat2PointCloud(Mat1f(4, 3, 0.f));
    EXPECT_THROW(FeatureData(cld).get<TypeParam >(), ExceptionTypeError);

    cld = Mat2PointCloud(Mat1f(4, 3, 1.f));
    EXPECT_THROW(FeatureData(cld).get<TypeParam >(), ExceptionTypeError);

    cld = Mat2PointCloud(Mat1f(4, 3, 2.f));
    EXPECT_THROW(FeatureData(cld).get<TypeParam >(), ExceptionTypeError);

    // single row
    cld = Mat2PointCloud(Mat1f(1, 3, 0.f));
    EXPECT_THROW(FeatureData(cld).get<TypeParam >(), ExceptionTypeError);

    cld = Mat2PointCloud(Mat1f(1, 3, 1.f));
    EXPECT_THROW(FeatureData(cld).get<TypeParam >(), ExceptionTypeError);

    // 3-channel
    cld = Mat2PointCloud(Mat3f(1, 1, 0.f));
    EXPECT_THROW(FeatureData(cld).get<TypeParam >(), ExceptionTypeError);

    cld = Mat2PointCloud(Mat3f(1, 1, 1.f));
    EXPECT_THROW(FeatureData(cld).get<TypeParam >(), ExceptionTypeError);
}

TYPED_TEST(FeatureDataPOD_Test, Invalid_VecVertices)
{
//    // empty
//    EXPECT_THROW(FeatureData(VecVertices()).get<TypeParam >(), ExceptionTypeError);

//    // multi-row
//    {
//        pcl::Vertices v;
//        v.vertices.push_back(1);
//        VecVertices vv;
//        vv.push_back(v);
//        vv.push_back(v);
//        EXPECT_THROW(FeatureData(vv).get<TypeParam >(), ExceptionBadDims);
//    }

//    // multi-col
//    {
//        pcl::Vertices v;
//        v.vertices.push_back(1);
//        v.vertices.push_back(2);
//        VecVertices vv;
//        vv.push_back(v);
//        EXPECT_THROW(FeatureData(vv).get<TypeParam >(), ExceptionBadDims);
//    }
}

#else // __WITH_PCL

TYPED_TEST(FeatureDataPOD_Test, DISABLED_Invalid_Cloud)
{
}

TYPED_TEST(FeatureDataPOD_Test, Invalid_VecVertices)
{
}

#endif // __WITH_PCL

} // annonymous namespace for test fixtures
<commit_msg>try out std::move<commit_after>#include "core/featuredata.h"

#include "core/exception.h"
#include "ts/ts.h"

using namespace std;
using namespace cv;
using namespace sem;

namespace {

/**
 * @brief Test FeatureData class
 * @todo define guards around PCL dependent tests
 */
class FeatureDataTest : public ::testing::Test
{
protected:
    virtual void SetUp()
    {
        mat_ = Mat_f(4, 3);
        randn(mat_, 0.f, 100.f);

        cld_ = Mat2PointCloud(mat_.clone());
        mat_ = PointCloud2Mat(cld_).clone();
    }

    Mat_f mat_;
    CloudXYZ::Ptr cld_;
};

/**
 * @brief Initialize test object with Cloud object, then call getters.
 */
TEST_F(FeatureDataTest, Init_Cloud)
{
    FeatureData to(cld_);

    Mat_f m = to.get<Mat_f>();
    CloudXYZ::Ptr cld = to.get<CloudXYZ::Ptr>();

    EXPECT_MAT_EQ(m, mat_);
    EXPECT_MAT_EQ(PointCloud2Mat(cld), mat_);
}

/**
 * @brief Initialize test object with Mat object, then call getters.
 */
TEST_F(FeatureDataTest, Init_Mat_f)
{
    FeatureData to(mat_);

    Mat_f m = to.get<Mat_f>();
    CloudXYZ::Ptr cld = to.get<CloudXYZ::Ptr>();

    EXPECT_MAT_EQ(m, mat_);
    EXPECT_MAT_EQ(PointCloud2Mat(cld), mat_);
}

/**
 * @brief Verify initializing with Mat and getting a mat only involves a shared copy
 */
TEST_F(FeatureDataTest, Same_Mat)
{
    FeatureData to(mat_);

    Mat_f m = to.get<Mat_f>();
    EXPECT_MAT_EQ(m, mat_);
    EXPECT_EQ(m.data, mat_.data) << "Both Mats are not pointing to the same memory location.";
    ASSERT_NE(m.clone().data, mat_.data) << "Cannot still be pointing to the same memory chunk after cloning.";
}

/**
 * @brief Test caching of cloud reference
 * by comparing what the pointers are pointing at and verifying the use count increased by 1 after calling get
 */
TEST_F(FeatureDataTest, Cached_Cloud)
{
    FeatureData to(mat_);

    CloudXYZ::Ptr cld = to.get<CloudXYZ::Ptr>();
    EXPECT_NE(cld, cld_);
    long old_cld_use_count = cld.use_count();

    CloudXYZ::Ptr cld2 = to.get<CloudXYZ::Ptr>();
    EXPECT_NE(cld2, cld_);
    EXPECT_EQ(cld2, cld);

    // check use count increased
    EXPECT_EQ(cld2.use_count(), cld.use_count());
    EXPECT_EQ(cld2.use_count(), old_cld_use_count+1);
}

/**
 * @brief Type-Parameterized tests around FeatureData class with POD typed feature data
 */
template <class T>
class FeatureDataPOD_Test : public ::testing::Test
{
protected:
};
typedef ::testing::Types<float, int, uchar> PODTypes;
TYPED_TEST_CASE(FeatureDataPOD_Test, PODTypes);

TYPED_TEST(FeatureDataPOD_Test, FromMat_Invalid)
{
    // empty
    EXPECT_THROW(FeatureData(Mat_f()).get<TypeParam >(), ExceptionBadDims);
    EXPECT_THROW(FeatureData(Mat_f(0, 0)).get<TypeParam >(), ExceptionBadDims);
    EXPECT_THROW(FeatureData(Mat_f(1, 0)).get<TypeParam >(), ExceptionBadDims);
    EXPECT_THROW(FeatureData(Mat_f(0, 1)).get<TypeParam >(), ExceptionBadDims);

    // multiple elements
    EXPECT_THROW(FeatureData(Mat_f(2, 1)).get<TypeParam >(), ExceptionBadDims);
    EXPECT_THROW(FeatureData(Mat_f(1, 2)).get<TypeParam >(), ExceptionBadDims);
    EXPECT_THROW(FeatureData(Mat_f(2, 2)).get<TypeParam >(), ExceptionBadDims);

    // multiple elements + initialized with scalar
    EXPECT_THROW(FeatureData(Mat_f(2, 1, 1.f)).get<TypeParam >(), ExceptionBadDims);
    EXPECT_THROW(FeatureData(Mat_f(1, 2, 0.f)).get<TypeParam >(), ExceptionBadDims);
    EXPECT_THROW(FeatureData(Mat_f(2, 2, 3.f)).get<TypeParam >(), ExceptionBadDims);
}

TYPED_TEST(FeatureDataPOD_Test, FromMat)
{
    float _v = 256; // to cover a range of values common between all of our PODs
    while(--_v >= 0) {

        FeatureData to(Mat1f(1, 1, _v));
        EXPECT_EQ(static_cast<TypeParam >(_v), to.get<TypeParam >()) << "Value mismatch.";
    }
}

/**
 * @todo: anyway to make this less manual?
 */
TYPED_TEST(FeatureDataPOD_Test, FromPOD)
{
    float vf = 256.f; // to cover a range of values common between all of our PODs
    TypeParam _v = static_cast<TypeParam >(vf); // to cover a range of values common between all of our PODs
    while(--vf >= 0.f) {

        FeatureData to(--_v);
        EXPECT_EQ( static_cast<float >(_v),  to.get<float>() )  << "Value mismatch while getting float.";
        EXPECT_EQ( static_cast<int >(_v),    to.get<int>()   )  << "Value mismatch while getting int.";
        EXPECT_EQ( static_cast<uchar >(_v),  to.get<uchar>() )  << "Value mismatch while getting uchar.";

        EXPECT_MAT_EQ( Mat_f(1, 1, static_cast<float >(_v)), to.get<Mat_f >()) << "Value mismatch while getting Mat_f.";

#ifdef __WITH_PCL
        EXPECT_THROW( to.get<CloudXYZ::Ptr >(), ExceptionTypeError );

        {
            VecVertices vv = to.get<VecVertices >();
            EXPECT_SIZE(1, vv);
            EXPECT_SIZE(1, vv[0].vertices);

            EXPECT_EQ(static_cast<uint32_t>(_v), vv[0].vertices[0]);
        }
#endif // __WITH_PCL
    }
}

#ifdef __WITH_PCL // PCL support required for these tests

TYPED_TEST(FeatureDataPOD_Test, Invalid_Cloud)
{
    // empty
    CloudXYZ::Ptr cld(new CloudXYZ);
    EXPECT_THROW(FeatureData(cld).get<TypeParam >(), ExceptionTypeError);

    // multi-row, 3-col
    cld = Mat2PointCloud(Mat1f(4, 3, 0.f));
    EXPECT_THROW(FeatureData(cld).get<TypeParam >(), ExceptionTypeError);

    cld = Mat2PointCloud(Mat1f(4, 3, 1.f));
    EXPECT_THROW(FeatureData(cld).get<TypeParam >(), ExceptionTypeError);

    cld = Mat2PointCloud(Mat1f(4, 3, 2.f));
    EXPECT_THROW(FeatureData(cld).get<TypeParam >(), ExceptionTypeError);

    // single row
    cld = Mat2PointCloud(Mat1f(1, 3, 0.f));
    EXPECT_THROW(FeatureData(cld).get<TypeParam >(), ExceptionTypeError);

    cld = Mat2PointCloud(Mat1f(1, 3, 1.f));
    EXPECT_THROW(FeatureData(cld).get<TypeParam >(), ExceptionTypeError);

    // 3-channel
    cld = Mat2PointCloud(Mat3f(1, 1, 0.f));
    EXPECT_THROW(FeatureData(cld).get<TypeParam >(), ExceptionTypeError);

    cld = Mat2PointCloud(Mat3f(1, 1, 1.f));
    EXPECT_THROW(FeatureData(cld).get<TypeParam >(), ExceptionTypeError);
}

TYPED_TEST(FeatureDataPOD_Test, Invalid_VecVertices)
{
    std::string str = "Hello";
    std::vector<std::string> v;

    // uses the push_back(const T&) overload, which means
    // we'll incur the cost of copying str
    v.push_back(str);
    std::cout << "After copy, str is \"" << str << "\"\n";

    // uses the rvalue reference push_back(T&&) overload,
    // which means no strings will be copied; instead, the contents
    // of str will be moved into the vector.  This is less
    // expensive, but also means str might now be empty.
    v.push_back(std::move(str));
    std::cout << "After move, str is \"" << str << "\"\n";

    std::cout << "The contents of the vector are \"" << v[0]
                                         << "\", \"" << v[1] << "\"\n";

    // string move assignment operator is often implemented as swap,
    // in this case, the moved-from object is NOT empty
    std::string str2 = "Good-bye";
    std::cout << "Before move from str2, str2 = '" << str2 << "'\n";
    v[0] = std::move(str2);

    std::cout << "After move from str2, str2 = '" << str2 << "'\n";
    std::cout << "The contents of the vector are \"" << v[0]
                                         << "\", \"" << v[1] << "\"\n";

//    // empty
//    EXPECT_THROW(FeatureData(VecVertices()).get<TypeParam >(), ExceptionTypeError);

//    // multi-row
//    {
//        pcl::Vertices v;
//        v.vertices.push_back(1);
//        VecVertices vv;
//        vv.push_back(v);
//        vv.push_back(v);
//        EXPECT_THROW(FeatureData(vv).get<TypeParam >(), ExceptionBadDims);
//    }

//    // multi-col
//    {
//        pcl::Vertices v;
//        v.vertices.push_back(1);
//        v.vertices.push_back(2);
//        VecVertices vv;
//        vv.push_back(v);
//        EXPECT_THROW(FeatureData(vv).get<TypeParam >(), ExceptionBadDims);
//    }
}

#else // __WITH_PCL

TYPED_TEST(FeatureDataPOD_Test, DISABLED_Invalid_Cloud)
{
}

TYPED_TEST(FeatureDataPOD_Test, Invalid_VecVertices)
{
}

#endif // __WITH_PCL

} // annonymous namespace for test fixtures
<|endoftext|>


<commit_before>inline
opt_feat::opt_feat(const std::string in_path,
		   const std::string in_actionNames,
		   const int in_col,
		   const int in_row,
		   const int in_scale_factor,
		   const int in_shift,
		   const int in_scene, //only for kth
		   const int in_dim
)
:path(in_path), actionNames(in_actionNames), col(in_col), row(in_row), scale_factor(in_scale_factor), shift(in_shift), total_scene(in_scene), dim(in_dim)
{

  actions.load( actionNames );
  //dim = 14;
  //dim = 12; //Action Recognition from Video Using feature Covariance Matrices
}

inline
void
opt_feat::features_all_videos( field<string> all_people )
{
  int n_actions = actions.n_rows;
  int n_peo =  all_people.n_rows;
  //all_people.print("people");

   int nProcessors=omp_get_max_threads();
   std::cout<<nProcessors<<std::endl;
   omp_set_num_threads(n_actions);
   std::cout<<omp_get_num_threads()<<std::endl;

  for (int sc = 1; sc<=total_scene; ++sc) //scene
  {
    for (int pe = 0; pe< n_peo; ++pe)
    {
      wall_clock timer;
      timer.tic();

      //Tantos cores como # de acciones. Ver cuando toma para una persona y 6 acciones
      // #pragma omp for
      for (int act=0; act<n_actions; ++act)
      {
	features_video_i.clear();
	labels_video_i.clear();
	std::stringstream ss_video_name;
	ss_video_name << path << actions (act) << "/" << all_people (pe) << "_" << actions (act) << "_d" << sc << "_uncomp.avi";
	//Imprimir el thread que esta usando
	cout << ss_video_name.str() << endl;

	feature_video( ss_video_name.str() ) ; //all_actions_matrix is calculated inside this method
	mat mat_features_video_i;
	vec lab_video_i;

	if (features_video_i.size()>0)
	{
	  mat_features_video_i.zeros( dim,features_video_i.size() );
	  lab_video_i.zeros( features_video_i.size() );
	  for (uword i = 0; i < features_video_i.size(); ++i)
	  {
	    mat_features_video_i.col(i) = features_video_i.at(i)/norm(features_video_i.at(i),2);
	    lab_video_i(i) = labels_video_i.at(i);
	  }
	}
	else
	{
	  mat_features_video_i.zeros(dim,0);
	}
	std::stringstream save_folder;
	std::stringstream save_feat_video_i;
	std::stringstream save_labels_video_i;
	//tmp_ss4 << "./features_training_" << col << "x" << row << "/feature_vectors_dim" << dim << peo_train (pe) << "_" << actions(act)<< ".dat";

	cout << "Saving.." << endl;
	save_folder << "./kth-features_dim" << dim <<  "/sc" << sc << "/scale" << scale_factor << "-shift"<< shift ;
	save_feat_video_i   << save_folder.str() << "/" << all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".h5";
	save_labels_video_i << save_folder.str() << "/lab_" << all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".h5";

	cout << save_feat_video_i.str() << endl;
	//getchar();
	mat_features_video_i.save( save_feat_video_i.str(), hdf5_binary );
	lab_video_i.save( save_labels_video_i.str(), hdf5_binary );
      }

      double n = timer.toc();
      cout << "number of seconds: " << n << endl;
      getchar();
    }
  }
}

// //****************** Feature Extraction**************************************
// //***************************************************************************
inline
void
opt_feat::feature_video( std::string one_video )
{

  int new_row = row;
  int new_col = col;

  cv::VideoCapture capVideo(one_video);
  int n_frames = capVideo.get(CV_CAP_PROP_FRAME_COUNT);

  if( !capVideo.isOpened() )
  {
    cout << "Video couldn't be opened" << endl;
    return;
  }

  cv::Mat prevgray, gray, flow, cflow, frame, prevflow;
  cv::Mat ixMat, iyMat, ixxMat, iyyMat;
  cv::Mat flow_xy[2], mag, ang;

  string text;

  for(int fr=0; fr<n_frames; fr++){

    //cout << fr << " " ;

    bool bSuccess = capVideo.read(frame); // read a new frame from video

    if (!bSuccess) //if not success, break loop
    {
      cout << "Cannot read the frame from video file" << endl;
      break;
    }

     if (scale_factor!=1)
     {
       new_row = row*scale_factor;
       new_col = col*scale_factor;
       cv::resize( frame, frame, cv::Size(new_row, new_col) );
     }

    cv::cvtColor(frame, gray, CV_BGR2GRAY);

    if( prevgray.data )
    {
      //cout << t << " " ;
      cv::calcOpticalFlowFarneback(prevgray,
				   gray,
				   flow,
				   0.5, //pyr_scale
				   3,   //levels
				   9,   //winsize
				   1,   //iterations
				   5,   //poly_n
				   1.1, //poly_sigma
				   0);  //flags

      //optical flow
      cv::split(flow, flow_xy);
      cv::cartToPolar(flow_xy[0], flow_xy[1], mag, ang, true);

      cv::Sobel(gray, ixMat, CV_32F, 1, 0, 1);
      cv::Sobel(gray, iyMat, CV_32F, 0, 1, 1);
      cv::Sobel(gray, ixxMat, CV_32F, 2, 0, 1);
      cv::Sobel(gray, iyyMat, CV_32F, 0, 2, 1);

      float  ux = 0, uy = 0, vx = 0,  vy = 0;
      float u, v;

      if( prevflow.data )
      {
	//cout << new_col << " " << new_row << endl;

	for (int x = 0 ; x < new_col ; ++x ){
	  for (int y = 0 ; y < new_row ; ++y ) {

	    vec features_one_pixel(dim);
	    u = flow.at<cv::Vec2f>(y, x)[0];
	    v = flow.at<cv::Vec2f>(y, x)[1];

	    //cout << "x= " << x << " - y= " << y << endl;
	    // x grad
	    //cout << " x y grad" << endl;
	    float ix = ixMat.at<float>(y, x);
	    //cout << " y grad" << endl;
	    float iy = iyMat.at<float>(y, x);

	    // grad direction &  grad magnitude. (Edges)
	    //cout << "grad direction &  grad magnitude" << endl;
	    float gd = std::atan2(std::abs(iy), std::abs(ix));
	    float gm = std::sqrt(ix * ix + iy * iy);

	    // x second grad
	    //cout << "x y  second grad " << endl;
	    float ixx = ixxMat.at<float>(y, x);
	    // y second grad
	    float iyy = iyyMat.at<float>(y, x);

	    //du/dt
	    float ut = u - prevflow.at<cv::Vec2f>(y, x)[0];
	    // dv/dt
	    float vt = v - prevflow.at<cv::Vec2f>(y, x)[1];

	    if (x>0 && y>0 )
	    {
	      ux = u - flow.at<cv::Vec2f>(y, x - 1)[0];
	      uy = u - flow.at<cv::Vec2f>(y - 1, x)[0];
	      vx = v - flow.at<cv::Vec2f>(y, x - 1)[1];
	      vy = v - flow.at<cv::Vec2f>(y - 1, x)[1];
	    }

	    float Div = (ux + vy);
	    float Vor = (vx - uy);
	    //Adding more features
            mat G (2,2);
            mat S;
            float gd_opflow = ang.at<float>(y,x);
            float mg_opflow = mag.at<float>(y,x);
            //Gradient Tensor
            G   << ux << uy << endr
            << vx << vy << endr;

            //Rate of Stein Tensor
            S = 0.5*(G + G.t());

            float tr_G = trace(G);
            float tr_G2 = trace( square(G) );
            float tr_S = trace(S);
            float tr_S2 = trace(square(S));

            //Tensor Invariants  of the optical flow
            float Gten = 0.5*( tr_G*tr_G - tr_G2 );
            float Sten = 0.5*( tr_S*tr_S - tr_S2 );

	    if (dim ==12)
	    {
	    features_one_pixel  << x       << y       << fr   << gm  << u    << v
				<< abs(ut) << abs(vt) << Div  << Vor << Gten << Sten;
	    }

	    if (dim ==14)
	    {

	    features_one_pixel  << x << y << abs(ix) << abs(iy) << abs(ixx)
	    << abs(iyy) << gm << gd <<  u << v << abs(ut)
	    << abs(vt) << (ux + vy)  << (vx - uy);
	    }

	    if (!is_finite( features_one_pixel ) )
	    {
	      cout << "It's not FINITE... continue???" << endl;
	      getchar();
	    }
	    // Plotting Moving pixels
	    //cout << " " << gm;

	    double is_zero = accu(abs(features_one_pixel));

	    if (gm>40 && is_finite( features_one_pixel ) && is_zero!=0 ) // Empirically set to 40
	    {

	      frame.at<cv::Vec3b>(y,x)[0] = 0;
	      frame.at<cv::Vec3b>(y,x)[1] = 0;
	      frame.at<cv::Vec3b>(y,x)[2] = 255;
	      features_video_i.push_back(features_one_pixel);
	      labels_video_i.push_back( fr );
	    }
	  }
	}
      }

      if(cv::waitKey(30)>=0)
	break;

    }

      std::swap(prevgray, gray);
      std::swap(prevflow, flow);

     //cv::imshow("color", frame);
     //cv::waitKey(1);

  }
}<commit_msg>Re-calculate for dim=14 features<commit_after>inline
opt_feat::opt_feat(const std::string in_path,
		   const std::string in_actionNames,
		   const int in_col,
		   const int in_row,
		   const int in_scale_factor,
		   const int in_shift,
		   const int in_scene, //only for kth
		   const int in_dim
)
:path(in_path), actionNames(in_actionNames), col(in_col), row(in_row), scale_factor(in_scale_factor), shift(in_shift), total_scene(in_scene), dim(in_dim)
{

  actions.load( actionNames );
  //dim = 14;
  //dim = 12; //Action Recognition from Video Using feature Covariance Matrices
}

inline
void
opt_feat::features_all_videos( field<string> all_people )
{
  int n_actions = actions.n_rows;
  int n_peo =  all_people.n_rows;
  //all_people.print("people");

   int nProcessors=omp_get_max_threads();
   std::cout<<nProcessors<<std::endl;
   omp_set_num_threads(n_actions);
   std::cout<< omp_get_num_threads()<<std::endl;

  for (int sc = 1; sc<=total_scene; ++sc) //scene
  {
    for (int pe = 0; pe< n_peo; ++pe)
    {
      wall_clock timer;
      timer.tic();

      //Tantos cores como # de acciones. Ver cuando toma para una persona y 6 acciones
      #pragma omp for
      for (int act=0; act<n_actions; ++act)
      {
	features_video_i.clear();
	labels_video_i.clear();
	std::stringstream ss_video_name;
	ss_video_name << path << actions (act) << "/" << all_people (pe) << "_" << actions (act) << "_d" << sc << "_uncomp.avi";
	//Imprimir el thread que esta usando
	int tid=omp_get_thread_num();
        //std::cout<<tid<<"\t tid"<<std::endl;

	cout << "Processing on "<< tid << " for "<< ss_video_name.str() << endl;

	feature_video( ss_video_name.str() ) ; //all_actions_matrix is calculated inside this method
	mat mat_features_video_i;
	vec lab_video_i;

	if (features_video_i.size()>0)
	{
	  mat_features_video_i.zeros( dim,features_video_i.size() );
	  lab_video_i.zeros( features_video_i.size() );
	  for (uword i = 0; i < features_video_i.size(); ++i)
	  {
	    mat_features_video_i.col(i) = features_video_i.at(i)/norm(features_video_i.at(i),2);
	    lab_video_i(i) = labels_video_i.at(i);
	  }
	}
	else
	{
	  mat_features_video_i.zeros(dim,0);
	}
	std::stringstream save_folder;
	std::stringstream save_feat_video_i;
	std::stringstream save_labels_video_i;
	//tmp_ss4 << "./features_training_" << col << "x" << row << "/feature_vectors_dim" << dim << peo_train (pe) << "_" << actions(act)<< ".dat";

	cout << "Saving.." << endl;
	save_folder << "./kth-features_dim" << dim <<  "/sc" << sc << "/scale" << scale_factor << "-shift"<< shift ;
	save_feat_video_i   << save_folder.str() << "/" << all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".h5";
	save_labels_video_i << save_folder.str() << "/lab_" << all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".h5";

	cout << save_feat_video_i.str() << endl;
	//getchar();
	mat_features_video_i.save( save_feat_video_i.str(), hdf5_binary );
	lab_video_i.save( save_labels_video_i.str(), hdf5_binary );
      }

      #pragma omp barrier
      double n = timer.toc();
      cout << "number of seconds: " << n << endl;
      getchar();
    }
  }
}

// //****************** Feature Extraction**************************************
// //***************************************************************************
inline
void
opt_feat::feature_video( std::string one_video )
{

  int new_row = row;
  int new_col = col;

  cv::VideoCapture capVideo(one_video);
  int n_frames = capVideo.get(CV_CAP_PROP_FRAME_COUNT);

  if( !capVideo.isOpened() )
  {
    cout << "Video couldn't be opened" << endl;
    return;
  }

  cv::Mat prevgray, gray, flow, cflow, frame, prevflow;
  cv::Mat ixMat, iyMat, ixxMat, iyyMat;
  cv::Mat flow_xy[2], mag, ang;

  string text;

  for(int fr=0; fr<n_frames; fr++){

    //cout << fr << " " ;

    bool bSuccess = capVideo.read(frame); // read a new frame from video

    if (!bSuccess) //if not success, break loop
    {
      cout << "Cannot read the frame from video file" << endl;
      break;
    }

     if (scale_factor!=1)
     {
       new_row = row*scale_factor;
       new_col = col*scale_factor;
       cv::resize( frame, frame, cv::Size(new_row, new_col) );
     }

    cv::cvtColor(frame, gray, CV_BGR2GRAY);

    if( prevgray.data )
    {
      //cout << t << " " ;
      cv::calcOpticalFlowFarneback(prevgray,
				   gray,
				   flow,
				   0.5, //pyr_scale
				   3,   //levels
				   9,   //winsize
				   1,   //iterations
				   5,   //poly_n
				   1.1, //poly_sigma
				   0);  //flags

      //optical flow
      cv::split(flow, flow_xy);
      cv::cartToPolar(flow_xy[0], flow_xy[1], mag, ang, true);

      cv::Sobel(gray, ixMat, CV_32F, 1, 0, 1);
      cv::Sobel(gray, iyMat, CV_32F, 0, 1, 1);
      cv::Sobel(gray, ixxMat, CV_32F, 2, 0, 1);
      cv::Sobel(gray, iyyMat, CV_32F, 0, 2, 1);

      float  ux = 0, uy = 0, vx = 0,  vy = 0;
      float u, v;

      if( prevflow.data )
      {
	//cout << new_col << " " << new_row << endl;

	for (int x = 0 ; x < new_col ; ++x ){
	  for (int y = 0 ; y < new_row ; ++y ) {

	    vec features_one_pixel(dim);
	    u = flow.at<cv::Vec2f>(y, x)[0];
	    v = flow.at<cv::Vec2f>(y, x)[1];

	    //cout << "x= " << x << " - y= " << y << endl;
	    // x grad
	    //cout << " x y grad" << endl;
	    float ix = ixMat.at<float>(y, x);
	    //cout << " y grad" << endl;
	    float iy = iyMat.at<float>(y, x);

	    // grad direction &  grad magnitude. (Edges)
	    //cout << "grad direction &  grad magnitude" << endl;
	    float gd = std::atan2(std::abs(iy), std::abs(ix));
	    float gm = std::sqrt(ix * ix + iy * iy);

	    // x second grad
	    //cout << "x y  second grad " << endl;
	    float ixx = ixxMat.at<float>(y, x);
	    // y second grad
	    float iyy = iyyMat.at<float>(y, x);

	    //du/dt
	    float ut = u - prevflow.at<cv::Vec2f>(y, x)[0];
	    // dv/dt
	    float vt = v - prevflow.at<cv::Vec2f>(y, x)[1];

	    if (x>0 && y>0 )
	    {
	      ux = u - flow.at<cv::Vec2f>(y, x - 1)[0];
	      uy = u - flow.at<cv::Vec2f>(y - 1, x)[0];
	      vx = v - flow.at<cv::Vec2f>(y, x - 1)[1];
	      vy = v - flow.at<cv::Vec2f>(y - 1, x)[1];
	    }

	    float Div = (ux + vy);
	    float Vor = (vx - uy);
	    //Adding more features
            mat G (2,2);
            mat S;
            float gd_opflow = ang.at<float>(y,x);
            float mg_opflow = mag.at<float>(y,x);
            //Gradient Tensor
            G   << ux << uy << endr
            << vx << vy << endr;

            //Rate of Stein Tensor
            S = 0.5*(G + G.t());

            float tr_G = trace(G);
            float tr_G2 = trace( square(G) );
            float tr_S = trace(S);
            float tr_S2 = trace(square(S));

            //Tensor Invariants  of the optical flow
            float Gten = 0.5*( tr_G*tr_G - tr_G2 );
            float Sten = 0.5*( tr_S*tr_S - tr_S2 );

	    if (dim ==12)
	    {
	    features_one_pixel  << x       << y       << fr   << gm  << u    << v
				<< abs(ut) << abs(vt) << Div  << Vor << Gten << Sten;
	    }

	    if (dim ==14)
	    {

	    features_one_pixel  << x << y << abs(ix) << abs(iy) << abs(ixx)
	    << abs(iyy) << gm << gd <<  u << v << abs(ut)
	    << abs(vt) << (ux + vy)  << (vx - uy);
	    }

	    if (!is_finite( features_one_pixel ) )
	    {
	      cout << "It's not FINITE... continue???" << endl;
	      getchar();
	    }
	    // Plotting Moving pixels
	    //cout << " " << gm;

	    double is_zero = accu(abs(features_one_pixel));

	    if (gm>40 && is_finite( features_one_pixel ) && is_zero!=0 ) // Empirically set to 40
	    {

	      frame.at<cv::Vec3b>(y,x)[0] = 0;
	      frame.at<cv::Vec3b>(y,x)[1] = 0;
	      frame.at<cv::Vec3b>(y,x)[2] = 255;
	      features_video_i.push_back(features_one_pixel);
	      labels_video_i.push_back( fr );
	    }
	  }
	}
      }

      if(cv::waitKey(30)>=0)
	break;

    }

      std::swap(prevgray, gray);
      std::swap(prevflow, flow);

     //cv::imshow("color", frame);
     //cv::waitKey(1);

  }
}<|endoftext|>