mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-28 07:48:37 -04:00
foo
This commit is contained in:
parent
c8b6ece0de
commit
9bad163654
721
panda/src/mpg123/common.c
Normal file
721
panda/src/mpg123/common.c
Normal file
@ -0,0 +1,721 @@
|
||||
/* GPL clean */
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef READ_MMAP
|
||||
#include <sys/mman.h>
|
||||
#ifndef MAP_FAILED
|
||||
#define MAP_FAILED ( (void *) -1 )
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "mpg123.h"
|
||||
#include "genre.h"
|
||||
#include "common.h"
|
||||
|
||||
int tabsel_123[2][3][16] = {
|
||||
{ {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,},
|
||||
{0,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384,},
|
||||
{0,32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320,} },
|
||||
|
||||
{ {0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,},
|
||||
{0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,},
|
||||
{0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,} }
|
||||
};
|
||||
|
||||
long freqs[9] = { 44100, 48000, 32000, 22050, 24000, 16000 , 11025 , 12000 , 8000 };
|
||||
|
||||
struct bitstream_info bsi;
|
||||
|
||||
static int fsizeold=0,ssize;
|
||||
static unsigned char bsspace[2][MAXFRAMESIZE+512]; /* MAXFRAMESIZE */
|
||||
static unsigned char *bsbuf=bsspace[1],*bsbufold;
|
||||
static int bsnum=0;
|
||||
|
||||
static unsigned long oldhead = 0;
|
||||
unsigned long firsthead=0;
|
||||
|
||||
unsigned char *pcm_sample;
|
||||
int pcm_point = 0;
|
||||
int audiobufsize = AUDIOBUFSIZE;
|
||||
|
||||
static int decode_header(struct frame *fr,unsigned long newhead);
|
||||
|
||||
void audio_flush(int outmode, struct audio_info_struct *ai)
|
||||
{
|
||||
if (pcm_point) {
|
||||
switch (outmode) {
|
||||
case DECODE_FILE:
|
||||
write (OutputDescriptor, pcm_sample, pcm_point);
|
||||
break;
|
||||
case DECODE_AUDIO:
|
||||
audio_play_samples (ai, pcm_sample, pcm_point);
|
||||
break;
|
||||
case DECODE_BUFFER:
|
||||
write (buffer_fd[1], pcm_sample, pcm_point);
|
||||
break;
|
||||
case DECODE_WAV:
|
||||
case DECODE_CDR:
|
||||
case DECODE_AU:
|
||||
wav_write(pcm_sample, pcm_point);
|
||||
break;
|
||||
}
|
||||
pcm_point = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(WIN32) && !defined(GENERIC)
|
||||
void (*catchsignal(int signum, void(*handler)()))()
|
||||
{
|
||||
struct sigaction new_sa;
|
||||
struct sigaction old_sa;
|
||||
|
||||
#ifdef DONT_CATCH_SIGNALS
|
||||
printf ("Not catching any signals.\n");
|
||||
return ((void (*)()) -1);
|
||||
#endif
|
||||
|
||||
new_sa.sa_handler = handler;
|
||||
sigemptyset(&new_sa.sa_mask);
|
||||
new_sa.sa_flags = 0;
|
||||
if (sigaction(signum, &new_sa, &old_sa) == -1)
|
||||
return ((void (*)()) -1);
|
||||
return (old_sa.sa_handler);
|
||||
}
|
||||
#endif
|
||||
|
||||
void read_frame_init (void)
|
||||
{
|
||||
oldhead = 0;
|
||||
firsthead = 0;
|
||||
}
|
||||
|
||||
int head_check(unsigned long head)
|
||||
{
|
||||
/* fprintf(stderr,"HC"); */
|
||||
if( (head & 0xffe00000) != 0xffe00000)
|
||||
return FALSE;
|
||||
if(!((head>>17)&3))
|
||||
return FALSE;
|
||||
if( ((head>>12)&0xf) == 0xf)
|
||||
return FALSE;
|
||||
if( ((head>>10)&0x3) == 0x3 )
|
||||
return FALSE;
|
||||
#if 0
|
||||
/* this would match on MPEG1/Layer1 streams with CRC = off */
|
||||
if ((head & 0xffff0000) == 0xffff0000)
|
||||
return FALSE;
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************
|
||||
* read next frame
|
||||
*/
|
||||
int read_frame(struct frame *fr)
|
||||
{
|
||||
unsigned long newhead;
|
||||
static unsigned char ssave[34];
|
||||
|
||||
fsizeold=fr->framesize; /* for Layer3 */
|
||||
|
||||
if (param.halfspeed) {
|
||||
static int halfphase = 0;
|
||||
if (halfphase--) {
|
||||
bsi.bitindex = 0;
|
||||
bsi.wordpointer = (unsigned char *) bsbuf;
|
||||
if (fr->lay == 3)
|
||||
memcpy (bsbuf, ssave, ssize);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
halfphase = param.halfspeed - 1;
|
||||
}
|
||||
|
||||
read_again:
|
||||
if(!rd->head_read(rd,&newhead))
|
||||
return FALSE;
|
||||
|
||||
if(1 || oldhead != newhead || !oldhead) {
|
||||
|
||||
init_resync:
|
||||
|
||||
fr->header_change = 2;
|
||||
if(oldhead) {
|
||||
if((oldhead & 0xc00) == (newhead & 0xc00)) {
|
||||
if( (oldhead & 0xc0) == 0 && (newhead & 0xc0) == 0)
|
||||
fr->header_change = 1;
|
||||
else if( (oldhead & 0xc0) > 0 && (newhead & 0xc0) > 0)
|
||||
fr->header_change = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef SKIP_JUNK
|
||||
if(!firsthead && !head_check(newhead) ) {
|
||||
int i;
|
||||
|
||||
fprintf(stderr,"Junk at the beginning %08lx\n",newhead);
|
||||
|
||||
/* I even saw RIFF headers at the beginning of MPEG streams ;( */
|
||||
if(newhead == ('R'<<24)+('I'<<16)+('F'<<8)+'F') {
|
||||
if(!rd->head_read(rd,&newhead))
|
||||
return 0;
|
||||
while(newhead != ('d'<<24)+('a'<<16)+('t'<<8)+'a') {
|
||||
if(!rd->head_shift(rd,&newhead))
|
||||
return 0;
|
||||
}
|
||||
if(!rd->head_read(rd,&newhead))
|
||||
return 0;
|
||||
/* fprintf(stderr,"Skipped RIFF header!\n"); */
|
||||
goto read_again;
|
||||
}
|
||||
{
|
||||
/* step in byte steps through next 64K */
|
||||
for(i=0;i<65536;i++) {
|
||||
if(!rd->head_shift(rd,&newhead))
|
||||
return 0;
|
||||
if(head_check(newhead))
|
||||
break;
|
||||
}
|
||||
if(i == 65536) {
|
||||
fprintf(stderr,"Giving up searching valid MPEG header\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* should we additionaly check, whether a new frame starts at
|
||||
* the next expected position? (some kind of read ahead)
|
||||
* We could implement this easily, at least for files.
|
||||
*/
|
||||
}
|
||||
#endif
|
||||
|
||||
if( (newhead & 0xffe00000) != 0xffe00000) {
|
||||
if (!param.quiet)
|
||||
fprintf(stderr,"Illegal Audio-MPEG-Header 0x%08lx at offset 0x%lx.\n",
|
||||
newhead,rd->tell(rd)-4);
|
||||
/* and those ugly ID3 tags */
|
||||
if((newhead & 0xffffff00) == ('T'<<24)+('A'<<16)+('G'<<8)) {
|
||||
rd->skip_bytes(rd,124);
|
||||
fprintf(stderr,"Skipped ID3 Tag!\n");
|
||||
goto read_again;
|
||||
}
|
||||
if (param.tryresync) {
|
||||
int try = 0;
|
||||
/* Read more bytes until we find something that looks
|
||||
reasonably like a valid header. This is not a
|
||||
perfect strategy, but it should get us back on the
|
||||
track within a short time (and hopefully without
|
||||
too much distortion in the audio output). */
|
||||
do {
|
||||
try++;
|
||||
if(!rd->head_shift(rd,&newhead))
|
||||
return 0;
|
||||
if (!oldhead)
|
||||
goto init_resync; /* "considered harmful", eh? */
|
||||
|
||||
} while ((newhead & HDRCMPMASK) != (oldhead & HDRCMPMASK)
|
||||
&& (newhead & HDRCMPMASK) != (firsthead & HDRCMPMASK));
|
||||
if (!param.quiet)
|
||||
fprintf (stderr, "Skipped %d bytes in input.\n", try);
|
||||
}
|
||||
else
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* fprintf(stderr,"+"); */
|
||||
|
||||
if (!firsthead) {
|
||||
if(!decode_header(fr,newhead)) {
|
||||
/* fprintf(stderr,"A"); */
|
||||
goto read_again;
|
||||
}
|
||||
firsthead = newhead;
|
||||
|
||||
}
|
||||
else if(!decode_header(fr,newhead)) {
|
||||
/* fprintf(stderr,"B: %08lx\n",newhead); */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* fprintf(stderr,"-"); */
|
||||
}
|
||||
else
|
||||
fr->header_change = 0;
|
||||
|
||||
/* fprintf(stderr,"FS: %d\n",fr->framesize); */
|
||||
|
||||
/* flip/init buffer for Layer 3 */
|
||||
bsbufold = bsbuf;
|
||||
bsbuf = bsspace[bsnum]+512;
|
||||
bsnum = (bsnum + 1) & 1;
|
||||
|
||||
/* read main data into memory */
|
||||
if(!rd->read_frame_body(rd,bsbuf,fr->framesize))
|
||||
return 0;
|
||||
|
||||
{
|
||||
/* Test */
|
||||
static struct vbrHeader head;
|
||||
static int vbr = 0;
|
||||
if(!vbr) {
|
||||
getVBRHeader(&head,bsbuf,fr);
|
||||
vbr = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* fprintf(stderr,"Got it\n"); */
|
||||
|
||||
bsi.bitindex = 0;
|
||||
bsi.wordpointer = (unsigned char *) bsbuf;
|
||||
|
||||
if (param.halfspeed && fr->lay == 3)
|
||||
memcpy (ssave, bsbuf, ssize);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/****************************************
|
||||
* HACK,HACK,HACK: step back <num> frames
|
||||
* can only work if the 'stream' isn't a real stream but a file
|
||||
*/
|
||||
int back_frame(struct reader *rds,struct frame *fr,int num)
|
||||
{
|
||||
long bytes;
|
||||
unsigned long newhead;
|
||||
|
||||
if(!firsthead)
|
||||
return 0;
|
||||
|
||||
bytes = (fr->framesize+8)*(num+2);
|
||||
|
||||
if(rds->back_bytes(rds,bytes) < 0)
|
||||
return -1;
|
||||
if(!rds->head_read(rds,&newhead))
|
||||
return -1;
|
||||
|
||||
while( (newhead & HDRCMPMASK) != (firsthead & HDRCMPMASK) ) {
|
||||
if(!rds->head_shift(rds,&newhead))
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(rds->back_bytes(rds,4) <0)
|
||||
return -1;
|
||||
|
||||
read_frame(fr);
|
||||
read_frame(fr);
|
||||
|
||||
if(fr->lay == 3) {
|
||||
set_pointer(512);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* decode a header and write the information
|
||||
* into the frame structure
|
||||
*/
|
||||
static int decode_header(struct frame *fr,unsigned long newhead)
|
||||
{
|
||||
if(!head_check(newhead)) {
|
||||
fprintf(stderr,"Oopps header is wrong\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( newhead & (1<<20) ) {
|
||||
fr->lsf = (newhead & (1<<19)) ? 0x0 : 0x1;
|
||||
fr->mpeg25 = 0;
|
||||
}
|
||||
else {
|
||||
fr->lsf = 1;
|
||||
fr->mpeg25 = 1;
|
||||
}
|
||||
|
||||
if (!param.tryresync || !oldhead) {
|
||||
/* If "tryresync" is true, assume that certain
|
||||
parameters do not change within the stream! */
|
||||
fr->lay = 4-((newhead>>17)&3);
|
||||
if( ((newhead>>10)&0x3) == 0x3) {
|
||||
fprintf(stderr,"Stream error\n");
|
||||
exit(1);
|
||||
}
|
||||
if(fr->mpeg25) {
|
||||
fr->sampling_frequency = 6 + ((newhead>>10)&0x3);
|
||||
}
|
||||
else
|
||||
fr->sampling_frequency = ((newhead>>10)&0x3) + (fr->lsf*3);
|
||||
fr->error_protection = ((newhead>>16)&0x1)^0x1;
|
||||
}
|
||||
|
||||
fr->bitrate_index = ((newhead>>12)&0xf);
|
||||
fr->padding = ((newhead>>9)&0x1);
|
||||
fr->extension = ((newhead>>8)&0x1);
|
||||
fr->mode = ((newhead>>6)&0x3);
|
||||
fr->mode_ext = ((newhead>>4)&0x3);
|
||||
fr->copyright = ((newhead>>3)&0x1);
|
||||
fr->original = ((newhead>>2)&0x1);
|
||||
fr->emphasis = newhead & 0x3;
|
||||
|
||||
fr->stereo = (fr->mode == MPG_MD_MONO) ? 1 : 2;
|
||||
|
||||
oldhead = newhead;
|
||||
|
||||
if(!fr->bitrate_index) {
|
||||
fprintf(stderr,"Free format not supported: (head %08lx)\n",newhead);
|
||||
return (0);
|
||||
}
|
||||
|
||||
switch(fr->lay) {
|
||||
case 1:
|
||||
fr->framesize = (long) tabsel_123[fr->lsf][0][fr->bitrate_index] * 12000;
|
||||
fr->framesize /= freqs[fr->sampling_frequency];
|
||||
fr->framesize = ((fr->framesize+fr->padding)<<2)-4;
|
||||
break;
|
||||
case 2:
|
||||
fr->framesize = (long) tabsel_123[fr->lsf][1][fr->bitrate_index] * 144000;
|
||||
fr->framesize /= freqs[fr->sampling_frequency];
|
||||
fr->framesize += fr->padding - 4;
|
||||
break;
|
||||
case 3:
|
||||
if(fr->lsf)
|
||||
ssize = (fr->stereo == 1) ? 9 : 17;
|
||||
else
|
||||
ssize = (fr->stereo == 1) ? 17 : 32;
|
||||
if(fr->error_protection)
|
||||
ssize += 2;
|
||||
fr->framesize = (long) tabsel_123[fr->lsf][2][fr->bitrate_index] * 144000;
|
||||
fr->framesize /= freqs[fr->sampling_frequency]<<(fr->lsf);
|
||||
fr->framesize = fr->framesize + fr->padding - 4;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"Sorry, unknown layer type.\n");
|
||||
return (0);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef MPG123_REMOTE
|
||||
void print_rheader(struct frame *fr)
|
||||
{
|
||||
static char *modes[4] = { "Stereo", "Joint-Stereo", "Dual-Channel", "Single-Channel" };
|
||||
static char *layers[4] = { "Unknown" , "I", "II", "III" };
|
||||
static char *mpeg_type[2] = { "1.0" , "2.0" };
|
||||
|
||||
/* version, layer, freq, mode, channels, bitrate, BPF */
|
||||
fprintf(stderr,"@I %s %s %ld %s %d %d %d\n",
|
||||
mpeg_type[fr->lsf],layers[fr->lay],freqs[fr->sampling_frequency],
|
||||
modes[fr->mode],fr->stereo,
|
||||
tabsel_123[fr->lsf][fr->lay-1][fr->bitrate_index],
|
||||
fr->framesize+4);
|
||||
}
|
||||
#endif
|
||||
|
||||
void print_header(struct frame *fr)
|
||||
{
|
||||
static char *modes[4] = { "Stereo", "Joint-Stereo", "Dual-Channel", "Single-Channel" };
|
||||
static char *layers[4] = { "Unknown" , "I", "II", "III" };
|
||||
|
||||
fprintf(stderr,"MPEG %s, Layer: %s, Freq: %ld, mode: %s, modext: %d, BPF : %d\n",
|
||||
fr->mpeg25 ? "2.5" : (fr->lsf ? "2.0" : "1.0"),
|
||||
layers[fr->lay],freqs[fr->sampling_frequency],
|
||||
modes[fr->mode],fr->mode_ext,fr->framesize+4);
|
||||
fprintf(stderr,"Channels: %d, copyright: %s, original: %s, CRC: %s, emphasis: %d.\n",
|
||||
fr->stereo,fr->copyright?"Yes":"No",
|
||||
fr->original?"Yes":"No",fr->error_protection?"Yes":"No",
|
||||
fr->emphasis);
|
||||
fprintf(stderr,"Bitrate: %d Kbits/s, Extension value: %d\n",
|
||||
tabsel_123[fr->lsf][fr->lay-1][fr->bitrate_index],fr->extension);
|
||||
}
|
||||
|
||||
void print_header_compact(struct frame *fr)
|
||||
{
|
||||
static char *modes[4] = { "stereo", "joint-stereo", "dual-channel", "mono" };
|
||||
static char *layers[4] = { "Unknown" , "I", "II", "III" };
|
||||
|
||||
fprintf(stderr,"MPEG %s layer %s, %d kbit/s, %ld Hz %s\n",
|
||||
fr->mpeg25 ? "2.5" : (fr->lsf ? "2.0" : "1.0"),
|
||||
layers[fr->lay],
|
||||
tabsel_123[fr->lsf][fr->lay-1][fr->bitrate_index],
|
||||
freqs[fr->sampling_frequency], modes[fr->mode]);
|
||||
}
|
||||
|
||||
void print_id3_tag(unsigned char *buf)
|
||||
{
|
||||
struct id3tag {
|
||||
char tag[3];
|
||||
char title[30];
|
||||
char artist[30];
|
||||
char album[30];
|
||||
char year[4];
|
||||
char comment[30];
|
||||
unsigned char genre;
|
||||
};
|
||||
struct id3tag *tag = (struct id3tag *) buf;
|
||||
char title[31]={0,};
|
||||
char artist[31]={0,};
|
||||
char album[31]={0,};
|
||||
char year[5]={0,};
|
||||
char comment[31]={0,};
|
||||
char genre[31]={0,};
|
||||
|
||||
if(param.quiet)
|
||||
return;
|
||||
|
||||
strncpy(title,tag->title,30);
|
||||
strncpy(artist,tag->artist,30);
|
||||
strncpy(album,tag->album,30);
|
||||
strncpy(year,tag->year,4);
|
||||
strncpy(comment,tag->comment,30);
|
||||
|
||||
if ( tag->genre < sizeof(genre_table)/sizeof(*genre_table) ) {
|
||||
strncpy(genre, genre_table[tag->genre], 30);
|
||||
} else {
|
||||
strncpy(genre,"Unknown",30);
|
||||
}
|
||||
|
||||
fprintf(stderr,"Title : %-30s Artist: %s\n",title,artist);
|
||||
fprintf(stderr,"Album : %-30s Year : %4s\n",album,year);
|
||||
fprintf(stderr,"Comment: %-30s Genre : %s\n",comment,genre);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* removed the strndup for better portability */
|
||||
/*
|
||||
* Allocate space for a new string containing the first
|
||||
* "num" characters of "src". The resulting string is
|
||||
* always zero-terminated. Returns NULL if malloc fails.
|
||||
*/
|
||||
char *strndup (const char *src, int num)
|
||||
{
|
||||
char *dst;
|
||||
|
||||
if (!(dst = (char *) malloc(num+1)))
|
||||
return (NULL);
|
||||
dst[num] = '\0';
|
||||
return (strncpy(dst, src, num));
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Split "path" into directory and filename components.
|
||||
*
|
||||
* Return value is 0 if no directory was specified (i.e.
|
||||
* "path" does not contain a '/'), OR if the directory
|
||||
* is the same as on the previous call to this function.
|
||||
*
|
||||
* Return value is 1 if a directory was specified AND it
|
||||
* is different from the previous one (if any).
|
||||
*/
|
||||
|
||||
int split_dir_file (const char *path, char **dname, char **fname)
|
||||
{
|
||||
static char *lastdir = NULL;
|
||||
char *slashpos;
|
||||
|
||||
if ((slashpos = strrchr(path, '/'))) {
|
||||
*fname = slashpos + 1;
|
||||
*dname = strdup(path); /* , 1 + slashpos - path); */
|
||||
if(!(*dname)) {
|
||||
perror("memory");
|
||||
exit(1);
|
||||
}
|
||||
(*dname)[1 + slashpos - path] = 0;
|
||||
if (lastdir && !strcmp(lastdir, *dname)) {
|
||||
/*** same as previous directory ***/
|
||||
free (*dname);
|
||||
*dname = lastdir;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
/*** different directory ***/
|
||||
if (lastdir)
|
||||
free (lastdir);
|
||||
lastdir = *dname;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*** no directory specified ***/
|
||||
if (lastdir) {
|
||||
free (lastdir);
|
||||
lastdir = NULL;
|
||||
};
|
||||
*dname = NULL;
|
||||
*fname = (char *)path;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void set_pointer(long backstep)
|
||||
{
|
||||
bsi.wordpointer = bsbuf + ssize - backstep;
|
||||
if (backstep)
|
||||
memcpy(bsi.wordpointer,bsbufold+fsizeold-backstep,backstep);
|
||||
bsi.bitindex = 0;
|
||||
}
|
||||
|
||||
/********************************/
|
||||
|
||||
double compute_bpf(struct frame *fr)
|
||||
{
|
||||
double bpf;
|
||||
|
||||
switch(fr->lay) {
|
||||
case 1:
|
||||
bpf = tabsel_123[fr->lsf][0][fr->bitrate_index];
|
||||
bpf *= 12000.0 * 4.0;
|
||||
bpf /= freqs[fr->sampling_frequency] <<(fr->lsf);
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
bpf = tabsel_123[fr->lsf][fr->lay-1][fr->bitrate_index];
|
||||
bpf *= 144000;
|
||||
bpf /= freqs[fr->sampling_frequency] << (fr->lsf);
|
||||
break;
|
||||
default:
|
||||
bpf = 1.0;
|
||||
}
|
||||
|
||||
return bpf;
|
||||
}
|
||||
|
||||
double compute_tpf(struct frame *fr)
|
||||
{
|
||||
static int bs[4] = { 0,384,1152,1152 };
|
||||
double tpf;
|
||||
|
||||
tpf = (double) bs[fr->lay];
|
||||
tpf /= freqs[fr->sampling_frequency] << (fr->lsf);
|
||||
return tpf;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns number of frames queued up in output buffer, i.e.
|
||||
* offset between currently played and currently decoded frame.
|
||||
*/
|
||||
|
||||
long compute_buffer_offset(struct frame *fr)
|
||||
{
|
||||
long bufsize;
|
||||
|
||||
/*
|
||||
* buffermem->buf[0] holds output sampling rate,
|
||||
* buffermem->buf[1] holds number of channels,
|
||||
* buffermem->buf[2] holds audio format of output.
|
||||
*/
|
||||
|
||||
if(!param.usebuffer || !(bufsize=xfermem_get_usedspace(buffermem))
|
||||
|| !buffermem->buf[0] || !buffermem->buf[1])
|
||||
return 0;
|
||||
|
||||
bufsize = (long)((double) bufsize / buffermem->buf[0] /
|
||||
buffermem->buf[1] / compute_tpf(fr));
|
||||
|
||||
if((buffermem->buf[2] & AUDIO_FORMAT_MASK) == AUDIO_FORMAT_16)
|
||||
return bufsize/2;
|
||||
else
|
||||
return bufsize;
|
||||
}
|
||||
|
||||
void print_stat(struct frame *fr,int no,long buffsize,struct audio_info_struct *ai)
|
||||
{
|
||||
double bpf,tpf,tim1,tim2;
|
||||
double dt = 0.0;
|
||||
int sno,rno;
|
||||
char outbuf[256];
|
||||
|
||||
if(!rd || !fr)
|
||||
return;
|
||||
|
||||
outbuf[0] = 0;
|
||||
|
||||
#ifndef GENERIC
|
||||
{
|
||||
struct timeval t;
|
||||
fd_set serr;
|
||||
int n,errfd = fileno(stderr);
|
||||
|
||||
t.tv_sec=t.tv_usec=0;
|
||||
|
||||
FD_ZERO(&serr);
|
||||
FD_SET(errfd,&serr);
|
||||
n = select(errfd+1,NULL,&serr,NULL,&t);
|
||||
if(n <= 0)
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
bpf = compute_bpf(fr);
|
||||
tpf = compute_tpf(fr);
|
||||
|
||||
if(buffsize > 0 && ai && ai->rate > 0 && ai->channels > 0) {
|
||||
dt = (double) buffsize / ai->rate / ai->channels;
|
||||
if( (ai->format & AUDIO_FORMAT_MASK) == AUDIO_FORMAT_16)
|
||||
dt *= 0.5;
|
||||
}
|
||||
|
||||
rno = 0;
|
||||
sno = no;
|
||||
if(rd->filelen >= 0) {
|
||||
long t = rd->tell(rd);
|
||||
rno = (int)((double)(rd->filelen-t)/bpf);
|
||||
sno = (int)((double)t/bpf);
|
||||
}
|
||||
|
||||
sprintf(outbuf+strlen(outbuf),"\rFrame# %5d [%5d], ",sno,rno);
|
||||
|
||||
tim1 = sno*tpf-dt;
|
||||
tim2 = rno*tpf+dt;
|
||||
#if 0
|
||||
tim1 = tim1 < 0 ? 0.0 : tim1;
|
||||
#endif
|
||||
tim2 = tim2 < 0 ? 0.0 : tim2;
|
||||
|
||||
sprintf(outbuf+strlen(outbuf),"Time: %02u:%02u.%02u [%02u:%02u.%02u], ",
|
||||
(unsigned int)tim1/60,
|
||||
(unsigned int)tim1%60,
|
||||
(unsigned int)(tim1*100)%100,
|
||||
(unsigned int)tim2/60,
|
||||
(unsigned int)tim2%60,
|
||||
(unsigned int)(tim2*100)%100);
|
||||
|
||||
if(param.usebuffer)
|
||||
sprintf(outbuf+strlen(outbuf),"[%8ld] ",(long)buffsize);
|
||||
write(fileno(stderr),outbuf,strlen(outbuf));
|
||||
#if 0
|
||||
fflush(out); /* hmm not really nec. */
|
||||
#endif
|
||||
}
|
||||
|
||||
int get_songlen(struct frame *fr,int no)
|
||||
{
|
||||
double tpf;
|
||||
|
||||
if(!fr)
|
||||
return 0;
|
||||
|
||||
if(no < 0) {
|
||||
if(!rd || rd->filelen < 0)
|
||||
return 0;
|
||||
no = (double) rd->filelen / compute_bpf(fr);
|
||||
}
|
||||
|
||||
tpf = compute_tpf(fr);
|
||||
return no*tpf;
|
||||
}
|
||||
|
||||
|
19
panda/src/mpg123/common.h
Normal file
19
panda/src/mpg123/common.h
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* common.h
|
||||
*/
|
||||
|
||||
extern void print_id3_tag(unsigned char *buf);
|
||||
extern unsigned long firsthead;
|
||||
extern int tabsel_123[2][3][16];
|
||||
extern double compute_tpf(struct frame *fr);
|
||||
extern double compute_bpf(struct frame *fr);
|
||||
extern long compute_buffer_offset(struct frame *fr);
|
||||
|
||||
/*
|
||||
struct bitstream_info {
|
||||
int bitindex;
|
||||
unsigned char *wordpointer;
|
||||
};
|
||||
*/
|
||||
|
||||
|
263
panda/src/mpg123/genre.h
Normal file
263
panda/src/mpg123/genre.h
Normal file
@ -0,0 +1,263 @@
|
||||
char *genre_table[] =
|
||||
{
|
||||
"Blues",
|
||||
"Classic Rock",
|
||||
"Country",
|
||||
"Dance",
|
||||
"Disco",
|
||||
"Funk",
|
||||
"Grunge",
|
||||
"Hip-Hop",
|
||||
"Jazz",
|
||||
"Metal",
|
||||
"New Age",
|
||||
"Oldies",
|
||||
"Other",
|
||||
"Pop",
|
||||
"R&B",
|
||||
"Rap",
|
||||
"Reggae",
|
||||
"Rock",
|
||||
"Techno",
|
||||
"Industrial",
|
||||
"Alternative",
|
||||
"Ska",
|
||||
"Death Metal",
|
||||
"Pranks",
|
||||
"Soundtrack",
|
||||
"Euro-Techno",
|
||||
"Ambient",
|
||||
"Trip-Hop",
|
||||
"Vocal",
|
||||
"Jazz+Funk",
|
||||
"Fusion",
|
||||
"Trance",
|
||||
"Classical",
|
||||
"Instrumental",
|
||||
"Acid",
|
||||
"House",
|
||||
"Game",
|
||||
"Sound Clip",
|
||||
"Gospel",
|
||||
"Noise",
|
||||
"AlternRock",
|
||||
"Bass",
|
||||
"Soul",
|
||||
"Punk",
|
||||
"Space",
|
||||
"Meditative",
|
||||
"Instrumental Pop",
|
||||
"Instrumental Rock",
|
||||
"Ethnic",
|
||||
"Gothic",
|
||||
"Darkwave",
|
||||
"Techno-Industrial",
|
||||
"Electronic",
|
||||
"Pop-Folk",
|
||||
"Eurodance",
|
||||
"Dream",
|
||||
"Southern Rock",
|
||||
"Comedy",
|
||||
"Cult",
|
||||
"Gangsta",
|
||||
"Top 40",
|
||||
"Christian Rap",
|
||||
"Pop/Funk",
|
||||
"Jungle",
|
||||
"Native American",
|
||||
"Cabaret",
|
||||
"New Wave",
|
||||
"Psychadelic",
|
||||
"Rave",
|
||||
"Showtunes",
|
||||
"Trailer",
|
||||
"Lo-Fi",
|
||||
"Tribal",
|
||||
"Acid Punk",
|
||||
"Acid Jazz",
|
||||
"Polka",
|
||||
"Retro",
|
||||
"Musical",
|
||||
"Rock & Roll",
|
||||
"Hard Rock",
|
||||
"Folk",
|
||||
"Folk/Rock",
|
||||
"National folk",
|
||||
"Swing",
|
||||
"Fast-fusion",
|
||||
"Bebob",
|
||||
"Latin",
|
||||
"Revival",
|
||||
"Celtic",
|
||||
"Bluegrass",
|
||||
"Avantgarde",
|
||||
"Gothic Rock",
|
||||
"Progressive Rock",
|
||||
"Psychedelic Rock",
|
||||
"Symphonic Rock",
|
||||
"Slow Rock",
|
||||
"Big Band",
|
||||
"Chorus",
|
||||
"Easy Listening",
|
||||
"Acoustic",
|
||||
"Humour",
|
||||
"Speech",
|
||||
"Chanson",
|
||||
"Opera",
|
||||
"Chamber Music",
|
||||
"Sonata",
|
||||
"Symphony",
|
||||
"Booty Bass",
|
||||
"Primus",
|
||||
"Porn Groove",
|
||||
"Satire",
|
||||
"Slow Jam",
|
||||
"Club",
|
||||
"Tango",
|
||||
"Samba",
|
||||
"Folklore",
|
||||
"Ballad",
|
||||
"Powder Ballad",
|
||||
"Rhythmic Soul",
|
||||
"Freestyle",
|
||||
"Duet",
|
||||
"Punk Rock",
|
||||
"Drum Solo",
|
||||
"A Capella",
|
||||
"Euro-House",
|
||||
"Dance Hall",
|
||||
"Goa",
|
||||
"Drum & Bass",
|
||||
"Club House",
|
||||
"Hardcore",
|
||||
"Terror",
|
||||
"Indie",
|
||||
"BritPop",
|
||||
"NegerPunk",
|
||||
"Polsk Punk",
|
||||
"Beat",
|
||||
"Christian Gangsta",
|
||||
"Heavy Metal",
|
||||
"Black Metal",
|
||||
"Crossover",
|
||||
"Contemporary C",
|
||||
"Christian Rock",
|
||||
"Merengue",
|
||||
"Salsa",
|
||||
"Thrash Metal",
|
||||
"Anime",
|
||||
"JPop",
|
||||
"SynthPop"
|
||||
/* ,
|
||||
"Unknown",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
""
|
||||
*/
|
||||
};
|
||||
|
||||
const int genre_count = ((int)(sizeof(genre_table)/sizeof(char*))-1);
|
127
panda/src/mpg123/getbits.c
Normal file
127
panda/src/mpg123/getbits.c
Normal file
@ -0,0 +1,127 @@
|
||||
#include "mpg123.h"
|
||||
#include "common.h"
|
||||
|
||||
#if 0
|
||||
static void check_buffer_range(int size)
|
||||
{
|
||||
int pos = (bsi->wordpointer-bsbuf) + (size>>3);
|
||||
|
||||
if( pos >= fsizeold) {
|
||||
fprintf(stderr,"Pointer out of range (%d,%d)!\n",pos,fsizeold);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void backbits(struct bitstream_info *bsi,int number_of_bits)
|
||||
{
|
||||
bsi->bitindex -= number_of_bits;
|
||||
bsi->wordpointer += (bsi->bitindex>>3);
|
||||
bsi->bitindex &= 0x7;
|
||||
}
|
||||
|
||||
int getbitoffset(struct bitstream_info *bsi)
|
||||
{
|
||||
return (-bsi->bitindex)&0x7;
|
||||
}
|
||||
|
||||
int getbyte(struct bitstream_info *bsi)
|
||||
{
|
||||
#ifdef DEBUG_GETBITS
|
||||
if(bsi->bitindex)
|
||||
fprintf(stderr,"getbyte called unsynched!\n");
|
||||
#endif
|
||||
return *bsi->wordpointer++;
|
||||
}
|
||||
|
||||
unsigned int getbits(struct bitstream_info *bsi,int number_of_bits)
|
||||
{
|
||||
unsigned long rval;
|
||||
|
||||
#ifdef DEBUG_GETBITS
|
||||
fprintf(stderr,"g%d",number_of_bits);
|
||||
#endif
|
||||
|
||||
if(!number_of_bits)
|
||||
return 0;
|
||||
|
||||
#if 0
|
||||
check_buffer_range(number_of_bits+bsi->bitindex);
|
||||
#endif
|
||||
|
||||
{
|
||||
rval = bsi->wordpointer[0];
|
||||
rval <<= 8;
|
||||
rval |= bsi->wordpointer[1];
|
||||
rval <<= 8;
|
||||
rval |= bsi->wordpointer[2];
|
||||
|
||||
rval <<= bsi->bitindex;
|
||||
rval &= 0xffffff;
|
||||
|
||||
bsi->bitindex += number_of_bits;
|
||||
|
||||
rval >>= (24-number_of_bits);
|
||||
|
||||
bsi->wordpointer += (bsi->bitindex>>3);
|
||||
bsi->bitindex &= 7;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_GETBITS
|
||||
fprintf(stderr,":%x ",rval);
|
||||
#endif
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
unsigned int getbits_fast(struct bitstream_info *bsi,int number_of_bits)
|
||||
{
|
||||
unsigned int rval;
|
||||
#ifdef DEBUG_GETBITS
|
||||
fprintf(stderr,"g%d",number_of_bits);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
check_buffer_range(number_of_bits+bsi->bitindex);
|
||||
#endif
|
||||
|
||||
rval = (unsigned char) (bsi->wordpointer[0] << bsi->bitindex);
|
||||
rval |= ((unsigned int) bsi->wordpointer[1]<<bsi->bitindex)>>8;
|
||||
rval <<= number_of_bits;
|
||||
rval >>= 8;
|
||||
|
||||
bsi->bitindex += number_of_bits;
|
||||
|
||||
bsi->wordpointer += (bsi->bitindex>>3);
|
||||
bsi->bitindex &= 7;
|
||||
|
||||
#ifdef DEBUG_GETBITS
|
||||
fprintf(stderr,":%x ",rval);
|
||||
#endif
|
||||
return rval;
|
||||
}
|
||||
|
||||
unsigned int get1bit(struct bitstream_info *bsi)
|
||||
{
|
||||
unsigned char rval;
|
||||
|
||||
#ifdef DEBUG_GETBITS
|
||||
fprintf(stderr,"g%d",1);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
check_buffer_range(1+bsi->bitindex);
|
||||
#endif
|
||||
|
||||
rval = *(bsi->wordpointer) << bsi->bitindex;
|
||||
|
||||
bsi->bitindex++;
|
||||
bsi->wordpointer += (bsi->bitindex>>3);
|
||||
bsi->bitindex &= 7;
|
||||
|
||||
#ifdef DEBUG_GETBITS
|
||||
fprintf(stderr,":%d ",rval>>7);
|
||||
#endif
|
||||
|
||||
return rval>>7;
|
||||
}
|
||||
|
33
panda/src/mpg123/getbits.h
Normal file
33
panda/src/mpg123/getbits.h
Normal file
@ -0,0 +1,33 @@
|
||||
|
||||
/* that's the same file as getits.c but with defines to
|
||||
force inlining */
|
||||
|
||||
static unsigned long rval;
|
||||
static unsigned char rval_uc;
|
||||
|
||||
#define backbits(nob) ((void)( \
|
||||
bsi.bitindex -= (nob), \
|
||||
bsi.wordpointer += (bsi.bitindex>>3), \
|
||||
bsi.bitindex &= 0x7 ))
|
||||
|
||||
#define getbitoffset() ((-bsi.bitindex)&0x7)
|
||||
#define getbyte() (*bsi.wordpointer++)
|
||||
|
||||
#define getbits(nob) ( \
|
||||
rval = bsi.wordpointer[0], rval <<= 8, rval |= bsi.wordpointer[1], \
|
||||
rval <<= 8, rval |= bsi.wordpointer[2], rval <<= bsi.bitindex, \
|
||||
rval &= 0xffffff, bsi.bitindex += (nob), \
|
||||
rval >>= (24-(nob)), bsi.wordpointer += (bsi.bitindex>>3), \
|
||||
bsi.bitindex &= 7,rval)
|
||||
|
||||
#define getbits_fast(nob) ( \
|
||||
rval = (unsigned char) (bsi.wordpointer[0] << bsi.bitindex), \
|
||||
rval |= ((unsigned long) bsi.wordpointer[1]<<bsi.bitindex)>>8, \
|
||||
rval <<= (nob), rval >>= 8, \
|
||||
bsi.bitindex += (nob), bsi.wordpointer += (bsi.bitindex>>3), \
|
||||
bsi.bitindex &= 7, rval )
|
||||
|
||||
#define get1bit() ( \
|
||||
rval_uc = *bsi.wordpointer << bsi.bitindex, bsi.bitindex++, \
|
||||
bsi.wordpointer += (bsi.bitindex>>3), bsi.bitindex &= 7, rval_uc>>7 )
|
||||
|
411
panda/src/mpg123/mpg123.h
Normal file
411
panda/src/mpg123/mpg123.h
Normal file
@ -0,0 +1,411 @@
|
||||
/*
|
||||
* mpg123 defines
|
||||
* used source: musicout.h from mpegaudio package
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <sys/signal.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
|
||||
typedef unsigned char byte;
|
||||
|
||||
#ifdef OS2
|
||||
#include <float.h>
|
||||
#endif
|
||||
|
||||
#define MPG123_REMOTE
|
||||
#ifdef HPUX
|
||||
#define random rand
|
||||
#define srandom srand
|
||||
#endif
|
||||
|
||||
#define FRONTEND_NONE 0
|
||||
#define FRONTEND_SAJBER 1
|
||||
#define FRONTEND_TK3PLAY 2
|
||||
#define FRONTEND_GENERIC 3
|
||||
|
||||
#define SKIP_JUNK 1
|
||||
|
||||
#ifdef _WIN32 /* Win32 Additions By Tony Million */
|
||||
# undef WIN32
|
||||
# define WIN32
|
||||
|
||||
# define M_PI 3.14159265358979323846
|
||||
# define M_SQRT2 1.41421356237309504880
|
||||
# define REAL_IS_FLOAT
|
||||
# define NEW_DCT9
|
||||
|
||||
# define random rand
|
||||
# define srandom srand
|
||||
|
||||
# undef MPG123_REMOTE /* Get rid of this stuff for Win32 */
|
||||
#endif
|
||||
|
||||
#include "xfermem.h"
|
||||
|
||||
#ifdef SUNOS
|
||||
#define memmove(dst,src,size) bcopy(src,dst,size)
|
||||
#endif
|
||||
|
||||
#ifdef REAL_IS_FLOAT
|
||||
# define real float
|
||||
#elif defined(REAL_IS_LONG_DOUBLE)
|
||||
# define real long double
|
||||
#else
|
||||
# define real double
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define INLINE inline
|
||||
#else
|
||||
#define INLINE
|
||||
#endif
|
||||
|
||||
#include "audio.h"
|
||||
|
||||
/* AUDIOBUFSIZE = n*64 with n=1,2,3 ... */
|
||||
#define AUDIOBUFSIZE 16384
|
||||
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
|
||||
#define MAX_NAME_SIZE 81
|
||||
#define SBLIMIT 32
|
||||
#define SCALE_BLOCK 12
|
||||
#define SSLIMIT 18
|
||||
|
||||
#define MPG_MD_STEREO 0
|
||||
#define MPG_MD_JOINT_STEREO 1
|
||||
#define MPG_MD_DUAL_CHANNEL 2
|
||||
#define MPG_MD_MONO 3
|
||||
|
||||
#define MAXFRAMESIZE 1792
|
||||
#define HDRCMPMASK 0xfffffd00
|
||||
|
||||
#define MAXOUTBURST 32768
|
||||
|
||||
/* Pre Shift fo 16 to 8 bit converter table */
|
||||
#define AUSHIFT (3)
|
||||
|
||||
|
||||
struct al_table
|
||||
{
|
||||
short bits;
|
||||
short d;
|
||||
};
|
||||
|
||||
struct frame {
|
||||
struct al_table *alloc;
|
||||
int (*synth)(real *,int,unsigned char *,int *);
|
||||
int (*synth_mono)(real *,unsigned char *,int *);
|
||||
#ifdef USE_3DNOW
|
||||
void (*dct36)(real *,real *,real *,real *,real *);
|
||||
#endif
|
||||
int stereo;
|
||||
int jsbound;
|
||||
int single;
|
||||
int II_sblimit;
|
||||
int down_sample_sblimit;
|
||||
int lsf;
|
||||
int mpeg25;
|
||||
int down_sample;
|
||||
int header_change;
|
||||
int lay;
|
||||
int error_protection;
|
||||
int bitrate_index;
|
||||
int sampling_frequency;
|
||||
int padding;
|
||||
int extension;
|
||||
int mode;
|
||||
int mode_ext;
|
||||
int copyright;
|
||||
int original;
|
||||
int emphasis;
|
||||
int framesize; /* computed framesize */
|
||||
};
|
||||
|
||||
#define VBR_TOC_SIZE 100
|
||||
|
||||
#define VBR_FRAMES_FLAG 0x0001
|
||||
#define VBR_BYTES_FLAG 0x0002
|
||||
#define VBR_TOC_FLAG 0x0004
|
||||
#define VBR_SCALE_FLAG 0x0008
|
||||
|
||||
struct vbrHeader {
|
||||
unsigned long flags;
|
||||
unsigned long frames;
|
||||
unsigned long bytes;
|
||||
unsigned long scale;
|
||||
unsigned char toc[100];
|
||||
};
|
||||
|
||||
struct parameter {
|
||||
int aggressive; /* renice to max. priority */
|
||||
int shuffle; /* shuffle/random play */
|
||||
int remote; /* remote operation */
|
||||
int outmode; /* where to out the decoded sampels */
|
||||
int quiet; /* shut up! */
|
||||
int xterm_title; /* print filename in xterm title */
|
||||
long usebuffer; /* second level buffer size */
|
||||
int tryresync; /* resync stream after error */
|
||||
int verbose; /* verbose level */
|
||||
#ifdef TERM_CONTROL
|
||||
int term_ctrl;
|
||||
#endif
|
||||
int force_mono;
|
||||
int force_stereo;
|
||||
int force_8bit;
|
||||
long force_rate;
|
||||
int down_sample;
|
||||
int checkrange;
|
||||
long doublespeed;
|
||||
long halfspeed;
|
||||
int force_reopen;
|
||||
int stat_3dnow; /* automatic/force/force-off 3DNow! optimized code */
|
||||
int test_3dnow;
|
||||
long realtime;
|
||||
char filename[256];
|
||||
char *esdserver;
|
||||
char *equalfile;
|
||||
int enable_equalizer;
|
||||
long outscale;
|
||||
long startFrame;
|
||||
};
|
||||
|
||||
struct bitstream_info {
|
||||
int bitindex;
|
||||
unsigned char *wordpointer;
|
||||
};
|
||||
|
||||
struct mpstr {
|
||||
int bsize;
|
||||
int framesize;
|
||||
int fsizeold;
|
||||
struct frame fr;
|
||||
/* int (*do_layer)(struct mpstr *,struct frame *fr,int,struct audio_info_struct *); */
|
||||
unsigned char bsspace[2][MAXFRAMESIZE+512]; /* MAXFRAMESIZE */
|
||||
real hybrid_block[2][2][SBLIMIT*SSLIMIT];
|
||||
int hybrid_blc[2];
|
||||
unsigned long header;
|
||||
int bsnum;
|
||||
real synth_buffs[2][2][0x110];
|
||||
int synth_bo;
|
||||
|
||||
struct bitstream_info bsi;
|
||||
};
|
||||
|
||||
extern struct bitstream_info bsi;
|
||||
|
||||
struct reader {
|
||||
int (*init)(struct reader *);
|
||||
void (*close)(struct reader *);
|
||||
int (*head_read)(struct reader *,unsigned long *newhead);
|
||||
int (*head_shift)(struct reader *,unsigned long *head);
|
||||
int (*skip_bytes)(struct reader *,int len);
|
||||
int (*read_frame_body)(struct reader *,unsigned char *,int size);
|
||||
int (*back_bytes)(struct reader *,int bytes);
|
||||
int (*back_frame)(struct reader *,struct frame *,int num);
|
||||
long (*tell)(struct reader *);
|
||||
void (*rewind)(struct reader *);
|
||||
long filelen;
|
||||
long filepos;
|
||||
int filept;
|
||||
int flags;
|
||||
unsigned char id3buf[128];
|
||||
};
|
||||
#define READER_FD_OPENED 0x1
|
||||
#define READER_ID3TAG 0x2
|
||||
|
||||
extern struct reader *rd,readers[];
|
||||
|
||||
extern int halfspeed;
|
||||
extern int buffer_fd[2];
|
||||
extern txfermem *buffermem;
|
||||
extern char *prgName, *prgVersion;
|
||||
|
||||
#ifndef NOXFERMEM
|
||||
extern void buffer_loop(struct audio_info_struct *ai,sigset_t *oldsigset);
|
||||
#endif
|
||||
|
||||
|
||||
/* ------ Declarations from "httpget.c" ------ */
|
||||
|
||||
extern char *proxyurl;
|
||||
extern unsigned long proxyip;
|
||||
extern int http_open (char *url);
|
||||
extern char *httpauth;
|
||||
|
||||
/* ------ Declarations from "common.c" ------ */
|
||||
|
||||
extern void audio_flush(int, struct audio_info_struct *);
|
||||
extern void (*catchsignal(int signum, void(*handler)()))();
|
||||
|
||||
extern void print_header(struct frame *);
|
||||
extern void print_header_compact(struct frame *);
|
||||
extern void print_id3_tag(unsigned char *buf);
|
||||
|
||||
extern int split_dir_file(const char *path, char **dname, char **fname);
|
||||
|
||||
extern unsigned int get1bit(struct bitstream_info *);
|
||||
extern unsigned int getbits(struct bitstream_info *,int);
|
||||
extern unsigned int getbits_fast(struct bitstream_info *,int);
|
||||
extern void backbits(struct bitstream_info *,int);
|
||||
extern int getbitoffset(struct bitstream_info *);
|
||||
extern int getbyte(struct bitstream_info *);
|
||||
|
||||
extern void set_pointer(long);
|
||||
|
||||
extern unsigned char *pcm_sample;
|
||||
extern int pcm_point;
|
||||
extern int audiobufsize;
|
||||
|
||||
extern int OutputDescriptor;
|
||||
|
||||
struct gr_info_s {
|
||||
int scfsi;
|
||||
unsigned part2_3_length;
|
||||
unsigned big_values;
|
||||
unsigned scalefac_compress;
|
||||
unsigned block_type;
|
||||
unsigned mixed_block_flag;
|
||||
unsigned table_select[3];
|
||||
unsigned subblock_gain[3];
|
||||
unsigned maxband[3];
|
||||
unsigned maxbandl;
|
||||
unsigned maxb;
|
||||
unsigned region1start;
|
||||
unsigned region2start;
|
||||
unsigned preflag;
|
||||
unsigned scalefac_scale;
|
||||
unsigned count1table_select;
|
||||
real *full_gain[3];
|
||||
real *pow2gain;
|
||||
};
|
||||
|
||||
struct III_sideinfo
|
||||
{
|
||||
unsigned main_data_begin;
|
||||
unsigned private_bits;
|
||||
struct {
|
||||
struct gr_info_s gr[2];
|
||||
} ch[2];
|
||||
};
|
||||
|
||||
extern struct reader *open_stream(char *,int fd);
|
||||
extern void read_frame_init (void);
|
||||
extern int read_frame(struct frame *fr);
|
||||
extern int play_frame(struct mpstr *mp,int init,struct frame *fr);
|
||||
extern int do_layer3(struct mpstr *mp,struct frame *fr,int,struct audio_info_struct *);
|
||||
extern int do_layer2(struct mpstr *mp,struct frame *fr,int,struct audio_info_struct *);
|
||||
extern int do_layer1(struct mpstr *mp,struct frame *fr,int,struct audio_info_struct *);
|
||||
extern void do_equalizer(real *bandPtr,int channel);
|
||||
|
||||
#ifdef PENTIUM_OPT
|
||||
extern int synth_1to1_pent (real *,int,unsigned char *);
|
||||
#endif
|
||||
extern int synth_1to1 (real *,int,unsigned char *,int *);
|
||||
extern int synth_1to1_8bit (real *,int,unsigned char *,int *);
|
||||
extern int synth_1to1_mono (real *,unsigned char *,int *);
|
||||
extern int synth_1to1_mono2stereo (real *,unsigned char *,int *);
|
||||
extern int synth_1to1_8bit_mono (real *,unsigned char *,int *);
|
||||
extern int synth_1to1_8bit_mono2stereo (real *,unsigned char *,int *);
|
||||
|
||||
extern int synth_2to1 (real *,int,unsigned char *,int *);
|
||||
extern int synth_2to1_8bit (real *,int,unsigned char *,int *);
|
||||
extern int synth_2to1_mono (real *,unsigned char *,int *);
|
||||
extern int synth_2to1_mono2stereo (real *,unsigned char *,int *);
|
||||
extern int synth_2to1_8bit_mono (real *,unsigned char *,int *);
|
||||
extern int synth_2to1_8bit_mono2stereo (real *,unsigned char *,int *);
|
||||
|
||||
extern int synth_4to1 (real *,int,unsigned char *,int *);
|
||||
extern int synth_4to1_8bit (real *,int,unsigned char *,int *);
|
||||
extern int synth_4to1_mono (real *,unsigned char *,int *);
|
||||
extern int synth_4to1_mono2stereo (real *,unsigned char *,int *);
|
||||
extern int synth_4to1_8bit_mono (real *,unsigned char *,int *);
|
||||
extern int synth_4to1_8bit_mono2stereo (real *,unsigned char *,int *);
|
||||
|
||||
extern int synth_ntom (real *,int,unsigned char *,int *);
|
||||
extern int synth_ntom_8bit (real *,int,unsigned char *,int *);
|
||||
extern int synth_ntom_mono (real *,unsigned char *,int *);
|
||||
extern int synth_ntom_mono2stereo (real *,unsigned char *,int *);
|
||||
extern int synth_ntom_8bit_mono (real *,unsigned char *,int *);
|
||||
extern int synth_ntom_8bit_mono2stereo (real *,unsigned char *,int *);
|
||||
|
||||
extern void rewindNbits(int bits);
|
||||
extern int hsstell(void);
|
||||
extern void set_pointer(long);
|
||||
extern void huffman_decoder(int ,int *);
|
||||
extern void huffman_count1(int,int *);
|
||||
extern void print_stat(struct frame *fr,int no,long buffsize,struct audio_info_struct *ai);
|
||||
extern int get_songlen(struct frame *fr,int no);
|
||||
|
||||
extern void init_layer3(int);
|
||||
extern void init_layer2(void);
|
||||
extern void make_decode_tables(long scale);
|
||||
extern void make_conv16to8_table(int);
|
||||
extern void dct64(real *,real *,real *);
|
||||
|
||||
#ifdef USE_MMX
|
||||
extern void dct64_MMX(short *a,short *b,real *c);
|
||||
extern int synth_1to1_MMX(real *, int, short *, short *, int *);
|
||||
#endif
|
||||
|
||||
extern void synth_ntom_set_step(long,long);
|
||||
|
||||
extern void control_generic(struct mpstr *,struct frame *fr);
|
||||
extern void control_sajber(struct mpstr *,struct frame *fr);
|
||||
extern void control_tk3play(struct mpstr *,struct frame *fr);
|
||||
|
||||
extern int cdr_open(struct audio_info_struct *ai, char *ame);
|
||||
extern int au_open(struct audio_info_struct *ai, char *name);
|
||||
extern int wav_open(struct audio_info_struct *ai, char *wavfilename);
|
||||
extern int wav_write(unsigned char *buf,int len);
|
||||
extern int cdr_close(void);
|
||||
extern int au_close(void);
|
||||
extern int wav_close(void);
|
||||
|
||||
extern int au_open(struct audio_info_struct *ai, char *aufilename);
|
||||
extern int au_close(void);
|
||||
|
||||
extern int cdr_open(struct audio_info_struct *ai, char *cdrfilename);
|
||||
extern int cdr_close(void);
|
||||
|
||||
extern int getVBRHeader(struct vbrHeader *head,unsigned char *buf,
|
||||
struct frame *fr);
|
||||
|
||||
|
||||
extern unsigned char *conv16to8;
|
||||
extern long freqs[9];
|
||||
extern real muls[27][64];
|
||||
extern real decwin[512+32];
|
||||
#ifndef USE_MMX
|
||||
extern real *pnts[5];
|
||||
#endif
|
||||
|
||||
extern real equalizer[2][32];
|
||||
extern real equalizer_sum[2][32];
|
||||
extern int equalizer_cnt;
|
||||
|
||||
extern struct audio_name audio_val2name[];
|
||||
|
||||
extern struct parameter param;
|
||||
|
||||
/* 486 optimizations */
|
||||
#define FIR_BUFFER_SIZE 128
|
||||
extern void dct64_486(int *a,int *b,real *c);
|
||||
extern int synth_1to1_486(real *bandPtr,int channel,unsigned char *out,int nb_blocks);
|
||||
|
||||
/* 3DNow! optimizations */
|
||||
#ifdef USE_3DNOW
|
||||
extern int getcpuflags(void);
|
||||
extern void dct36(real *,real *,real *,real *,real *);
|
||||
extern void dct36_3dnow(real *,real *,real *,real *,real *);
|
||||
extern int synth_1to1_3dnow(real *,int,unsigned char *,int *);
|
||||
#endif
|
279
panda/src/mpg123/xfermem.c
Normal file
279
panda/src/mpg123/xfermem.c
Normal file
@ -0,0 +1,279 @@
|
||||
/*
|
||||
* xfermem.c
|
||||
*
|
||||
* Oliver Fromme <oliver.fromme@heim3.tu-clausthal.de>
|
||||
* Sun Apr 6 02:26:26 MET DST 1997
|
||||
*
|
||||
* See xfermem.h for documentation/description.
|
||||
*/
|
||||
|
||||
#ifndef NOXFERMEM
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/socket.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef AIX
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
|
||||
#include "mpg123.h"
|
||||
|
||||
#ifndef USE_MMAP
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#endif
|
||||
|
||||
extern int errno;
|
||||
|
||||
#if defined (USE_MMAP) && defined(MAP_ANONYMOUS) && !defined(MAP_ANON)
|
||||
#define MAP_ANON MAP_ANONYMOUS
|
||||
#endif
|
||||
|
||||
void xfermem_init (txfermem **xf, int bufsize, int msize, int skipbuf)
|
||||
{
|
||||
int regsize = bufsize + msize + skipbuf + sizeof(txfermem);
|
||||
extern int preload;
|
||||
|
||||
#ifdef USE_MMAP
|
||||
# ifdef MAP_ANON
|
||||
if ((*xf = (txfermem *) mmap(0, regsize, PROT_READ | PROT_WRITE,
|
||||
MAP_ANON | MAP_SHARED, -1, 0)) == (txfermem *) -1) {
|
||||
perror ("mmap()");
|
||||
exit (1);
|
||||
}
|
||||
# else
|
||||
int devzero;
|
||||
if ((devzero = open("/dev/zero", O_RDWR, 0)) == -1) {
|
||||
perror ("open(/dev/zero)");
|
||||
exit (1);
|
||||
}
|
||||
if ((*xf = (txfermem *) mmap(0, regsize, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, devzero, 0)) == (txfermem *) -1) {
|
||||
perror ("mmap()");
|
||||
exit (1);
|
||||
}
|
||||
close (devzero);
|
||||
# endif
|
||||
#else
|
||||
struct shmid_ds shmemds;
|
||||
int shmemid;
|
||||
if ((shmemid = shmget(IPC_PRIVATE, regsize, IPC_CREAT | 0600)) == -1) {
|
||||
perror ("shmget()");
|
||||
exit (1);
|
||||
}
|
||||
if ((*xf = (txfermem *) shmat(shmemid, 0, 0)) == (txfermem *) -1) {
|
||||
perror ("shmat()");
|
||||
shmctl (shmemid, IPC_RMID, &shmemds);
|
||||
exit (1);
|
||||
}
|
||||
if (shmctl(shmemid, IPC_RMID, &shmemds) == -1) {
|
||||
perror ("shmctl()");
|
||||
xfermem_done (*xf);
|
||||
exit (1);
|
||||
}
|
||||
#endif
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, (*xf)->fd) < 0) {
|
||||
perror ("socketpair()");
|
||||
xfermem_done (*xf);
|
||||
exit (1);
|
||||
}
|
||||
(*xf)->freeindex = (*xf)->readindex = 0;
|
||||
(*xf)->wakeme[0] = (*xf)->wakeme[1] = FALSE;
|
||||
(*xf)->data = ((byte *) *xf) + sizeof(txfermem) + msize;
|
||||
(*xf)->metadata = ((byte *) *xf) + sizeof(txfermem);
|
||||
(*xf)->size = bufsize;
|
||||
(*xf)->metasize = msize + skipbuf;
|
||||
preload = bufsize>>3;
|
||||
}
|
||||
|
||||
void xfermem_done (txfermem *xf)
|
||||
{
|
||||
if(!xf)
|
||||
return;
|
||||
#ifdef USE_MMAP
|
||||
munmap ((caddr_t) xf, xf->size + xf->metasize + sizeof(txfermem));
|
||||
#else
|
||||
if (shmdt((void *) xf) == -1) {
|
||||
perror ("shmdt()");
|
||||
exit (1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void xfermem_init_writer (txfermem *xf)
|
||||
{
|
||||
if(xf)
|
||||
close (xf->fd[XF_READER]);
|
||||
}
|
||||
|
||||
void xfermem_init_reader (txfermem *xf)
|
||||
{
|
||||
if(xf)
|
||||
close (xf->fd[XF_WRITER]);
|
||||
}
|
||||
|
||||
int xfermem_get_freespace (txfermem *xf)
|
||||
{
|
||||
int freeindex, readindex;
|
||||
|
||||
if(!xf)
|
||||
return 0;
|
||||
|
||||
if ((freeindex = xf->freeindex) < 0
|
||||
|| (readindex = xf->readindex) < 0)
|
||||
return (0);
|
||||
if (readindex > freeindex)
|
||||
return ((readindex - freeindex) - 1);
|
||||
else
|
||||
return ((xf->size - (freeindex - readindex)) - 1);
|
||||
}
|
||||
|
||||
int xfermem_get_usedspace (txfermem *xf)
|
||||
{
|
||||
int freeindex, readindex;
|
||||
|
||||
if(!xf)
|
||||
return 0;
|
||||
|
||||
if ((freeindex = xf->freeindex) < 0
|
||||
|| (readindex = xf->readindex) < 0)
|
||||
return (0);
|
||||
if (freeindex >= readindex)
|
||||
return (freeindex - readindex);
|
||||
else
|
||||
return (xf->size - (readindex - freeindex));
|
||||
}
|
||||
|
||||
int xfermem_getcmd (int fd, int block)
|
||||
{
|
||||
fd_set selfds;
|
||||
byte cmd;
|
||||
|
||||
for (;;) {
|
||||
struct timeval selto = {0, 0};
|
||||
|
||||
FD_ZERO (&selfds);
|
||||
FD_SET (fd, &selfds);
|
||||
/* #ifdef HPUX */ /* seems to trigger performance problems? strange */
|
||||
#if 0
|
||||
switch (select(FD_SETSIZE, (int *) &selfds, NULL, NULL, block ? NULL : &selto)) {
|
||||
#else
|
||||
switch (select(FD_SETSIZE, &selfds, NULL, NULL, block ? NULL : &selto)) {
|
||||
#endif
|
||||
case 0:
|
||||
if (!block)
|
||||
return (0);
|
||||
continue;
|
||||
case -1:
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
return (-2);
|
||||
case 1:
|
||||
if (FD_ISSET(fd, &selfds))
|
||||
switch (read(fd, &cmd, 1)) {
|
||||
case 0: /* EOF */
|
||||
return (-1);
|
||||
case -1:
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
return (-3);
|
||||
case 1:
|
||||
return (cmd);
|
||||
default: /* ?!? */
|
||||
return (-4);
|
||||
}
|
||||
else /* ?!? */
|
||||
return (-5);
|
||||
default: /* ?!? */
|
||||
return (-6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int xfermem_putcmd (int fd, byte cmd)
|
||||
{
|
||||
for (;;) {
|
||||
switch (write(fd, &cmd, 1)) {
|
||||
case 1:
|
||||
return (1);
|
||||
case -1:
|
||||
if (errno != EINTR)
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int xfermem_block (int readwrite, txfermem *xf)
|
||||
{
|
||||
int myfd = xf->fd[readwrite];
|
||||
int result;
|
||||
|
||||
xf->wakeme[readwrite] = TRUE;
|
||||
if (xf->wakeme[1 - readwrite])
|
||||
xfermem_putcmd (myfd, XF_CMD_WAKEUP);
|
||||
result = xfermem_getcmd(myfd, TRUE);
|
||||
xf->wakeme[readwrite] = FALSE;
|
||||
return ((result <= 0) ? -1 : result);
|
||||
}
|
||||
|
||||
#elif defined(WIN32)
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "xfermem.h"
|
||||
|
||||
extern int errno;
|
||||
|
||||
void xfermem_init (txfermem **xf, int bufsize, int msize, int skipbuf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
void xfermem_done (txfermem *xf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
void xfermem_init_writer (txfermem *xf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
void xfermem_init_reader (txfermem *xf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int xfermem_get_freespace (txfermem *xf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int xfermem_get_usedspace (txfermem *xf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int xfermem_getcmd (int fd, int block)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int xfermem_putcmd (int fd, byte cmd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int xfermem_block (int readwrite, txfermem *xf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* eof */
|
||||
|
60
panda/src/mpg123/xfermem.h
Normal file
60
panda/src/mpg123/xfermem.h
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* xfermem.h
|
||||
*
|
||||
* Oliver Fromme <oliver.fromme@heim3.tu-clausthal.de>
|
||||
* Sat Mar 29 04:41:34 MET 1997
|
||||
*
|
||||
* This is a stand-alone module which implements a unidirectional,
|
||||
* fast pipe using mmap(). Its primary use is to transfer large
|
||||
* amounts of data from a parent process to its child process,
|
||||
* with a buffer in between which decouples blocking conditions
|
||||
* on both sides. Control information is transferred between the
|
||||
* processes through a socketpair. See xftest.c for an example on
|
||||
* how to use this module.
|
||||
*/
|
||||
|
||||
#ifndef TRUE
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
int freeindex; /* [W] next free index */
|
||||
int readindex; /* [R] next index to read */
|
||||
int fd[2];
|
||||
int wakeme[2];
|
||||
byte *data;
|
||||
byte *metadata;
|
||||
int size;
|
||||
int metasize;
|
||||
int buf[3];
|
||||
} txfermem;
|
||||
/*
|
||||
* [W] -- May be written to by the writing process only!
|
||||
* [R] -- May be written to by the reading process only!
|
||||
* All other entries are initialized once.
|
||||
*/
|
||||
|
||||
void xfermem_init (txfermem **xf, int bufsize, int msize,int skipbuf);
|
||||
void xfermem_init_writer (txfermem *xf);
|
||||
void xfermem_init_reader (txfermem *xf);
|
||||
|
||||
int xfermem_write (txfermem *xf, byte *data, int count);
|
||||
int xfermem_read (txfermem *xf, byte *data, int count);
|
||||
|
||||
int xfermem_get_freespace (txfermem *xf);
|
||||
int xfermem_get_usedspace (txfermem *xf);
|
||||
#define XF_CMD_WAKEUP_INFO 0x04
|
||||
#define XF_CMD_WAKEUP 0x02
|
||||
#define XF_CMD_TERMINATE 0x03
|
||||
#define XF_WRITER 0
|
||||
#define XF_READER 1
|
||||
int xfermem_getcmd (int fd, int block);
|
||||
int xfermem_putcmd (int fd, byte cmd);
|
||||
int xfermem_block (int fd, txfermem *xf);
|
||||
|
||||
void xfermem_done (txfermem *xf);
|
||||
#define xfermem_done_writer xfermem_init_reader
|
||||
#define xfermem_done_reader xfermem_init_writer
|
||||
|
||||
/* EOF */
|
Loading…
x
Reference in New Issue
Block a user