Audio-MPC

 view release on metacpan or  search on metacpan

MPC.xs  view on Meta::CPAN

		} 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));

MPC.xs  view on Meta::CPAN

    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 )