diff --git a/programs/media/ac97snd/ac97snd.sln b/programs/media/ac97snd/ac97snd.sln
index 06659561e7..2dae87d64c 100644
--- a/programs/media/ac97snd/ac97snd.sln
+++ b/programs/media/ac97snd/ac97snd.sln
@@ -1,22 +1,24 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ac97snd", "ac97snd\ac97snd.vcproj", "{5146AAEE-C15C-47C5-A245-64050C820145}"
- ProjectSection(ProjectDependencies) = postProject
- {6BB005B0-3277-4C8C-950F-38E15A4E440C} = {6BB005B0-3277-4C8C-950F-38E15A4E440C}
- EndProjectSection
-EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mpg", "mpg\mpg.vcproj", "{6BB005B0-3277-4C8C-950F-38E15A4E440C}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ac97snd", "ac97snd\ac97snd.vcproj", "{5146AAEE-C15C-47C5-A245-64050C820145}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {5146AAEE-C15C-47C5-A245-64050C820145}.Release|Win32.ActiveCfg = Release|Win32
- {5146AAEE-C15C-47C5-A245-64050C820145}.Release|Win32.Build.0 = Release|Win32
+ {6BB005B0-3277-4C8C-950F-38E15A4E440C}.Debug|Win32.ActiveCfg = Debug|Win32
+ {6BB005B0-3277-4C8C-950F-38E15A4E440C}.Debug|Win32.Build.0 = Debug|Win32
{6BB005B0-3277-4C8C-950F-38E15A4E440C}.Release|Win32.ActiveCfg = Release|Win32
{6BB005B0-3277-4C8C-950F-38E15A4E440C}.Release|Win32.Build.0 = Release|Win32
+ {5146AAEE-C15C-47C5-A245-64050C820145}.Debug|Win32.ActiveCfg = Debug|Win32
+ {5146AAEE-C15C-47C5-A245-64050C820145}.Debug|Win32.Build.0 = Debug|Win32
+ {5146AAEE-C15C-47C5-A245-64050C820145}.Release|Win32.ActiveCfg = Release|Win32
+ {5146AAEE-C15C-47C5-A245-64050C820145}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/programs/media/ac97snd/ac97snd/ac97snd.vcproj b/programs/media/ac97snd/ac97snd/ac97snd.vcproj
index 60da8ea256..9bf64a965a 100644
--- a/programs/media/ac97snd/ac97snd/ac97snd.vcproj
+++ b/programs/media/ac97snd/ac97snd/ac97snd.vcproj
@@ -14,7 +14,7 @@
@@ -141,7 +141,8 @@
+
+
+
> Vol- Vol+";
+char header[] = "AC97 MP3 player";
+char buttons_xm[] = " Play Stop Vol- Vol+"; /* uFMOD integration */
+char buttons_wav[] = " Play Stop << >> Vol- Vol+"; /* uFMOD integration */
+char *buttons_text = buttons_wav; /* uFMOD integration */
+
+void play_xm(); /* uFMOD integration */
void (*snd_play)();
void draw_window()
{
+ int len; /* uFMOD integration */
BeginDraw();
DrawWindow(100,100,299,72,0x404040,3,0,0,0);
@@ -85,19 +95,20 @@ void draw_window()
draw_bar(7,41,286,11,0x404040);
draw_bar(7,55,286,11,0x404040);
- write_text(12,58,0x004000|FONT0, fname, strlen(fname));
- write_text(11,57,0x00FF20|FONT0, fname, strlen(fname));
+ len = strlen(filename); /* uFMOD integration */
+ if(len > 47) len = 47; /* uFMOD integration */
+ write_text(11,57,0x00FF20|FONT0, filename, len); /* uFMOD integration */
- write_text(8,8,0xFFFFFF|FONT0, header, strlen(header));
- write_text(12,28,0x404040|FONT0,buttons_text,strlen(buttons_text));
- write_text(11,27,0xA0FFA0|FONT0,buttons_text,strlen(buttons_text));
+ write_text(8,8,FONT0, header, sizeof(header)-1); /* uFMOD integration */
+ write_text(12,28,0x404040|FONT0,buttons_text,sizeof(buttons_wav)-1); /* uFMOD integration */
+ write_text(11,27,0xA0FFA0|FONT0,buttons_text,sizeof(buttons_wav)-1); /* uFMOD integration */
EndDraw();
};
void draw_progress_bar()
{ DWORD x;
- x = 287.0f * (float)(rd.filepos-rd.strremain)/(float)fileinfo.size;
+ x = (DWORD)(287.0f * (float)(rd.filepos-rd.strremain)/(float)fileinfo.size); /* uFMOD integration */
if(x==0) return;
draw_bar(7,41,x,11,0xA0A0A0);
draw_bar(x+7,41,287-x,11,0x404040);
@@ -119,6 +130,7 @@ int main(int argc, char *argv[]) //int argc, char *argv[])
int retval;
int err;
int ver;
+ unsigned char *ttl, *cur; /* uFMOD integration */
fname = argv[1];
debug_out_str("\n\rPlay file ");
@@ -157,28 +169,74 @@ int main(int argc, char *argv[]) //int argc, char *argv[])
create_reader(&rd, inpbuf, 0x10000);
init_reader(&rd,fname);
-
- fmt = test_wav((WAVEHEADER*)testbuff);
- if (fmt != 0)
+
+ filename = strrchr(fname,'/')+1;
+ if( !(fileext = strrchr(filename,'.')))
+ return 0;
+
+ if(!_stricmp(fileext,".mp3"))
{
- snd_play = &play_wave;
- set_reader(&rd, 44);
- outbuf = UserAlloc(32*1024);
- touch(outbuf, 32768);
- }
- else
- { fmt = test_mp3(testbuff);
- if(fmt ==0) return 0;
- snd_play = &play_mp3;
-
- outremain = 0x40000 ;
- outbuf = UserAlloc(outremain);
- touch(outbuf, outremain);
- make_decode_tables(32767);
- init_layer2();
- init_layer3(32);
- fr.single = -1;
+ fmt = test_mp3(testbuff);
+ if(!fmt)
+ {
+ debug_out_str("\n\rInvalid MP3 file");
+ return 0;
+ };
+ snd_play = &play_mp3;
+ outremain = 0x40000;
+ outbuf = UserAlloc(outremain);
+ touch(outbuf, outremain);
+ make_decode_tables(32767);
+ init_layer2();
+ init_layer3(32);
+ fr.single = -1;
+ goto play;
};
+
+ if(!_stricmp(fileext,".xm"))
+ {
+ if(uFMOD_LoadSong(fname))
+ {
+ buttons_text = buttons_xm; /* uFMOD integration */
+ fmt = PCM_2_16_48; /* uFMOD integration */
+ snd_play = &play_xm; /* uFMOD integration */
+ ttl = uFMOD_GetTitle(); /* uFMOD integration */
+ cur = ttl; /* uFMOD integration */
+ err = 0; /* uFMOD integration */
+ while(*cur && *cur++ != ' ') err++; /* uFMOD integration */
+ if(err){ /* uFMOD integration */
+ cur = fname; /* uFMOD integration */
+ while(*cur) cur++; /* uFMOD integration */
+ *cur++ = ' '; /* uFMOD integration */
+ *cur++ = '|'; /* uFMOD integration */
+ *cur++ = ' '; /* uFMOD integration */
+ while(*ttl) *cur++ = *ttl++; /* uFMOD integration */
+ }
+ goto play;
+ }
+ debug_out_str("\n\rInvalid XM file");
+ return 0;
+ };
+
+ if(!_stricmp(fileext, ".wav"))
+ {
+ fmt = test_wav((WAVEHEADER*)testbuff);
+ if(fmt)
+ {
+ snd_play = &play_wave;
+ set_reader(&rd, 44);
+ outbuf = UserAlloc(32*1024);
+ touch(outbuf, 32768);
+ goto play;
+ }
+ debug_out_str("\n\rInvalid WAV file");
+ return 0;
+ };
+
+ debug_out_str("\n\rUsupported file");
+ return 0;
+
+play:
status = ST_PLAY;
@@ -206,6 +264,7 @@ int main(int argc, char *argv[]) //int argc, char *argv[])
continue;
case ST_EXIT:
+ uFMOD_StopSong(); /* uFMOD integration */
StopBuffer(hBuff);
DestroyBuffer(hBuff);
return 0;
@@ -217,7 +276,7 @@ int main(int argc, char *argv[]) //int argc, char *argv[])
void touch(char *buf, int size)
{ int i;
char a;
- for ( i = 0;i < size; i+=4096)
+ for ( i = 0;i < size; i+=4096) //alloc all pages
a = buf[i];
};
@@ -231,13 +290,20 @@ DWORD test_mp3(char *buf)
if(!rd.head_read(&rd,&hdr))
return 0;
if(!decode_header(&fr,hdr))
- { rd.strpos-=3;
- rd.stream-=3;
- rd.strremain+=3;
- continue;
+ {
+ if((hdr & 0xffffff00) == 0x49443300)
+ {
+ int id3length = 0;
+ id3length = parse_new_id3(&rd, hdr);
+ continue;
+ };
+ rd.strpos-=3;
+ rd.stream-=3;
+ rd.strremain+=3;
+ continue;
};
break;
- };
+ };
first_sync = rd.filepos-rd.strremain-4;
@@ -245,7 +311,7 @@ DWORD test_mp3(char *buf)
whdr.riff_format = 0x45564157;
whdr.wFormatTag = 0x01;
whdr.nSamplesPerSec = freqs[fr.sampling_frequency];
- whdr.nChannels = 2; //mpginfo.channels;
+ whdr.nChannels = 2;
whdr.wBitsPerSample = 16;
return test_wav(&whdr);
@@ -324,26 +390,35 @@ void play_mp3()
};
void play_wave()
-{ int retval;
+{ int count;
set_reader(&rd,44);
- retval = 0;
while(1)
{
if(status!=ST_PLAY)
break;
- if( !stream_read_raw(&rd,outbuf,32768))
- { done = 1;
- break;
- };
- WaveOut(hBuff,outbuf,32768);
+ if( count=stream_read_raw(&rd,outbuf,32768))
+ {
+ WaveOut(hBuff,outbuf,count);
+ continue;
+ }
+ done = 1;
+ break;
};
if(status != ST_EXIT)
- status = ST_STOP;
+ status = ST_STOP;
};
+void play_xm(){ /* uFMOD integration */
+ while(status == ST_PLAY){ /* uFMOD integration */
+ uFMOD_WaveOut(hBuff); /* uFMOD integration */
+ delay(8); /* uFMOD integration */
+ } /* uFMOD integration */
+ if(status != ST_EXIT) status = ST_STOP; /* uFMOD integration */
+} /* uFMOD integration */
+
void snd_stop()
{
StopBuffer(hBuff);
@@ -519,7 +594,7 @@ void EndDraw()
};
///*********
-void *memmove ( void * dst, void * src, int count)
+void *memmove ( void * dst, void * src, unsigned int count) /* uFMOD integration */
{ void *ret;
ret = dst;
@@ -555,6 +630,40 @@ void * __cdecl mem_cpy(void * dst,const void * src,size_t count)
return(ret);
}
+char * __cdecl strrchr (const char * string,int ch)
+{
+ char *start = (char *)string;
+
+ while (*string++) /* find end of string */
+ ;
+ /* search towards front */
+ while (--string != start && *string != (char)ch)
+ ;
+
+ if (*string == (char)ch) /* char found ? */
+ return( (char *)string );
+
+ return(NULL);
+}
+
+int __cdecl _stricmp (const char * dst, const char * src)
+{
+ int f, l;
+
+ do
+ {
+ if ( ((f = (unsigned char)(*(dst++))) >= 'A') && (f <= 'Z') )
+ f -= 'A' - 'a';
+ if ( ((l = (unsigned char)(*(src++))) >= 'A') && (l <= 'Z') )
+ l -= 'A' - 'a';
+ }
+ while ( f && (f == l) );
+
+ return(f - l);
+}
+
+
+
// debug_out_str(formats[fmt]);
// debug_out_str("\x0D\x0A\x00");
@@ -584,6 +693,3 @@ void * __cdecl mem_cpy(void * dst,const void * src,size_t count)
// debug_out_hex(fmt);
// debug_out_str("\x0D\x0A\x00");
-
-
-
diff --git a/programs/media/ac97snd/mpg/mpg.vcproj b/programs/media/ac97snd/mpg/mpg.vcproj
index 454e1b56c8..d80ff3ccb6 100644
--- a/programs/media/ac97snd/mpg/mpg.vcproj
+++ b/programs/media/ac97snd/mpg/mpg.vcproj
@@ -14,7 +14,7 @@
@@ -229,6 +229,16 @@
+
+
+
-#include
-#ifndef _AUDIO_H_
-#define _AUDIO_H_
-
-typedef unsigned char byte;
-#define off_t long
-
-//#define I486_OPT 1
-
-#define SKIP_JUNK 1
-# define M_PI 3.14159265358979323846
-# define M_SQRT2 1.41421356237309504880
-# define REAL_IS_FLOAT
-# define NEW_DCT9
-
-#ifdef REAL_IS_FLOAT
-# define real float
-# define REAL_SCANF "%f"
-# define REAL_PRINTF "%f"
-#else
-# define real double
-# define REAL_SCANF "%lf"
-# define REAL_PRINTF "%f"
-#endif
-
-#ifndef DOUBLE_TO_REAL
-# define DOUBLE_TO_REAL(x) (x)
-#endif
-#ifndef REAL_TO_SHORT
-# define REAL_TO_SHORT(x) (x)
-#endif
-#ifndef REAL_PLUS_32767
-# define REAL_PLUS_32767 32767.0
-#endif
-#ifndef REAL_MINUS_32768
-# define REAL_MINUS_32768 -32768.0
-#endif
-#ifndef REAL_MUL
-# define REAL_MUL(x, y) ((x) * (y))
-#endif
-
-#define INLINE
-/* 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
-
-/* I suspect that 32767 would be a better idea here, but Michael put this in... */
-#define MAXOUTBURST 32768
-
-/* Pre Shift fo 16 to 8 bit converter table */
-#define AUSHIFT (3)
-
-struct bitstream_info
-{ int bitindex;
- unsigned char *wordpointer;
-};
-extern struct bitstream_info bsi;
-
-struct reader
-{
- char *hFile;
- unsigned char *buffer;
- unsigned char *stream;
- int strpos;
- int strremain;
- int filelen;
- int filepos;
-
- int (*head_read)(struct reader *,unsigned long *newhead);
- int (*read_frame_body)(struct reader *,unsigned char *,int size);
- };
-
+
+#include
+#include
+#ifndef _AUDIO_H_
+#define _AUDIO_H_
+
+typedef unsigned char byte;
+#define off_t long
+
+//#define I486_OPT 1
+
+#define SKIP_JUNK 1
+# define M_PI 3.14159265358979323846
+# define M_SQRT2 1.41421356237309504880
+# define REAL_IS_FLOAT
+# define NEW_DCT9
+
+#ifdef REAL_IS_FLOAT
+# define real float
+# define REAL_SCANF "%f"
+# define REAL_PRINTF "%f"
+#else
+# define real double
+# define REAL_SCANF "%lf"
+# define REAL_PRINTF "%f"
+#endif
+
+#ifndef DOUBLE_TO_REAL
+# define DOUBLE_TO_REAL(x) (x)
+#endif
+#ifndef REAL_TO_SHORT
+# define REAL_TO_SHORT(x) (x)
+#endif
+#ifndef REAL_PLUS_32767
+# define REAL_PLUS_32767 32767.0
+#endif
+#ifndef REAL_MINUS_32768
+# define REAL_MINUS_32768 -32768.0
+#endif
+#ifndef REAL_MUL
+# define REAL_MUL(x, y) ((x) * (y))
+#endif
+
+#define INLINE
+/* 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
+
+/* I suspect that 32767 would be a better idea here, but Michael put this in... */
+#define MAXOUTBURST 32768
+
+/* Pre Shift fo 16 to 8 bit converter table */
+#define AUSHIFT (3)
+
+struct bitstream_info
+{ int bitindex;
+ unsigned char *wordpointer;
+};
+extern struct bitstream_info bsi;
+
+struct reader
+{
+ char *hFile;
+ unsigned char *buffer;
+ unsigned char *stream;
+ int strpos;
+ int strremain;
+ int filelen;
+ int filepos;
+
+ int (*head_read)(struct reader *,unsigned long *newhead);
+ int (*read_frame_body)(struct reader *,unsigned char *,int size);
+ };
+
int parse_new_id3(struct reader *rd, unsigned long newhead);
-
-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 *);
- int stereo; /* I _think_ 1 for mono and 2 for stereo */
- int jsbound;
- int single;
- int II_sblimit;
- int down_sample_sblimit;
- int lsf; /* 0: MPEG 1.0; 1: MPEG 2.0/2.5 -- both used as bool and array index! */
- int mpeg25;
- int down_sample;
- int header_change;
- int lay;
- int (*do_layer)(struct frame *fr,byte *pcm_out, int *pcm_size);
- 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 */
- int vbr; /* 1 if variable bitrate was detected */
- unsigned long num; /* the nth frame in some stream... */
-};
-
-#if 0
-struct parameter {
- int aggressive; /* renice to max. priority */
- int shuffle; /* shuffle/random play */
- int remote; /* remote operation */
- int remote_err; /* remote operation to stderr */
- int outmode; /* where to out the decoded sampels */
- int quiet; /* shut up! */
- int xterm_title; /* Change xterm title to song names? */
- long usebuffer; /* second level buffer size */
- int tryresync; /* resync stream after error */
- int verbose; /* verbose level */
- int force_mono;
- int force_stereo;
- int force_8bit;
- long force_rate;
- int down_sample;
- int checkrange;
- long doublespeed;
- long halfspeed;
- int force_reopen;
- long realtime;
- char filename[256];
- long listentry; /* possibility to choose playback of one entry in playlist (0: off, > 0 : select, < 0; just show list*/
- int rva; /* (which) rva to do: <0: nothing, 0: radio/mix/track 1: album/audiophile */
- char* listname; /* name of playlist */
- int long_id3;
-};
-#endif
-
-#if 0
-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);
- long (*skip_bytes)(struct reader *,off_t len);
- int (*read_frame_body)(struct reader *,unsigned char *,int size);
- int (*back_bytes)(struct reader *,off_t bytes);
- int (*back_frame)(struct reader *,struct frame *,long num);
- off_t (*tell)(struct reader *);
- void (*rewind)(struct reader *);
- off_t filelen;
- off_t filepos;
- int filept;
- int flags;
- unsigned char id3buf[128];
-};
-#endif
-
-#define READER_FD_OPENED 0x1
-#define READER_ID3TAG 0x2
-#define READER_SEEKABLE 0x4
-
-//extern void audio_flush(int, struct audio_info_struct *);
-
-//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(void);
-extern unsigned int getbits(int);
-extern unsigned int getbits_fast(int);
-//extern void backbits(int);
-//extern int getbitoffset(void);
-//extern int getbyte(void);
-
-//extern void set_pointer(long);
-
-//extern unsigned char *pcm_sample;
-//extern int pcm_point;
-//extern int audiobufsize;
-
-//extern int OutputDescriptor;
-
-#ifdef VARMODESUPPORT
-extern int varmode;
-extern int playlimit;
-#endif
-
-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 int open_stream(char *,int fd);
-extern void read_frame_init (struct frame* fr);
-int read_frame(struct reader *rd, struct frame *fr);
-
-
-/* why extern? */
-void prepare_audioinfo(struct frame *fr, struct audio_info_struct *nai);
-int play_frame(int init,struct frame *fr);
-int do_layer1(struct frame *fr,byte *pcm_sample, int *pcm_point);
-int do_layer2(struct frame *fr,byte *pcm_sample, int *pcm_point);
-int do_layer3(struct frame *fr,byte *pcm_sample, int *pcm_point);
-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,unsigned long 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 int 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 int synth_ntom_set_step(long,long);
-
-
-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
-
-/* avoid the SIGINT in terminal control */
-void next_track(void);
-extern long outscale;
-
-#endif
-
-void set_pointer(long backstep);
-int __stdcall create_reader(struct reader *rd,byte *buffer, int buffsize);
-int __stdcall init_reader(struct reader *rd, char *file);
-int __stdcall decode_header(struct frame *fr,unsigned long newhead);
-int __stdcall set_reader(struct reader *rd, unsigned int filepos);
+
+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 *);
+ int stereo; /* I _think_ 1 for mono and 2 for stereo */
+ int jsbound;
+ int single;
+ int II_sblimit;
+ int down_sample_sblimit;
+ int lsf; /* 0: MPEG 1.0; 1: MPEG 2.0/2.5 -- both used as bool and array index! */
+ int mpeg25;
+ int down_sample;
+ int header_change;
+ int lay;
+ int (*do_layer)(struct frame *fr,byte *pcm_out, int *pcm_size);
+ 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 */
+ int vbr; /* 1 if variable bitrate was detected */
+ unsigned long num; /* the nth frame in some stream... */
+};
+
+#if 0
+struct parameter {
+ int aggressive; /* renice to max. priority */
+ int shuffle; /* shuffle/random play */
+ int remote; /* remote operation */
+ int remote_err; /* remote operation to stderr */
+ int outmode; /* where to out the decoded sampels */
+ int quiet; /* shut up! */
+ int xterm_title; /* Change xterm title to song names? */
+ long usebuffer; /* second level buffer size */
+ int tryresync; /* resync stream after error */
+ int verbose; /* verbose level */
+ int force_mono;
+ int force_stereo;
+ int force_8bit;
+ long force_rate;
+ int down_sample;
+ int checkrange;
+ long doublespeed;
+ long halfspeed;
+ int force_reopen;
+ long realtime;
+ char filename[256];
+ long listentry; /* possibility to choose playback of one entry in playlist (0: off, > 0 : select, < 0; just show list*/
+ int rva; /* (which) rva to do: <0: nothing, 0: radio/mix/track 1: album/audiophile */
+ char* listname; /* name of playlist */
+ int long_id3;
+};
+#endif
+
+#if 0
+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);
+ long (*skip_bytes)(struct reader *,off_t len);
+ int (*read_frame_body)(struct reader *,unsigned char *,int size);
+ int (*back_bytes)(struct reader *,off_t bytes);
+ int (*back_frame)(struct reader *,struct frame *,long num);
+ off_t (*tell)(struct reader *);
+ void (*rewind)(struct reader *);
+ off_t filelen;
+ off_t filepos;
+ int filept;
+ int flags;
+ unsigned char id3buf[128];
+};
+#endif
+
+#define READER_FD_OPENED 0x1
+#define READER_ID3TAG 0x2
+#define READER_SEEKABLE 0x4
+
+//extern void audio_flush(int, struct audio_info_struct *);
+
+//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(void);
+extern unsigned int getbits(int);
+extern unsigned int getbits_fast(int);
+//extern void backbits(int);
+//extern int getbitoffset(void);
+//extern int getbyte(void);
+
+//extern void set_pointer(long);
+
+//extern unsigned char *pcm_sample;
+//extern int pcm_point;
+//extern int audiobufsize;
+
+//extern int OutputDescriptor;
+
+#ifdef VARMODESUPPORT
+extern int varmode;
+extern int playlimit;
+#endif
+
+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 int open_stream(char *,int fd);
+extern void read_frame_init (struct frame* fr);
+int read_frame(struct reader *rd, struct frame *fr);
+
+
+/* why extern? */
+void prepare_audioinfo(struct frame *fr, struct audio_info_struct *nai);
+int play_frame(int init,struct frame *fr);
+int do_layer1(struct frame *fr,byte *pcm_sample, int *pcm_point);
+int do_layer2(struct frame *fr,byte *pcm_sample, int *pcm_point);
+int do_layer3(struct frame *fr,byte *pcm_sample, int *pcm_point);
+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,unsigned long 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 int 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 int synth_ntom_set_step(long,long);
+
+
+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
+
+/* avoid the SIGINT in terminal control */
+void next_track(void);
+extern long outscale;
+
+#endif
+
+void set_pointer(long backstep);
+int __stdcall create_reader(struct reader *rd,byte *buffer, int buffsize);
+int __stdcall init_reader(struct reader *rd, char *file);
+int __stdcall decode_header(struct frame *fr,unsigned long newhead);
+int __stdcall set_reader(struct reader *rd, unsigned int filepos);
double pow_test(double, double);
void * __cdecl mem_cpy(void * dst,const void * src,size_t count);
-void init_dct();
+void init_dct();
void reset_mpg();
#ifdef __cplusplus
}
diff --git a/programs/media/ac97snd/mpg/readers.c b/programs/media/ac97snd/mpg/readers.c
index 046bbadbd7..9133f59e43 100644
--- a/programs/media/ac97snd/mpg/readers.c
+++ b/programs/media/ac97snd/mpg/readers.c
@@ -1,955 +1,969 @@
-#include "mpg123.h"
-#include "..\kolibri.h"
-
-#define MAXFRAMESIZE 3456
-
-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;
-
-struct bitstream_info bsi;
-
-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,} }
-};
-
-int freqs[9] = { 44100, 48000, 32000, 22050, 24000, 16000 , 11025 , 12000 , 8000 };
-
-int stream_head_read(struct reader *rd,unsigned long *newhead);
-int stream_read_raw(struct reader *rd,unsigned char *buf, int size);
-
-void set_synth_functions(struct frame *fr)
-{
-#ifdef USE_3DNOW
- static func_dct36 funcs_dct36[2] = {dct36 , dct36_3dnow};
-#endif
-
- fr->synth = synth_1to1;
- fr->synth_mono = synth_1to1_mono2stereo;;
-
-/* TODO: make autodetection for _all_ x86 optimizations (maybe just for i586+ and keep separate 486 build?) */
-#ifdef USE_3DNOW
- /* check cpuflags bit 31 (3DNow!) and 23 (MMX) */
- if((param.stat_3dnow < 2) &&
- ((param.stat_3dnow == 1) ||
- (getcpuflags() & 0x80800000) == 0x80800000))
- {
- fr->synth = funcs[2][ds]; /* 3DNow! optimized synth_1to1() */
- fr->dct36 = funcs_dct36[1]; /* 3DNow! optimized dct36() */
- }
- else
- {
- fr->dct36 = funcs_dct36[0];
- }
-#endif
-}
-
-int __stdcall create_reader(struct reader *rd,byte *buffer, int buffsize)
-{ rd->head_read = stream_head_read;
- rd->read_frame_body = stream_read_raw;
-
- rd->buffer = buffer;
- rd->stream = buffer;
- rd->strpos = 0;
-
- rd->strremain = 0;
- rd->filepos = 0;
- return 1;
-};
-
-int __stdcall init_reader(struct reader *rd, char *file)
-{ FILEINFO fileinfo;
- int retval;
- int bytes;
-
- rd->hFile = file;
+#include "mpg123.h"
+#include "..\kolibri.h"
+
+#define MAXFRAMESIZE 3456
+
+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;
+
+struct bitstream_info bsi;
+
+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,} }
+};
+
+int freqs[9] = { 44100, 48000, 32000, 22050, 24000, 16000 , 11025 , 12000 , 8000 };
+
+int stream_head_read(struct reader *rd,unsigned long *newhead);
+int stream_read_raw(struct reader *rd,unsigned char *buf, int size);
+
+void set_synth_functions(struct frame *fr)
+{
+#ifdef USE_3DNOW
+ static func_dct36 funcs_dct36[2] = {dct36 , dct36_3dnow};
+#endif
+
+ fr->synth = synth_1to1;
+ fr->synth_mono = synth_1to1_mono2stereo;;
+
+/* TODO: make autodetection for _all_ x86 optimizations (maybe just for i586+ and keep separate 486 build?) */
+#ifdef USE_3DNOW
+ /* check cpuflags bit 31 (3DNow!) and 23 (MMX) */
+ if((param.stat_3dnow < 2) &&
+ ((param.stat_3dnow == 1) ||
+ (getcpuflags() & 0x80800000) == 0x80800000))
+ {
+ fr->synth = funcs[2][ds]; /* 3DNow! optimized synth_1to1() */
+ fr->dct36 = funcs_dct36[1]; /* 3DNow! optimized dct36() */
+ }
+ else
+ {
+ fr->dct36 = funcs_dct36[0];
+ }
+#endif
+}
+
+int __stdcall create_reader(struct reader *rd,byte *buffer, int buffsize)
+{ rd->head_read = stream_head_read;
+ rd->read_frame_body = stream_read_raw;
+
+ rd->buffer = buffer;
+ rd->stream = buffer;
+ rd->strpos = 0;
+
+ rd->strremain = 0;
+ rd->filepos = 0;
+ return 1;
+};
+
+int __stdcall init_reader(struct reader *rd, char *file)
+{ FILEINFO fileinfo;
+ int retval;
+ int bytes;
+
+ rd->hFile = file;
get_fileinfo(file, &fileinfo);
- rd->filelen = fileinfo.size;
- rd->strpos = 0;
+ rd->filelen = fileinfo.size;
+ rd->strpos = 0;
retval=read_file (file,rd->buffer,0,0x10000,&bytes);
+
+ if( (retval==0)||(retval==6))
+ {
+ rd->strremain=bytes;
+ rd->filepos=bytes;
+ rd->strpos = 0;
+ return 1;
+ };
+ return 0;
+};
+
+static int fill_reader(struct reader *rd)
+{ int retval;
+ int bytes;
+
+ if(rd->strremain > 0)
+ mem_cpy(rd->buffer,rd->stream,rd->strremain);
+
+ rd->stream = rd->buffer;
+ retval=read_file (rd->hFile,rd->buffer+rd->strremain,rd->filepos,
+ 0x10000-rd->strremain,&bytes);
+ if( (retval==0)||(retval==6))
+ {
+ rd->strremain+=bytes;
+ rd->filepos+=bytes;
+ rd->strpos = 0;
+ return bytes;
+ };
+ return 0;
+};
+
+int __stdcall set_reader(struct reader *rd, unsigned int filepos)
+{ int retval;
+ unsigned int bytes;
+ retval=read_file (rd->hFile,rd->buffer,filepos,0x10000,&bytes);
+ if( (retval==0)||(retval==6))
+ {
+ rd->stream = rd->buffer;
+ rd->strremain=bytes;
+ rd->filepos=filepos+bytes;
+ rd->strpos = 0;
+
+ fsizeold=0;
+ firsthead=0;
+ bsbufold = 0;
+ bsbuf = bsspace[1];
+ bsnum = 0;
+ ssize=0;
+ oldhead=0;
+ memset(bsspace,0,sizeof(bsspace));
+ return 1;
+ };
+ return 0;
+};
+
+static int stream_head_read(struct reader *rd,unsigned long *newhead)
+{
+ if(rd->strremain < 4)
+ if( !fill_reader(rd))
+ return 0;
+ *newhead = (rd->stream[0]<<24)|(rd->stream[1] << 16)|
+ (rd->stream[2] << 8)| rd->stream[3];
+ rd->strpos+=4;
+ rd->stream+=4;
+ rd->strremain-=4;
+ return TRUE;
+};
+
+int stream_read_raw(struct reader *rd,unsigned char *buf, int size)
+{
+
+ if(rd->strremain < size) fill_reader(rd);
+
+ if(size > rd->strremain) size=rd->strremain;
+
+ if(size>0)
+ {
+ mem_cpy(buf,rd->stream,size);
+ rd->strpos+=size;
+ rd->stream+=size;
+ rd->strremain-=size;
+ return size;
+ };
+ return 0;
+};
+
+void set_pointer(long backstep)
+{
+ bsi.wordpointer = bsbuf + ssize - backstep;
+ if (backstep)
+ mem_cpy(bsi.wordpointer,bsbufold+fsizeold-backstep,backstep);
+ bsi.bitindex = 0;
+}
+
+int head_check(unsigned long head)
+{ if
+ (
+ /* first 11 bits are set to 1 for frame sync */
+ ((head & 0xffe00000) != 0xffe00000)
+ ||
+ /* layer: 01,10,11 is 1,2,3; 00 is reserved */
+ (!((head>>17)&3))
+ ||
+ /* 1111 means bad bitrate */
+ (((head>>12)&0xf) == 0xf)
+ ||
+ /* 0000 means free format... */
+ (((head>>12)&0xf) == 0x0)
+ ||
+ /* sampling freq: 11 is reserved */
+ (((head>>10)&0x3) == 0x3 )
+ /* here used to be a mpeg 2.5 check... re-enabled 2.5 decoding due to lack of evidence that it is really not good */
+ )
+ {
+ return FALSE;
+ }
+ /* if no check failed, the header is valid (hopefully)*/
+ else
+ {
+ return TRUE;
+ }
+}
+
+int __stdcall decode_header(struct frame *fr,unsigned long newhead)
+{
+ if(!head_check(newhead))
+ return 0;
+ if( newhead & (1<<20) )
+ { fr->lsf = (newhead & (1<<19)) ? 0x0 : 0x1;
+ fr->mpeg25 = 0;
+ }
+ else
+ { fr->lsf = 1;
+ fr->mpeg25 = 1;
+ };
+
+ fr->lay = 4-((newhead>>17)&3);
+ 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)
+ return (0);
+
+ switch(fr->lay)
+ { case 1:
+ fr->do_layer = do_layer1;
+#ifdef VARMODESUPPORT
+ if (varmode) {
+ error("Sorry, layer-1 not supported in varmode.");
+ return (0);
+ }
+#endif
+ 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->do_layer = do_layer2;
+#ifdef VARMODESUPPORT
+ if (varmode) {
+ error("Sorry, layer-2 not supported in varmode.");
+ return (0);
+ }
+#endif
+ 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:
+ fr->do_layer = do_layer3;
+ 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:
+ return (0);
+ }
+ if (fr->framesize > MAXFRAMESIZE)
+ return (0);
+ return 1;
+}
+
+
+int read_frame(struct reader *rd, struct frame *fr)
+{ unsigned long newhead;
+ static unsigned char ssave[34];
+ //off_t framepos;
+ fsizeold=fr->framesize; /* for Layer3 */
+
+read_again:
+
+ if(!rd->head_read(rd,&newhead))
+ return FALSE;
+
+ if(!decode_header(fr,newhead))
+ {
+ if((newhead & 0xffffff00) == 0x49443300)
+ {
+ int id3length = 0;
+ id3length = parse_new_id3(rd, newhead);
+ goto read_again;
+ };
+ rd->strpos-=3;
+ rd->stream-=3;
+ rd->strremain+=3;
+ goto read_again;
+ };
+
+#if 0
+ if(1 || oldhead != newhead || !oldhead)
+ {
+
+init_resync:
+
+#ifdef SKIP_JUNK
+ /* watch out for junk/tags on beginning of stream by invalid header */
+ if(!firsthead && !head_check(newhead) && !free_format_header(newhead)) {
+ int i;
+
+ /* check for id3v2; first three bytes (of 4) are "ID3" */
+ if((newhead & (unsigned long) 0xffffff00) == (unsigned long) 0x49443300)
+ {
+ int id3length = 0;
+ id3length = parse_new_id3(newhead, rd);
+ goto read_again;
+ }
+ else if(param.verbose > 1) fprintf(stderr,"Note: Junk at the beginning (0x%08lx)\n",newhead);
+
+ /* I even saw RIFF headers at the beginning of MPEG streams ;( */
+ if(newhead == ('R'<<24)+('I'<<16)+('F'<<8)+'F') {
+ if(param.verbose > 1) fprintf(stderr, "Note: Looks like a RIFF header.\n");
+ 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;
+ if(param.verbose > 1) fprintf(stderr,"Note: Skipped RIFF header!\n");
+ goto read_again;
+ }
+ /* unhandled junk... just continue search for a header */
+ /* 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)) */
+ if(head_check(newhead) && decode_header(fr, newhead))
+ break;
+ }
+ if(i == 65536) {
+ if(!param.quiet) error("Giving up searching valid MPEG header after 64K of junk.");
+ 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
+
+ /* first attempt of read ahead check to find the real first header; cannot believe what junk is out there! */
+ /* for now, a spurious first free format header screws up here; need free format support for detecting false free format headers... */
+ if(!firsthead && rd->flags & READER_SEEKABLE && head_check(newhead) && decode_header(fr, newhead))
+ {
+ unsigned long nexthead = 0;
+ int hd = 0;
+ off_t start = rd->tell(rd);
+ debug1("doing ahead check with BPF %d", fr->framesize+4);
+ /* step framesize bytes forward and read next possible header*/
+ if(rd->back_bytes(rd, -fr->framesize))
+ {
+ error("cannot seek!");
+ return 0;
+ }
+ hd = rd->head_read(rd,&nexthead);
+ if(rd->back_bytes(rd, rd->tell(rd)-start))
+ {
+ error("cannot seek!");
+ return 0;
+ }
+ if(!hd)
+ {
+ warning("cannot read next header, a one-frame stream? Duh...");
+ }
+ else
+ {
+ debug2("does next header 0x%08lx match first 0x%08lx?", nexthead, newhead);
+ /* not allowing free format yet */
+ if(!head_check(nexthead) || (nexthead & HDRCMPMASK) != (newhead & HDRCMPMASK))
+ {
+ debug("No, the header was not valid, start from beginning...");
+ /* try next byte for valid header */
+ if(rd->back_bytes(rd, 3))
+ {
+ error("cannot seek!");
+ return 0;
+ }
+ goto read_again;
+ }
+ }
+ }
+
+ /* why has this head check been avoided here before? */
+ if(!head_check(newhead))
+ {
+ if(!firsthead && free_format_header(newhead))
+ {
+ error1("Header 0x%08lx seems to indicate a free format stream; I do not handle that yet", newhead);
+ goto read_again;
+ return 0;
+ }
+ /* and those ugly ID3 tags */
+ if((newhead & 0xffffff00) == ('T'<<24)+('A'<<16)+('G'<<8)) {
+ rd->skip_bytes(rd,124);
+ if (param.verbose > 1) fprintf(stderr,"Note: Skipped ID3 Tag!\n");
+ goto read_again;
+ }
+ /* duplicated code from above! */
+ /* check for id3v2; first three bytes (of 4) are "ID3" */
+ if((newhead & (unsigned long) 0xffffff00) == (unsigned long) 0x49443300)
+ {
+ int id3length = 0;
+ id3length = parse_new_id3(newhead, rd);
+ goto read_again;
+ }
+ else if (give_note)
+ {
+ fprintf(stderr,"Note: Illegal Audio-MPEG-Header 0x%08lx at offset 0x%lx.\n", newhead,rd->tell(rd)-4);
+ }
+
+ if(give_note && (newhead & 0xffffff00) == ('b'<<24)+('m'<<16)+('p'<<8)) fprintf(stderr,"Note: Could be a BMP album art.\n");
+ if (param.tryresync || do_recover) {
+ int try = 0;
+ /* TODO: make this more robust, I'd like to cat two mp3 fragments together (in a dirty way) and still have mpg123 beign able to decode all it somehow. */
+ if(give_note) fprintf(stderr, "Note: Trying to resync...\n");
+ /* 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 {
+ if(!rd->head_shift(rd,&newhead))
+ return 0;
+ /* debug2("resync try %i, got newhead 0x%08lx", try, newhead); */
+ if (!oldhead)
+ {
+ debug("going to init_resync...");
+ goto init_resync; /* "considered harmful", eh? */
+ }
+ /* we should perhaps collect a list of valid headers that occured in file... there can be more */
+ /* Michael's new resync routine seems to work better with the one frame readahead (and some input buffering?) */
+ } while
+ (
+ ++try < RESYNC_LIMIT
+ && (newhead & HDRCMPMASK) != (oldhead & HDRCMPMASK)
+ && (newhead & HDRCMPMASK) != (firsthead & HDRCMPMASK)
+ );
+ /* too many false positives
+ }while (!(head_check(newhead) && decode_header(fr, newhead))); */
+ if(try == RESYNC_LIMIT)
+ {
+ error("giving up resync - your stream is not nice... perhaps an improved routine could catch up");
+ return 0;
+ }
+
+ if (give_note)
+ fprintf (stderr, "Note: Skipped %d bytes in input.\n", try);
+ }
+ else
+ {
+ error("not attempting to resync...");
+ return (0);
+ }
+ }
+
+ if (!firsthead) {
+ if(!decode_header(fr,newhead))
+ {
+ error("decode header failed before first valid one, going to read again");
+ goto read_again;
+ }
+ }
+ else
+ if(!decode_header(fr,newhead))
+ {
+ error("decode header failed - goto resync");
+ /* return 0; */
+ goto init_resync;
+ }
+ }
+ else
+ fr->header_change = 0;
+#endif
+
+ bsbufold = bsbuf;
+ bsbuf = bsspace[bsnum]+512;
+ bsnum = (bsnum + 1) & 1;
+ /* if filepos is invalid, so is framepos */
+ //framepos = rd->filepos - 4;
+ /* read main data into memory */
+ /* 0 is error! */
+
+ if(rd->read_frame_body(rd,bsbuf,fr->framesize) < fr->framesize)
+ return 0;
+
+#if 0
+ if(!firsthead)
+ {
+ /* following stuff is actually layer3 specific (in practice, not in theory) */
+ if(fr->lay == 3)
+ {
+ /*
+ going to look for Xing or Info at some position after the header
+ MPEG 1 MPEG 2/2.5 (LSF)
+ Stereo, Joint Stereo, Dual Channel 32 17
+ Mono 17 9
+
+ Also, how to avoid false positives? I guess I should interpret more of the header to rule that out(?).
+ I hope that ensuring all zeros until tag start is enough.
+ */
+ size_t lame_offset = (fr->stereo == 2) ? (fr->lsf ? 17 : 32 ) : (fr->lsf ? 9 : 17);
+ if(fr->framesize >= 120+lame_offset) /* traditional Xing header is 120 bytes */
+ {
+ size_t i;
+ int lame_type = 0;
+ /* only search for tag when all zero before it (apart from checksum) */
+ for(i=2; i < lame_offset; ++i) if(bsbuf[i] != 0) break;
+ if(i == lame_offset)
+ {
+ if
+ (
+ (bsbuf[lame_offset] == 'I')
+ && (bsbuf[lame_offset+1] == 'n')
+ && (bsbuf[lame_offset+2] == 'f')
+ && (bsbuf[lame_offset+3] == 'o')
+ )
+ {
+ lame_type = 1; /* We still have to see what there is */
+ }
+ else if
+ (
+ (bsbuf[lame_offset] == 'X')
+ && (bsbuf[lame_offset+1] == 'i')
+ && (bsbuf[lame_offset+2] == 'n')
+ && (bsbuf[lame_offset+3] == 'g')
+ )
+ {
+ lame_type = 2;
+ vbr = VBR; /* Xing header means always VBR */
+ }
+ if(lame_type)
+ {
+ unsigned long xing_flags;
+
+ /* we have one of these headers... */
+ if(param.verbose > 1) fprintf(stderr, "Note: Xing/Lame/Info header detected\n");
+ /* now interpret the Xing part, I have 120 bytes total for sure */
+ /* there are 4 bytes for flags, but only the last byte contains known ones */
+ lame_offset += 4; /* now first byte after Xing/Name */
+ /* 4 bytes dword for flags */
+ #define make_long(a, o) ((((unsigned long) a[o]) << 24) | (((unsigned long) a[o+1]) << 16) | (((unsigned long) a[o+2]) << 8) | ((unsigned long) a[o+3]))
+ /* 16 bit */
+ #define make_short(a,o) ((((unsigned short) a[o]) << 8) | ((unsigned short) a[o+1]))
+ xing_flags = make_long(bsbuf, lame_offset);
+ lame_offset += 4;
+ debug1("Xing: flags 0x%08lx", xing_flags);
+ if(xing_flags & 1) /* frames */
+ {
+ /*
+ In theory, one should use that value for skipping...
+ When I know the exact number of samples I could simply count in audio_flush,
+ but that's problematic with seeking and such.
+ I still miss the real solution for detecting the end.
+ */
+ track_frames = make_long(bsbuf, lame_offset);
+ if(track_frames > TRACK_MAX_FRAMES) track_frames = 0; /* endless stream? */
+ #ifdef GAPLESS
+ /* if no further info there, remove/add at least the decoder delay */
+ if(param.gapless)
+ {
+ unsigned long length = track_frames * spf(fr);
+ if(length > 1)
+ layer3_gapless_init(DECODER_DELAY+GAP_SHIFT, length+DECODER_DELAY+GAP_SHIFT);
+ }
+ #endif
+ debug1("Xing: %lu frames", track_frames);
+ lame_offset += 4;
+ }
+ if(xing_flags & 0x2) /* bytes */
+ {
+ #ifdef DEBUG
+ unsigned long xing_bytes = make_long(bsbuf, lame_offset);
+ debug1("Xing: %lu bytes", xing_bytes);
+ #endif
+ lame_offset += 4;
+ }
+ if(xing_flags & 0x4) /* TOC */
+ {
+ lame_offset += 100; /* just skip */
+ }
+ if(xing_flags & 0x8) /* VBR quality */
+ {
+ #ifdef DEBUG
+ unsigned long xing_quality = make_long(bsbuf, lame_offset);
+ debug1("Xing: quality = %lu", xing_quality);
+ #endif
+ lame_offset += 4;
+ }
+ /* I guess that either 0 or LAME extra data follows */
+ /* there may this crc16 be floating around... (?) */
+ if(bsbuf[lame_offset] != 0)
+ {
+ unsigned char lame_vbr;
+ float replay_gain[2] = {0,0};
+ float peak = 0;
+ float gain_offset = 0; /* going to be +6 for old lame that used 83dB */
+ char nb[10];
+ memcpy(nb, bsbuf+lame_offset, 9);
+ nb[9] = 0;
+ debug1("Info: Encoder: %s", nb);
+ if(!strncmp("LAME", nb, 4))
+ {
+ gain_offset = 6;
+ debug("TODO: finish lame detetcion...");
+ }
+ lame_offset += 9;
+ /* the 4 big bits are tag revision, the small bits vbr method */
+ lame_vbr = bsbuf[lame_offset] & 15;
+ debug1("Info: rev %u", bsbuf[lame_offset] >> 4);
+ debug1("Info: vbr mode %u", lame_vbr);
+ lame_offset += 1;
+ switch(lame_vbr)
+ {
+ /* from rev1 proposal... not sure if all good in practice */
+ case 1:
+ case 8: vbr = CBR; break;
+ case 2:
+ case 9: vbr = ABR; break;
+ default: vbr = VBR; /* 00==unknown is taken as VBR */
+ }
+ /* skipping: lowpass filter value */
+ lame_offset += 1;
+ /* replaygain */
+ /* 32bit float: peak amplitude -- why did I parse it as int before??*/
+ /* Ah, yes, lame seems to store it as int since some day in 2003; I've only seen zeros anyway until now, bah! */
+ if
+ (
+ (bsbuf[lame_offset] != 0)
+ || (bsbuf[lame_offset+1] != 0)
+ || (bsbuf[lame_offset+2] != 0)
+ || (bsbuf[lame_offset+3] != 0)
+ )
+ {
+ debug("Wow! Is there _really_ a non-zero peak value? Now is it stored as float or int - how should I know?");
+ peak = *(float*) (bsbuf+lame_offset);
+ }
+ debug1("Info: peak = %f (I won't use this)", peak);
+ peak = 0; /* until better times arrived */
+ lame_offset += 4;
+ /*
+ ReplayGain values - lame only writes radio mode gain...
+ 16bit gain, 3 bits name, 3 bits originator, sign (1=-, 0=+), dB value*10 in 9 bits (fixed point)
+ ignore the setting if name or originator == 000!
+ radio 0 0 1 0 1 1 1 0 0 1 1 1 1 1 0 1
+ audiophile 0 1 0 0 1 0 0 0 0 0 0 1 0 1 0 0
+ */
+
+ for(i =0; i < 2; ++i)
+ {
+ unsigned char origin = (bsbuf[lame_offset] >> 2) & 0x7; /* the 3 bits after that... */
+ if(origin != 0)
+ {
+ unsigned char gt = bsbuf[lame_offset] >> 5; /* only first 3 bits */
+ if(gt == 1) gt = 0; /* radio */
+ else if(gt == 2) gt = 1; /* audiophile */
+ else continue;
+ /* get the 9 bits into a number, divide by 10, multiply sign... happy bit banging */
+ replay_gain[0] = ((bsbuf[lame_offset] & 0x2) ? -0.1 : 0.1) * (make_short(bsbuf, lame_offset) & 0x1f);
+ }
+ lame_offset += 2;
+ }
+ debug1("Info: Radio Gain = %03.1fdB", replay_gain[0]);
+ debug1("Info: Audiophile Gain = %03.1fdB", replay_gain[1]);
+ for(i=0; i < 2; ++i)
+ {
+ if(rva_level[i] <= 0)
+ {
+ rva_peak[i] = 0; /* at some time the parsed peak should be used */
+ rva_gain[i] = replay_gain[i];
+ rva_level[i] = 0;
+ }
+ }
+ lame_offset += 1; /* skipping encoding flags byte */
+ if(vbr == ABR)
+ {
+ abr_rate = bsbuf[lame_offset];
+ debug1("Info: ABR rate = %u", abr_rate);
+ }
+ lame_offset += 1;
+ /* encoder delay and padding, two 12 bit values... lame does write them from int ...*/
+ #ifdef GAPLESS
+ if(param.gapless)
+ {
+ /*
+ Temporary hack that doesn't work with seeking and also is not waterproof but works most of the time;
+ in future the lame delay/padding and frame number info should be passed to layer3.c and the junk samples avoided at the source.
+ */
+ unsigned long length = track_frames * spf(fr);
+ unsigned long skipbegin = DECODER_DELAY + ((((int) bsbuf[lame_offset]) << 4) | (((int) bsbuf[lame_offset+1]) >> 4));
+ unsigned long skipend = -DECODER_DELAY + (((((int) bsbuf[lame_offset+1]) << 8) | (((int) bsbuf[lame_offset+2]))) & 0xfff);
+ debug3("preparing gapless mode for layer3: length %lu, skipbegin %lu, skipend %lu", length, skipbegin, skipend);
+ if(length > 1)
+ layer3_gapless_init(skipbegin+GAP_SHIFT, (skipend < length) ? length-skipend+GAP_SHIFT : length+GAP_SHIFT);
+ }
+ #endif
+ }
+ /* switch buffer back ... */
+ bsbuf = bsspace[bsnum]+512;
+ bsnum = (bsnum + 1) & 1;
+ goto read_again;
+ }
+ }
+ }
+ } /* end block for Xing/Lame/Info tag */
+ firsthead = newhead; /* _now_ it's time to store it... the first real header */
+ debug1("firsthead: %08lx", firsthead);
+ /* now adjust volume */
+ do_rva();
+ /* and print id3 info */
+ if(!param.quiet) print_id3_tag(rd->flags & READER_ID3TAG ? rd->id3buf : NULL);
+ }
+#endif
+
+ bsi.bitindex = 0;
+ bsi.wordpointer = (unsigned char *) bsbuf;
+ set_synth_functions(fr);
+ if (fr->error_protection)
+ getbits(16);
+ return 1;
+}
+
+
+#if 0
+
+static int stream_back_bytes(struct reader *rds, off_t bytes)
+{
+ if(stream_lseek(rds,-bytes,SEEK_CUR) < 0)
+ return -1;
+ /* you sure you want the buffer to resync here? */
+ if(param.usebuffer)
+ buffer_resync();
+ return 0;
+}
+
+
+/* this function strangely is define to seek num frames _back_ (and is called with -offset - duh!) */
+/* also... let that int be a long in future! */
+static int stream_back_frame(struct reader *rds,struct frame *fr,long num)
+{
+ if(rds->flags & READER_SEEKABLE)
+ {
+ unsigned long newframe, preframe;
+ if(num > 0) /* back! */
+ {
+ if(num > fr->num) newframe = 0;
+ else newframe = fr->num-num;
+ }
+ else newframe = fr->num-num;
+
+ /* two leading frames? hm, doesn't seem to be really needed... */
+ /*if(newframe > 1) newframe -= 2;
+ else newframe = 0;*/
+
+ /* now seek to nearest leading index position and read from there until newframe is reached */
+ if(stream_lseek(rds,frame_index_find(newframe, &preframe),SEEK_SET) < 0)
+ return -1;
+
+ debug2("going to %lu; just got %lu", newframe, preframe);
+
+ fr->num = preframe;
+
+ while(fr->num < newframe)
+ {
+ /* try to be non-fatal now... frameNum only gets advanced on success anyway */
+ if(!read_frame(fr)) break;
+ }
+
+ /* this is not needed at last? */
+ /*read_frame(fr);
+ read_frame(fr);*/
+
+ if(fr->lay == 3) {
+ set_pointer(512);
+ }
+
+ debug1("arrived at %lu", fr->num);
+
+ if(param.usebuffer)
+ buffer_resync();
+
+ return 0;
+
+ }
+ else return -1; /* invalid, no seek happened */
+}
+
+static int stream_head_read(struct reader *rds,unsigned long *newhead)
+{
+ unsigned char hbuf[4];
+
+ if(fullread(rds,hbuf,4) != 4)
+ return FALSE;
- if (retval) return 0;
-
- rd->strremain = bytes;
- rd->filepos = bytes;
- return 1;
-};
-
-static int fill_reader(struct reader *rd)
-{ int retval;
- int bytes;
-
- mem_cpy(rd->buffer,rd->stream,rd->strremain);
- rd->stream = rd->buffer;
-
- retval=read_file (rd->hFile,rd->buffer+rd->strremain,rd->filepos,
- 0x10000-rd->strremain,&bytes);
- if (retval) return 0;
- if(!bytes) return 0;
- rd->strremain+=bytes;
- rd->filepos+=bytes;
- rd->strpos = 0;
- return 1;
-};
-
-int __stdcall set_reader(struct reader *rd, unsigned int filepos)
-{ int retval;
- unsigned int bytes;
- retval=read_file (rd->hFile,rd->buffer,filepos,0x10000,&bytes);
- if (retval) return 0;
- rd->stream = rd->buffer;
- rd->strremain=bytes;
- rd->filepos=filepos+bytes;
- rd->strpos = 0;
-
- fsizeold=0;
- firsthead=0;
- bsbufold = 0;
- bsbuf = bsspace[1];
- bsnum = 0;
- ssize=0;
- oldhead=0;
- memset(bsspace,0,sizeof(bsspace));
- return 1;
-};
-
-static int stream_head_read(struct reader *rd,unsigned long *newhead)
-{
- if(rd->strremain < 4)
- if( !fill_reader(rd))
- return 0;
- *newhead = (rd->stream[0]<<24)|(rd->stream[1] << 16)|
- (rd->stream[2] << 8)| rd->stream[3];
- rd->strpos+=4;
- rd->stream+=4;
- rd->strremain-=4;
- return TRUE;
-};
-
-int stream_read_raw(struct reader *rd,unsigned char *buf, int size)
-{
- if(rd->strremain < size)
- if( !fill_reader(rd))
- return 0;
-
- mem_cpy(buf,rd->stream,size);
- rd->strpos+=size;
- rd->stream+=size;
- rd->strremain-=size;
- return 1;
-};
-
-void set_pointer(long backstep)
-{
- bsi.wordpointer = bsbuf + ssize - backstep;
- if (backstep)
- mem_cpy(bsi.wordpointer,bsbufold+fsizeold-backstep,backstep);
- bsi.bitindex = 0;
-}
-
-int head_check(unsigned long head)
-{ if
- (
- /* first 11 bits are set to 1 for frame sync */
- ((head & 0xffe00000) != 0xffe00000)
- ||
- /* layer: 01,10,11 is 1,2,3; 00 is reserved */
- (!((head>>17)&3))
- ||
- /* 1111 means bad bitrate */
- (((head>>12)&0xf) == 0xf)
- ||
- /* 0000 means free format... */
- (((head>>12)&0xf) == 0x0)
- ||
- /* sampling freq: 11 is reserved */
- (((head>>10)&0x3) == 0x3 )
- /* here used to be a mpeg 2.5 check... re-enabled 2.5 decoding due to lack of evidence that it is really not good */
- )
- {
- return FALSE;
- }
- /* if no check failed, the header is valid (hopefully)*/
- else
- {
- return TRUE;
- }
-}
-
-int __stdcall decode_header(struct frame *fr,unsigned long newhead)
-{
- if(!head_check(newhead))
- return 0;
- if( newhead & (1<<20) )
- { fr->lsf = (newhead & (1<<19)) ? 0x0 : 0x1;
- fr->mpeg25 = 0;
- }
- else
- { fr->lsf = 1;
- fr->mpeg25 = 1;
- };
-
- fr->lay = 4-((newhead>>17)&3);
- 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)
- return (0);
-
- switch(fr->lay)
- { case 1:
- fr->do_layer = do_layer1;
-#ifdef VARMODESUPPORT
- if (varmode) {
- error("Sorry, layer-1 not supported in varmode.");
- return (0);
- }
-#endif
- 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->do_layer = do_layer2;
-#ifdef VARMODESUPPORT
- if (varmode) {
- error("Sorry, layer-2 not supported in varmode.");
- return (0);
- }
-#endif
- 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:
- fr->do_layer = do_layer3;
- 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:
- return (0);
- }
- if (fr->framesize > MAXFRAMESIZE)
- return (0);
- return 1;
-}
-
-
-int read_frame(struct reader *rd, struct frame *fr)
-{ unsigned long newhead;
- static unsigned char ssave[34];
- //off_t framepos;
- fsizeold=fr->framesize; /* for Layer3 */
-
-read_again:
-
- if(!rd->head_read(rd,&newhead))
- return FALSE;
-
- if(!decode_header(fr,newhead))
- {
- if((newhead & 0xffffff00) == 0x49443300)
- {
- int id3length = 0;
- id3length = parse_new_id3(rd, newhead);
- goto read_again;
- };
- rd->strpos-=3;
- rd->stream-=3;
- rd->strremain+=3;
- goto read_again;
- };
-
-#if 0
- if(1 || oldhead != newhead || !oldhead)
- {
-
-init_resync:
-
-#ifdef SKIP_JUNK
- /* watch out for junk/tags on beginning of stream by invalid header */
- if(!firsthead && !head_check(newhead) && !free_format_header(newhead)) {
- int i;
-
- /* check for id3v2; first three bytes (of 4) are "ID3" */
- if((newhead & (unsigned long) 0xffffff00) == (unsigned long) 0x49443300)
- {
- int id3length = 0;
- id3length = parse_new_id3(newhead, rd);
- goto read_again;
- }
- else if(param.verbose > 1) fprintf(stderr,"Note: Junk at the beginning (0x%08lx)\n",newhead);
-
- /* I even saw RIFF headers at the beginning of MPEG streams ;( */
- if(newhead == ('R'<<24)+('I'<<16)+('F'<<8)+'F') {
- if(param.verbose > 1) fprintf(stderr, "Note: Looks like a RIFF header.\n");
- 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;
- if(param.verbose > 1) fprintf(stderr,"Note: Skipped RIFF header!\n");
- goto read_again;
- }
- /* unhandled junk... just continue search for a header */
- /* 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)) */
- if(head_check(newhead) && decode_header(fr, newhead))
- break;
- }
- if(i == 65536) {
- if(!param.quiet) error("Giving up searching valid MPEG header after 64K of junk.");
- 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
-
- /* first attempt of read ahead check to find the real first header; cannot believe what junk is out there! */
- /* for now, a spurious first free format header screws up here; need free format support for detecting false free format headers... */
- if(!firsthead && rd->flags & READER_SEEKABLE && head_check(newhead) && decode_header(fr, newhead))
- {
- unsigned long nexthead = 0;
- int hd = 0;
- off_t start = rd->tell(rd);
- debug1("doing ahead check with BPF %d", fr->framesize+4);
- /* step framesize bytes forward and read next possible header*/
- if(rd->back_bytes(rd, -fr->framesize))
- {
- error("cannot seek!");
- return 0;
- }
- hd = rd->head_read(rd,&nexthead);
- if(rd->back_bytes(rd, rd->tell(rd)-start))
- {
- error("cannot seek!");
- return 0;
- }
- if(!hd)
- {
- warning("cannot read next header, a one-frame stream? Duh...");
- }
- else
- {
- debug2("does next header 0x%08lx match first 0x%08lx?", nexthead, newhead);
- /* not allowing free format yet */
- if(!head_check(nexthead) || (nexthead & HDRCMPMASK) != (newhead & HDRCMPMASK))
- {
- debug("No, the header was not valid, start from beginning...");
- /* try next byte for valid header */
- if(rd->back_bytes(rd, 3))
- {
- error("cannot seek!");
- return 0;
- }
- goto read_again;
- }
- }
- }
-
- /* why has this head check been avoided here before? */
- if(!head_check(newhead))
- {
- if(!firsthead && free_format_header(newhead))
- {
- error1("Header 0x%08lx seems to indicate a free format stream; I do not handle that yet", newhead);
- goto read_again;
- return 0;
- }
- /* and those ugly ID3 tags */
- if((newhead & 0xffffff00) == ('T'<<24)+('A'<<16)+('G'<<8)) {
- rd->skip_bytes(rd,124);
- if (param.verbose > 1) fprintf(stderr,"Note: Skipped ID3 Tag!\n");
- goto read_again;
- }
- /* duplicated code from above! */
- /* check for id3v2; first three bytes (of 4) are "ID3" */
- if((newhead & (unsigned long) 0xffffff00) == (unsigned long) 0x49443300)
- {
- int id3length = 0;
- id3length = parse_new_id3(newhead, rd);
- goto read_again;
- }
- else if (give_note)
- {
- fprintf(stderr,"Note: Illegal Audio-MPEG-Header 0x%08lx at offset 0x%lx.\n", newhead,rd->tell(rd)-4);
- }
-
- if(give_note && (newhead & 0xffffff00) == ('b'<<24)+('m'<<16)+('p'<<8)) fprintf(stderr,"Note: Could be a BMP album art.\n");
- if (param.tryresync || do_recover) {
- int try = 0;
- /* TODO: make this more robust, I'd like to cat two mp3 fragments together (in a dirty way) and still have mpg123 beign able to decode all it somehow. */
- if(give_note) fprintf(stderr, "Note: Trying to resync...\n");
- /* 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 {
- if(!rd->head_shift(rd,&newhead))
- return 0;
- /* debug2("resync try %i, got newhead 0x%08lx", try, newhead); */
- if (!oldhead)
- {
- debug("going to init_resync...");
- goto init_resync; /* "considered harmful", eh? */
- }
- /* we should perhaps collect a list of valid headers that occured in file... there can be more */
- /* Michael's new resync routine seems to work better with the one frame readahead (and some input buffering?) */
- } while
- (
- ++try < RESYNC_LIMIT
- && (newhead & HDRCMPMASK) != (oldhead & HDRCMPMASK)
- && (newhead & HDRCMPMASK) != (firsthead & HDRCMPMASK)
- );
- /* too many false positives
- }while (!(head_check(newhead) && decode_header(fr, newhead))); */
- if(try == RESYNC_LIMIT)
- {
- error("giving up resync - your stream is not nice... perhaps an improved routine could catch up");
- return 0;
- }
-
- if (give_note)
- fprintf (stderr, "Note: Skipped %d bytes in input.\n", try);
- }
- else
- {
- error("not attempting to resync...");
- return (0);
- }
- }
-
- if (!firsthead) {
- if(!decode_header(fr,newhead))
- {
- error("decode header failed before first valid one, going to read again");
- goto read_again;
- }
- }
- else
- if(!decode_header(fr,newhead))
- {
- error("decode header failed - goto resync");
- /* return 0; */
- goto init_resync;
- }
- }
- else
- fr->header_change = 0;
-#endif
-
- bsbufold = bsbuf;
- bsbuf = bsspace[bsnum]+512;
- bsnum = (bsnum + 1) & 1;
- /* if filepos is invalid, so is framepos */
- //framepos = rd->filepos - 4;
- /* read main data into memory */
- /* 0 is error! */
-
- if(!rd->read_frame_body(rd,bsbuf,fr->framesize))
- return 0;
-
-#if 0
- if(!firsthead)
- {
- /* following stuff is actually layer3 specific (in practice, not in theory) */
- if(fr->lay == 3)
- {
- /*
- going to look for Xing or Info at some position after the header
- MPEG 1 MPEG 2/2.5 (LSF)
- Stereo, Joint Stereo, Dual Channel 32 17
- Mono 17 9
-
- Also, how to avoid false positives? I guess I should interpret more of the header to rule that out(?).
- I hope that ensuring all zeros until tag start is enough.
- */
- size_t lame_offset = (fr->stereo == 2) ? (fr->lsf ? 17 : 32 ) : (fr->lsf ? 9 : 17);
- if(fr->framesize >= 120+lame_offset) /* traditional Xing header is 120 bytes */
- {
- size_t i;
- int lame_type = 0;
- /* only search for tag when all zero before it (apart from checksum) */
- for(i=2; i < lame_offset; ++i) if(bsbuf[i] != 0) break;
- if(i == lame_offset)
- {
- if
- (
- (bsbuf[lame_offset] == 'I')
- && (bsbuf[lame_offset+1] == 'n')
- && (bsbuf[lame_offset+2] == 'f')
- && (bsbuf[lame_offset+3] == 'o')
- )
- {
- lame_type = 1; /* We still have to see what there is */
- }
- else if
- (
- (bsbuf[lame_offset] == 'X')
- && (bsbuf[lame_offset+1] == 'i')
- && (bsbuf[lame_offset+2] == 'n')
- && (bsbuf[lame_offset+3] == 'g')
- )
- {
- lame_type = 2;
- vbr = VBR; /* Xing header means always VBR */
- }
- if(lame_type)
- {
- unsigned long xing_flags;
-
- /* we have one of these headers... */
- if(param.verbose > 1) fprintf(stderr, "Note: Xing/Lame/Info header detected\n");
- /* now interpret the Xing part, I have 120 bytes total for sure */
- /* there are 4 bytes for flags, but only the last byte contains known ones */
- lame_offset += 4; /* now first byte after Xing/Name */
- /* 4 bytes dword for flags */
- #define make_long(a, o) ((((unsigned long) a[o]) << 24) | (((unsigned long) a[o+1]) << 16) | (((unsigned long) a[o+2]) << 8) | ((unsigned long) a[o+3]))
- /* 16 bit */
- #define make_short(a,o) ((((unsigned short) a[o]) << 8) | ((unsigned short) a[o+1]))
- xing_flags = make_long(bsbuf, lame_offset);
- lame_offset += 4;
- debug1("Xing: flags 0x%08lx", xing_flags);
- if(xing_flags & 1) /* frames */
- {
- /*
- In theory, one should use that value for skipping...
- When I know the exact number of samples I could simply count in audio_flush,
- but that's problematic with seeking and such.
- I still miss the real solution for detecting the end.
- */
- track_frames = make_long(bsbuf, lame_offset);
- if(track_frames > TRACK_MAX_FRAMES) track_frames = 0; /* endless stream? */
- #ifdef GAPLESS
- /* if no further info there, remove/add at least the decoder delay */
- if(param.gapless)
- {
- unsigned long length = track_frames * spf(fr);
- if(length > 1)
- layer3_gapless_init(DECODER_DELAY+GAP_SHIFT, length+DECODER_DELAY+GAP_SHIFT);
- }
- #endif
- debug1("Xing: %lu frames", track_frames);
- lame_offset += 4;
- }
- if(xing_flags & 0x2) /* bytes */
- {
- #ifdef DEBUG
- unsigned long xing_bytes = make_long(bsbuf, lame_offset);
- debug1("Xing: %lu bytes", xing_bytes);
- #endif
- lame_offset += 4;
- }
- if(xing_flags & 0x4) /* TOC */
- {
- lame_offset += 100; /* just skip */
- }
- if(xing_flags & 0x8) /* VBR quality */
- {
- #ifdef DEBUG
- unsigned long xing_quality = make_long(bsbuf, lame_offset);
- debug1("Xing: quality = %lu", xing_quality);
- #endif
- lame_offset += 4;
- }
- /* I guess that either 0 or LAME extra data follows */
- /* there may this crc16 be floating around... (?) */
- if(bsbuf[lame_offset] != 0)
- {
- unsigned char lame_vbr;
- float replay_gain[2] = {0,0};
- float peak = 0;
- float gain_offset = 0; /* going to be +6 for old lame that used 83dB */
- char nb[10];
- memcpy(nb, bsbuf+lame_offset, 9);
- nb[9] = 0;
- debug1("Info: Encoder: %s", nb);
- if(!strncmp("LAME", nb, 4))
- {
- gain_offset = 6;
- debug("TODO: finish lame detetcion...");
- }
- lame_offset += 9;
- /* the 4 big bits are tag revision, the small bits vbr method */
- lame_vbr = bsbuf[lame_offset] & 15;
- debug1("Info: rev %u", bsbuf[lame_offset] >> 4);
- debug1("Info: vbr mode %u", lame_vbr);
- lame_offset += 1;
- switch(lame_vbr)
- {
- /* from rev1 proposal... not sure if all good in practice */
- case 1:
- case 8: vbr = CBR; break;
- case 2:
- case 9: vbr = ABR; break;
- default: vbr = VBR; /* 00==unknown is taken as VBR */
- }
- /* skipping: lowpass filter value */
- lame_offset += 1;
- /* replaygain */
- /* 32bit float: peak amplitude -- why did I parse it as int before??*/
- /* Ah, yes, lame seems to store it as int since some day in 2003; I've only seen zeros anyway until now, bah! */
- if
- (
- (bsbuf[lame_offset] != 0)
- || (bsbuf[lame_offset+1] != 0)
- || (bsbuf[lame_offset+2] != 0)
- || (bsbuf[lame_offset+3] != 0)
- )
- {
- debug("Wow! Is there _really_ a non-zero peak value? Now is it stored as float or int - how should I know?");
- peak = *(float*) (bsbuf+lame_offset);
- }
- debug1("Info: peak = %f (I won't use this)", peak);
- peak = 0; /* until better times arrived */
- lame_offset += 4;
- /*
- ReplayGain values - lame only writes radio mode gain...
- 16bit gain, 3 bits name, 3 bits originator, sign (1=-, 0=+), dB value*10 in 9 bits (fixed point)
- ignore the setting if name or originator == 000!
- radio 0 0 1 0 1 1 1 0 0 1 1 1 1 1 0 1
- audiophile 0 1 0 0 1 0 0 0 0 0 0 1 0 1 0 0
- */
-
- for(i =0; i < 2; ++i)
- {
- unsigned char origin = (bsbuf[lame_offset] >> 2) & 0x7; /* the 3 bits after that... */
- if(origin != 0)
- {
- unsigned char gt = bsbuf[lame_offset] >> 5; /* only first 3 bits */
- if(gt == 1) gt = 0; /* radio */
- else if(gt == 2) gt = 1; /* audiophile */
- else continue;
- /* get the 9 bits into a number, divide by 10, multiply sign... happy bit banging */
- replay_gain[0] = ((bsbuf[lame_offset] & 0x2) ? -0.1 : 0.1) * (make_short(bsbuf, lame_offset) & 0x1f);
- }
- lame_offset += 2;
- }
- debug1("Info: Radio Gain = %03.1fdB", replay_gain[0]);
- debug1("Info: Audiophile Gain = %03.1fdB", replay_gain[1]);
- for(i=0; i < 2; ++i)
- {
- if(rva_level[i] <= 0)
- {
- rva_peak[i] = 0; /* at some time the parsed peak should be used */
- rva_gain[i] = replay_gain[i];
- rva_level[i] = 0;
- }
- }
- lame_offset += 1; /* skipping encoding flags byte */
- if(vbr == ABR)
- {
- abr_rate = bsbuf[lame_offset];
- debug1("Info: ABR rate = %u", abr_rate);
- }
- lame_offset += 1;
- /* encoder delay and padding, two 12 bit values... lame does write them from int ...*/
- #ifdef GAPLESS
- if(param.gapless)
- {
- /*
- Temporary hack that doesn't work with seeking and also is not waterproof but works most of the time;
- in future the lame delay/padding and frame number info should be passed to layer3.c and the junk samples avoided at the source.
- */
- unsigned long length = track_frames * spf(fr);
- unsigned long skipbegin = DECODER_DELAY + ((((int) bsbuf[lame_offset]) << 4) | (((int) bsbuf[lame_offset+1]) >> 4));
- unsigned long skipend = -DECODER_DELAY + (((((int) bsbuf[lame_offset+1]) << 8) | (((int) bsbuf[lame_offset+2]))) & 0xfff);
- debug3("preparing gapless mode for layer3: length %lu, skipbegin %lu, skipend %lu", length, skipbegin, skipend);
- if(length > 1)
- layer3_gapless_init(skipbegin+GAP_SHIFT, (skipend < length) ? length-skipend+GAP_SHIFT : length+GAP_SHIFT);
- }
- #endif
- }
- /* switch buffer back ... */
- bsbuf = bsspace[bsnum]+512;
- bsnum = (bsnum + 1) & 1;
- goto read_again;
- }
- }
- }
- } /* end block for Xing/Lame/Info tag */
- firsthead = newhead; /* _now_ it's time to store it... the first real header */
- debug1("firsthead: %08lx", firsthead);
- /* now adjust volume */
- do_rva();
- /* and print id3 info */
- if(!param.quiet) print_id3_tag(rd->flags & READER_ID3TAG ? rd->id3buf : NULL);
- }
-#endif
-
- bsi.bitindex = 0;
- bsi.wordpointer = (unsigned char *) bsbuf;
- set_synth_functions(fr);
- if (fr->error_protection)
- getbits(16);
- return 1;
-}
-
-
-#if 0
-
-static int stream_back_bytes(struct reader *rds, off_t bytes)
-{
- if(stream_lseek(rds,-bytes,SEEK_CUR) < 0)
- return -1;
- /* you sure you want the buffer to resync here? */
- if(param.usebuffer)
- buffer_resync();
- return 0;
-}
-
-
-/* this function strangely is define to seek num frames _back_ (and is called with -offset - duh!) */
-/* also... let that int be a long in future! */
-static int stream_back_frame(struct reader *rds,struct frame *fr,long num)
-{
- if(rds->flags & READER_SEEKABLE)
- {
- unsigned long newframe, preframe;
- if(num > 0) /* back! */
- {
- if(num > fr->num) newframe = 0;
- else newframe = fr->num-num;
- }
- else newframe = fr->num-num;
-
- /* two leading frames? hm, doesn't seem to be really needed... */
- /*if(newframe > 1) newframe -= 2;
- else newframe = 0;*/
-
- /* now seek to nearest leading index position and read from there until newframe is reached */
- if(stream_lseek(rds,frame_index_find(newframe, &preframe),SEEK_SET) < 0)
- return -1;
-
- debug2("going to %lu; just got %lu", newframe, preframe);
-
- fr->num = preframe;
-
- while(fr->num < newframe)
- {
- /* try to be non-fatal now... frameNum only gets advanced on success anyway */
- if(!read_frame(fr)) break;
- }
-
- /* this is not needed at last? */
- /*read_frame(fr);
- read_frame(fr);*/
-
- if(fr->lay == 3) {
- set_pointer(512);
- }
-
- debug1("arrived at %lu", fr->num);
-
- if(param.usebuffer)
- buffer_resync();
-
- return 0;
-
- }
- else return -1; /* invalid, no seek happened */
-}
-
-static int stream_head_read(struct reader *rds,unsigned long *newhead)
-{
- unsigned char hbuf[4];
-
- if(fullread(rds,hbuf,4) != 4)
- return FALSE;
-
- *newhead = ((unsigned long) hbuf[0] << 24) |
- ((unsigned long) hbuf[1] << 16) |
- ((unsigned long) hbuf[2] << 8) |
- (unsigned long) hbuf[3];
-
- return TRUE;
-}
-
-static int stream_head_shift(struct reader *rds,unsigned long *head)
-{
- unsigned char hbuf;
-
- if(fullread(rds,&hbuf,1) != 1)
- return 0;
- *head <<= 8;
- *head |= hbuf;
- *head &= 0xffffffff;
- return 1;
-}
-
-static off_t stream_skip_bytes(struct reader *rds,off_t len)
-{
- if (rds->filelen >= 0) {
- off_t ret = stream_lseek(rds, len, SEEK_CUR);
- if (param.usebuffer)
- buffer_resync();
- return ret;
- } else if (len >= 0) {
- unsigned char buf[1024]; /* ThOr: Compaq cxx complained and it makes sense to me... or should one do a cast? What for? */
- off_t ret;
- while (len > 0) {
- off_t num = len < sizeof(buf) ? len : sizeof(buf);
- ret = fullread(rds, buf, num);
- if (ret < 0)
- return ret;
- len -= ret;
- }
- return rds->filepos;
- } else
- return -1;
-}
-
-static int stream_read_frame_body(struct reader *rds,unsigned char *buf,
- int size)
-{
- long l;
-
- if( (l=fullread(rds,buf,size)) != size)
- {
- if(l <= 0)
- return 0;
- memset(buf+l,0,size-l);
- }
-
- return 1;
-}
-
-static off_t stream_tell(struct reader *rds)
-{
- return rds->filepos;
-}
-
-static void stream_rewind(struct reader *rds)
-{
- stream_lseek(rds,0,SEEK_SET);
- if(param.usebuffer)
- buffer_resync();
-}
-
-static off_t get_fileinfo(struct reader *rds,char *buf)
-{
- off_t len;
-
- if((len=lseek(rds->filept,0,SEEK_END)) < 0) {
- return -1;
- }
- if(lseek(rds->filept,-128,SEEK_END) < 0)
- return -1;
- if(fullread(rds,(unsigned char *)buf,128) != 128) {
- return -1;
- }
- if(!strncmp(buf,"TAG",3)) {
- len -= 128;
- }
- if(lseek(rds->filept,0,SEEK_SET) < 0)
- return -1;
- if(len <= 0)
- return -1;
- return len;
-}
-
-#endif
-
- #define syncsafe_to_long(buf,res) \
- ( \
- (((buf)[0]|(buf)[1]|(buf)[2]|(buf)[3]) & 0x80) ? 0 : \
- (res = (((unsigned long) (buf)[0]) << 27) \
- | (((unsigned long) (buf)[1]) << 14) \
- | (((unsigned long) (buf)[2]) << 7) \
- | ((unsigned long) (buf)[3]) \
- ,1) \
- )
-
+ *newhead = ((unsigned long) hbuf[0] << 24) |
+ ((unsigned long) hbuf[1] << 16) |
+ ((unsigned long) hbuf[2] << 8) |
+ (unsigned long) hbuf[3];
+
+ return TRUE;
+}
+
+static int stream_head_shift(struct reader *rds,unsigned long *head)
+{
+ unsigned char hbuf;
+
+ if(fullread(rds,&hbuf,1) != 1)
+ return 0;
+ *head <<= 8;
+ *head |= hbuf;
+ *head &= 0xffffffff;
+ return 1;
+}
+
+static off_t stream_skip_bytes(struct reader *rds,off_t len)
+{
+ if (rds->filelen >= 0) {
+ off_t ret = stream_lseek(rds, len, SEEK_CUR);
+ if (param.usebuffer)
+ buffer_resync();
+ return ret;
+ } else if (len >= 0) {
+ unsigned char buf[1024]; /* ThOr: Compaq cxx complained and it makes sense to me... or should one do a cast? What for? */
+ off_t ret;
+ while (len > 0) {
+ off_t num = len < sizeof(buf) ? len : sizeof(buf);
+ ret = fullread(rds, buf, num);
+ if (ret < 0)
+ return ret;
+ len -= ret;
+ }
+ return rds->filepos;
+ } else
+ return -1;
+}
+
+static int stream_read_frame_body(struct reader *rds,unsigned char *buf,
+ int size)
+{
+ long l;
+
+ if( (l=fullread(rds,buf,size)) != size)
+ {
+ if(l <= 0)
+ return 0;
+ memset(buf+l,0,size-l);
+ }
+
+ return 1;
+}
+
+static off_t stream_tell(struct reader *rds)
+{
+ return rds->filepos;
+}
+
+static void stream_rewind(struct reader *rds)
+{
+ stream_lseek(rds,0,SEEK_SET);
+ if(param.usebuffer)
+ buffer_resync();
+}
+
+static off_t get_fileinfo(struct reader *rds,char *buf)
+{
+ off_t len;
+
+ if((len=lseek(rds->filept,0,SEEK_END)) < 0) {
+ return -1;
+ }
+ if(lseek(rds->filept,-128,SEEK_END) < 0)
+ return -1;
+ if(fullread(rds,(unsigned char *)buf,128) != 128) {
+ return -1;
+ }
+ if(!strncmp(buf,"TAG",3)) {
+ len -= 128;
+ }
+ if(lseek(rds->filept,0,SEEK_SET) < 0)
+ return -1;
+ if(len <= 0)
+ return -1;
+ return len;
+}
+
+#endif
+
+ #define syncsafe_to_long(buf,res) \
+ ( \
+ (((buf)[0]|(buf)[1]|(buf)[2]|(buf)[3]) & 0x80) ? 0 : \
+ (res = (((unsigned long) (buf)[0]) << 27) \
+ | (((unsigned long) (buf)[1]) << 14) \
+ | (((unsigned long) (buf)[2]) << 7) \
+ | ((unsigned long) (buf)[3]) \
+ ,1) \
+ )
+
int parse_new_id3(struct reader *rd, unsigned long header)
{
- #define UNSYNC_FLAG 128
- #define EXTHEAD_FLAG 64
- #define EXP_FLAG 32
- #define FOOTER_FLAG 16
- #define UNKNOWN_FLAGS 15 /* 00001111*/
- unsigned char buf[6];
- unsigned long length=0;
- unsigned char flags = 0;
- int ret = 1;
- unsigned char* tagdata = NULL;
- unsigned char major = header & 0xff;
-
- if(major == 0xff) return -1;
-
- if (!rd->read_frame_body(rd,buf,6))
- return 0;
- if(buf[0] == 0xff) /* major version, will never be 0xff */
- return -1;
-
- /* second new byte are some nice flags, if these are invalid skip the whole thing */
- flags = buf[1];
- /* use 4 bytes from buf to construct 28bit uint value and return 1; return 0 if bytes are not syncsafe */
+ #define UNSYNC_FLAG 128
+ #define EXTHEAD_FLAG 64
+ #define EXP_FLAG 32
+ #define FOOTER_FLAG 16
+ #define UNKNOWN_FLAGS 15 /* 00001111*/
+ unsigned char buf[6];
+ unsigned long length=0;
+ unsigned char flags = 0;
+ int ret = 1;
+ unsigned char* tagdata = NULL;
+ unsigned char major = header & 0xff;
- if(!syncsafe_to_long(buf+2,length))
- return -1;
-
-
- rd->strpos+=length;
- rd->stream+=length;
- rd->strremain-=length;
-
-#if 0
- /* skip if unknown version/scary flags, parse otherwise */
- if((flags & UNKNOWN_FLAGS) || (major > 4))
- {
- /* going to skip because there are unknown flags set */
- if(!rds->skip_bytes(rds,length)) /* will not store data in backbuff! */
-
- rd->strpos+=length;
- rd->stream+=length;
- rd->strremain-=length;
- ret = 0;
- };
-#endif
+ if(major == 0xff) return -1;
+
+ if (rd->read_frame_body(rd,buf,6)<6)
+ return 0;
+ if(buf[0] == 0xff) /* major version, will never be 0xff */
+ return -1;
+
+ /* second new byte are some nice flags, if these are invalid skip the whole thing */
+ flags = buf[1];
+ /* use 4 bytes from buf to construct 28bit uint value and return 1; return 0 if bytes are not syncsafe */
+
+ if(!syncsafe_to_long(buf+2,length))
+ return -1;
+
+
+ rd->strpos+=length;
+ rd->stream+=length;
+ rd->strremain-=length;
+
+#if 0
+ /* skip if unknown version/scary flags, parse otherwise */
+ if((flags & UNKNOWN_FLAGS) || (major > 4))
+ {
+ /* going to skip because there are unknown flags set */
+ if(!rds->skip_bytes(rds,length)) /* will not store data in backbuff! */
+
+ rd->strpos+=length;
+ rd->stream+=length;
+ rd->strremain-=length;
+ ret = 0;
+ };
+#endif
return length;
};
diff --git a/programs/media/ac97snd/ufmod-codec.h b/programs/media/ac97snd/ufmod-codec.h
new file mode 100644
index 0000000000..0f382b50b6
--- /dev/null
+++ b/programs/media/ac97snd/ufmod-codec.h
@@ -0,0 +1,90 @@
+/*
+ uFMOD AC97SND codec header file
+ Target OS: KolibriOS
+ Compiler: Visual C
+
+ NOTE: ufmod.obj should be rebuilt setting UF_MODE=AC97SND
+ in order to make it usable in AC97SND player.
+
+ The Infinity Sound driver handle should be available as
+ a public symbol named hSound. It is so when using Serge's
+ sound.lib.
+*/
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* HANDLE uFMOD_LoadSong(char *lpXM);
+ ---
+ Description:
+ ---
+ Loads the given XM song and starts playing it as soon as you
+ call uFMOD_WaveOut for the first time. It will stop any
+ currently playing song before loading the new one. Heap should
+ be initialized before calling this function!
+ ---
+ Parameters:
+ ---
+ lpXM
+ Specifies the filename of the song to load.
+ ---
+ Return Values:
+ ---
+ On success, returns a non zero value. Returns 0 on failure.
+*/
+int __cdecl uFMOD_LoadSong(char*);
+
+/* int uFMOD_WaveOut(SNDBUF hBuff)
+ ---
+ Description:
+ ---
+ Updates the internal playback buffer.
+ ---
+ Parameters:
+ ---
+ hBuff
+ The Infinity Sound buffer to update.
+ ---
+ Remarks:
+ ---
+ Playback doesn't actually begin when calling uFMOD_LoadSong,
+ but when calling uFMOD_WaveOut after a successful uFMOD_LoadSong
+ call. Afterwards, you should call uFMOD_WaveOut repeatedly at
+ least once every 250 ms to prevent "buffer underruns".
+ uFMOD_WaveOut is a non-blocking function.
+ ---
+ Return Values:
+ ---
+ Returns non zero on error.
+*/
+int __cdecl uFMOD_WaveOut(unsigned int);
+
+/* void uFMOD_StopSong(void)
+ ---
+ Description:
+ ---
+ Stops the currently playing song, freeing the associated
+ resources.
+ ---
+ Remarks:
+ ---
+ Does nothing if no song is playing at the time the call is made.
+*/
+void __cdecl uFMOD_StopSong();
+
+/* unsigned char* _uFMOD_GetTitle(void)
+ ---
+ Description:
+ ---
+ Returns the current song's title.
+ ---
+ Remarks:
+ ---
+ Not every song has a title, so be prepared to get an empty string.
+*/
+unsigned char* __cdecl uFMOD_GetTitle();
+
+#ifdef __cplusplus
+ }
+#endif