mirror of
https://github.com/AlexandreRouma/SDRPlusPlus.git
synced 2025-01-18 22:23:04 +01:00
134 lines
3.5 KiB
C++
134 lines
3.5 KiB
C++
#include "riff.h"
|
|
#include <string.h>
|
|
#include <stdexcept>
|
|
|
|
namespace riff {
|
|
const char* RIFF_SIGNATURE = "RIFF";
|
|
const char* LIST_SIGNATURE = "LIST";
|
|
const size_t RIFF_LABEL_SIZE = 4;
|
|
|
|
bool Writer::open(std::string path, const char form[4]) {
|
|
std::lock_guard<std::recursive_mutex> lck(mtx);
|
|
|
|
// Open file
|
|
file = std::ofstream(path, std::ios::out | std::ios::binary);
|
|
if (!file.is_open()) { return false; }
|
|
|
|
// Begin RIFF chunk
|
|
beginRIFF(form);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Writer::isOpen() {
|
|
std::lock_guard<std::recursive_mutex> lck(mtx);
|
|
return file.is_open();
|
|
}
|
|
|
|
void Writer::close() {
|
|
std::lock_guard<std::recursive_mutex> lck(mtx);
|
|
|
|
if (!isOpen()) { return; }
|
|
|
|
// Finalize RIFF chunk
|
|
endRIFF();
|
|
|
|
// Close file
|
|
file.close();
|
|
}
|
|
|
|
void Writer::beginList(const char id[4]) {
|
|
std::lock_guard<std::recursive_mutex> lck(mtx);
|
|
|
|
// Create chunk with the LIST ID and write id
|
|
beginChunk(LIST_SIGNATURE);
|
|
write((uint8_t*)id, RIFF_LABEL_SIZE);
|
|
}
|
|
|
|
void Writer::endList() {
|
|
std::lock_guard<std::recursive_mutex> lck(mtx);
|
|
|
|
if (chunks.empty()) {
|
|
throw std::runtime_error("No chunk to end");
|
|
}
|
|
if (memcmp(chunks.top().hdr.id, LIST_SIGNATURE, RIFF_LABEL_SIZE)) {
|
|
throw std::runtime_error("Top chunk not LIST chunk");
|
|
}
|
|
|
|
endChunk();
|
|
}
|
|
|
|
void Writer::beginChunk(const char id[4]) {
|
|
std::lock_guard<std::recursive_mutex> lck(mtx);
|
|
|
|
// Create and write header
|
|
ChunkDesc desc;
|
|
desc.pos = file.tellp();
|
|
memcpy(desc.hdr.id, id, sizeof(desc.hdr.id));
|
|
desc.hdr.size = 0;
|
|
file.write((char*)&desc.hdr, sizeof(ChunkHeader));
|
|
|
|
// Save descriptor
|
|
chunks.push(desc);
|
|
}
|
|
|
|
void Writer::endChunk() {
|
|
std::lock_guard<std::recursive_mutex> lck(mtx);
|
|
|
|
if (chunks.empty()) {
|
|
throw std::runtime_error("No chunk to end");
|
|
}
|
|
|
|
// Get descriptor
|
|
ChunkDesc desc = chunks.top();
|
|
chunks.pop();
|
|
|
|
// Write size
|
|
auto pos = file.tellp();
|
|
auto npos = desc.pos;
|
|
npos += 4;
|
|
file.seekp(npos);
|
|
file.write((char*)&desc.hdr.size, sizeof(desc.hdr.size));
|
|
file.seekp(pos);
|
|
|
|
// If parent chunk, increment its size
|
|
if (!chunks.empty()) {
|
|
chunks.top().hdr.size += desc.hdr.size;
|
|
}
|
|
}
|
|
|
|
void Writer::write(const uint8_t* data, size_t len) {
|
|
std::lock_guard<std::recursive_mutex> lck(mtx);
|
|
|
|
if (chunks.empty()) {
|
|
throw std::runtime_error("No chunk to write into");
|
|
}
|
|
file.write((char*)data, len);
|
|
chunks.top().hdr.size += len;
|
|
}
|
|
|
|
void Writer::beginRIFF(const char form[4]) {
|
|
std::lock_guard<std::recursive_mutex> lck(mtx);
|
|
|
|
if (!chunks.empty()) {
|
|
throw std::runtime_error("Can't create RIFF chunk on an existing RIFF file");
|
|
}
|
|
|
|
// Create chunk with RIFF ID and write form
|
|
beginChunk(RIFF_SIGNATURE);
|
|
write((uint8_t*)form, RIFF_LABEL_SIZE);
|
|
}
|
|
|
|
void Writer::endRIFF() {
|
|
std::lock_guard<std::recursive_mutex> lck(mtx);
|
|
|
|
if (chunks.empty()) {
|
|
throw std::runtime_error("No chunk to end");
|
|
}
|
|
if (memcmp(chunks.top().hdr.id, RIFF_SIGNATURE, RIFF_LABEL_SIZE)) {
|
|
throw std::runtime_error("Top chunk not RIFF chunk");
|
|
}
|
|
|
|
endChunk();
|
|
}
|
|
} |