81 lines
2.4 KiB
C++
81 lines
2.4 KiB
C++
|
#include "audio.h"
|
||
|
|
||
|
#include <mad.h>
|
||
|
|
||
|
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<const W::Vocabulary&>(ev.getData());
|
||
|
const W::Uint64& index = static_cast<const W::Uint64&>(vc.at(u"index"));
|
||
|
const W::Uint64& amount = static_cast<const W::Uint64&>(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<uint64_t, uint64_t>& 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);
|
||
|
}
|