// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild

#include "creative_voice_file.h"
#include "kaitai/exceptions.h"
const std::set<creative_voice_file_t::block_types_t> creative_voice_file_t::_values_block_types_t{
    creative_voice_file_t::BLOCK_TYPES_TERMINATOR,
    creative_voice_file_t::BLOCK_TYPES_SOUND_DATA,
    creative_voice_file_t::BLOCK_TYPES_SOUND_DATA_CONT,
    creative_voice_file_t::BLOCK_TYPES_SILENCE,
    creative_voice_file_t::BLOCK_TYPES_MARKER,
    creative_voice_file_t::BLOCK_TYPES_TEXT,
    creative_voice_file_t::BLOCK_TYPES_REPEAT_START,
    creative_voice_file_t::BLOCK_TYPES_REPEAT_END,
    creative_voice_file_t::BLOCK_TYPES_EXTRA_INFO,
    creative_voice_file_t::BLOCK_TYPES_SOUND_DATA_NEW,
};
bool creative_voice_file_t::_is_defined_block_types_t(creative_voice_file_t::block_types_t v) {
    return creative_voice_file_t::_values_block_types_t.find(v) != creative_voice_file_t::_values_block_types_t.end();
}
const std::set<creative_voice_file_t::codecs_t> creative_voice_file_t::_values_codecs_t{
    creative_voice_file_t::CODECS_PCM_8BIT_UNSIGNED,
    creative_voice_file_t::CODECS_ADPCM_4BIT,
    creative_voice_file_t::CODECS_ADPCM_2_6BIT,
    creative_voice_file_t::CODECS_ADPCM_2_BIT,
    creative_voice_file_t::CODECS_PCM_16BIT_SIGNED,
    creative_voice_file_t::CODECS_ALAW,
    creative_voice_file_t::CODECS_ULAW,
    creative_voice_file_t::CODECS_ADPCM_4_TO_16BIT,
};
bool creative_voice_file_t::_is_defined_codecs_t(creative_voice_file_t::codecs_t v) {
    return creative_voice_file_t::_values_codecs_t.find(v) != creative_voice_file_t::_values_codecs_t.end();
}

creative_voice_file_t::creative_voice_file_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, creative_voice_file_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root ? p__root : this;
    m_blocks = nullptr;
    _read();
}

void creative_voice_file_t::_read() {
    m_magic = m__io->read_bytes(20);
    if (!(m_magic == std::string("\x43\x72\x65\x61\x74\x69\x76\x65\x20\x56\x6F\x69\x63\x65\x20\x46\x69\x6C\x65\x1A", 20))) {
        throw kaitai::validation_not_equal_error<std::string>(std::string("\x43\x72\x65\x61\x74\x69\x76\x65\x20\x56\x6F\x69\x63\x65\x20\x46\x69\x6C\x65\x1A", 20), m_magic, m__io, std::string("/seq/0"));
    }
    m_header_size = m__io->read_u2le();
    m_version = m__io->read_u2le();
    m_checksum = m__io->read_u2le();
    m_blocks = std::unique_ptr<std::vector<std::unique_ptr<block_t>>>(new std::vector<std::unique_ptr<block_t>>());
    {
        int i = 0;
        while (!m__io->is_eof()) {
            m_blocks->push_back(std::move(std::unique_ptr<block_t>(new block_t(m__io, this, m__root))));
            i++;
        }
    }
}

creative_voice_file_t::~creative_voice_file_t() {
    _clean_up();
}

void creative_voice_file_t::_clean_up() {
}

creative_voice_file_t::block_t::block_t(kaitai::kstream* p__io, creative_voice_file_t* p__parent, creative_voice_file_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m__io__raw_body = nullptr;
    f_body_size = false;
    _read();
}

void creative_voice_file_t::block_t::_read() {
    m_block_type = static_cast<creative_voice_file_t::block_types_t>(m__io->read_u1());
    n_body_size1 = true;
    if (block_type() != creative_voice_file_t::BLOCK_TYPES_TERMINATOR) {
        n_body_size1 = false;
        m_body_size1 = m__io->read_u2le();
    }
    n_body_size2 = true;
    if (block_type() != creative_voice_file_t::BLOCK_TYPES_TERMINATOR) {
        n_body_size2 = false;
        m_body_size2 = m__io->read_u1();
    }
    n_body = true;
    if (block_type() != creative_voice_file_t::BLOCK_TYPES_TERMINATOR) {
        n_body = false;
        n_body = true;
        switch (block_type()) {
        case creative_voice_file_t::BLOCK_TYPES_EXTRA_INFO: {
            n_body = false;
            m__raw_body = m__io->read_bytes(body_size());
            m__io__raw_body = std::unique_ptr<kaitai::kstream>(new kaitai::kstream(m__raw_body));
            m_body = std::unique_ptr<block_extra_info_t>(new block_extra_info_t(m__io__raw_body.get(), this, m__root));
            break;
        }
        case creative_voice_file_t::BLOCK_TYPES_MARKER: {
            n_body = false;
            m__raw_body = m__io->read_bytes(body_size());
            m__io__raw_body = std::unique_ptr<kaitai::kstream>(new kaitai::kstream(m__raw_body));
            m_body = std::unique_ptr<block_marker_t>(new block_marker_t(m__io__raw_body.get(), this, m__root));
            break;
        }
        case creative_voice_file_t::BLOCK_TYPES_REPEAT_START: {
            n_body = false;
            m__raw_body = m__io->read_bytes(body_size());
            m__io__raw_body = std::unique_ptr<kaitai::kstream>(new kaitai::kstream(m__raw_body));
            m_body = std::unique_ptr<block_repeat_start_t>(new block_repeat_start_t(m__io__raw_body.get(), this, m__root));
            break;
        }
        case creative_voice_file_t::BLOCK_TYPES_SILENCE: {
            n_body = false;
            m__raw_body = m__io->read_bytes(body_size());
            m__io__raw_body = std::unique_ptr<kaitai::kstream>(new kaitai::kstream(m__raw_body));
            m_body = std::unique_ptr<block_silence_t>(new block_silence_t(m__io__raw_body.get(), this, m__root));
            break;
        }
        case creative_voice_file_t::BLOCK_TYPES_SOUND_DATA: {
            n_body = false;
            m__raw_body = m__io->read_bytes(body_size());
            m__io__raw_body = std::unique_ptr<kaitai::kstream>(new kaitai::kstream(m__raw_body));
            m_body = std::unique_ptr<block_sound_data_t>(new block_sound_data_t(m__io__raw_body.get(), this, m__root));
            break;
        }
        case creative_voice_file_t::BLOCK_TYPES_SOUND_DATA_NEW: {
            n_body = false;
            m__raw_body = m__io->read_bytes(body_size());
            m__io__raw_body = std::unique_ptr<kaitai::kstream>(new kaitai::kstream(m__raw_body));
            m_body = std::unique_ptr<block_sound_data_new_t>(new block_sound_data_new_t(m__io__raw_body.get(), this, m__root));
            break;
        }
        default: {
            m__raw_body = m__io->read_bytes(body_size());
            break;
        }
        }
    }
}

creative_voice_file_t::block_t::~block_t() {
    _clean_up();
}

void creative_voice_file_t::block_t::_clean_up() {
    if (!n_body_size1) {
    }
    if (!n_body_size2) {
    }
    if (!n_body) {
    }
}

int32_t creative_voice_file_t::block_t::body_size() {
    if (f_body_size)
        return m_body_size;
    f_body_size = true;
    n_body_size = true;
    if (block_type() != creative_voice_file_t::BLOCK_TYPES_TERMINATOR) {
        n_body_size = false;
        m_body_size = body_size1() + (body_size2() << 16);
    }
    return m_body_size;
}

creative_voice_file_t::block_extra_info_t::block_extra_info_t(kaitai::kstream* p__io, creative_voice_file_t::block_t* p__parent, creative_voice_file_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    f_num_channels = false;
    f_sample_rate = false;
    _read();
}

void creative_voice_file_t::block_extra_info_t::_read() {
    m_freq_div = m__io->read_u2le();
    m_codec = static_cast<creative_voice_file_t::codecs_t>(m__io->read_u1());
    m_num_channels_1 = m__io->read_u1();
}

creative_voice_file_t::block_extra_info_t::~block_extra_info_t() {
    _clean_up();
}

void creative_voice_file_t::block_extra_info_t::_clean_up() {
}

int32_t creative_voice_file_t::block_extra_info_t::num_channels() {
    if (f_num_channels)
        return m_num_channels;
    f_num_channels = true;
    m_num_channels = num_channels_1() + 1;
    return m_num_channels;
}

double creative_voice_file_t::block_extra_info_t::sample_rate() {
    if (f_sample_rate)
        return m_sample_rate;
    f_sample_rate = true;
    m_sample_rate = 256000000.0 / (num_channels() * (65536 - freq_div()));
    return m_sample_rate;
}

creative_voice_file_t::block_marker_t::block_marker_t(kaitai::kstream* p__io, creative_voice_file_t::block_t* p__parent, creative_voice_file_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    _read();
}

void creative_voice_file_t::block_marker_t::_read() {
    m_marker_id = m__io->read_u2le();
}

creative_voice_file_t::block_marker_t::~block_marker_t() {
    _clean_up();
}

void creative_voice_file_t::block_marker_t::_clean_up() {
}

creative_voice_file_t::block_repeat_start_t::block_repeat_start_t(kaitai::kstream* p__io, creative_voice_file_t::block_t* p__parent, creative_voice_file_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    _read();
}

void creative_voice_file_t::block_repeat_start_t::_read() {
    m_repeat_count_1 = m__io->read_u2le();
}

creative_voice_file_t::block_repeat_start_t::~block_repeat_start_t() {
    _clean_up();
}

void creative_voice_file_t::block_repeat_start_t::_clean_up() {
}

creative_voice_file_t::block_silence_t::block_silence_t(kaitai::kstream* p__io, creative_voice_file_t::block_t* p__parent, creative_voice_file_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    f_duration_sec = false;
    f_sample_rate = false;
    _read();
}

void creative_voice_file_t::block_silence_t::_read() {
    m_duration_samples = m__io->read_u2le();
    m_freq_div = m__io->read_u1();
}

creative_voice_file_t::block_silence_t::~block_silence_t() {
    _clean_up();
}

void creative_voice_file_t::block_silence_t::_clean_up() {
}

double creative_voice_file_t::block_silence_t::duration_sec() {
    if (f_duration_sec)
        return m_duration_sec;
    f_duration_sec = true;
    m_duration_sec = duration_samples() / sample_rate();
    return m_duration_sec;
}

double creative_voice_file_t::block_silence_t::sample_rate() {
    if (f_sample_rate)
        return m_sample_rate;
    f_sample_rate = true;
    m_sample_rate = 1000000.0 / (256 - freq_div());
    return m_sample_rate;
}

creative_voice_file_t::block_sound_data_t::block_sound_data_t(kaitai::kstream* p__io, creative_voice_file_t::block_t* p__parent, creative_voice_file_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    f_sample_rate = false;
    _read();
}

void creative_voice_file_t::block_sound_data_t::_read() {
    m_freq_div = m__io->read_u1();
    m_codec = static_cast<creative_voice_file_t::codecs_t>(m__io->read_u1());
    m_wave = m__io->read_bytes_full();
}

creative_voice_file_t::block_sound_data_t::~block_sound_data_t() {
    _clean_up();
}

void creative_voice_file_t::block_sound_data_t::_clean_up() {
}

double creative_voice_file_t::block_sound_data_t::sample_rate() {
    if (f_sample_rate)
        return m_sample_rate;
    f_sample_rate = true;
    m_sample_rate = 1000000.0 / (256 - freq_div());
    return m_sample_rate;
}

creative_voice_file_t::block_sound_data_new_t::block_sound_data_new_t(kaitai::kstream* p__io, creative_voice_file_t::block_t* p__parent, creative_voice_file_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    _read();
}

void creative_voice_file_t::block_sound_data_new_t::_read() {
    m_sample_rate = m__io->read_u4le();
    m_bits_per_sample = m__io->read_u1();
    m_num_channels = m__io->read_u1();
    m_codec = static_cast<creative_voice_file_t::codecs_t>(m__io->read_u2le());
    m_reserved = m__io->read_bytes(4);
    m_wave = m__io->read_bytes_full();
}

creative_voice_file_t::block_sound_data_new_t::~block_sound_data_new_t() {
    _clean_up();
}

void creative_voice_file_t::block_sound_data_new_t::_clean_up() {
}
