156 lines
3.5 KiB
C++
156 lines
3.5 KiB
C++
/*
|
|
* Cantata
|
|
*
|
|
* Copyright (c) 2011-2022 Craig Drummond <craig.p.drummond@gmail.com>
|
|
*
|
|
*/
|
|
/* This class is a C++/Qt version of input_ffmpeg.c from libebur128
|
|
*/
|
|
|
|
/* See LICENSE file for copyright and license details. */
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
#include <mpg123.h>
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
#include <QFile>
|
|
#include <QString>
|
|
#include <QByteArray>
|
|
#include "ebur128/ebur128.h"
|
|
#include "mpg123input.h"
|
|
|
|
struct Mpg123Input::Handle {
|
|
Handle()
|
|
: mpg123(0)
|
|
, rate(0)
|
|
, channels(0)
|
|
, encoding(0)
|
|
, buffer(0) {
|
|
}
|
|
~Handle() {
|
|
if (buffer) {
|
|
free(buffer);
|
|
}
|
|
}
|
|
mpg123_handle *mpg123;
|
|
long rate;
|
|
int channels, encoding;
|
|
float *buffer;
|
|
};
|
|
|
|
void Mpg123Input::init()
|
|
{
|
|
static int i=false;
|
|
if (!i) {
|
|
mpg123_init();
|
|
}
|
|
}
|
|
|
|
Mpg123Input::Mpg123Input(const QString &fileName)
|
|
{
|
|
handle=new Handle;
|
|
|
|
QByteArray fName=QFile::encodeName(fileName);
|
|
bool ok=false;
|
|
int result;
|
|
handle->mpg123 = mpg123_new(NULL, &result);
|
|
if (handle->mpg123 &&
|
|
MPG123_OK==mpg123_open(handle->mpg123, fName.constData()) &&
|
|
MPG123_OK==mpg123_getformat(handle->mpg123, &handle->rate, &handle->channels, &handle->encoding) &&
|
|
MPG123_OK==mpg123_format_none(handle->mpg123) &&
|
|
MPG123_OK==mpg123_format(handle->mpg123, handle->rate, handle->channels, MPG123_ENC_FLOAT_32)) {
|
|
|
|
mpg123_close(handle->mpg123);
|
|
if (MPG123_OK==mpg123_open(handle->mpg123, fName.constData()) &&
|
|
MPG123_OK==mpg123_getformat(handle->mpg123, &handle->rate, &handle->channels, &handle->encoding)) {
|
|
ok=true;
|
|
}
|
|
}
|
|
|
|
if (!ok) {
|
|
if (handle->mpg123) {
|
|
mpg123_close(handle->mpg123);
|
|
mpg123_delete(handle->mpg123);
|
|
handle->mpg123 = NULL;
|
|
}
|
|
delete handle;
|
|
handle = 0;
|
|
}
|
|
}
|
|
|
|
Mpg123Input::~Mpg123Input()
|
|
{
|
|
if (handle) {
|
|
if (handle->mpg123) {
|
|
mpg123_close(handle->mpg123);
|
|
mpg123_delete(handle->mpg123);
|
|
handle->mpg123 = NULL;
|
|
}
|
|
delete handle;
|
|
handle = 0;
|
|
}
|
|
}
|
|
|
|
size_t Mpg123Input::totalFrames() const
|
|
{
|
|
if (!handle) {
|
|
return 0;
|
|
}
|
|
|
|
off_t length = mpg123_length(handle->mpg123);
|
|
return MPG123_ERR==length ? 0 : (size_t) length;
|
|
}
|
|
|
|
unsigned int Mpg123Input::channels() const
|
|
{
|
|
return handle ? (unsigned int)handle->channels : 0;
|
|
}
|
|
|
|
unsigned long Mpg123Input::sampleRate() const
|
|
{
|
|
return handle ? (unsigned long)handle->rate : 0;
|
|
}
|
|
|
|
bool Mpg123Input::allocateBuffer()
|
|
{
|
|
if (!handle) {
|
|
return false;
|
|
}
|
|
|
|
handle->buffer = (float*) malloc((size_t) handle->rate *
|
|
(size_t) handle->channels *
|
|
sizeof(float));
|
|
return handle->buffer;
|
|
}
|
|
|
|
float * Mpg123Input::buffer() const
|
|
{
|
|
return handle ? handle->buffer : 0;
|
|
}
|
|
|
|
bool Mpg123Input::setChannelMap(int *st) const
|
|
{
|
|
Q_UNUSED(st)
|
|
return false;
|
|
}
|
|
|
|
size_t Mpg123Input::readFrames()
|
|
{
|
|
if (!handle) {
|
|
return 0;
|
|
}
|
|
|
|
size_t numberRead;
|
|
int result = mpg123_read(handle->mpg123, (unsigned char*) handle->buffer,
|
|
(size_t) handle->rate *
|
|
(size_t) handle->channels * sizeof(float),
|
|
&numberRead);
|
|
if (MPG123_OK!=result && MPG123_DONE!=result) {
|
|
return 0;
|
|
}
|
|
numberRead /= (size_t) handle->channels * sizeof(float);
|
|
return numberRead;
|
|
}
|