diff options
Diffstat (limited to 'setedit/mp3/libamp/audiolib.c')
-rw-r--r-- | setedit/mp3/libamp/audiolib.c | 408 |
1 files changed, 408 insertions, 0 deletions
diff --git a/setedit/mp3/libamp/audiolib.c b/setedit/mp3/libamp/audiolib.c new file mode 100644 index 0000000..1fdfb5a --- /dev/null +++ b/setedit/mp3/libamp/audiolib.c @@ -0,0 +1,408 @@ +/* + Amp Library interface + (audio.c + guicontrol.c) + Adapted by Ove Kaaven <ovek@arcticnet.no> + */ + + +#include "amp.h" + +#include <sys/types.h> +#include <sys/stat.h> + +#ifndef __DJGPP__ +#ifndef __BEOS__ +#include <sys/uio.h> +#endif +#endif + +#ifndef __DJGPP__ +#include <sys/socket.h> +#endif +#include <errno.h> +#include <stdio.h> +#include <fcntl.h> +#include <unistd.h> +#include <string.h> + +#define AUDIO +#include "audio.h" +#include "formats.h" +#include "getbits.h" +#include "huffman.h" +#include "layer2.h" +#include "layer3.h" +#include "position.h" +#include "rtbuf.h" +#include "transform.h" +#include "controldata.h" +#include "guicontrol.h" + +#include "libamp.h" + +#ifndef __BEOS__ +typedef int bool; +#endif + +void calculate_t43(void); + +int install_amp(void) +{ + static bool is_installed=FALSE; + + if (!is_installed) { +/* initialise_decoder */ + premultiply(); + imdct_init(); + calculate_t43(); + +/* args */ + AUDIO_BUFFER_SIZE=300*1024; + A_DUMP_BINARY=FALSE; + A_QUIET=TRUE; + A_FORMAT_WAVE=FALSE; + A_SHOW_CNT=FALSE; + A_SET_VOLUME=-1; + A_SHOW_TIME=0; + A_AUDIO_PLAY=TRUE; + A_WRITE_TO_FILE=FALSE; + A_MSG_STDOUT=FALSE; + A_DOWNMIX=FALSE; + + is_installed=TRUE; + } + + return(is_installed); +} + +int amp_bitrate,amp_samprat; +int amp_mpg_ver,amp_layer,amp_stereo,amp_pollsize; +int amp_playing,amp_draining,amp_loaded=FALSE,amp_reverse_phase=FALSE; +int amp_looping; +int amp_dec_frame,amp_dec_time; +int amp_frame,amp_time; +struct AUDIO_HEADER amp_cur_header; + +void get_amp_info(struct AUDIO_HEADER*header) +{ + /* show_header from dump.c */ + amp_bitrate=t_bitrate[header->ID][3-header->layer][header->bitrate_index]; + amp_samprat=t_sampling_frequency[header->ID][header->sampling_frequency]; + + amp_layer=4-header->layer; + if (header->ID==1) amp_mpg_ver=1; else amp_mpg_ver=2; + + if (header->mode==3) amp_stereo=FALSE; else amp_stereo=TRUE; + + amp_pollsize=2*576; + if (amp_layer==3) + if (!header->ID) amp_pollsize=576; +} + +int read_amp_frame(struct AUDIO_HEADER*header) +{ + if (header->layer==1) { + if (layer3_frame(header,amp_dec_frame)) { + unload_amp(); + warn(" error. blip.\n"); + return(0); + } + } else if (header->layer==2) + if (layer2_frame(header,amp_dec_frame)) { + unload_amp(); + warn(" error. blip.\n"); + return(0); + } + return(1); +} + + +int load_amp(char*filename,int loop) +{ + int g; + + if (amp_loaded) + if (!unload_amp()) return(0); + + if (!install_amp()) return(0); + + if ((in_file=fopen(filename,"rb"))==NULL) { + warn("Could not open file: %s\n",filename); + return(0); + } + +/* initialise_globals */ + append=data=nch=0; + f_bdirty=TRUE; + bclean_bytes=0; + memset(s,0,sizeof s); + memset(res,0,sizeof res); + +/* load MPEG header */ + if ((g=gethdr(&_cur_header))!=0) { + report_header_error(g); + fclose(in_file); + return(0); + } + if (amp_cur_header.protection_bit==0) getcrc(); + + get_amp_info(&_cur_header); + +/* setup_audio */ + if (AUDIO_BUFFER_SIZE==0) + audioOpen(amp_samprat,(amp_stereo && !A_DOWNMIX),A_SET_VOLUME); + else + audioBufferOpen(amp_samprat,(amp_stereo && !A_DOWNMIX),A_SET_VOLUME); + + amp_looping=loop; + amp_dec_time=amp_dec_frame=0; + amp_time=amp_frame=0; + + return(amp_playing=amp_loaded=TRUE); +} + +extern int audioUsedSpace(void); +extern int audioSpaceRemaining(void); +extern int audioReady(void); +extern int audioStop(void); +extern int audioStart(void); +extern int audioBufferPad(void); +extern unsigned audioBufferGetFrame(void); +extern int audioIsPlaying(void); + +static void update_track_pos(void) +{ + int new_frame=audioBufferGetFrame(); + + if (new_frame>=0) { + amp_frame=new_frame; + } + amp_time=amp_frame*1152/amp_samprat; +} + +static int init_stop(void) +{ + amp_playing=FALSE; + /* check for any data left to play in buffer */ + if (audioIsPlaying()) { + amp_draining=TRUE; + return(0); + } + /* nothing left to play, stop */ + audioStop(); + return(-1); +} + +static int fetch_header(struct AUDIO_HEADER*header) +{ + int g; + + if ((g=gethdr(header))!=0) { + report_header_error(g); + if (g==GETHDR_EOF && A_FORMAT_WAVE) wav_end(header); + A_WRITE_TO_FILE=FALSE; A_FORMAT_WAVE=FALSE; + return(-1); + } + + if (header->protection_bit==0) getcrc(); + + return(0); +} + +static int init_rewind(struct AUDIO_HEADER*header) +{ + fseek(in_file,0,SEEK_SET); + amp_dec_time=amp_dec_frame=0; + + return(fetch_header(header)); +} + +static int exec_replay(void) +{ + if (!(amp_playing||amp_draining)) { + amp_frame=amp_dec_frame; + audioStart(); + update_track_pos(); + } + + amp_draining=FALSE; + + return(amp_playing=TRUE); +} + +static int init_replay(void) +{ + if (init_rewind(&_cur_header)<0) { + return(init_stop()); + } + + return(exec_replay()); +} + +static int end_of_track(void) +{ + if (amp_looping) { + return(init_replay()); + } else { + return(init_stop()); + } +} + +int poll_amp(void) +{ + int poll_size; + + if (!amp_loaded) + return(-1); + if (!amp_playing) + { + if (amp_draining) + { + if (audioUsedSpace()) + { + audioBufferPad(); + /* try to move some data from buffer to sound card */ + audioBufferWrite(NULL,0); + } + update_track_pos(); + /* check for any data left to play in buffer */ + if (audioIsPlaying()) + return(0); + /* nothing left to play, stop */ + amp_draining=FALSE; audioStop(); + return(-1); + } + else + return(-1); + } + + poll_size=2*576; + if (amp_cur_header.layer==1) + if (!amp_cur_header.ID) poll_size=576; + +/* make sure we have enough buffer space left, to avoid blocking */ + if (audioSpaceRemaining()<poll_size) { + /* try to move some data from buffer to sound card */ + audioBufferWrite(NULL,0); + update_track_pos(); + /* failing that, return */ + if (audioSpaceRemaining()<poll_size) return(0); + } + + amp_dec_frame++; + amp_dec_time=amp_dec_frame*1152/amp_samprat; + + if (!read_amp_frame(&_cur_header)) { + update_track_pos(); + return(end_of_track()); + } + + update_track_pos(); + + /* get next header */ + if (fetch_header(&_cur_header)<0) { + return(end_of_track()); + } + + return(1); +} + +int run_amp(void) +{ + int ret=1; + + if (!amp_loaded) return(-1); + if (!(amp_playing||amp_draining)) return(-1); + while ((ret=poll_amp())>0); + return(ret); +} + +int replay_amp(void) +{ + if (!amp_loaded) return(-1); + if (amp_playing) { + audioStop(); amp_playing=amp_draining=FALSE; + } + return(init_replay()); +} + +int stop_amp(void) +{ + if (!amp_loaded) + return(-1); + if (amp_playing) + { + audioStop(); + amp_playing=amp_draining=FALSE; + } + return 0; +} + +int seek_amp_abs(int frame) +{ + if (!amp_loaded) return(-1); + if (amp_playing) { + audioStop(); amp_playing=amp_draining=FALSE; + } + + if (frame>amp_dec_frame) { + amp_dec_frame+=ffwd(&_cur_header,frame-amp_dec_frame); + exec_replay(); + return(0); + } else + if (frame<amp_dec_frame) { + if (frame<(amp_dec_frame/2)) { + if (init_rewind(&_cur_header)<0) return(-1); + amp_dec_frame+=ffwd(&_cur_header,frame); + } else { + amp_dec_frame-=rew(&_cur_header,amp_dec_frame-frame); + } + exec_replay(); + return(0); + } else { + exec_replay(); + return(0); + } +} + +int seek_amp_rel(int framecnt) +{ + int frame; + + frame=amp_frame+framecnt; + if (frame<0) frame=0; + return(seek_amp_abs(frame)); +} + +int unload_amp(void) +{ + if (!amp_loaded) return(0); + amp_loaded=amp_playing=amp_draining=FALSE; + if (AUDIO_BUFFER_SIZE!=0) + audioBufferClose(); + else + audioClose(); + fclose(in_file); + return(1); +} + +void report_header_error(int err) +{ + switch (err) { + case GETHDR_ERR: die("error reading mpeg bitstream. exiting.\n"); + break; + case GETHDR_NS : warn("this is a file in MPEG 2.5 format, which is not defined\n"); + warn("by ISO/MPEG. It is \"a special Fraunhofer format\".\n"); + warn("amp does not support this format. sorry.\n"); + break; + case GETHDR_FL1: warn("ISO/MPEG layer 1 is not supported by amp (yet).\n"); + break; + case GETHDR_FF : warn("free format bitstreams are not supported. sorry.\n"); + break; + case GETHDR_SYN: warn("oops, we're out of sync.\n"); + break; + case GETHDR_EOF: + default: ; /* some stupid compilers need the semicolon */ + } +} + |