mirror of
https://github.com/isledecomp/SIEdit.git
synced 2025-02-17 00:40:42 -05:00
app/lib: keep data chunked
This commit is contained in:
parent
68926a5afe
commit
7ef15f4e42
7 changed files with 109 additions and 60 deletions
|
@ -61,6 +61,8 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||
InitializeMenuBar();
|
||||
|
||||
splitter->setSizes({99999, 99999});
|
||||
|
||||
setWindowTitle(tr("SI Editor"));
|
||||
}
|
||||
|
||||
void MainWindow::OpenFilename(const QString &s)
|
||||
|
@ -127,7 +129,8 @@ void MainWindow::ExtractObject(si::Object *obj)
|
|||
if (!s.isEmpty()) {
|
||||
QFile f(s);
|
||||
if (f.open(QFile::WriteOnly)) {
|
||||
f.write(obj->data().data(), obj->data().size());
|
||||
bytearray b = obj->GetNormalizedData();
|
||||
f.write(b.data(), b.size());
|
||||
f.close();
|
||||
} else {
|
||||
QMessageBox::critical(this, QString(), tr("Failed to write to file \"%1\".").arg(s));
|
||||
|
|
|
@ -28,7 +28,8 @@ void BitmapPanel::OnOpeningData(void *data)
|
|||
{
|
||||
si::Object *o = static_cast<si::Object*>(data);
|
||||
|
||||
QByteArray b(o->data().data(), o->data().size());
|
||||
si::bytearray processed = o->GetNormalizedData();
|
||||
QByteArray b(processed.data(), processed.size());
|
||||
QBuffer buf(&b);
|
||||
QImage img;
|
||||
img.load(&buf, "BMP");
|
||||
|
|
|
@ -40,20 +40,8 @@ void WavPanel::OnOpeningData(void *data)
|
|||
si::Object *o = static_cast<si::Object*>(data);
|
||||
|
||||
// Find fmt and data
|
||||
auto dat = o->data().data();
|
||||
for (size_t i=0; i<o->data().size(); i++) {
|
||||
if (!memcmp(dat+i, "fmt ", 4)) {
|
||||
header_ = *(si::WAVFormatHeader *)(dat+i+8);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (size_t i=0; i<o->data().size(); i++) {
|
||||
if (!memcmp(dat+i, "data", 4)) {
|
||||
uint32_t sz = *(uint32_t*)(dat+i+4);
|
||||
playhead_slider_->setMaximum(sz/GetSampleSize());
|
||||
break;
|
||||
}
|
||||
}
|
||||
header_ = *o->GetFileHeader().cast<si::WAVFormatHeader>();
|
||||
playhead_slider_->setMaximum(o->GetFileBodySize()/GetSampleSize());
|
||||
}
|
||||
|
||||
void WavPanel::OnClosingData(void *data)
|
||||
|
@ -71,37 +59,20 @@ void WavPanel::Play(bool e)
|
|||
{
|
||||
if (audio_out_) {
|
||||
audio_out_->stop();
|
||||
//audio_out_->deleteLater();
|
||||
delete audio_out_;
|
||||
audio_out_ = nullptr;
|
||||
}
|
||||
buffer_.close();
|
||||
array_.clear();
|
||||
playback_timer_->stop();
|
||||
|
||||
if (e) {
|
||||
const si::bytearray &lib = static_cast<si::Object*>(GetData())->data();
|
||||
array_ = QByteArray(lib.data(), lib.size());
|
||||
si::Object *o = static_cast<si::Object*>(GetData());
|
||||
si::bytearray pcm = o->GetFileBody();
|
||||
array_ = QByteArray(pcm.data(), pcm.size());
|
||||
buffer_.open(QBuffer::ReadOnly);
|
||||
|
||||
size_t start = 0;
|
||||
si::WAVFormatHeader header;
|
||||
|
||||
// Find fmt and data
|
||||
auto dat = lib.data();
|
||||
for (size_t i=0; i<lib.size(); i++) {
|
||||
if (!memcmp(dat+i, "fmt ", 4)) {
|
||||
header = *(si::WAVFormatHeader *)(dat+i+8);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (size_t i=0; i<lib.size(); i++) {
|
||||
if (!memcmp(dat+i, "data", 4)) {
|
||||
start = i + 8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
buffer_start_ = start;
|
||||
|
||||
if (playhead_slider_->value() < playhead_slider_->maximum()) {
|
||||
start += playhead_slider_->value() * GetSampleSize();
|
||||
|
@ -110,9 +81,9 @@ void WavPanel::Play(bool e)
|
|||
buffer_.seek(start);
|
||||
|
||||
QAudioFormat audio_fmt;
|
||||
audio_fmt.setSampleRate(header.SampleRate);
|
||||
audio_fmt.setChannelCount(header.Channels);
|
||||
audio_fmt.setSampleSize(header.BitsPerSample);
|
||||
audio_fmt.setSampleRate(header_.SampleRate);
|
||||
audio_fmt.setChannelCount(header_.Channels);
|
||||
audio_fmt.setSampleSize(header_.BitsPerSample);
|
||||
audio_fmt.setByteOrder(QAudioFormat::LittleEndian);
|
||||
audio_fmt.setCodec(QStringLiteral("audio/pcm"));
|
||||
audio_fmt.setSampleType(QAudioFormat::SignedInt);
|
||||
|
@ -127,7 +98,7 @@ void WavPanel::Play(bool e)
|
|||
|
||||
void WavPanel::TimerUpdate()
|
||||
{
|
||||
playhead_slider_->setValue((buffer_.pos() - buffer_start_) / GetSampleSize());
|
||||
playhead_slider_->setValue(buffer_.pos() / GetSampleSize());
|
||||
}
|
||||
|
||||
void WavPanel::OutputChanged(QAudio::State state)
|
||||
|
@ -141,6 +112,6 @@ void WavPanel::OutputChanged(QAudio::State state)
|
|||
void WavPanel::SliderMoved(int i)
|
||||
{
|
||||
if (buffer_.isOpen()) {
|
||||
buffer_.seek(buffer_start_ + i * GetSampleSize());
|
||||
buffer_.seek(i * GetSampleSize());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,9 +30,9 @@ private:
|
|||
QAudioOutput *audio_out_;
|
||||
QBuffer buffer_;
|
||||
QByteArray array_;
|
||||
size_t buffer_start_;
|
||||
QTimer *playback_timer_;
|
||||
si::WAVFormatHeader header_;
|
||||
QByteArray play_buffer_;
|
||||
|
||||
private slots:
|
||||
void Play(bool e);
|
||||
|
|
|
@ -90,7 +90,7 @@ bool Interleaf::ParseStream(Chunk *chunk)
|
|||
for (ChunkMap::const_iterator it=data.begin(); it!=data.end(); it++) {
|
||||
Object *o = obj->FindSubObjectWithID(it->first);
|
||||
if (o) {
|
||||
o->ProcessData(it->second);
|
||||
o->SetChunkedData(it->second);
|
||||
} else {
|
||||
std::cout << "Failed to find object with ID " << it->first << std::endl;
|
||||
}
|
||||
|
|
|
@ -47,28 +47,40 @@ bool Object::Parse(Chunk *chunk)
|
|||
return true;
|
||||
}
|
||||
|
||||
void Object::ProcessData(const std::vector<bytearray> &chunks)
|
||||
bytearray Object::GetNormalizedData() const
|
||||
{
|
||||
switch (filetype_) {
|
||||
return ToPackedData(filetype(), data_);
|
||||
}
|
||||
|
||||
void Object::SetNormalizedData(const bytearray &d)
|
||||
{
|
||||
SetChunkedData(ToChunkedData(filetype(), d));
|
||||
}
|
||||
|
||||
bytearray Object::ToPackedData(MxOb::FileType filetype, const ChunkedData &chunks)
|
||||
{
|
||||
bytearray data;
|
||||
|
||||
switch (filetype) {
|
||||
case MxOb::WAV:
|
||||
{
|
||||
// Make space for WAVE header
|
||||
data_.resize(0x2C);
|
||||
data.resize(0x2C);
|
||||
|
||||
// Merge all chunks after the first one
|
||||
for (size_t i=1; i<chunks.size(); i++) {
|
||||
data_.append(chunks[i]);
|
||||
data.append(chunks[i]);
|
||||
}
|
||||
|
||||
// Copy boilerplate bytes for header
|
||||
uint32_t *header = reinterpret_cast<uint32_t *>(data_.data());
|
||||
uint32_t *header = reinterpret_cast<uint32_t *>(data.data());
|
||||
header[0] = Chunk::TYPE_RIFF; // "RIFF"
|
||||
header[1] = data_.size() - 8; // Size of total file
|
||||
header[1] = data.size() - 8; // Size of total file
|
||||
header[2] = 0x45564157; // "WAVE"
|
||||
header[3] = 0x20746D66; // "fmt "
|
||||
header[4] = 16; // Size of fmt chunk
|
||||
header[9] = 0x61746164; // "data"
|
||||
header[10] = data_.size() - 0x2C; // Size of data chunk
|
||||
header[10] = data.size() - 0x2C; // Size of data chunk
|
||||
|
||||
// Copy fmt header from chunk 1
|
||||
memcpy(&header[5], chunks[0].data(), 16);
|
||||
|
@ -77,27 +89,77 @@ void Object::ProcessData(const std::vector<bytearray> &chunks)
|
|||
case MxOb::STL:
|
||||
{
|
||||
// Make space for BMP header
|
||||
data_.resize(14);
|
||||
data.resize(14);
|
||||
|
||||
// Merge all chunks after the first one
|
||||
for (size_t i=0; i<chunks.size(); i++) {
|
||||
data_.append(chunks[i]);
|
||||
data.append(chunks[i]);
|
||||
}
|
||||
|
||||
// Set BM identifier
|
||||
*(uint16_t *)(data_.data()) = 0x4D42;
|
||||
*(uint16_t *)(data.data()) = 0x4D42;
|
||||
|
||||
// Set file size
|
||||
*(uint32_t*)(data_.data()+2) = data_.size();
|
||||
*(uint32_t*)(data.data()+2) = data.size();
|
||||
|
||||
// Set reserved bytes
|
||||
*(uint32_t*)(data_.data()+6) = 0;
|
||||
*(uint32_t*)(data.data()+6) = 0;
|
||||
|
||||
// Set offset
|
||||
*(uint32_t*)(data_.data()+10) = chunks.at(0).size() + 14;
|
||||
*(uint32_t*)(data.data()+10) = chunks.at(0).size() + 14;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
Object::ChunkedData Object::ToChunkedData(MxOb::FileType filetype, const bytearray &chunks)
|
||||
{
|
||||
// FIXME: STUB
|
||||
return ChunkedData();
|
||||
}
|
||||
|
||||
bytearray Object::GetFileHeader() const
|
||||
{
|
||||
switch (filetype()) {
|
||||
case MxOb::WAV:
|
||||
case MxOb::STL:
|
||||
return data_.at(0);
|
||||
}
|
||||
|
||||
return bytearray();
|
||||
}
|
||||
|
||||
bytearray Object::GetFileBody() const
|
||||
{
|
||||
bytearray b;
|
||||
|
||||
switch (filetype()) {
|
||||
case MxOb::WAV:
|
||||
case MxOb::STL:
|
||||
for (size_t i=1; i<data_.size(); i++) {
|
||||
b.append(data_.at(i));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
size_t Object::GetFileBodySize() const
|
||||
{
|
||||
size_t s = 0;
|
||||
switch (filetype()) {
|
||||
case MxOb::WAV:
|
||||
case MxOb::STL:
|
||||
for (size_t i=1; i<data_.size(); i++) {
|
||||
s += data_.at(i).size();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
Object *Object::FindSubObjectWithID(uint32_t id)
|
||||
|
|
18
lib/object.h
18
lib/object.h
|
@ -10,16 +10,28 @@ namespace si {
|
|||
class Object : public Core
|
||||
{
|
||||
public:
|
||||
using ChunkedData = std::vector<bytearray>;
|
||||
|
||||
Object();
|
||||
|
||||
bool Parse(Chunk *chunk);
|
||||
void ProcessData(const std::vector<bytearray> &chunks);
|
||||
void SetChunkedData(const ChunkedData &cd) { data_ = cd; }
|
||||
|
||||
LIBWEAVER_EXPORT bytearray GetNormalizedData() const;
|
||||
LIBWEAVER_EXPORT void SetNormalizedData(const bytearray &d);
|
||||
|
||||
LIBWEAVER_EXPORT static bytearray ToPackedData(MxOb::FileType filetype, const ChunkedData &chunks);
|
||||
LIBWEAVER_EXPORT static ChunkedData ToChunkedData(MxOb::FileType filetype, const bytearray &chunks);
|
||||
|
||||
LIBWEAVER_EXPORT bytearray GetFileHeader() const;
|
||||
LIBWEAVER_EXPORT bytearray GetFileBody() const;
|
||||
LIBWEAVER_EXPORT size_t GetFileBodySize() const;
|
||||
|
||||
const MxOb::FileType &filetype() const { return filetype_; }
|
||||
const uint32_t &id() const { return id_; }
|
||||
const std::string &name() const { return name_; }
|
||||
const std::string &filename() const { return filename_; }
|
||||
bytearray &data() { return data_; }
|
||||
const ChunkedData &data() const { return data_; }
|
||||
|
||||
Object *FindSubObjectWithID(uint32_t id);
|
||||
|
||||
|
@ -46,7 +58,7 @@ private:
|
|||
uint32_t unknown30_;
|
||||
uint32_t unknown31_;
|
||||
|
||||
bytearray data_;
|
||||
ChunkedData data_;
|
||||
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue