Audio-MPC
view release on metacpan or search on metacpan
} else
str = savepv(ERR_TMPL_FILE_NO);
break;
case ERROR_CODE_DECODER:
str = savepv(ERR_TMPL_DECODER);
break;
}
return str;
}
};
class MPC {
private:
mpc_reader_file *mr;
mpc_streaminfo msi;
mpc_decoder md;
MPC_SAMPLE_FORMAT mbuf[MPC_DECODER_BUFFER_LENGTH];
FILE* mfile;
PerlIO* mperlio;
SV* mcustomreader;
public:
MPC (pTHX_ FILE *file, char *fname = NULL) throw (MPC_exception) {
int ec;
New(0, mr, 1, mpc_reader_file);
mfile = file;
mpc_reader_setup_file_reader(mr, mfile);
mpc_streaminfo_init(&msi);
mpc_decoder_setup(&md, &mr->reader);
mperlio = NULL;
mcustomreader = Nullsv;
if ((ec = mpc_streaminfo_read(&msi, &mr->reader)) != ERROR_CODE_OK) {
Safefree(mr);
throw MPC_exception (ec, fname);
}
if (mpc_decoder_initialize(&md, &msi) == FALSE) {
Safefree(mr);
throw MPC_exception (ERROR_CODE_DECODER);
}
}
MPC (pTHX_ PerlIO *file, char *fname = NULL) throw (MPC_exception) {
int ec;
New(0, mr, 1, mpc_reader_file);
mperlio = file;
mfile = PerlIO_exportFILE(mperlio, NULL);
mpc_reader_setup_file_reader(mr, mfile);
mpc_streaminfo_init(&msi);
mpc_decoder_setup(&md, &mr->reader);
mcustomreader = Nullsv;
if ((ec = mpc_streaminfo_read(&msi, &mr->reader)) != ERROR_CODE_OK) {
Safefree(mr);
throw MPC_exception (ec, fname);
}
if (mpc_decoder_initialize(&md, &msi) == FALSE) {
Safefree(mr);
throw MPC_exception (ERROR_CODE_DECODER);
}
}
MPC (pTHX_ MPC_data *mpcdata, SV *obj) throw (MPC_exception) {
int ec;
New(0, mr, 1, mpc_reader_file);
mr->reader.read = read_impl; /* SCRESTO */
mr->reader.seek = seek_impl;
mr->reader.tell = tell_impl;
mr->reader.get_size = get_size_impl;
mr->reader.canseek = canseek_impl;
mr->reader.data = mpcdata;
mpc_streaminfo_init(&msi);
mpc_decoder_setup(&md, &mr->reader);
/* delayed initialization of 'self' field */
mcustomreader = mpcdata->self = obj;
if ((ec = mpc_streaminfo_read(&msi, &mr->reader)) != ERROR_CODE_OK) {
throw MPC_exception (ec);
}
if (mpc_decoder_initialize(&md, &msi) == FALSE) {
throw MPC_exception (ERROR_CODE_DECODER);
}
SvREFCNT_inc(mcustomreader);
}
void shutdown (pTHX) {
if (mcustomreader) {
SvREFCNT_dec(mcustomreader);
return;
}
if (mperlio)
PerlIO_releaseFILE(mperlio, mfile);
else if (mfile)
fclose(mfile);
}
~MPC () {
Safefree(mr);
}
MPC_SAMPLE_FORMAT* decode (int *len) {
*len = mpc_decoder_decode(&md, mbuf, 0, 0);
return mbuf;
}
int seek_sample (long long sample) {
if (mpc_decoder_seek_sample(&md, sample))
return 1;
return 0;
}
int seek_seconds (double second) {
if (mpc_decoder_seek_seconds(&md, second))
return 1;
return 0;
}
#define BO16(a) \
if (endian == MPC_BIG_ENDIAN) { \
short b = a; \
a = ((b & 0x00ff)<<8) | \
((b & 0xff00)>>8); \
}
#define BO32(a) \
if (endian == MPC_BIG_ENDIAN) { \
int b = a; \
a = ((b & 0xff000000)>>24) | \
((b & 0x00ff0000)>>8) | \
((b & 0x0000ff00)<<8) | \
((b & 0x000000ff)<<24); \
}
wav_header get_wave_header (unsigned int datalen, int endian) {
wav_header header;
memcpy(header.riff, endian != MPC_BIG_ENDIAN ? "RIFF" : "RIFX", 4 * sizeof(char));
int gain_title () { return msi.gain_title; }
int gain_album () { return msi.gain_album; }
int peak_title () { return msi.peak_title; }
int peak_album () { return msi.peak_album; }
int is_gapless () { return msi.is_true_gapless; }
int last_frame_samples () { return msi.last_frame_samples; }
int encoder_version () { return msi.encoder_version; }
char* encoder () { return msi.encoder; }
IV tag_offset () { return msi.tag_offset; }
IV total_length () { return msi.total_file_length; }
};
#ifdef MPC_FIXED_POINT
static int
shift_signed(MPC_SAMPLE_FORMAT val, int shift)
{
if (shift > 0)
val <<= shift;
else if (shift < 0)
val >>= -shift;
return (int)val;
}
#endif
SV *ZERO_BUT_TRUE;
CV *DEF_READ, *DEF_SEEK, *DEF_TELL, *DEF_GET_SIZE, *DEF_CANSEEK;
MODULE = Audio::MPC PACKAGE = Audio::MPC
INCLUDE: const-xs.inc
PROTOTYPES: DISABLE
BOOT:
{
ZERO_BUT_TRUE = newSVpvn("0 but true", 10);
DEF_READ = get_cv("Audio::MPC::Reader::read", FALSE);
DEF_SEEK = get_cv("Audio::MPC::Reader::seek", FALSE);
DEF_TELL = get_cv("Audio::MPC::Reader::tell", FALSE);
DEF_GET_SIZE = get_cv("Audio::MPC::Reader::get_size", FALSE);
DEF_CANSEEK = get_cv("Audio::MPC::Reader::canseek", FALSE);
}
char *
errstr (...)
CODE:
{
RETVAL = errstr ? errstr : const_cast<char*>("");
}
OUTPUT:
RETVAL
MPC *
MPC::new (...)
CODE:
{
FILE *file;
PerlIO *perlio = NULL;
char *fname = NULL;
MPC_data *mpcdata = NULL;
bool isperlio = false;
if (items == 1 || !SvOK(ST(1))) {
perlio = PerlIO_stdin();
file = PerlIO_exportFILE(PerlIO_stdin(), NULL);
isperlio = true;
}
else {
if (sv_isobject(ST(1)) and sv_derived_from(ST(1), "Audio::MPC::Reader")) {
mpcdata = (MPC_data*)SvIV(SvRV(ST(1)));
}
else if (!SvROK(ST(1))) {
file = fopen(fname = SvPV_nolen(ST(1)), "r");
if (!file) {
MPC_exception e(ERROR_CODE_FILE, fname);
errstr = e.to_string();
XSRETURN_UNDEF;
}
}
else if (glob_ref(ST(1))) {
perlio = IoIFP(sv_2io(ST(1)));
isperlio = true;
}
}
try {
if (mpcdata) RETVAL = new MPC (aTHX_ mpcdata, ST(1));
else if (isperlio) RETVAL = new MPC (aTHX_ perlio, fname);
else RETVAL = new MPC (aTHX_ file, fname);
} catch (MPC_exception e) {
errstr = e.to_string();
XSRETURN_UNDEF;
}
}
OUTPUT:
RETVAL
int
MPC::decode (sv, endian = MPC_LITTLE_ENDIAN)
SV *sv;
int endian;
CODE:
{
#define STEREO 2
#define BPS 16
#define SAMPLE_SIZE (BPS>>3)
#define FLOAT_SCALE (1 << (BPS - 1))
register int i;
int nsamples;
char *ptr;
if (SvREADONLY(sv))
croak("First argument to MPC::decode must not be read-only");
MPC_SAMPLE_FORMAT *samples = THIS->decode(&nsamples);
if (nsamples == 0) {
ST(0) = sv_mortalcopy(ZERO_BUT_TRUE);
XSRETURN(1);
}
if (nsamples == -1)
XSRETURN_UNDEF;
SvUPGRADE(sv, SVt_PV);
ptr = SvGROW(sv, nsamples * STEREO * SAMPLE_SIZE + 1);
RETVAL = nsamples * STEREO * SAMPLE_SIZE;
for (i = 0; i < nsamples * STEREO; i++) {
int val;
#ifdef MPC_FIXED_POINT
val = shift_signed(samples[i], BPS - MPC_FIXED_POINT_SCALE_SHIFT);
#else
val = (int)(samples[i] * FLOAT_SCALE);
#endif
if (endian == MPC_LITTLE_ENDIAN) {
*ptr++ = (unsigned char)val & 0xFF;
*ptr++ = (unsigned char)(val>>8) & 0xFF;
} else if (endian == MPC_BIG_ENDIAN) {
*ptr++ = (unsigned char)(val>>8) & 0xFF;
*ptr++ = (unsigned char)val & 0xFF;
}
}
SvCUR_set(sv, RETVAL);
SvPOK_on(sv);
*SvEND(sv) = 0;
}
OUTPUT:
( run in 0.443 second using v1.01-cache-2.11-cpan-6aa56a78535 )