test_sdk/hw/gtl_hw_player_file_wav.cpp

294 lines
7.9 KiB
C++
Raw Normal View History

#include "gtl_hw_player_file_wav.h"
#include "qmath.h"
namespace gtl
{
namespace hw
{
player_file_wav::player_file_wav(QObject *parent, QString path) : player_file(parent, path)
{
if (!_is_ok)
return;
_is_ok = false;
quint32 id_chunk;
quint32 size_chunk;
*_stream >> id_chunk;
if (id_chunk != 0x46464952 && id_chunk != 0x34365742)
return;
*_stream >> size_chunk;
// if (size_chunk != _file->size() - _file->pos())
// return;
*_stream >> id_chunk;
if (id_chunk != 0x45564157)
return;
while (!_stream->atEnd())
{
*_stream >> id_chunk;
if (id_chunk == 0x20746d66)
{
read_fmt_chunk();
if (_format != 1 && _format != 3)
return;
}
else if (id_chunk == 0x61746164)
{
read_data_chunk();
break;
}
else if (id_chunk == 0x34367364)
{
read_ds64_chunk();
}
else
{
read_unknown_chunk();
}
}
_file->seek(_pos_data + _size_data);
_time = (qreal)_size_data / _block_align / _rate;
_info = tr("rate: ") + QString::number(_rate, 'f', 0) + tr(" hz") + ";\r\n";
_info += tr("time: ") + QString::number(_time) + tr(" sec") + ";\r\n";
_info += tr("bits per sample: ") + QString::number(_bits_per_sample) + ";\r\n";
_info += "\r\n" + comment();
_is_ok = true;
}
player_file_wav::~player_file_wav()
{
}
bool player_file_wav::get_data(qreal *data, int &samples, bool is_cyclic, bool &is_continued)
{
quint64 smps = 0;
QByteArray buffer(samples * _block_align, 0);
while (smps < samples)
{
quint64 smps_to_end = (_pos_data + _size_data - _file->pos()) / _block_align;
if (smps_to_end < (samples - smps))
{
int bytes = _stream->readRawData((char*)&buffer.data()[smps*_block_align], smps_to_end*_block_align);
if (bytes < 0)
return false;
smps += bytes / _block_align;
_file->seek(_pos_data);
if (!is_cyclic)
{
samples = smps;
is_continued = false;
break;
}
}
else
{
int bytes = _stream->readRawData((char*)&buffer.data()[smps*_block_align], (samples - smps)*_block_align);
if (bytes < 0)
return false;
smps += bytes / _block_align;
}
}
qint32 sample;
int bytes_per_sample = _block_align / channels();
int bits_shift = 32 - _bits_per_sample;
qreal factor = qPow(2, bits_shift);
for (int i = 0; i < samples * channels(); i++)
{
std::copy(&buffer.data()[i*bytes_per_sample], &buffer.data()[i*bytes_per_sample + bytes_per_sample], (char*)&sample);
if (_bits_per_sample)
sample -= 128;
sample = sample << bits_shift;
data[i] = 10.0 * sample / (sample < 0 ? 2147483648 : 2147483647);
}
return true;
}
bool player_file_wav::get_data(qreal *data, int &idx, int &samples, bool is_cyclic /*= false*/)
{
_mutex.lock();
quint64 smps = 0;
_file->seek(_pos_data + idx*_block_align);
QByteArray buffer(samples * _block_align, 0);
while (smps < samples)
{
quint64 smps_to_end = (_pos_data + _size_data - _file->pos()) / _block_align;
if (smps_to_end < (samples - smps))
{
int bytes = _stream->readRawData((char*)&buffer.data()[smps*_block_align], smps_to_end*_block_align);
if (bytes <= 0)
{
_mutex.unlock();
samples = smps;
return false;
}
smps += bytes / _block_align;
if (!is_cyclic)
{
samples = smps;
break;
}
else
_file->seek(_pos_data);
}
else
{
int bytes = _stream->readRawData((char*)&buffer.data()[smps*_block_align], (samples - smps)*_block_align);
if (bytes < 0)
{
_mutex.unlock();
samples = smps;
return false;
}
smps += bytes / _block_align;
}
}
qint32 sample;
int bytes_per_sample = _block_align / channels();
int bits_shift = 32 - _bits_per_sample;
qreal factor = qPow(2, bits_shift);
for (int i = 0; i < samples * channels(); i++)
{
std::copy(&buffer.data()[i*bytes_per_sample], &buffer.data()[i*bytes_per_sample + bytes_per_sample], (char*)&sample);
if (_format == 3)
{
data[i] = *((float*)&sample);
}
else
{
if (_bits_per_sample)
sample -= 128;
sample = sample << bits_shift;
data[i] = 10.0 * sample / (sample < 0 ? 2147483648 : 2147483647);
}
}
int pos = _file->pos();
int size = _pos_data + _size_data;
bool is_compete = _file->pos() == _pos_data + _size_data;
if (is_compete)
seek_to_start();
idx = (_file->pos() - _pos_data) / _block_align;
_mutex.unlock();
return is_compete && !is_cyclic;
}
void player_file_wav::read_fmt_chunk()
{
quint32 size_chunk;
*_stream >> size_chunk;
quint64 pos_chunk = _file->pos();
quint32 tmp_32;
quint16 tmp_16;
*_stream >> _format;
if (_format == 1 || _format == 3)
{
*_stream >> tmp_16;
_channels = tmp_16;
*_stream >> tmp_32;
_rate = tmp_32;
*_stream >> tmp_32; // avg bytes per second
*_stream >> _block_align;
*_stream >> _bits_per_sample;
}
_file->seek(pos_chunk + size_chunk);
}
void player_file_wav::read_data_chunk()
{
quint32 size;
*_stream >> size;
if (size != 0xffffffff)
_size_data = size;
_pos_data = _file->pos();
// _stream->skipRawData(_size_data);
}
void player_file_wav::read_ds64_chunk()
{
quint32 high;
quint32 low;
quint32 size;
*_stream >> size;
*_stream >> low;
*_stream >> high;
*_stream >> low;
*_stream >> high;
_size_data = low + ((quint64)high << 32);
*_stream >> low;
*_stream >> high;
*_stream >> low;
}
void player_file_wav::read_unknown_chunk()
{
quint32 size;
*_stream >> size;
_stream->skipRawData(size);
}
}
}