[PD-cvs] externals/august/readanysf~/src Fifo.cpp, NONE, 1.1 Input.cpp, NONE, 1.1 InputFile.cpp, NONE, 1.1 InputStream.cpp, NONE, 1.1 Makefile.am, NONE, 1.1 Makefile.in, NONE, 1.1 ReadFlac.cpp, NONE, 1.1 ReadFlac.cpp.seekable, NONE, 1.1 ReadMad.cpp, NONE, 1.1 ReadRaw.cpp, NONE, 1.1 ReadVorbis.cpp, NONE, 1.1 Readsf.cpp, NONE, 1.1 config.h.in, NONE, 1.1 main.cpp, NONE, 1.1 simple.pd, NONE, 1.1
B. Bogart
bbogart at users.sourceforge.net
Sat Aug 13 03:17:01 CEST 2005
- Previous message: [PD-cvs] externals/august/readanysf~/include Fifo.h, NONE, 1.1 Input.h, NONE, 1.1 InputFile.h, NONE, 1.1 InputStream.h, NONE, 1.1 Makefile, NONE, 1.1 Makefile.am, NONE, 1.1 Makefile.in, NONE, 1.1 ReadFlac.h, NONE, 1.1 ReadFlac.h.seekable, NONE, 1.1 ReadMad.h, NONE, 1.1 ReadRaw.h, NONE, 1.1 ReadVorbis.h, NONE, 1.1 Readsf.h, NONE, 1.1 generic.h, NONE, 1.1 main.h, NONE, 1.1 stamp-h2.in, NONE, 1.1
- Next message: [PD-cvs] externals/august/readanysf~ AUTHORS, NONE, 1.1 COPYING, NONE, 1.1 ChangeLog, NONE, 1.1 INSTALL, NONE, 1.1 Makefile.am, NONE, 1.1 Makefile.in, NONE, 1.1 NEWS, NONE, 1.1 README, NONE, 1.1 aclocal.m4, NONE, 1.1 boot.sh, NONE, 1.1 config.guess, NONE, 1.1 config.h.in, NONE, 1.1 config.sub, NONE, 1.1 configure, NONE, 1.1 configure.ac, NONE, 1.1 depcomp, NONE, 1.1 install-sh, NONE, 1.1 missing, NONE, 1.1 mkinstalldirs, NONE, 1.1 readanysf-help.pd, NONE, 1.1 stamp-h1.in, NONE, 1.1
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /cvsroot/pure-data/externals/august/readanysf~/src
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26207/src
Added Files:
Fifo.cpp Input.cpp InputFile.cpp InputStream.cpp Makefile.am
Makefile.in ReadFlac.cpp ReadFlac.cpp.seekable ReadMad.cpp
ReadRaw.cpp ReadVorbis.cpp Readsf.cpp config.h.in main.cpp
simple.pd
Log Message:
Initial commit of readanysf~ 0.13.1 for August
--- NEW FILE: ReadMad.cpp ---
/*
* readanysf~ external for pd.
*
* Copyright (C) 2003 August Black
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* ReadMad.cpp || much code studied from Andy Lo-A-Foe <www.alsaplayer.org>
*/
#ifdef READ_MAD
//#include <m_pd.h>
#include "ReadMad.h"
#include <iostream>
using namespace std;
#define mad_f_tofloat(x) ((float) ((x) / (float) (1L << MAD_F_FRACBITS)))
ReadMad::ReadMad (Input * input) {
in = input;
bytes_avail = 0; // IMPORTANT!!!
//map_offset = 0; // do we need this?
bitrate = 0;
samplesperframe = 0;
samplestotal = 0;
time = 0;
nr_frames = 0;
lengthinseconds = 0.0;
}
ReadMad::~ReadMad () {
if (mad_init) {
mad_synth_finish (&synth);
mad_frame_finish (&frame);
mad_stream_finish (&stream);
mad_init = 0;
}
}
bool ReadMad::fill_buffer (long newoffset) {
size_t bytes_read;
if (!seekable) return false;
if ( in->SeekSet( offset + newoffset ) == -1 )
return false;
bytes_read = in->Read( (void *)mad_map, MAD_BUFSIZE );
if (bytes_read == 0) {
//cout << "ReadMad:: fillbuf offset, got zero on read, EOF?" << endl;
return 0; }
if (bytes_read < 0 ) {
//cout << "ReadMad:: fillbuf offset got -1 on read, ERROR?" << endl;
return 0; }
bytes_avail = bytes_read;
return true;
//map_offset = newoffset;
}
bool ReadMad::fill_buffer () {
size_t bytes_read, br;
memmove (mad_map, mad_map + MAD_BUFSIZE - bytes_avail, bytes_avail);
br = bytes_read = MAD_BUFSIZE - bytes_avail;
bytes_read = in->Read ((void *) (mad_map + bytes_avail), bytes_read);
if (bytes_read == 0) {
//cout << "ReadMad:: got zero on read, EOF? br=%d",br);
return 0;
}
if (bytes_read < 0 ) {
//cout << "ReadMad:: got -1 on read, ERROR?" << endl;
return 0; }
//map_offset += (MAD_BUFSIZE - bytes_avail);
bytes_avail += bytes_read;
return 1;
}
int ReadMad::Decode (float *buffer, int size) {
struct mad_pcm *pcm;
mad_fixed_t const *left_ch;
mad_fixed_t const *right_ch;
int nsamples;
int nchannels;
bool ret =1;
//if (MAD_BUFSIZE > size)
//return false;
if (bytes_avail < 3072) {
//cout << "Filling buffer = %d,%d", bytes_avail,map_offset + MAD_BUFSIZE - bytes_avail);
ret = fill_buffer (); // map_offset + MAD_BUFSIZE - bytes_avail);
if ( ret == 0 && in->get_recover() ) { // got EOF on stream, but we want to recover
nsamples = 0;
while (nsamples < size/2)
buffer[nsamples++] = 0.0;
return nsamples;
}
mad_stream_buffer (&stream, mad_map, bytes_avail);
}
if (mad_frame_decode (&frame, &stream) == -1) {
if (!MAD_RECOVERABLE (stream.error)) {
mad_frame_mute (&frame);
return 0;
} else {
if ( !ret ) { // error or EOF
// not if stream input goes down, fill buffer with
// cout << "ReadMad:: seems we have end of file" << endl;
return 0;
}
// cout << "ReadMad::MAD error: (not fatal)" << endl;
}
}
mad_synth_frame (&synth, &frame);
{
pcm = &synth.pcm;
nsamples = pcm->length;
nchannels = pcm->channels;
left_ch = pcm->samples[0];
right_ch = pcm->samples[1];
int x = 0;
while (nsamples--) {
buffer[x++] = mad_f_tofloat (*(left_ch++));
if (nchannels == 2)
buffer[x++] = mad_f_tofloat (*(right_ch++));
}
}
bytes_avail = stream.bufend - stream.next_frame;
//if (pcm->length != 1152)
//cout << " %d", pcm->length);
return pcm->length * nchannels;
}
ssize_t ReadMad::find_initial_frame (uint8_t * buf, int size) {
uint8_t *data = buf;
int ext_header = 0;
int pos = 0;
ssize_t header_size = 0;
while (pos < (size - 10)) {
if (pos == 0 && data[pos] == 0x0d && data[pos + 1] == 0x0a)
pos += 2;
if (data[pos] == 0xff && (data[pos + 1] == 0xfb
|| data[pos + 1] == 0xfa
|| data[pos + 1] == 0xf3
|| data[pos + 1] == 0xe2
|| data[pos + 1] == 0xe3))
{
//error("found header at %d", pos);
return pos;
}
if (pos == 0 && data[pos] == 0x0d && data[pos + 1] == 0x0a) {
return -1; // Let MAD figure this out
}
if (pos == 0 && (data[pos] == 'I' && data[pos + 1] == 'D' && data[pos + 2] == '3')) {
header_size = (data[pos + 6] << 21) + (data[pos + 7] << 14) + (data[pos + 8] << 7) + data[pos + 9]; /* syncsafe integer */
if (data[pos + 5] & 0x10) {
ext_header = 1;
header_size += 10; /* 10 byte extended header */
}
header_size += 10;
if (header_size > MAD_BUFSIZE) {
//cout << "Header larger than 32K (%d)", header_size);
return header_size;
}
return header_size;
} else if (data[pos] == 'R' && data[pos + 1] == 'I' &&
data[pos + 2] == 'F' && data[pos + 3] == 'F')
{
pos += 4;
//error("Found a RIFF header" << endl;
while (pos < size) {
if (data[pos] == 'd' && data[pos + 1] == 'a'
&& data[pos + 2] == 't'
&& data[pos + 3] == 'a')
{
pos += 8; /* skip 'data' and ignore size */
return pos;
} else
pos++;
}
cout << "MAD debug: invalid header" << endl;
return -1;
} else if (pos == 0 && data[pos] == 'T' && data[pos + 1] == 'A'
&& data[pos + 2] == 'G') {
return 128; /* TAG is fixed 128 bytes, we assume! */
}
else
{
pos++;
}
}
cout << "MAD debug: potential problem file or unhandled info block" << endl;
//cout << "next 4 bytes = %x %x %x %x (index = %d, size = %d)",
//data[header_size], data[header_size + 1],
//data[header_size + 2], data[header_size + 3],
//header_size, size);
return -1;
}
bool ReadMad::Initialize () {
if (in->get_format () == FORMAT_HTTP_MP3)
seekable = 0;
else
seekable = 1; //assume seekable if its a file
mad_synth_init (&synth);
mad_stream_init (&stream);
mad_frame_init (&frame);
memset (&xing, 0, sizeof (struct xing));
xing_init (&xing);
mad_init = 1;
fill_buffer ();
offset = find_initial_frame (mad_map, bytes_avail < MAD_BUFSIZE ? bytes_avail : MAD_BUFSIZE);
if (offset < 0) {
offset = 0;
for (int i=0; i < 10; i++) { // lets try this a coupla times to sync on a proper header
fill_buffer();
offset = find_initial_frame (mad_map, bytes_avail < MAD_BUFSIZE ? bytes_avail : MAD_BUFSIZE);
if ( offset > 0) {
//cout << "ReadMad:: found Header on %d try\n", i);
break;
}
}
if ( offset < 0 ) {
cout << "ReadMad::mad_open() couldn't find valid MPEG header\n" << endl;
return false;
}
}
if (offset > bytes_avail) {
//cout << "ReadMad:: offset > bytes_avail " << endl;
if ( !fill_buffer() ) {
cout << "ReadMad::couldn't read from InputFIFO, bailing..." << endl;
return 0;
}
mad_stream_buffer (&stream, mad_map, bytes_avail);
} else {
//cout << "ReadMad:: not sure why we are here, offset = %d, bytes_avail = %d", offset, bytes_avail);
mad_stream_buffer (&stream, mad_map + offset,
bytes_avail - offset);
bytes_avail -= offset;
}
if ((mad_frame_decode (&frame, &stream) != 0)) {
//error("MAD error: %s", error_str(data->stream.error, data->str));
switch (stream.error) {
case MAD_ERROR_BUFLEN:
cout << "MAD_ERROR_BUFLEN" << endl;
return false; //return 0;
case MAD_ERROR_LOSTSYNC:
if (mad_header_decode (&frame.header, &stream) == -1) {
cout << "ReadMad::Invalid header (" << in->get_filename () << ")" << endl;
}
mad_stream_buffer (&stream, stream.this_frame, bytes_avail - (stream.this_frame - mad_map));
bytes_avail -= (stream.this_frame - mad_map);
//cout << "avail = %d", data->bytes_avail);
mad_frame_decode (&frame, &stream);
break;
case MAD_ERROR_BADBITALLOC:
cout << "MAD_ERROR_BADBITALLOC" << endl;
return false; //return 0;
case MAD_ERROR_BADCRC:
cout << "MAD_ERROR_BADCRC" << endl; //error_str( stream.error, str));
case 0x232:
case 0x235:
break;
default:
cout << "ReadMad:: no valid frame found at start" << endl;
//cout << "No valid frame found at start (pos: %d, error: 0x%x --> %x %x %x %x) (%s)", offset, stream.error, stream.this_frame[0], stream.this_frame[1], stream.this_frame[2], stream.this_frame[3], in->get_filename ());
return false; //return 0;
}
}
if (stream.error != MAD_ERROR_LOSTSYNC)
if (xing_parse
(&xing, stream.anc_ptr, stream.anc_bitlen) == 0)
{
// We use the xing data later on
}
num_channels = (frame.header.mode == MAD_MODE_SINGLE_CHANNEL) ? 1 : 2;
samplerate = (double) frame.header.samplerate;
bitrate = frame.header.bitrate;
mad_synth_frame (&synth, &frame);
/* Calculate some values */
bytes_avail = stream.bufend - stream.next_frame;
if (seekable) {
int64_t lframes;
long oldpos = in->SeekCur (0);
in->SeekEnd (0);
filesize = in->SeekCur (0);
filesize -= offset;
in->SeekSet (oldpos);
if (bitrate)
lengthinseconds = (float) ((filesize * 8) / (bitrate));
else
lengthinseconds = 0.0;
time = (long) lengthinseconds;
samplesperframe = 32 * MAD_NSBSAMPLES (&frame.header);
samplestotal = (long) (samplerate * (time + 1));
lframes = samplestotal / samplesperframe;
nr_frames = xing.frames ? xing.frames : (int) lframes;
}
mad_init = 1;
if (xing.frames) {
//cout << "xing.frames " << xing.frames << endl;
seekable = 1;
}
return true; //return 1;
}
bool ReadMad::Rewind () {
if (in == NULL)
return false;
if (!seekable)
return true;
seek_bytes (0);
return true;
}
bool ReadMad::PCM_seek (long position) {
long byte_offset;
if (!seekable)
return false;
byte_offset = (long) (((double) position / (double) samplestotal) * filesize);
seek_bytes (byte_offset);
return true;
}
bool ReadMad::TIME_seek (double seconds) {
//double time = ( filesize * 8) / (bitrate);
long byte_offset;
if (!seekable)
return false;
byte_offset = (int) ((seconds / (double) time) * filesize);
seek_bytes (byte_offset);
return true;
}
void ReadMad::seek_bytes (long byte_offset) {
struct mad_header header;
int skip;
mad_header_init (&header);
bytes_avail = 0;
skip = 0;
//The total size in bytes for any given frame can be calculated with the following formula:
//FrameSize = 144 * BitRate / (SampleRate + Padding).
// 417.96 bytes: 144 * 128000 / (44100 + 0)
if (byte_offset > 4 * 418){
skip = 3;
}
//(seekpos / song length) * (filelength).
//cout << "byte_offset %ld, position %ld, samplestotal %ld, filesize %ld",
// byte_offset, position, samplestotal, filesize);
fill_buffer ( byte_offset );
mad_stream_buffer (&stream, mad_map, bytes_avail);
skip++;
while (skip--)
{
mad_frame_decode (&frame, &stream);
if (skip == 0)
mad_synth_frame (&synth, &frame);
}
bytes_avail = stream.bufend - stream.next_frame;
return;
}
// /////////////// xing stuff
void ReadMad::xing_init (struct xing *xing) {
xing->flags = 0;
}
/*
* NAME: xing->parse()
* DESCRIPTION: parse a Xing VBR header
*/
int
ReadMad::xing_parse (struct xing *xing, struct mad_bitptr ptr,
unsigned int bitlen)
{
if (bitlen < 64 || mad_bit_read (&ptr, 32) != XING_MAGIC)
goto fail;
xing->flags = mad_bit_read (&ptr, 32);
bitlen -= 64;
if (xing->flags & XING_FRAMES)
{
if (bitlen < 32)
goto fail;
xing->frames = mad_bit_read (&ptr, 32);
bitlen -= 32;
}
if (xing->flags & XING_BYTES)
{
if (bitlen < 32)
goto fail;
xing->bytes = mad_bit_read (&ptr, 32);
bitlen -= 32;
}
if (xing->flags & XING_TOC)
{
int i;
if (bitlen < 800)
goto fail;
for (i = 0; i < 100; ++i)
xing->toc[i] = mad_bit_read (&ptr, 8);
bitlen -= 800;
}
if (xing->flags & XING_SCALE)
{
if (bitlen < 32)
goto fail;
xing->scale = mad_bit_read (&ptr, 32);
bitlen -= 32;
}
return 0;
fail:
xing->flags = 0;
return -1;
}
#endif
--- NEW FILE: main.cpp ---
/*
* readanysf~ external for pd.
*
* Copyright (C) 2003, 2004 August Black
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* main.cpp
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include "main.h"
readanysf::readanysf ()
{
fifo = new Fifo (FIFOSIZE);
request = R_NOTHING;
state = STATE_IDLE;
loop = false;
eof = true;
format = -1;
readsf = NULL;
in = NULL;
floatmsg = 0.0;
cachemsg = 0.0;
outtick = 1000;
counttick = 0;
lengthinseconds = 0.0;
sendout = false;
src_buffer = (float *) malloc ((Blocksize ()) * 2 * FLOATSIZE);
src_mode = SRC_SINC_FASTEST;
src_state = NULL;
src_data.input_frames = 0;
AddInAnything (); // add one inlet for any message
AddOutSignal ("audio out Left");
AddOutSignal ("audio out Right");
AddOutAnything (); // add one float outlet (has index 2)
FLEXT_ADDMETHOD_ (0, "start", m_start);
FLEXT_ADDMETHOD_ (0, "play", m_start);
FLEXT_ADDMETHOD_ (0, "pause", m_pause);
FLEXT_ADDMETHOD_ (0, "stop", m_stop);
FLEXT_ADDMETHOD_ (0, "open", m_open);
FLEXT_ADDMETHOD_ (0, "reopen", m_reopen);
FLEXT_ADDMETHOD_ (0, "loop", m_loop_f);
FLEXT_ADDMETHOD_ (0, "recover", m_recover);
FLEXT_ADDMETHOD_ (0, "set_tick", m_set_tick);
FLEXT_ADDMETHOD_ (0, "pcm_seek", m_pcm_seek);
FLEXT_ADDMETHOD_ (0, "time_seek", m_time_seek);
FLEXT_ADDMETHOD_ (0, "speed", m_src_factor);
//FLEXT_ADDBANG(0,m_bang);
FLEXT_CALLMETHOD (m_child);
//post("Blocksize = %d", Blocksize());
}
readanysf::~readanysf () {
setSys (STATE_IDLE, R_QUIT);
cond.Signal ();
if (readsf != NULL)
delete (readsf);
if (fifo != NULL)
delete (fifo);
if (in != NULL)
delete (in);
}
void readanysf::m_bang () {
ToOutBang (2);
}
void readanysf::m_loop_f (float f) {
if (f == 0.0) {
post ("readanysf~:: looping Off");
varmutex.Lock ();
loop = false;
varmutex.Unlock ();
return;
} else {
post ("readanysf~:: looping On");
varmutex.Lock ();
loop = true;
varmutex.Unlock ();
return;
}
}
void readanysf::m_recover (float f) {
if (f == 0.0) { //dangerous!!!!
post ("readanysf~:: stream recover Off");
varmutex.Lock ();
if (in != NULL) in->set_recover(false);
varmutex.Unlock ();
return;
} else {
post ("readanysf~:: stream recover On");
varmutex.Lock ();
if (in != NULL) in->set_recover(true);
varmutex.Unlock ();
return;
}
}
void readanysf::m_start () {
int st = getState();
if ( st == STATE_STARTUP ) {
post("readanysf~:: still starting up....wait a bit please");
m_bang();
return;
}
if ( st != STATE_STREAM ) {
varmutex.Lock ();
eof = false;
pcmseek = 0;
timeseek = 0.0;
//if ( st != STATE_IDLE )
// floatmsg = 0.0;
varmutex.Unlock ();
bzero ((void *) src_buffer, sizeof (src_buffer));
if ( readsf == NULL ) { // nothing is opened, lets open it
//setSys (STATE_IDLE, R_OPEN);
post ("readanysf~:: first select a file.");
m_bang();
} else {
setSys (STATE_STREAM, R_PROCESS);
}
} else {
post ("readanysf~:: already playing");
}
cond.Signal ();
return;
}
void readanysf::m_time_seek (float f) {
if (f > 0.0) {
varmutex.Lock ();
timeseek = (double) f;
varmutex.Unlock ();
setRequest (R_PROCESS);
}
cond.Signal ();
}
void readanysf::m_pcm_seek (int i) {
if (i > 0)
{
varmutex.Lock ();
pcmseek = (long) i;
varmutex.Unlock ();
setRequest (R_PROCESS);
}
cond.Signal ();
}
void readanysf::m_set_tick (int i) {
varmutex.Lock ();
if (i > 1)
outtick = i;
varmutex.Unlock ();
}
void readanysf::m_stop () {
setSys (STATE_IDLE, R_STOP);
varmutex.Lock ();
floatmsg = 0.0;
bzero ((void *) src_buffer, sizeof (src_buffer));
varmutex.Unlock ();
cond.Signal ();
}
void readanysf::m_pause () {
setState (STATE_IDLE);
cond.Signal ();
}
void readanysf::m_open (t_symbol * s) {
//cond.Signal();
sprintf (filename, GetString (s));
if (getRequest () != R_OPEN) {
//post ("readanysf~:: opening...");
setSys (STATE_IDLE, R_OPEN);
varmutex.Lock ();
floatmsg = 0.0;
pcmseek = 0;
timeseek = 0.0;
format = -1;
varmutex.Unlock ();
ToOutFloat (2, 0.0 ); // send a 0.0 to float output
// we are at the beginning of the file
} else { // kill old file ???
post ("readanysf~:: still initailizing old file, please be patient");
}
cond.Signal ();
}
void readanysf::m_reopen ( ) {
int st = getState();
int rq = getRequest ();
post ("readanysf~:: reopening...");
if ( rq == R_NOTHING && filename[0] != 0 ) {
setSys (STATE_IDLE, R_OPEN);
varmutex.Lock ();
floatmsg = 0.0;
pcmseek = 0;
timeseek = 0.0;
format = -1;
varmutex.Unlock ();
ToOutFloat (2, 0.0 ); // send a 0.0 to float output
// we are at the beginning of the file
cond.Signal ();
} else {
setSys (STATE_IDLE, R_PROCESS);
cond.Signal ();
}
}
void readanysf::m_src_factor (float f) {
if (src_is_valid_ratio (f)) {
varmutex.Lock ();
src_factor = (double) f;
varmutex.Unlock ();
}
}
void readanysf::FillFifo () {
int ret, wret;
if (readsf == NULL || in == NULL)
return;
varmutex.Lock ();
if (pcmseek) {
//post("readanysf~:: seeking..");
if (readsf->PCM_seek (pcmseek)) {
floatmsg = pcmseek / samplerate;
fifo->Flush ();
//setRequest( R_PROCESS );
}
pcmseek = 0;
}
if (timeseek != 0.0) {
if (readsf->TIME_seek (timeseek))
{
floatmsg = timeseek;
fifo->Flush ();
//setRequest( R_PROCESS );
}
timeseek = 0.0;
}
varmutex.Unlock ();
while (fifo->FreeSpace () > INOUTSIZE) { // leave enough space for odd chunks
ret = readsf->Decode (read_buffer, READBUFFER);
varmutex.Lock ();
cachemsg = in->get_cachesize ();
// we should fix this - this is only a relative position
// we need to account for FIFO size
floatmsg += (float) (ret / num_channels / samplerate);
varmutex.Unlock ();
if (ret > 0) {
wret = fifo->Write ((void *) read_buffer, ret * FLOATSIZE);
} else {
//post("eof, %d", ret);
readsf->Rewind ();
//post("Rewound the file");
varmutex.Lock ();
floatmsg = 0.0;
if (!loop) {
//state = STATE_IDLE; //this is premature. we check for eof in m_signal routine
eof = true;
varmutex.Unlock ();
setRequest (R_NOTHING);
break;
} //else {
//post("Should loop here");
//setSys (STATE_STREAM, R_PROCESS);
//}
varmutex.Unlock ();
}
}
}
void readanysf::m_child () {
int req;
while ((req = getRequest ()) != R_QUIT) {
switch (req) {
case R_STOP:
if (readsf != NULL) {
//post("Trying to kill the readsf");
delete (readsf);
readsf = NULL;
//post("killed it");
}
if (in != NULL) {
delete (in);
in = NULL;
}
fifo->Flush ();
setSys (STATE_IDLE, R_NOTHING);
break;
case R_OPEN:
if (readsf != NULL && in != NULL && strcmp (filename, in->get_filename ()) == 0) {
// all is well here, we are just opening the same file again
// this happens when you open a file , hit play and then try to
// open it again
post("opening file again...");
fifo->Flush ();
readsf->Rewind();
setSys (STATE_IDLE, R_PROCESS);
} else {
// Set state to STARTUP at begingin of open and make sure to set
// it to IDLE or NOTHING after succesfully opening;
setState( STATE_STARTUP );
if (readsf != NULL) {
delete (readsf);
readsf = NULL;
}
if (in != NULL) {
delete (in);
in = NULL;
}
//check if its a stream or file; if ( strcmp( "http://")..
if (!strncasecmp (filename, "http://", 7)) {
in = new InputStream ();
post("Opening stream: %s", filename);
} else {
in = new InputFile ();
post("Opening file: %s", filename);
}
//if ( in != NULL )
format = in->Open (filename);
switch (format) {
case FORMAT_WAVE:
case FORMAT_AIFF:
case FORMAT_NEXT:
readsf = new ReadRaw (in);
break;
#ifdef READ_MAD
case FORMAT_HTTP_MP3:
case FORMAT_MAD:
readsf = new ReadMad (in);
break;
#endif
#ifdef READ_VORBIS
case FORMAT_VORBIS:
case FORMAT_HTTP_VORBIS:
readsf = new ReadVorbis (in);
break;
#endif
#ifdef READ_FLAC
case FORMAT_FLAC:
//post("readanysf~:: trying to make a ReadFLAC");
readsf = new ReadFlac (in);
break;
#endif
default:
// probably got here 'cause we opend a stream and didn't connect
// InputStream will then return a -1 on Open
m_bang();
break;
}
fifo->Flush ();
if (format >= 0 && readsf != NULL) {
if (readsf->Initialize ()) {
//post("readanysf~:: successfully initialized, format = %d", format);
varmutex.Lock ();
num_channels = readsf->get_channels ();
samplerate = readsf->get_samplerate ();
if (num_channels > 2)
num_channels = 2;
src_factor = Samplerate() / samplerate;
if (!src_is_valid_ratio (src_factor) )
src_factor = 1.0;
lengthinseconds = readsf->get_lengthinseconds();
sendout = true;
varmutex.Unlock();
setSys (STATE_IDLE, R_PROCESS);
fifo->Flush ();
} else {
post("Readanysf:: Couldn't initialize the file/stream!!!, sucks for you dude");
if (readsf != NULL) // safe without locking ???
delete (readsf);
if ( in != NULL) // es bueno aqui?
delete (in);
setSys (STATE_IDLE, R_NOTHING);
readsf = NULL;
in = NULL; // muy importante
varmutex.Lock ();
filename[0] = 0;
varmutex.Unlock ();
m_bang ();
}
} else { // not a recognized file type
post ("file not recognized, format = %d", format);
setSys (STATE_IDLE, R_NOTHING);
m_bang ();
}
}
break;
case R_PROCESS:
FillFifo (); //take care of mutex locking in FillFifo routine
case R_NOTHING:
default:
cond.Wait ();
}
}
return;
}
int readanysf::m_resample (int frames) {
unsigned int size, out_gen;
if (src_factor == 1.0) {
size = frames * num_channels * FLOATSIZE;
fifo->Read ((void *) src_buffer, size);
return size / FLOATSIZE;
}
if (src_channels != num_channels) {
src_state = src_delete (src_state);
src_state = src_new (src_mode, num_channels, &src_error);
src_channels = num_channels;
}
src_data.output_frames = frames;
out_gen = 0;
while (src_data.output_frames > 0) {
if (src_data.input_frames <= 0) {
if (src_factor > 1.0)
size = frames * num_channels * FLOATSIZE;
else
size = 1024 * num_channels * FLOATSIZE;
fifo->Read ((void *) pd_buffer, size);
src_data.data_in = pd_buffer;
src_data.data_out = src_buffer;
src_data.input_frames =
size / FLOATSIZE / num_channels;
}
src_data.src_ratio = src_factor;
if ((src_error = src_process (src_state, &src_data))) {
post ("readanysf~:: SRC error: %s", src_strerror (src_error));
return 0;
} else {
if (src_data.output_frames_gen == 0)
{
break;
}
src_data.data_in += src_data.input_frames_used * num_channels;
src_data.input_frames -= src_data.input_frames_used;
src_data.output_frames -= src_data.output_frames_gen;
out_gen += src_data.output_frames_gen;
}
}
//if (out_gen != frames) {
//post("outgen %d, frames %d", out_gen, frames);
//}
return out_gen * num_channels;
}
FLEXT_NEW_DSP ("readanysf~", readanysf)
void readanysf::m_signal (int n, float *const *in, float *const *out) {
float *outs1 = out[0];
float *outs2 = out[1];
t_atom lst[2];
varmutex.Lock ();
if (counttick++ > outtick) {
SetString (lst[0], "cache");
SetFloat (lst[1], cachemsg);
ToOutAnything (2, GetSymbol (lst[0]), 2, lst + 1);
counttick = 0;
}
varmutex.Unlock ();
if (getState () == STATE_STREAM) {
varmutex.Lock ();
int ch = num_channels;
int size = m_resample (n);
bool endoffile = eof;
int fmt = format;
if (counttick == 0) { //lock it here?
//ToOutFloat (2, floatmsg - (FIFOSECONDS / ch));
ToOutFloat ( 2, floatmsg );
}
varmutex.Unlock ();
if (size < n * ch)
{
if (endoffile) // we should do a mutex here!!!
{
fifo->Flush ();
if (fmt >= FORMAT_HTTP_MP3) {
post("-------------------> End of Stream");
setSys (STATE_IDLE, R_STOP);
cond.Signal ();
} else {
setSys (STATE_IDLE, R_PROCESS);
}
m_bang (); // bang out at end of file
}
else
{
//post("not EOF, but buffer is empty");
}
//if not eof, buffer is stuck somehow so lets keep crunching.
//in any case fill from size returned to the end with zeros
for (int x = size; x < (n * ch); x += ch)
{
*outs1++ = 0.0;
*outs2++ = 0.0;
}
}
if (fifo->FreeSpace () > INOUTSIZE)
{
if (getRequest () == R_PROCESS && !endoffile)
{
cond.Signal (); // tell the child that the fifo is hungry
}
}
if (ch > 1)
{
for (int x = 0; x < size; x += 2)
{
*outs1++ = src_buffer[x];
*outs2++ = src_buffer[x + 1];
}
}
else
{ //mono
for (int x = 0; x < size; x++)
{
*outs1++ = src_buffer[x];
*outs2++ = src_buffer[x];
}
}
}
else
{ // we're not streaming. just zero out the audio outlets
varmutex.Lock ();
if (sendout)
{
SetString (lst[0], "length");
SetFloat (lst[1], lengthinseconds);
ToOutAnything (2, GetSymbol (lst[0]), 2, lst + 1);
SetString (lst[0], "rate");
SetFloat (lst[1], (float) samplerate);
ToOutAnything (2, GetSymbol (lst[0]), 2, lst + 1);
sendout = false;
}
varmutex.Unlock ();
while (n--)
{
*outs1++ = 0.0;
*outs2++ = 0.0;
}
}
}
int readanysf::getState () {
int i;
sysmut.Lock ();
i = state;
sysmut.Unlock ();
return i;
}
int readanysf::getRequest () {
int i;
sysmut.Lock ();
i = request;
sysmut.Unlock ();
return i;
}
void readanysf::setSys (int sys, int req) {
sysmut.Lock ();
state = sys;
request = req;
sysmut.Unlock ();
return;
}
void readanysf::setState (int i) {
sysmut.Lock ();
state = i;
sysmut.Unlock ();
return;
}
void readanysf::setRequest (int i) {
sysmut.Lock ();
request = i;
sysmut.Unlock ();
return;
}
--- NEW FILE: Fifo.cpp ---
#include <stdio.h>
#include "Fifo.h"
Fifo::Fifo ()
{
astate = 0; // not allocated
buffer = NULL;
totsize = 0;
datasize = 0;
start = 0;
pthread_mutex_init (&mut, 0);
}
Fifo::Fifo (unsigned int size)
{
buffer = new char[size];
if (buffer != NULL)
{
astate = 1;
totsize = size;
datasize = 0;
start = 0;
}
else
{
astate = 0;
totsize = 0;
datasize = 0;
start = 0;
}
pthread_mutex_init (&mut, 0);
}
Fifo::~Fifo ()
{
pthread_mutex_lock (&mut);
if (astate)
delete buffer;
pthread_mutex_unlock (&mut);
}
void
Fifo::Flush ()
{
pthread_mutex_lock (&mut);
astate = 1;
//totsize = size;
datasize = 0;
start = 0;
pthread_mutex_unlock (&mut);
//for (int x =0; x < sizeof(buffer); x++) {
// buffer[x] = 0;
//}
}
int
Fifo::ReAlloc (unsigned int size)
{
pthread_mutex_lock (&mut);
if (astate)
delete buffer;
buffer = new char[size];
if (buffer != NULL)
{
astate = 1;
totsize = size;
datasize = 0;
start = 0;
pthread_mutex_unlock (&mut);
}
else
{
astate = 0;
totsize = 0;
datasize = 0;
start = 0;
pthread_mutex_unlock (&mut);
return -1;
}
return 0;
}
void *
Fifo::Read (void *buf, unsigned int &len)
{
pthread_mutex_lock (&mut);
if (len > datasize)
len = datasize;
unsigned int rest;
if (len > (totsize - start))
rest = len - (totsize - start);
else
rest = 0;
unsigned int first = len - rest;
memcpy (buf, buffer + start, first);
memcpy ((char *) buf + first, buffer, rest);
datasize -= len;
start += len;
if (start >= totsize)
start = rest;
//if (datasize == 0) printf("in fifo READ, data is zero\n");
pthread_mutex_unlock (&mut);
return buf;
}
int
Fifo::Write (void *buf, unsigned int len)
{
pthread_mutex_lock (&mut);
unsigned int end;
end = start + datasize;
if (end > totsize)
end = end - totsize;
if (len > (totsize - datasize))
{
pthread_mutex_unlock (&mut);
return -1;
}
unsigned int rest;
if ((len + end) > totsize)
rest = (len + end) - totsize;
else
rest = 0;
unsigned int first = len - rest;
memcpy (buffer + end, buf, first);
memcpy (buffer, (char *) buf + first, rest);
datasize += len;
//if (datasize == 0) printf("in fifo WRITE, data is zero\n");
pthread_mutex_unlock (&mut);
return len;
}
unsigned int
Fifo::FreeSpace (void)
{ // do we need locks here?
int x;
pthread_mutex_lock (&mut);
x = totsize - datasize;
pthread_mutex_unlock (&mut);
return x;
}
unsigned int
Fifo::UsedSpace (void)
{
int x;
pthread_mutex_lock (&mut);
x = datasize;
pthread_mutex_unlock (&mut);
return x;
}
--- NEW FILE: config.h.in ---
/* config.h.in. Generated automatically from configure.in by autoheader. */
--- NEW FILE: Makefile.in ---
# Makefile.in generated by automake 1.6.3 from Makefile.am.
# @configure_input@
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
# Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
SHELL = @SHELL@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_HEADER = $(INSTALL_DATA)
transform = @program_transform_name@
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
host_alias = @host_alias@
host_triplet = @host@
EXEEXT = @EXEEXT@
OBJEXT = @OBJEXT@
PATH_SEPARATOR = @PATH_SEPARATOR@
AMTAR = @AMTAR@
AWK = @AWK@
CPP = @CPP@
CXX = @CXX@
DEPDIR = @DEPDIR@
FLC_CFLAGS = @FLC_CFLAGS@
FLC_LIBS = @FLC_LIBS@
FLEXT_CFLAGS = @FLEXT_CFLAGS@
FLEXT_LIBS = @FLEXT_LIBS@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
MAD_CFLAGS = @MAD_CFLAGS@
MAD_LIBS = @MAD_LIBS@
PACKAGE = @PACKAGE@
PTHREAD_LIBS = @PTHREAD_LIBS@
SRC_LIBS = @SRC_LIBS@
STRIP = @STRIP@
VERSION = @VERSION@
VORBIS_CFLAGS = @VORBIS_CFLAGS@
VORBIS_LIBS = @VORBIS_LIBS@
am__include = @am__include@
am__quote = @am__quote@
install_sh = @install_sh@
pd_suffix = @pd_suffix@
INCLUDES = \
-I/usr/local/include/ -I/usr/local/lib/pd/flext/ -I../include/
CFLAGS = \
@FLEXT_CFLAGS@ @VORBIS_CFLAGS@ @MAD_CFLAGS@ @FLC_CFLAGS@
CXXFLAGS = \
@FLEXT_CFLAGS@ @VORBIS_CFLAGS@ @MAD_CFLAGS@ @FLC_CFLAGS@
bin_PROGRAMS = readanysf~. at pd_suffix@
readanysf__ at pd_suffix@_SOURCES = \
Fifo.cpp\
Input.cpp\
InputFile.cpp\
InputStream.cpp\
ReadRaw.cpp\
Readsf.cpp\
main.cpp\
ReadMad.cpp\
ReadVorbis.cpp \
ReadFlac.cpp
#readanysf__pd_linux_LDFLAGS = -L/usr/local/lib/pd/flext/
#### IMPORTANT!!! FLEXT_LIBS HAS TO CUM FIRST
readanysf__ at pd_suffix@_LDADD = \
@FLEXT_LIBS@ @PTHREAD_LIBS@ @SRC_LIBS@ @FLEXT_LIBS@ @VORBIS_LIBS@ @MAD_LIBS@ @FLC_LIBS@
subdir = src
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
bin_PROGRAMS = readanysf~. at pd_suffix@$(EXEEXT)
PROGRAMS = $(bin_PROGRAMS)
am_readanysf__ at pd_suffix@_OBJECTS = Fifo.$(OBJEXT) Input.$(OBJEXT) \
InputFile.$(OBJEXT) InputStream.$(OBJEXT) ReadRaw.$(OBJEXT) \
Readsf.$(OBJEXT) main.$(OBJEXT) ReadMad.$(OBJEXT) \
ReadVorbis.$(OBJEXT) ReadFlac.$(OBJEXT)
readanysf__ at pd_suffix@_OBJECTS = $(am_readanysf__ at pd_suffix@_OBJECTS)
readanysf__ at pd_suffix@_DEPENDENCIES =
readanysf__ at pd_suffix@_LDFLAGS =
DEFS = @DEFS@
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@AMDEP_TRUE at DEP_FILES = ./$(DEPDIR)/Fifo.Po ./$(DEPDIR)/Input.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/InputFile.Po ./$(DEPDIR)/InputStream.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/ReadFlac.Po ./$(DEPDIR)/ReadMad.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/ReadRaw.Po ./$(DEPDIR)/ReadVorbis.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/Readsf.Po ./$(DEPDIR)/main.Po
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
CXXLD = $(CXX)
CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
-o $@
DIST_SOURCES = $(readanysf__ at pd_suffix@_SOURCES)
DIST_COMMON = Makefile.am Makefile.in
SOURCES = $(readanysf__ at pd_suffix@_SOURCES)
all: all-am
.SUFFIXES:
.SUFFIXES: .cpp .o .obj
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4)
cd $(top_srcdir) && \
$(AUTOMAKE) --foreign src/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
install-binPROGRAMS: $(bin_PROGRAMS)
@$(NORMAL_INSTALL)
$(mkinstalldirs) $(DESTDIR)$(bindir)
@list='$(bin_PROGRAMS)'; for p in $$list; do \
p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
if test -f $$p \
; then \
f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) $$p $(DESTDIR)$(bindir)/$$f"; \
$(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) $$p $(DESTDIR)$(bindir)/$$f; \
else :; fi; \
done
uninstall-binPROGRAMS:
@$(NORMAL_UNINSTALL)
@list='$(bin_PROGRAMS)'; for p in $$list; do \
f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
echo " rm -f $(DESTDIR)$(bindir)/$$f"; \
rm -f $(DESTDIR)$(bindir)/$$f; \
done
clean-binPROGRAMS:
-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
readanysf~. at pd_suffix@$(EXEEXT): $(readanysf__ at pd_suffix@_OBJECTS) $(readanysf__ at pd_suffix@_DEPENDENCIES)
@rm -f readanysf~. at pd_suffix@$(EXEEXT)
$(CXXLINK) $(readanysf__ at pd_suffix@_LDFLAGS) $(readanysf__ at pd_suffix@_OBJECTS) $(readanysf__ at pd_suffix@_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT) core *.core
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/Fifo.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/Input.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/InputFile.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/InputStream.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ReadFlac.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ReadMad.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ReadRaw.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ReadVorbis.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/Readsf.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/main.Po at am__quote@
distclean-depend:
-rm -rf ./$(DEPDIR)
.cpp.o:
@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<
.cpp.obj:
@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CXXCOMPILE) -c -o $@ `cygpath -w $<`
CXXDEPMODE = @CXXDEPMODE@
uninstall-info-am:
ETAGS = etags
ETAGSFLAGS =
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
mkid -fID $$unique
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)$$tags$$unique" \
|| $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& cd $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) $$here
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
top_distdir = ..
distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
distdir: $(DISTFILES)
@list='$(DISTFILES)'; for file in $$list; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkinstalldirs) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(PROGRAMS)
installdirs:
$(mkinstalldirs) $(DESTDIR)$(bindir)
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f Makefile $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
distclean: distclean-am
distclean-am: clean-am distclean-compile distclean-depend \
distclean-generic distclean-tags
dvi: dvi-am
dvi-am:
info: info-am
info-am:
install-data-am:
install-exec-am: install-binPROGRAMS
install-info: install-info-am
install-man:
installcheck-am:
maintainer-clean: maintainer-clean-am
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic
uninstall-am: uninstall-binPROGRAMS uninstall-info-am
.PHONY: GTAGS all all-am check check-am clean clean-binPROGRAMS \
clean-generic distclean distclean-compile distclean-depend \
distclean-generic distclean-tags distdir dvi dvi-am info \
info-am install install-am install-binPROGRAMS install-data \
install-data-am install-exec install-exec-am install-info \
install-info-am install-man install-strip installcheck \
installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic tags uninstall uninstall-am \
uninstall-binPROGRAMS uninstall-info-am
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
--- NEW FILE: Input.cpp ---
#include "Input.h"
#include <iostream.h>
Input::Input ()
{
fd = 0;
format = -1;
verbosity = 1;
recover=false;
}
Input::~Input ()
{
}
int
Input::Open (const char *pathname)
{
return -1;
}
int
Input::Close ()
{
return -1;
}
int
Input::Read (void *buf, unsigned int count)
{
return -1;
}
long
Input::SeekSet (long offset)
{
return -1;
}
long
Input::SeekCur (long offset)
{
return -1;
}
long
Input::SeekEnd (long offset)
{
return -1;
}
float
Input::get_cachesize ()
{
return 0.0;
}
--- NEW FILE: Readsf.cpp ---
/*
* readanysf~ external for pd.
*
* Copyright (C) 2003 August Black
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Readsf.cpp
*/
#include "Readsf.h"
Readsf::Readsf( )
{
}
Readsf::Readsf( Input *input )
{
in = input;
num_channels = 1;
samplerate = 44100;
lengthinseconds =0;
}
Readsf::~Readsf()
{
}
int Readsf::Decode(float *buffer, int size) {
if (CHUNKSIZE > (unsigned int)size) return 0;
for(unsigned int c=0;c< CHUNKSIZE;c++) {
buffer[c] = 0.0;
}
return CHUNKSIZE;
}
bool Readsf::Initialize()
{
//printf( "%s\n", filename);
return false;
}
bool Readsf::Rewind() {
return false;
}
bool Readsf::PCM_seek(long bytes) {
return false;
}
bool Readsf::TIME_seek(double seconds) {
return false;
}
--- NEW FILE: InputStream.cpp ---
#include "InputStream.h"
#include <iostream> // cout, cerr
#include <string> // strcpy, etc.
using namespace std;
int receive (int fd, unsigned char *rcvbuffer, int size) {
fd_set set;
struct timeval tv;
int ret = -1;
int selret = -1;
tv.tv_sec = 1;
tv.tv_usec = 500;
FD_ZERO(&set);
FD_SET(fd, &set);
selret= select(fd +1, &set, NULL, NULL, &tv);
if ( selret > 0 ) {
// we can now be certain that ret will return something.
ret = recv (fd, rcvbuffer, size, 0);
if (ret < 0 ) {
cerr << "InputStream:: receive error" << endl;
return -1;
}
return ret;
} else if ( selret == -1 ){
cerr << "InputStream:: receive: select timed out, returned "<< selret << endl;
return -1;
}
// return zero...means keep on selecting
return 0;
}
void * fill_infifo (void *zz) {
int ret, wret, last_type, last_state;
unsigned char tmp[SOCKET_READSIZE];
InputStream *instream = (InputStream *) zz;
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &last_type);
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &last_state);
pthread_mutex_lock (instream->get_mutex ());
instream->set_threaded(true);
pthread_cond_signal (instream->get_condition ());
pthread_mutex_unlock (instream->get_mutex ());
//cout << "signalled parent thread" << endl;
while ( 1 ) {
while (instream->get_fifo()->FreeSpace() > SOCKET_READSIZE + 576) {
// it's possible to hang here, watch this
if ( instream->get_quit() ) break;
ret = receive (instream->get_fd() , tmp, SOCKET_READSIZE);
if (ret > 0){
wret = instream->get_fifo()->Write ((void *) tmp, ret * sizeof (unsigned char));
} else if ( ret == -1){
// got -1 on recieve. ...this means select failed and there is no data
cerr << "InputStream:: fill_infifo: select failed, our socket must have died" << endl;
if ( instream->get_recover() ) {
cout << "InputStream:: try to reconnect to server..." << endl;
if ( instream->socket_connect () < 0 ) {
cout << "InputStream:: tried to recover stream but socket connect failed" <<endl;
break;
}
} else {
break;
}
} else {
// got 0?? on recieve. ...select timed out, cause there wasn't any data
//cerr << "InputStream: fill_infifo: select timed out, no data. ret = " << ret << endl;
// keep on truckin' until we get a select and recv that sticks
}
}
if ( instream->get_quit() ) break;
//cerr << "InputStream: fifo is full" << endl;
pthread_mutex_lock (instream->get_mutex ());
pthread_cond_wait (instream->get_condition (), instream->get_mutex ());
pthread_mutex_unlock (instream->get_mutex ());
}
instream->set_threaded(false);
return NULL;
}
InputStream::InputStream () {
fd = 0;
format = -1;
threaded = false;
port = 0;
infifo = new Fifo( STREAM_FIFOSIZE );
quit = false;
recover = false;
verbosity = 1;
pthread_mutex_init(&mut, 0);
pthread_cond_init(&cond, 0);
}
InputStream::~InputStream () {
quit = true;
void *status;
if (threaded )
{
//cout << "canceling thread" << endl;
pthread_cond_signal ( &cond );
//pthread_cancel( childthread );
pthread_join( childthread, &status);
threaded = -1;
//cout << "thread canceled" << endl;
}
delete infifo;
}
// Open() returns the file type, either WAV, MP3, OGG, etc. see input.h
// this is a blocking call, in order to use the open command we need
// to figure out the format (ogg, mp3, etc). this has to block.
int InputStream::Open (const char *pathname) {
int rettype, thret;
filename = pathname;
if (verbosity > 1)
cout << "trying to open a socket connection" << endl;
SetUrl (pathname);
rettype = socket_connect( ); //hostname, mountpoint, port );
if (rettype < 0) { // couldn't connect or got a bad filetype
cerr << "InputStream:: Couldn't connect or got a bad filetype" <<endl;
return -1;
}
// start thread here to fill infifo
//cout << "creating thread" << endl;
thret = pthread_create(&childthread, NULL, fill_infifo, (void *)this);
if ( thret!= 0 )
return -1;
//wait for thread to be created.
pthread_mutex_lock( &mut );
while ( !threaded )
pthread_cond_wait( &cond, &mut );
pthread_mutex_unlock( &mut );
//cout << "threaded = " << threaded << "rettype = " << rettype << endl;
while ( get_fifo()->UsedSpace () < (unsigned int)(STREAM_FIFOSIZE / 2) ) {
usleep(100); // we need to wait here for some of the input buffer to fill.
//cout << "waiting for HTTP buffer to fill " << get_fifo()->UsedSpace () <<endl;
}
/* if ( rettype == FORMAT_HTTP_VORBIS) {
cout << "---------->Lets try to flush fifo and fill again" <<endl;
get_fifo()->Flush();
pthread_cond_signal ( &cond );
while ( get_fifo()->UsedSpace () < (unsigned int)(8500*2) ) {
usleep(1000); // we need to wait here for some of the input buffer to fill.
cout << "waiting for HTTP buffer to fill " << get_fifo()->UsedSpace () <<endl;
}
}*/
return rettype;
}
int InputStream::Close () {
// returns zero on success, or -1 if an error occurred
return sys_closesocket (fd);
}
int InputStream::Read (void *buf, unsigned int count) {
//if (quit) return -1; // return negative if the childthread exits
//and sets quit true
infifo->Read( buf , count);
pthread_cond_signal ( &cond );
return count;
}
long InputStream::SeekSet (long offset) {
return -1;
}
long InputStream::SeekCur (long offset) {
return -1;
}
long InputStream::SeekEnd (long offset) {
return -1;
}
int InputStream::get_line( char * str, int sock, int maxget) {
int i = 0;
while(i < maxget - 1) {
if ( recv(sock, str + i, 1, 0) <= 0 ) {
cerr << "InputStream : could not read from socket" << endl;
sys_closesocket(sock);
return (-1);
}
if ( str[i] == '\n' )
break;
if( str[i] == 0x0A) /* leave at end of line */
break;
if ( str[i] != '\r' )
i++;
}
str[i] = '\0';
return i;
}
// connect to shoutcast server
int InputStream::socket_connect ( ) {
struct sockaddr_in server;
struct hostent *hp;
int flags;
// variables used for communication with server
string strtmp; // tmp string for manipulating server strings
string line, parsed; // string for parsing x-audicast vars
char strret[STRBUF_SIZE]; // returned string from server
fd_set fdset;
struct timeval tv;
int relocate = false;
std::string::size_type ret;
fd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (fd < 0) {
if (verbosity > 0)
cerr << "InputStream: internal error while attempting to open socket" << endl;
return (-1);
}
//connect socket using hostname
server.sin_family = AF_INET;
hp = gethostbyname (hostname.c_str ());
if (hp == NULL) {
if (verbosity > 0)
cerr << "InputStream:: bad host?" << endl;
sys_closesocket (fd);
return (-1);
}
memcpy ((char *) &server.sin_addr, (char *) hp->h_addr, hp->h_length);
// assign client port number
server.sin_port = htons ((unsigned short) port);
flags = fcntl( fd, F_GETFL, 0);
fcntl( fd, F_SETFL, FNDELAY); // make this socket's calls non-blocking
// fcntl( fd, F_SETFL, flags | O_NONBLOCK);
if (connect( fd, (struct sockaddr *) &server, sizeof(server) ) == -1 && errno != EINPROGRESS) {
/*
* If non-blocking connect() couldn't finish, it returns
* EINPROGRESS. That's OK, we'll take care of it a little
* later, in the select(). But if some other error code was
* returned there's a real problem...
*/
sys_closesocket (fd);
return(-1);
} else {
//cout << " error is EINPROGRESS " << endl;
FD_ZERO (&fdset);
FD_SET (fd, &fdset);
tv.tv_sec = 1; /* seconds */
tv.tv_usec = 0; /* microseconds */
// you want to do the select on the WRITEablity of the socket, HTTP expects a get
// command, so make sure to pass args to both read and write fdset
switch (select( fd+1 , &fdset, &fdset, NULL, &tv) ) {
/*
* select() will return when the socket is ready for action,
* or when there is an error, or the when timeout specified
* using tval is exceeded without anything becoming ready.
*/
case 0: // timeout
//do whatever you do when you couldn't connect
cout << "InputStream:: connect timed out, bailing..." <<endl;
sys_closesocket (fd);
return (-1);
break;
case -1: // error
cout << "InputStream:: connection error, bailing..." <<endl;
sys_closesocket (fd);
return (-1);
break;
default: // your file descriptor is ready...
fcntl( fd, F_SETFL, flags);
break;
}
}
// build up stuff we need to send to server
// should change it to send GET and then read the header until
// it recieves "\n\n", and then parse the header
strtmp = "GET /" + mountpoint + " HTTP/1.0 \r\nHost: " + hostname +
"\r\nUser-Agent: Readanysf~ 0.5\r\nAccept: */*\r\n\r\n";
if (verbosity > 2)
cout << "sending...." << strtmp << endl;
if (send (fd, strtmp.c_str (), strtmp.length (), 0) < 0)
{
if (verbosity > 0)
cerr << "InputStream:: could not contact server... " << endl;
return (-1);
}
get_line( strret , fd , STRBUF_SIZE ) ;
strtmp = strret;
//cout << strtmp << endl;
ret = strtmp.find ("HTTP", 0);
if (ret != string::npos) { /* seems to be IceCast server */
ret = strtmp.find ("302", 0);
if (ret != string::npos) {
if (verbosity > 0)
cerr << "InputStream::need to relocate...not implemented yet, bailing" << endl;
relocate = true;
return (-1);
}
ret = strtmp.find ("200", 0);
if (ret == string::npos) {
if (verbosity > 0)
cerr << "InputStream : cannot connect to the (default) stream" << endl;
sys_closesocket (fd);
return (-1);
}
if (verbosity > 2)
cerr << "everything seems to be fine, now lets parse the server strings" << endl;
// go through header 10 times, line by line. this should be enough.
// we only need the Content-Type for checking if it's mp3 or vorbis
for (int i = 0; i < 10; i++)
{
get_line( strret , fd , STRBUF_SIZE ) ;
line = strret;
//cout << " Got line: " << line << endl;
// we could probable parse the Server flag for icecast 1
// or 2
// server type, but that is more trouble than what its
// worth
parsed = ParseHttp (line, "Server");
if (!parsed.empty ())
if (verbosity > 1)
cout << "server" << parsed << endl;
parsed = ParseHttp (line, "Content-Type");
if (!parsed.empty ()) {
std::string::size_type n;
if (verbosity > 1) cout << "Content-Type " << parsed << endl;
n = parsed.find ("ogg");
if (n != string::npos) {
if (verbosity > 1)
cout << "we have an ogg vorbis stream" << endl;
format = FORMAT_HTTP_VORBIS;
break; // found what we were looking for
}
n = parsed.find ("mpeg");
if (n != string::npos){
if (verbosity > 1)
cout << "we have an Mp3 stream" << endl;
format = FORMAT_HTTP_MP3;
break; // found what we were looking for
}
}
}
} else {
//cout << "not HTTP, could be ICY for shoutcast" << endl;
ret = strtmp.find ("ICY 200 OK", 0);
if (ret != string::npos) { /* seems to be IceCast server */
// we are only interested in mp3 or ogg content type
cout << "we have an ICY Mp3 stream" << endl;
format = FORMAT_HTTP_MP3;
} else {
cout << "Neither a Shoutcast or Icecast stream, hafta bail." << endl;
return -1;
}
}
return (format);
}
// parses string "str" for the item "parse", if found return the part of
// "str" after the ":" ex.
string InputStream::ParseHttp (string str, string parse) {
std::string::size_type ret;
ret = str.find (parse, 0);
if (ret != string::npos) {
return str.substr (parse.length () + 1, str.length () - parse.length ());
}
return "";
}
int InputStream::SetUrl (const char *url) {
string strtmp = url;
std::string::size_type p1, p2, tmp;
tmp = strtmp.find ("http://");
if (tmp < 0 || tmp > strtmp.length ())
return 0;
tmp = tmp + 7;
strtmp = strtmp.substr (tmp, strtmp.length () - tmp);
p2 = strtmp.find ("/", 0);
if (p2 < 0 || p2 > strtmp.length ()) {
p2 = strtmp.length();
//cout << "didn't find the / in the url" <<endl;
p1 = strtmp.find (":");
if (p1 < 0 || p1 > strtmp.length ()) {
port = 80; // set port to default 80
hostname = strtmp;
mountpoint = " "; // send blank mntpoint
} else {
// found the ":", setting port number
port = atoi (strtmp.substr (p1 + 1, p2 - p1 -1).c_str ());
hostname = strtmp.substr (0, p1);
mountpoint = " "; // send blank mntpoint
}
return 1; // didn't find the / in the URL
}
p1 = strtmp.find (":");
if (p1 < 0 || p1 > strtmp.length ()) {
// didn't find a ":", that
//
// means there's no port
port = 80; // set port to default 8000
hostname = strtmp.substr (0, p2);
mountpoint = strtmp.substr (p2 + 1, strtmp.length () - p2);
if (verbosity > 1)
cerr << "port is: default " << port << endl;
} else {
// found the ":", setting port number
port = atoi (strtmp.substr (p1 + 1, p2 - p1 - 1).c_str ());
hostname = strtmp.substr (0, p1);
mountpoint = strtmp.substr (p2 + 1, strtmp.length () - p2);
}
if (verbosity > 2 ) {
cout << "port: " << port << endl;
cout << "hostname: " << hostname << endl;
cout << "mount: " << mountpoint << endl;
}
return 1;
}
float InputStream::get_cachesize() {
return (float)infifo->UsedSpace();
}
// ~ parsed = ParseHttp( line, "x-audiocast-location" ) ;
// ~ if ( !parsed.empty()) cout << parsed << endl;
// ~ parsed = ParseHttp( line, "x-audiocast-admin" ) ;
// ~ if ( !parsed.empty()) cout << parsed << endl;
// ~ parsed = ParseHttp( line, "x-audiocast-server-url" ) ;
// ~ if ( !parsed.empty()) cout << parsed << endl;
// ~ parsed = ParseHttp( line, "x-audiocast-mount" ) ;
// ~ if ( !parsed.empty()) cout << parsed << endl;
// ~ parsed = ParseHttp( line, "x-audiocast-name" ) ;
// ~ if ( !parsed.empty()) cout << parsed << endl;
// ~ parsed = ParseHttp( line, "x-audiocast-description" ) ;
// ~ if ( !parsed.empty()) cout << parsed << endl;
// ~ parsed = ParseHttp( line, "x-audiocast-url:http" ) ;
// ~ if ( !parsed.empty()) cout << parsed << endl;
// ~ parsed = ParseHttp( line, "x-audiocast-genre" ) ;
// ~ if ( !parsed.empty()) cout << parsed << endl;
// ~ parsed = ParseHttp( line, "x-audiocast-bitrate" ) ;
// ~ if ( !parsed.empty()) cout << parsed << endl;
// ~ parsed = ParseHttp( line, "x-audiocast-public" ) ;
// ~ if ( !parsed.empty()) cout << parsed << endl;
--- NEW FILE: ReadVorbis.cpp ---
/*
* readanysf~ external for pd.
*
* Copyright (C) 2003 August Black
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* ReadVorbis.cpp || much code (C) by Olaf Matthes
* http://www.akustische-kunst.org/puredata/shout/shout.html
*/
#ifdef READ_VORBIS
#include "ReadVorbis.h"
//#include <m_pd.h>
#include <iostream>
using namespace std;
ReadVorbis::ReadVorbis( Input *input) {
in = input;
seekable = false;
callbacks.read_func = read_func;
callbacks.seek_func = seek_func;
callbacks.close_func = close_func;
callbacks.tell_func = tell_func;
}
ReadVorbis::~ReadVorbis(){
if ( ov_clear(&vf) != 0)
cout << "ReadVorbis::couldn't deconstruct the vorbis file reader" << endl;
//if (fp != NULL) { //don't know why, but this will cause a segfault
// fclose(fp);
//}
}
bool ReadVorbis::Initialize( ) {
vorbis_info *vi;
if ( in == NULL ) {
return 0;
}
if ( in->get_format() == FORMAT_HTTP_VORBIS ) {
seekable = false;
} else
seekable = true;
int err = ov_open_callbacks( (void *)in, &vf, NULL, 0, callbacks);
if( err < 0 ) {
cout << "ReadVorbis:: does not appear to be an Ogg bitstream.\n" << endl;
switch (err) {
case OV_EREAD:
cout << "ReadVorbis:: read from media retuned an error" << endl;
break;
case OV_ENOTVORBIS:
cout << "ReadVorbis:: bistream is not vorbis data" << endl;
break;
case OV_EVERSION:
cout << "ReadVorbis:: vorbis version mismatch" << endl;
break;
case OV_EBADHEADER:
cout << "ReadVorbis:: invalid vorbis btistream header" << endl;
break;
case OV_EFAULT:
cout << "ReadVorbis:: internal logic fault" << endl;
break;
default:
cout << "ReadVorbis:: general error on ov_open_callbacks" << endl;
break;
}
return false;
}
vi=ov_info(&vf,-1);
samplerate = (double)vi->rate;
num_channels = vi->channels;
if ( in->get_format() == FORMAT_HTTP_VORBIS )
lengthinseconds = 0.0;
else
lengthinseconds = (double)ov_time_total(&vf, -1);
//cout << "ReadVorbis: opening url: [%s] %ld (Hz), %d chan(s)",
// fullurl, vi->rate, vi->channels);
return true;
}
int ReadVorbis::Decode(float *buffer, int size) {
long ret = 0;
int current_section;
float **buftmp;
int x=0;
if (CHUNKSIZE > (unsigned int)size) return 0;
ret = ov_read_float(&vf, &buftmp , CHUNKSIZE, ¤t_section);
if (ret == 0 ) {
// This means it is a definite end of file, lets return zero here.
return 0;
} else if (ret <= 0) {
switch (ret) {
case OV_HOLE:
cout << "ReadVorbis:: there was an interruption in the data. " << endl;
cout << "one of: garbage between pages, loss of sync followed" <<
" by recapture, or a corrupt page" << endl;
break;
case OV_EBADLINK:
cout << "ReadVorbis:: an invalid stream section was supplied " <<
"to libvorbisfile, or the requested link is corrupt" << endl;
break;
default:
cout << "ReadVorbis:: unknown error on ov_read_float" << endl;
break;
}
for(int j = 0; j < 1024; j++) {
buffer[x++] = 0.0;
}
return 512;
} else {
// we should check here to see if ret is larger than size!
for(int j = 0; j < ret; j++) {
buffer[x++] = buftmp[0][j];
if (num_channels == 2)
buffer[x++] = buftmp[1][j];
}
}
//cout << "x %d", x);
return x; //ret;
}
size_t ReadVorbis::read_func(void *ptr, size_t size, size_t nmemb, void *datasource) {
Input * tmpin = ( Input *)datasource;
unsigned int get = size*nmemb;
size_t ret;
// cout << "ReadVorbis:: calling read function" << endl;
ret = tmpin->Read( ptr, get);
//cout << "read from fifo, get %d, ret %d, size %d, nmemb %d",
//get, ret,size,nmemb );
return ret;//size*nmemb;
}
int ReadVorbis::seek_func(void *datasource, ogg_int64_t offset, int whence) {
// InputStream will always return -1
Input * tmpin = ( Input *)datasource;
switch ( whence ) {
case SEEK_SET:
return tmpin->SeekSet( offset );
break;
case SEEK_CUR:
return tmpin->SeekCur( offset );
break;
case SEEK_END:
return tmpin->SeekEnd( offset );
break;
default:
return -1;
break;
}
}
int ReadVorbis::close_func(void *datasource) {
cout << "ReadVorbis:: calling close function" << endl;
//ov_clear(&vf);
//return tmpin->Close();
return 0;
}
long ReadVorbis::tell_func(void *datasource) {
// InputStream will always return -1
Input * tmpin = ( Input *)datasource;
return tmpin->SeekCur( 0 );
}
bool ReadVorbis::Rewind() {
ov_pcm_seek(&vf, 0);
return true; // need to return true here for fill_buffer of main.cpp
}
bool ReadVorbis::PCM_seek(long bytes) {
int ret = ov_pcm_seek(&vf, bytes);
if ( ret == 0)
return true;
else {
switch (ret) {
case OV_ENOSEEK:
cout << "ReadVorbis:: stream not seekable" << endl;
break;
case OV_EINVAL:
ret = ov_pcm_seek(&vf, 0);
if (ret == 0)
return true;
else
cout << "ReadVorbis:: invalid argument" << endl;
break;
case OV_EREAD:
cout << "ReadVorbis:: read returned an error" << endl;
break;
case OV_EOF:
cout << "ReadVorbis:: End of File" << endl;
break;
case OV_EBADLINK:
cout << "ReadVorbis:: invalid stream section" << endl;
break;
default:
cout << "ReadVorbis:: some other seek error PCM_seek" << endl;
break;
}
return false;
}
}
bool ReadVorbis::TIME_seek(double seconds) {
int ret = ov_time_seek(&vf, seconds);
if ( ret == 0)
return true;
else {
switch (ret) {
case OV_ENOSEEK:
cout << "ReadVorbis:: stream not seekable" << endl;
break;
case OV_EINVAL:
cout << "ReadVorbis:: invalid argument" << endl;
break;
case OV_EREAD:
cout << "ReadVorbis:: read returned an error" << endl;
break;
case OV_EOF:
cout << "ReadVorbis:: End of File" << endl;
break;
case OV_EBADLINK:
cout << "ReadVorbis:: invalid stream section" << endl;
break;
default:
cout << "ReadVorbis:: some other seek error Time_seek" << endl;
break;
}
return false;
}
}
#endif
--- NEW FILE: InputFile.cpp ---
#include "InputFile.h"
#include <iostream.h>
InputFile::InputFile () {
fd = 0;
format = -1;
recover = false;
}
InputFile::~InputFile () {
}
// returns the file type, either WAV, MP3, OGG, etc. see input.h
int InputFile::Open (const char *pathname) {
char buf[18];
filename = pathname;
fd = open (pathname, O_RDONLY);
if (fd == -1) {
// error opening the file, no dice
return -1;
}
int bytesread = read (fd, buf, 16);
if (bytesread < 4) {
// fill is too fucking small dude
close (fd);
return -1;
}
if (!strncmp (buf, ".snd", 4))
{
//rewind the stream
if ((lseek (fd, 0, SEEK_SET)) == -1)
return -1;
return format = FORMAT_NEXT; //, bigendian = 1;
}
else if (!strncmp (buf, "dns.", 4))
{
//rewind the stream
if ((lseek (fd, 0, SEEK_SET)) == -1)
return -1;
return format = FORMAT_NEXT; //, bigendian = 0;
}
else if (!strncmp (buf, "RIFF", 4))
{
if (bytesread < 12 || strncmp (buf + 8, "WAVE", 4))
{
cout << "bad header ?" << endl;
return -1;
}
//rewind the stream
if ((lseek (fd, 0, SEEK_SET)) == -1)
return -1;
return format = FORMAT_WAVE; //, bigendian = 0;
}
else if (!strncmp (buf, "FORM", 4))
{
if (bytesread < 12 || strncmp (buf + 8, "AIFF", 4))
return -1; //goto badheader;
//rewind the stream
if ((lseek (fd, 0, SEEK_SET)) == -1)
return -1;
return format = FORMAT_AIFF; //, bigendian = 1;
}
else if (!strncmp (buf, "OggS", 4)) {
//rewind the stream
if ((lseek (fd, 0, SEEK_SET)) == -1)
return -1;
#ifdef READ_VORBIS
return format = FORMAT_VORBIS;
#else
return -1;
#endif
}
else if (!strncmp (buf, "ID3", 3))
{
//rewind the stream
if ((lseek (fd, 0, SEEK_SET)) == -1)
return -1;
#ifdef READ_MAD
return format = FORMAT_MAD;
#else
return -1;
#endif
}
else if (!strncasecmp (buf, "FLAC", 4))
{
// } else if( !strncasecmp(thefile+strlen(thefile)-4,".fla",4) ) {
//rewind the stream
if ((lseek (fd, 0, SEEK_SET)) == -1)
return -1;
#ifdef READ_FLAC
return format = FORMAT_FLAC;
#else
return -1;
#endif
}
else
{
unsigned int sync;
sync = (unsigned char) buf[0];
sync = sync << 3;
sync |= ((unsigned char) buf[1] & 0xE0) >> 5;
if (sync == 0x7FF)
{
//rewind the stream
if ((lseek (fd, 0, SEEK_SET)) == -1)
return -1;
#ifdef READ_MAD
return format = FORMAT_MAD;
#else
return -1;
#endif
}
else if (!strncasecmp
(pathname + strlen (pathname) - 4, ".mp3", 4))
{
//trust that its mp3
//rewind the stream
if ((lseek (fd, 0, SEEK_SET)) == -1)
return -1;
cout << "doesnt seem like its an mp3, but if you say so" << endl;
#ifdef READ_MAD
return format = FORMAT_MAD;
#else
return -1;
#endif
}
}
return -1;
}
int
InputFile::Close ()
{
return close (fd);
}
int
InputFile::Read (void *buf, unsigned int count)
{
return read (fd, buf, count);
}
long
InputFile::SeekSet (long offset)
{
return lseek (fd, offset, SEEK_SET);
}
long
InputFile::SeekCur (long offset)
{
return lseek (fd, offset, SEEK_CUR);
}
long
InputFile::SeekEnd (long offset)
{
return lseek (fd, offset, SEEK_END);
}
--- NEW FILE: Makefile.am ---
INCLUDES =\
-I/usr/local/include/ -I/usr/local/lib/pd/flext/ -I../include/
CFLAGS = \
@FLEXT_CFLAGS@ @VORBIS_CFLAGS@ @MAD_CFLAGS@ @FLC_CFLAGS@
CXXFLAGS = \
@FLEXT_CFLAGS@ @VORBIS_CFLAGS@ @MAD_CFLAGS@ @FLC_CFLAGS@
bin_PROGRAMS = readanysf~. at pd_suffix@
readanysf__ at pd_suffix@_SOURCES = \
Fifo.cpp\
Input.cpp\
InputFile.cpp\
InputStream.cpp\
ReadRaw.cpp\
Readsf.cpp\
main.cpp\
ReadMad.cpp\
ReadVorbis.cpp \
ReadFlac.cpp
#readanysf__pd_linux_LDFLAGS = -L/usr/local/lib/pd/flext/
#### IMPORTANT!!! FLEXT_LIBS HAS TO CUM FIRST
readanysf__ at pd_suffix@_LDADD = \
@FLEXT_LIBS@ @PTHREAD_LIBS@ @SRC_LIBS@ @FLEXT_LIBS@ @VORBIS_LIBS@ @MAD_LIBS@ @FLC_LIBS@
--- NEW FILE: simple.pd ---
#N canvas 119 113 595 349 10;
#X obj 150 223 dac~;
#X msg 149 123 play;
#X msg 232 123 stop;
#X msg 187 123 pause;
#X obj 29 25 hsl 100 15 0 15 0 0 empty empty empty -2 -6 0 8 -44926
-1 -1 661 1;
#X floatatom 95 40 5 0 0 0 - - -;
#X msg 26 45 speed \$1;
#X msg 170 41 loop \$1;
#X obj 170 25 tgl 15 0 empty empty empty 0 -6 0 8 -44926 -1 -1 0 1
;
#X obj 214 282 nbx 4 10 -1e+37 1e+37 0 0 empty empty empty 0 -6 0 10
-241291 -1 -1 172.072 256;
#X obj 260 271 nbx 6 10 -1e+37 1e+37 0 0 empty empty empty 0 -6 0 10
-260818 -1 -1 0 256;
#X obj 307 255 nbx 5 10 -1e+37 1e+37 0 0 empty empty empty 0 -6 0 10
-260241 -1 -1 44100 256;
#X obj 353 242 nbx 7 12 -1e+37 1e+37 0 0 empty empty empty 0 -6 0 10
-259729 -1 -1 34273 256;
#X msg 21 269 \; pd dsp 1;
#X obj 21 244 loadbang;
#X obj 149 180 readanysf~;
#X obj 53 163 r rany;
#X obj 26 72 s rany;
#X obj 170 67 s rany;
#X msg 253 50 recover 1;
#N canvas 381 279 570 425 testfiles 0;
#X msg 308 151 open Schnucki.wav;
#X msg 42 111 open http://fro.at:8008/24k;
#X msg 308 132 open Schnucki.ogg;
#X msg 308 112 open Schnucki.mp3;
#X obj 43 372 s rany;
#X msg 42 131 open http://66.28.68.70:8000/;
#X msg 43 151 open http://212.23.57.33:8010;
#X msg 308 172 open Schnucki.fla;
#X msg 309 191 open Schnucki.aif;
#X text 301 85 some test files;
#X text 42 87 open some test streams;
#X connect 0 0 4 0;
#X connect 1 0 4 0;
#X connect 2 0 4 0;
#X connect 3 0 4 0;
#X connect 5 0 4 0;
#X connect 6 0 4 0;
#X connect 7 0 4 0;
#X connect 8 0 4 0;
#X restore 389 31 pd testfiles;
#N canvas 0 22 450 300 testseek 0;
#X msg 145 167 pcm_seek \$1;
#X floatatom 145 147 5 0 0 0 - - -;
#X obj 145 192 s rany;
#X floatatom 149 60 5 0 0 0 - - -;
#X obj 149 99 s rany;
#X msg 149 77 time_seek \$1;
#X obj 184 147 * 44100;
#X msg 145 126 13;
#X msg 149 41 13;
#X obj 204 124 f;
#X obj 208 102 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
-1;
#X floatatom 240 100 5 0 0 0 - - -;
#X msg 268 130 81;
#X msg 268 155 19;
#X connect 0 0 2 0;
#X connect 1 0 6 0;
#X connect 3 0 5 0;
#X connect 5 0 4 0;
#X connect 6 0 0 0;
#X connect 7 0 1 0;
#X connect 8 0 3 0;
#X connect 9 0 6 0;
#X connect 10 0 9 0;
#X connect 11 0 9 1;
#X connect 12 0 1 0;
#X connect 13 0 1 0;
#X restore 390 61 pd testseek;
#X obj 400 264 bng 15 250 50 0 empty empty empty 0 -6 0 8 -258699 -1
-1;
#X obj 214 223 route float length rate cache bang;
#X msg 413 163 open \$1;
#X obj 413 142 openpanel;
#X obj 413 123 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
-1;
#X text 409 103 Open a File on disk;
#X connect 1 0 15 0;
#X connect 2 0 15 0;
#X connect 3 0 15 0;
#X connect 4 0 5 0;
#X connect 4 0 6 0;
#X connect 6 0 17 0;
#X connect 7 0 18 0;
#X connect 8 0 7 0;
#X connect 14 0 13 0;
#X connect 15 0 0 0;
#X connect 15 1 0 1;
#X connect 15 2 23 0;
#X connect 16 0 15 0;
#X connect 19 0 18 0;
#X connect 23 0 9 0;
#X connect 23 1 10 0;
#X connect 23 2 11 0;
#X connect 23 3 12 0;
#X connect 23 4 22 0;
#X connect 24 0 15 0;
#X connect 25 0 24 0;
#X connect 26 0 25 0;
--- NEW FILE: ReadFlac.cpp.seekable ---
/*
* readanysf~ external for pd.
*
* Copyright (C) 2003,2004 August Black
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* ReadFlac.cpp
*
* much of the code comes from FLAC input plugin for Winamp3
* distributed with the flac source under the GPL
* Copyright (C) 2000,2001,2002,2003 Josh Coalson
*/
#ifdef READ_FLAC
//#include <m_pd.h>
#include "ReadFlac.h"
#include <iostream>
extern "C" {
#include "FLAC/metadata.h"
};
using namespace std;
ReadFlac::ReadFlac( Input *input ) {
in=input;
needs_seek = false;
seek_sample = 0;
samples_in_reservoir =0;
abort_flag = false;
decoder = NULL;
filelength = 0;
}
ReadFlac::~ReadFlac() {
cout << "exiting FLAC ..." << endl;
//exit(1);
cleanup();
}
bool ReadFlac::Initialize( ) {
//@@@ to be really "clean" we should go through the reader instead of directly to the file...
if(!FLAC__metadata_get_streaminfo(in->get_filename(), &streaminfo)) {
cout << "what the fuck" << endl;
return 1;
}
//length_msec = lengthInMsec();
/*cout << "FLAC:<%ihz:%ibps:%dch>",
streaminfo.data.stream_info.sample_rate,
streaminfo.data.stream_info.bits_per_sample,
streaminfo.data.stream_info.channels); //@@@ fix later
*/
samplerate = (double)streaminfo.data.stream_info.sample_rate;
num_channels = streaminfo.data.stream_info.channels;
lengthinseconds = streaminfo.data.stream_info.total_samples/samplerate;
filelength = in->SeekEnd(0);
filelength = in->SeekCur(0);
in->SeekSet(0);
decoder = FLAC__seekable_stream_decoder_new();
if(decoder == 0)
return false;
FLAC__seekable_stream_decoder_set_md5_checking(decoder, false);
FLAC__seekable_stream_decoder_set_read_callback(decoder, readCallback_);
FLAC__seekable_stream_decoder_set_seek_callback(decoder, seekCallback_);
FLAC__seekable_stream_decoder_set_tell_callback(decoder, tellCallback_);
FLAC__seekable_stream_decoder_set_length_callback(decoder, lengthCallback_);
FLAC__seekable_stream_decoder_set_eof_callback(decoder, eofCallback_);
FLAC__seekable_stream_decoder_set_write_callback(decoder, writeCallback_);
FLAC__seekable_stream_decoder_set_metadata_callback(decoder, metadataCallback_);
FLAC__seekable_stream_decoder_set_error_callback(decoder, errorCallback_);
FLAC__seekable_stream_decoder_set_client_data(decoder, this);
if(FLAC__seekable_stream_decoder_init(decoder) != FLAC__SEEKABLE_STREAM_DECODER_OK) {
cleanup();
return false;
}
if(!FLAC__seekable_stream_decoder_process_until_end_of_metadata(decoder)) {
cleanup();
return false;
}
return true;
}
int ReadFlac::Decode(float *buffer, int size) {
if(decoder == NULL)
return 0;
if(needs_seek) {
FLAC__seekable_stream_decoder_seek_absolute(decoder, seek_sample);
//cout << "seeking " << seek_sample << " samples" << endl;
needs_seek = false;
}
//while (samples_in_reservoir < 576) {
//if (samples_in_reservoir < 576) {
if(FLAC__seekable_stream_decoder_get_state(decoder) == FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM) {
cout << "FLAC: end of file" << endl;
return 0;
} else if(!FLAC__seekable_stream_decoder_process_single(decoder)) {
//ErrorCheck( FLAC__seekable_stream_decoder_get_state(decoder) );
//ErrorCheck( FLAC__seekable_stream_decoder_finish(decoder) );
//ErrorCheck( FLAC__seekable_stream_decoder_init(decoder) );
//FLAC__seekable_stream_decoder_reset(decoder);
//FLAC__seekable_stream_decoder_flush(decoder);
cout << "FLAC: no process single " << endl;
//break;
//exit(1);
//return 0;
//return samples_in_reservoir;
}
//}
int n = samples_in_reservoir; // > 576 ? samples_in_reservoir: 576;
const unsigned channels = streaminfo.data.stream_info.channels;
if(samples_in_reservoir == 0) {
//cout << "FLAC: reservoir is empty" << endl;
return 0;
} else {
//const unsigned bits_per_sample = streaminfo.data.stream_info.bits_per_sample;
//const unsigned bytes_per_sample = (bits_per_sample+7)/8;
//const unsigned sample_rate = streaminfo.data.stream_info.sample_rate;
unsigned i;
//16 > WHDR2 + 2 ? 16 : WHDR2 + 2
//unsigned delta;
for(i = 0; i < n*channels; i++)
buffer[i] = (float) ( reservoir[i]/ 32768.0 );
samples_in_reservoir = 0;
//const int bytes = n * channels * bytes_per_sample;
}
//if(eof)
//return 0;
return n*channels; //1;
}
bool ReadFlac::Rewind() {
needs_seek = true;
seek_sample = 0;
samples_in_reservoir = 0;
//ErrorCheck( FLAC__seekable_stream_decoder_get_state(decoder) );
//FLAC__seekable_stream_decoder_seek_absolute(decoder, 0);
return true;
}
bool ReadFlac::PCM_seek(long bytes) {
if ( bytes < (long) streaminfo.data.stream_info.total_samples ) {
needs_seek = true;
//bool ret = FLAC__seekable_stream_decoder_seek_absolute(decoder, bytes);
//if (ret) {
//samples_in_reservoir = 0;
//FLAC__seekable_stream_decoder_flush(decoder);
//cout << "successfull seeking" << endl;
//return true;
// }else {
//cout << "UNsuccessfull seeking" << endl;
//return false;
//}
seek_sample = bytes;
return true;
} else {
cout << " GOT HERE " << endl;
return false;
}
}
bool ReadFlac::TIME_seek(double seconds) {
//lengthInMsec();
if ( seconds < lengthinseconds ) {
//cout << "FLAC: time seek" << endl;
needs_seek = true;
seek_sample = (FLAC__uint64)(seconds * streaminfo.data.stream_info.sample_rate);
return true;
} else {
return false;
}
}
void ReadFlac::cleanup()
{
if(decoder) {
FLAC__seekable_stream_decoder_finish(decoder);
FLAC__seekable_stream_decoder_delete(decoder);
decoder = NULL;
}
}
FLAC__SeekableStreamDecoderReadStatus ReadFlac::readCallback_(const FLAC__SeekableStreamDecoder *decoder,
FLAC__byte buffer[],
unsigned *bytes,
void *client_data) {
ReadFlac *instance = (ReadFlac*)client_data;
*bytes = instance->in->Read( (char *)buffer, *bytes);
if (*bytes == 0) {
cout << "FLAC: read returned 0" << endl;
return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
} else {
return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
}
}
FLAC__SeekableStreamDecoderSeekStatus ReadFlac::seekCallback_(const FLAC__SeekableStreamDecoder *decoder,
FLAC__uint64 absolute_byte_offset,
void *client_data) {
//if (!client_data)
//return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
ReadFlac *instance = (ReadFlac*)client_data;
//if (!instance)
//return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
instance->ErrorCheck( FLAC__seekable_stream_decoder_get_state(decoder) );
//if (absolute_byte_offset < 0)
//absolute_byte_offset = 0;
long pos = instance->in->SeekSet( (long)absolute_byte_offset ) ;
if ( pos == -1 ) {
cout << "COULD NOT seek " << absolute_byte_offset << " bytes" << endl;
return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
} else {
//cout << "seeked %ld bytes", pos);
return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK;
}
}
FLAC__SeekableStreamDecoderTellStatus ReadFlac::tellCallback_(const FLAC__SeekableStreamDecoder *decoder,
FLAC__uint64 *absolute_byte_offset,
void *client_data) {
ReadFlac *instance = (ReadFlac*)client_data;
long pos = instance->in->SeekCur( *absolute_byte_offset );
if ( pos != -1 ) {
*absolute_byte_offset = pos;
//cout << "FLAC: tell is ok" << endl;
return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
} else {
cout << "FLAC: tell is NOT ok" << endl;
return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
}
}
FLAC__SeekableStreamDecoderLengthStatus ReadFlac::lengthCallback_(const FLAC__SeekableStreamDecoder *decoder,
FLAC__uint64 *stream_length,
void *client_data) {
ReadFlac *instance = (ReadFlac*)client_data;
*stream_length = (FLAC__uint64)instance->filelength;
return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
}
FLAC__bool ReadFlac::eofCallback_(const FLAC__SeekableStreamDecoder *decoder,
void *client_data) {
ReadFlac *instance = (ReadFlac*)client_data;
long pos = instance->in->SeekCur(0);
if ( pos == instance->filelength ) {
//instance->in->SeekSet(pos);
cout << "FLAC: eofCallback: it is EOF" << endl;
//exit(1);
return 1;
} else {
//post ("FLAC: eofCallback: not eof %ld, filelength %ld", pos, instance->filelength);
//instance->in->SeekSet(pos);
return 0;
}
}
FLAC__StreamDecoderWriteStatus ReadFlac::writeCallback_(const FLAC__SeekableStreamDecoder *decoder,
const FLAC__Frame *frame,
const FLAC__int32 * const buffer[],
void *client_data) {
ReadFlac *instance = (ReadFlac*)client_data;
//const unsigned bps = instance->streaminfo.data.stream_info.bits_per_sample;
const unsigned channels = instance->streaminfo.data.stream_info.channels;
const unsigned wide_samples = frame->header.blocksize;
unsigned wide_sample, sample, channel;
(void)decoder;
if(instance->abort_flag) {
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
}
//cout << "FLAC: blocksize = " << wide_samples << endl;
for(sample = instance->samples_in_reservoir*channels, wide_sample = 0;
wide_sample < wide_samples; wide_sample++)
for(channel = 0; channel < channels; channel++, sample++)
instance->reservoir[sample] = (FLAC__int16)buffer[channel][wide_sample];
instance->samples_in_reservoir += wide_samples;
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
}
void ReadFlac::metadataCallback_(const FLAC__SeekableStreamDecoder *decoder,
const FLAC__StreamMetadata *metadata,
void *client_data) {
ReadFlac *instance = (ReadFlac*)client_data;
(void)decoder;
//cout << "FLAC: metadata callback" << endl;
if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
instance->streaminfo = *metadata;
if(instance->streaminfo.data.stream_info.bits_per_sample != 16) {
cout << "\nFLAC: bps is not 16 ..Aboorting ...\n" << endl;
instance->abort_flag = true;
//exit(1);
return;
}
}
}
void ReadFlac::errorCallback_(const FLAC__SeekableStreamDecoder *decoder,
FLAC__StreamDecoderErrorStatus status,
void *client_data) {
ReadFlac *instance = (ReadFlac*)client_data;
(void)decoder;
if(status != FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC) {
cout << "FLAC: error callback - lost sync, trying reset,flush" << endl;
FLAC__seekable_stream_decoder_reset(instance->decoder);
FLAC__seekable_stream_decoder_flush(instance->decoder);
//instance->abort_flag = true;
}
}
void ReadFlac::ErrorCheck(int state) {
switch (state) {
case FLAC__SEEKABLE_STREAM_DECODER_SEEKING:
//cout << "SEEKING " << endl;
break;
case FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM :
cout << "END_OF_STREAM " << endl;
break;
case FLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR :
cout << "MEMORY_ALLOCATION_ERROR " << endl;
break;
case FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR :
cout << "STREAM_DECODER_ERROR " << endl;
break;
case FLAC__SEEKABLE_STREAM_DECODER_READ_ERROR :
cout << "READ_ERROR " << endl;
break;
case FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR :
cout << "SEEK_ERROR " << endl;
break;
case FLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK :
cout << "INVALID_CALLBACK " << endl;
break;
case FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED :
cout << "UNINITIALIZED " << endl;
break;
case FLAC__SEEKABLE_STREAM_DECODER_OK :
default:
cout << "OK" << endl;
break;
}
}
#endif
--- NEW FILE: ReadFlac.cpp ---
/*
* readanysf~ external for pd.
*
* Copyright (C) 2003,2004 August Black
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* ReadFlac.cpp
*
* much of the code comes from FLAC input plugin for Winamp3
* distributed with the flac source under the GPL
* Copyright (C) 2000,2001,2002,2003 Josh Coalson
*/
#ifdef READ_FLAC
//#include <m_pd.h>
#include "ReadFlac.h"
#include <iostream>
extern "C" {
#include "FLAC/metadata.h"
};
using namespace std;
ReadFlac::ReadFlac( Input *input ) {
in=input;
needs_seek = false;
seek_sample = 0;
samples_in_reservoir =0;
abort_flag = false;
decoder = NULL;
filelength = 0;
}
ReadFlac::~ReadFlac() {
cleanup();
}
bool ReadFlac::Initialize( ) {
//@@@ to be really "clean" we should go through the reader instead of directly to the file...
if(!FLAC__metadata_get_streaminfo(in->get_filename(), &streaminfo)) {
cout << "what the fuck" << endl;
return 1;
}
//length_msec = lengthInMsec();
/*cout << "FLAC:<%ihz:%ibps:%dch>",
streaminfo.data.stream_info.sample_rate,
streaminfo.data.stream_info.bits_per_sample,
streaminfo.data.stream_info.channels); //@@@ fix later
*/
samplerate = (double)streaminfo.data.stream_info.sample_rate;
num_channels = streaminfo.data.stream_info.channels;
lengthinseconds = streaminfo.data.stream_info.total_samples/samplerate;
filelength = in->SeekEnd(0);
filelength = in->SeekCur(0);
in->SeekSet(0);
decoder = FLAC__stream_decoder_new();
if(decoder == 0)
return false;
FLAC__stream_decoder_set_read_callback(decoder, readCallback_);
FLAC__stream_decoder_set_write_callback(decoder, writeCallback_);
FLAC__stream_decoder_set_metadata_callback(decoder, metadataCallback_);
FLAC__stream_decoder_set_error_callback(decoder, errorCallback_);
FLAC__stream_decoder_set_client_data(decoder, this);
if(FLAC__stream_decoder_init(decoder) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA ) {
cleanup();
return false;
}
if(!FLAC__stream_decoder_process_until_end_of_metadata(decoder)) {
cleanup();
return false;
}
return true;
}
int ReadFlac::Decode(float *buffer, int size) {
if(decoder == NULL)
return 0;
//while (samples_in_reservoir < 576) {
//if (samples_in_reservoir < 576) {
if(FLAC__stream_decoder_get_state(decoder) == FLAC__STREAM_DECODER_END_OF_STREAM) {
cout << "FLAC: end of file" << endl;
return 0;
} else if(!FLAC__stream_decoder_process_single(decoder)) {
//ErrorCheck( FLAC__stream_decoder_get_state(decoder) );
//ErrorCheck( FLAC__stream_decoder_finish(decoder) );
//ErrorCheck( FLAC__stream_decoder_init(decoder) );
//FLAC__stream_decoder_reset(decoder);
//FLAC__stream_decoder_flush(decoder);
cout << "FLAC: no process single " << endl;
//break;
//exit(1);
//return 0;
//return samples_in_reservoir;
}
//}
int n = samples_in_reservoir; // > 576 ? samples_in_reservoir: 576;
const unsigned channels = streaminfo.data.stream_info.channels;
if(samples_in_reservoir == 0) {
//cout << "FLAC: reservoir is empty" << endl;
return 0;
} else {
//const unsigned bits_per_sample = streaminfo.data.stream_info.bits_per_sample;
//const unsigned bytes_per_sample = (bits_per_sample+7)/8;
//const unsigned sample_rate = streaminfo.data.stream_info.sample_rate;
unsigned i;
//16 > WHDR2 + 2 ? 16 : WHDR2 + 2
//unsigned delta;
for(i = 0; i < n*channels; i++)
buffer[i] = (float) ( reservoir[i]/ 32768.0 );
samples_in_reservoir = 0;
//const int bytes = n * channels * bytes_per_sample;
}
//if(eof)
//return 0;
return n*channels; //1;
}
bool ReadFlac::Rewind() {
cleanup();
Initialize();
samples_in_reservoir = 0;
//ErrorCheck( FLAC__stream_decoder_get_state(decoder) );
//FLAC__stream_decoder_seek_absolute(decoder, 0);
return true;
}
bool ReadFlac::PCM_seek(long bytes) {
cout << "ReadFlac:: no seeking on flac files, sorry" << endl;
return false;
}
bool ReadFlac::TIME_seek(double seconds) {
cout << "ReadFlac:: no seeking on flac files, sorry" << endl;
return false;
}
void ReadFlac::cleanup()
{
if(decoder) {
FLAC__stream_decoder_finish(decoder);
FLAC__stream_decoder_delete(decoder);
decoder = NULL;
}
}
FLAC__StreamDecoderReadStatus ReadFlac::readCallback_(const FLAC__StreamDecoder *decoder,
FLAC__byte buffer[],
unsigned *bytes,
void *client_data) {
ReadFlac *instance = (ReadFlac*)client_data;
*bytes = instance->in->Read( (char *)buffer, *bytes);
if (*bytes == 0) {
cout << "FLAC: read returned 0" << endl;
return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM ;
} else {
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE ;
}
}
FLAC__StreamDecoderWriteStatus ReadFlac::writeCallback_(const FLAC__StreamDecoder *decoder,
const FLAC__Frame *frame,
const FLAC__int32 * const buffer[],
void *client_data) {
ReadFlac *instance = (ReadFlac*)client_data;
//const unsigned bps = instance->streaminfo.data.stream_info.bits_per_sample;
const unsigned channels = instance->streaminfo.data.stream_info.channels;
const unsigned wide_samples = frame->header.blocksize;
unsigned wide_sample, sample, channel;
(void)decoder;
if(instance->abort_flag) {
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
}
//cout << "FLAC: blocksize = " << wide_samples << endl;
for(sample = instance->samples_in_reservoir*channels, wide_sample = 0;
wide_sample < wide_samples; wide_sample++)
for(channel = 0; channel < channels; channel++, sample++)
instance->reservoir[sample] = (FLAC__int16)buffer[channel][wide_sample];
instance->samples_in_reservoir += wide_samples;
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
}
void ReadFlac::metadataCallback_(const FLAC__StreamDecoder *decoder,
const FLAC__StreamMetadata *metadata,
void *client_data) {
ReadFlac *instance = (ReadFlac*)client_data;
(void)decoder;
//cout << "FLAC: metadata callback" << endl;
if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
instance->streaminfo = *metadata;
if(instance->streaminfo.data.stream_info.bits_per_sample != 16) {
cout << "\nFLAC: bps is not 16 ..Aboorting ...\n" << endl;
instance->abort_flag = true;
//exit(1);
return;
}
}
}
void ReadFlac::errorCallback_(const FLAC__StreamDecoder *decoder,
FLAC__StreamDecoderErrorStatus status,
void *client_data) {
ReadFlac *instance = (ReadFlac*)client_data;
(void)decoder;
if(status != FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC) {
cout << "FLAC: error callback - lost sync, trying reset,flush" << endl;
FLAC__stream_decoder_reset(instance->decoder);
FLAC__stream_decoder_flush(instance->decoder);
//instance->abort_flag = true;
}
}
void ReadFlac::ErrorCheck(int state) {
switch (state) {
case FLAC__STREAM_DECODER_END_OF_STREAM :
cout << "END_OF_STREAM " << endl;
break;
case FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR :
cout << "MEMORY_ALLOCATION_ERROR " << endl;
break;
case FLAC__STREAM_DECODER_READ_FRAME :
cout << "READ_FRAME " << endl;
break;
case FLAC__STREAM_DECODER_INVALID_CALLBACK :
cout << "INVALID_CALLBACK " << endl;
break;
case FLAC__STREAM_DECODER_UNINITIALIZED :
cout << "UNINITIALIZED " << endl;
break;
case FLAC__STREAM_DECODER_ABORTED :
cout << "ABORTED " << endl;
default:
cout << "OK" << endl;
break;
}
}
#endif
--- NEW FILE: ReadRaw.cpp ---
/*
* readanysf~ external for pd.
*
* Copyright (C) 2003 August Black
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* ReadRaw.cpp || code here was kindly 'borrowed' from d_soundfile.c from
* puredata source code by Miller Puckette
*/
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <iostream>
#include "ReadRaw.h"
#include <m_pd.h>
//# define _F_FRACBITS 28
//# define do_f_fromint(x) ((x) << _F_FRACBITS)
#define SCALE (1./(1024. * 1024. * 1024. * 2.))
using namespace std;
int ambigendian(void) {
unsigned short s = 1;
unsigned char c = *(char *)(&s);
return (c==0);
}
static unsigned int swap4 (unsigned int n, int doit) {
if (doit)
return (((n & 0xff) << 24) | ((n & 0xff00) << 8) |
((n & 0xff0000) >> 8) | ((n & 0xff000000) >> 24));
else
return (n);
}
static unsigned short swap2 (unsigned int n, int doit) {
if (doit)
return (((n & 0xff) << 8) | ((n & 0xff00) >> 8));
else
return (n);
}
#define ULPOW2TO31 ((unsigned int)0x80000000)
#define DPOW2TO31 ((double)2147483648.0) /* 2^31 */
static double myUlongToDouble (unsigned int ul) {
double val;
if (ul & ULPOW2TO31)
val = DPOW2TO31 + (ul & (~ULPOW2TO31));
else
val = ul;
return val;
}
static double ieee_80_to_double (unsigned char *p) {
unsigned char sign;
short lexp = 0;
unsigned int mant1 = 0;
unsigned int mant0 = 0;
double val;
lexp = *p++;
lexp <<= 8;
lexp |= *p++;
sign = (lexp & 0x8000) ? 1 : 0;
lexp &= 0x7FFF;
mant1 = *p++;
mant1 <<= 8;
mant1 |= *p++;
mant1 <<= 8;
mant1 |= *p++;
mant1 <<= 8;
mant1 |= *p++;
mant0 = *p++;
mant0 <<= 8;
mant0 |= *p++;
mant0 <<= 8;
mant0 |= *p++;
mant0 <<= 8;
mant0 |= *p++;
if (mant1 == 0 && mant0 == 0 && lexp == 0 && sign == 0)
return 0.0;
else {
val = myUlongToDouble (mant0) * pow (2.0, -63.0);
val += myUlongToDouble (mant1) * pow (2.0, -31.0);
val *= pow (2.0, ((double) lexp) - 16383.0);
return sign ? -val : val;
}
}
ReadRaw::ReadRaw ()
{
}
ReadRaw::ReadRaw (Input * input) {
//char file;
in = input;
bigendian = ambigendian();
//bigendian = 0;
}
ReadRaw::~ReadRaw () {
if (in != NULL)
in->Close ();
}
bool ReadRaw::Initialize () {
char buf[128];
int format, swap;
//long bytelimit = 0x7fffffff;
if (in == NULL) {
cout << "ReadRaw:: Input is NULL, this is bad, bailing...." << endl;
//shouldn't ever happen, but just checking
return false; //cout << "already opened, now closing file" << endl;
}
int bytesread = in->Read (buf, READHDRSIZE);
if (bytesread < 4) {
cout << "ReadRaw:: bytesread is < 4, this is bad, bailing...." << endl;
return false;
}
format = in->get_format (); // we know the format already
if (format == FORMAT_NEXT){ /* nextstep header */
//unsigned int param;
bigendian = 1;
swap = (bigendian != ambigendian());
if (bytesread < (int) sizeof (t_nextstep)) {
cout << "ReadRaw:: bytesread < sizeof(nextstep), this is bad, bailing...."<< endl;
return false;
}
num_channels = swap4 (((t_nextstep *) buf)->ns_nchans, swap);
format = swap4 (((t_nextstep *) buf)->ns_format, swap);
samplerate = (double) swap4( ((t_nextstep *) buf)->ns_sr, swap );
headersize = swap4 (((t_nextstep *) buf)->ns_onset, swap);
if (format == NS_FORMAT_LINEAR_16)
bytespersamp = 2;
else if (format == NS_FORMAT_LINEAR_24)
bytespersamp = 3;
else if (format == NS_FORMAT_FLOAT)
bytespersamp = 4;
else
return false;
//bytelimit = 0x7fffffff;
} else if (format == FORMAT_WAVE) { /* wave header */
/* This is awful. You have to skip over chunks,
* except that if one happens to be a "fmt" chunk, you want to
* find out the format from that one. The case where the
* "fmt" chunk comes after the audio isn't handled. */
bigendian = 0;
swap = (bigendian != ambigendian());
headersize = 12;
if (bytesread < 20) {
cout << "ReadRaw:: bytesread < 20, this is bad, bailing...." << endl;
return false;
}
/* First we guess a number of channels, etc., in case there's
* no "fmt" chunk to follow. */
num_channels = 1;
bytespersamp = 2;
/* copy the first chunk header to beginnning of buffer. */
memcpy (buf, buf + headersize, sizeof (t_wavechunk));
/* read chunks in loop until we get to the data chunk */
while (strncmp (((t_wavechunk *) buf)->wc_id, "data", 4)) {
long chunksize = swap4 (((t_wavechunk *) buf)->wc_size,
swap), seekto = headersize + chunksize + 8, seekout;
if (!strncmp(((t_wavechunk *) buf)->wc_id, "fmt ", 4)) {
long commblockonset = headersize + 8;
seekout = in->SeekSet ( commblockonset);
if (seekout != commblockonset) {
cout << "ReadRaw:: Seek prob, seekout != commblockonset" << endl;
return false;
}
if ( in->Read ( buf, sizeof (t_fmt) ) < (int) sizeof (t_fmt)) {
cout << "ReadRaw:: Read prob, read < sizeopf(t_fmt)" << endl;
return false;
}
num_channels = swap2 (((t_fmt *) buf)->f_nchannels, swap);
samplerate = (double) swap2 (((t_fmt *) buf)->f_samplespersec, swap);
int sampsize = swap2 (((t_fmt *) buf)->f_nbitspersample, swap);
if (sampsize == 16)
bytespersamp = 2;
else if (sampsize == 24)
bytespersamp = 3;
else if (sampsize == 32)
bytespersamp = 4;
else {
cout << "ReadRaw:: bytespersamp is not supported, samplesize= "<< sampsize << endl;
//return false;
}
}
seekout = in->SeekSet ( seekto );
if (seekout != seekto) {
cout << "ReadRaw:: Seek prob, seekout != seekto"<< endl;
return false;
}
if ( in->Read ( buf, sizeof (t_wavechunk) ) < (int) sizeof (t_wavechunk)) {
cout << "ReadRaw:: Read prob, read < sizeof(wavechunk)" << endl;
return false;
}
/* cout << "new chunk %c %c %c %c at %d",
* ((t_wavechunk *)buf)->wc_id[0],
* ((t_wavechunk *)buf)->wc_id[1],
* ((t_wavechunk *)buf)->wc_id[2],
* ((t_wavechunk *)buf)->wc_id[3], seekto); */
headersize = seekto;
}
//bytelimit = swap4 (((t_wavechunk *) buf)->wc_size, swap);
headersize += 8;
} else {
/* AIFF. same as WAVE; actually predates it. Disgusting. */
bigendian = 1;
swap = (bigendian != ambigendian());
headersize = 12;
if (bytesread < 20)
return false;
/* First we guess a number of channels, etc., in case there's
* no COMM block to follow. */
num_channels = 1;
bytespersamp = 2;
/* copy the first chunk header to beginnning of buffer. */
memcpy (buf, buf + headersize, sizeof (t_datachunk));
/* read chunks in loop until we get to the data chunk */
while (strncmp (((t_datachunk *) buf)->dc_id, "SSND", 4)) {
long chunksize = swap4 (((t_datachunk *) buf)->dc_size,
swap), seekto = headersize + chunksize + 8, seekout;
if (!strncmp (((t_datachunk *) buf)->dc_id, "COMM", 4)) {
long commblockonset = headersize + 8;
seekout = in->SeekSet ( commblockonset );
if (seekout != commblockonset)
return false;
if ( in->Read (buf, sizeof (t_comm)) <
(int) sizeof (t_comm))
return false;
num_channels = swap2 (((t_comm *) buf)->c_nchannels, swap);
samplerate = ieee_80_to_double (((t_comm *) buf)->c_samprate);
format = swap2 (((t_comm *) buf)->c_bitspersamp, swap);
if (format == 16)
bytespersamp = 2;
else if (format == 24)
bytespersamp = 3;
else
return false;
}
seekout = in->SeekSet ( seekto );
if (seekout != seekto)
return false;
if ( in->Read (buf, sizeof (t_datachunk)) <
(int) sizeof (t_datachunk))
return false;
headersize = seekto;
}
//bytelimit = swap4 (((t_datachunk *) buf)->dc_size, bigendian);
headersize += 8;
}
//cout << "ReadRaw:: [%s] %1.0lf (Hz), %d chan(s), bps %d",in->get_filename(),
// samplerate, num_channels, bytespersamp);
//cout << " headersize = %d", headersize);
long tmp = in->SeekEnd(0); // get filesize
if (tmp == -1)
post ("couldn't seek on file");
lengthinseconds = (float) ((tmp - headersize) / bytespersamp / samplerate / num_channels);
/* seek past header and any sample frames to skip */
if ( ( in->SeekSet( headersize ) ) != -1 ) {
return true;
} else {
cout << "ReadRaw:: strange, wasn't able to seek on the file" << endl;
return false;
}
}
bool ReadRaw::Rewind () {
if ( ( in->SeekSet( headersize ) ) != -1 )
return true;
else
return false;
}
int ReadRaw::Decode (float *buffer, int size) {
int ret, x = 0;;
int chunk = WAVCHUNKSIZE * bytespersamp * num_channels;
int bytesperframe = bytespersamp * num_channels;
unsigned char *sp;
float ftmp;
if (chunk > size)
return 0;
ret = in->Read ( data, chunk );
ret = ret * bytespersamp;
if (bytespersamp == 2) {
for (int j = 0; j < ret; j += bytespersamp) {
sp = (unsigned char *) &data[j];
if (bigendian)
ftmp = SCALE * ((sp[0] << 24) | (sp[1] << 16));
else
ftmp = SCALE * ((sp[1] << 24) | (sp[0] << 16));
buffer[x++] = ftmp;
//if (num_channels == 1) buffer[x++] = ftmp;
sp += bytesperframe;
}
} else if (bytespersamp == 3) {
for (int j = 0; j < ret; j += bytespersamp) {
sp = (unsigned char *) &data[j];
if (bigendian)
ftmp = SCALE * ((sp[0] << 24) | (sp[1] << 16) | (sp[2] << 8));
else
ftmp = SCALE * ((sp[2] << 24) | (sp[1] << 16) | (sp[0] << 8));
buffer[x++] = ftmp;
//if (num_channels == 1) buffer[x++] = ftmp;
sp += bytesperframe;
}
} else if (bytespersamp == 4) {
for (int j = 0; j < ret; j += bytespersamp) {
sp = (unsigned char *) &data[j];
if (bigendian)
ftmp = (float) ((sp[0] << 24) | (sp[1] << 16) | (sp[2] << 8) | sp[3]);
else
ftmp = (float) ((sp[3] << 24) | (sp[2] << 16) | (sp[1] << 8) | sp[0]);
buffer[x++] = ftmp;
//if (num_channels == 1) buffer[x++] = ftmp;
sp += bytesperframe;
}
}
return x / 2; //num_channels; //always two
}
bool ReadRaw::PCM_seek (long frames) {
if (frames > (long) (lengthinseconds * samplerate))
return false;
if ( in->SeekSet ( headersize + (frames * num_channels * bytespersamp ) ) != -1 )
return true;
else {
cout << "ReadRaw:: fuck, no seeking!!" << endl;
return false;
}
}
bool ReadRaw::TIME_seek (double seconds) {
long frames = (long) (seconds * samplerate);
return PCM_seek (frames);
}
- Previous message: [PD-cvs] externals/august/readanysf~/include Fifo.h, NONE, 1.1 Input.h, NONE, 1.1 InputFile.h, NONE, 1.1 InputStream.h, NONE, 1.1 Makefile, NONE, 1.1 Makefile.am, NONE, 1.1 Makefile.in, NONE, 1.1 ReadFlac.h, NONE, 1.1 ReadFlac.h.seekable, NONE, 1.1 ReadMad.h, NONE, 1.1 ReadRaw.h, NONE, 1.1 ReadVorbis.h, NONE, 1.1 Readsf.h, NONE, 1.1 generic.h, NONE, 1.1 main.h, NONE, 1.1 stamp-h2.in, NONE, 1.1
- Next message: [PD-cvs] externals/august/readanysf~ AUTHORS, NONE, 1.1 COPYING, NONE, 1.1 ChangeLog, NONE, 1.1 INSTALL, NONE, 1.1 Makefile.am, NONE, 1.1 Makefile.in, NONE, 1.1 NEWS, NONE, 1.1 README, NONE, 1.1 aclocal.m4, NONE, 1.1 boot.sh, NONE, 1.1 config.guess, NONE, 1.1 config.h.in, NONE, 1.1 config.sub, NONE, 1.1 configure, NONE, 1.1 configure.ac, NONE, 1.1 depcomp, NONE, 1.1 install-sh, NONE, 1.1 missing, NONE, 1.1 mkinstalldirs, NONE, 1.1 readanysf-help.pd, NONE, 1.1 stamp-h1.in, NONE, 1.1
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the Pd-cvs
mailing list