#include "audio.h" #include M::Audio::Audio(W::Blob* p_file, const W::Address& addr, QObject* parent): File(p_file, addr, parent), frames() { W::Handler* requestFrames = W::Handler::create(address + W::Address({u"requestFrames"}), this, &M::Audio::_h_requestFrames); addHandler(requestFrames); } M::Audio::~Audio() {} M::Model::ModelType M::Audio::getType() const { return type; } void M::Audio::initAdditional(const W::String& p_mime) { File::initAdditional(p_mime); //TODO handle other than mp3 formats mad_stream stream; mad_header header; mad_stream_init(&stream); mad_header_init(&header); mad_stream_buffer(&stream, file->uchar(), file->size()); uint64_t length = 0; uint64_t tBits = 0; while(stream.error != MAD_ERROR_BUFLEN) { //TODO handle other errors; int success = mad_header_decode(&header, &stream); if (success == 0) { frames.emplace_back(stream.this_frame - stream.buffer, stream.next_frame - stream.this_frame); length += header.duration.seconds * MAD_TIMER_RESOLUTION + header.duration.fraction; tBits += header.bitrate; } } additional.insert(u"duration", new W::Uint64(length / MAD_TIMER_RESOLUTION)); additional.insert(u"bitrate", new W::Uint64(tBits / frames.size())); additional.insert(u"framesAmount", new W::Uint64(frames.size())); } void M::Audio::h_requestFrames(const W::Event& ev) { const W::Vocabulary& vc = static_cast(ev.getData()); const W::Uint64& index = static_cast(vc.at(u"index")); const W::Uint64& amount = static_cast(vc.at(u"amount")); W::Vocabulary* evc = new W::Vocabulary(); if (index + amount > frames.size()) { evc->insert(u"result", new W::Uint64(1)); } else { evc->insert(u"result", new W::Uint64(0)); uint64_t start = 0; uint64_t size = 0; bool first = true; for (int i = 0; i < amount; ++i) { const std::pair& pair = frames[index + i]; if (first) { start = pair.first; first = false; } size += pair.second; } evc->insert(u"data", file->slice(start, size)); evc->insert(u"amount", new W::Uint64(amount)); } response(evc, W::Address{u"responseFrames"}, ev); }