/** ** Supermodel ** A Sega Model 3 Arcade Emulator. ** Copyright 2011 Bart Trzynadlowski, Nik Henson ** ** This file is part of Supermodel. ** ** Supermodel is free software: you can redistribute it and/or modify it under ** the terms of the GNU General Public License as published by the Free ** Software Foundation, either version 3 of the License, or (at your option) ** any later version. ** ** Supermodel is distributed in the hope that it will be useful, but WITHOUT ** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ** FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ** more details. ** ** You should have received a copy of the GNU General Public License along ** with Supermodel. If not, see . **/ /* * position.cpp * * Amp library internal module. */ /* this file is a part of amp software, (C) tomislav uzelac 1996,1997 */ /* position.c ffwd/rew within a stream * * Creted by: Tomislav Uzelac, May 10 1997 */ #include #include #include "amp.h" #include "audio.h" #include "getbits.h" #define POSITION #include "position.h" /* Returns the number of frames actually skipped, -1 on error. * * Values in header are not changed if retval!=nframes. * This is not necessary because gethdr() doesn't clobber * the contents of header, but I don't want to rely on that. */ int ffwd(struct AUDIO_HEADER *header, int nframes) { int cnt=0,g; int hsize,bitrate,fs,mean_frame_size; struct AUDIO_HEADER tmp; memcpy(&tmp,header,sizeof(tmp)); while (cnt < nframes) { if (tmp.ID) if (tmp.mode==3) hsize=21; else hsize=36; else if (tmp.mode==3) hsize=13; else hsize=21; if (tmp.protection_bit==0) hsize+=2; if ((g=dummy_getinfo(hsize))) /* dummy_getinfo: reads hsize-4 bytes */ switch (g) { case GETHDR_EOF: return cnt; case GETHDR_ERR: default: return -1; } bitrate=t_bitrate[tmp.ID][3-tmp.layer][tmp.bitrate_index]; fs=t_sampling_frequency[tmp.ID][tmp.sampling_frequency]; if (tmp.ID) mean_frame_size=144000*bitrate/fs; else mean_frame_size=72000*bitrate/fs; fillbfr(mean_frame_size + tmp.padding_bit - hsize); if ((g=gethdr(&tmp))) switch (g) { case GETHDR_EOF: return cnt; case GETHDR_ERR: default: return -1; } cnt++; } memcpy(header,&tmp,sizeof(tmp)); return cnt; } /* Mostly the same as ffwd. Some streams might be 'tough', i.e. * the ones switching bitrates. */ int rew(struct AUDIO_HEADER *header, int nframes) { int cnt=0; int bitrate,fs,mean_frame_size; struct AUDIO_HEADER tmp; memcpy(&tmp,header,sizeof(tmp)); while (cnt < nframes) { /* ffwd/rew functions are to be called right after the header has been parsed * so we have to go back one frame + 4 bytes + 1 byte (in case padding was used). */ bitrate=t_bitrate[tmp.ID][3-tmp.layer][tmp.bitrate_index]; fs=t_sampling_frequency[tmp.ID][tmp.sampling_frequency]; if (tmp.ID) mean_frame_size=144000*bitrate/fs; else mean_frame_size=72000*bitrate/fs; if (rewind_stream(mean_frame_size) !=0) { memcpy(header,&tmp,sizeof(tmp)); return cnt; } if ((gethdr(&tmp))) return -1; cnt++; } /* We have to make sure that the bit reservoir contains enough data. * Hopefully, layer3_frame will take care of that. */ f_bdirty=TRUE; bclean_bytes=0; memcpy(header,&tmp,sizeof(tmp)); return cnt; } /* TODO: after the gethdr function is enhanced with the counter to count * the number of bytes to search for the next syncword, make the call to * gethdr() from rew() have that counter something like (frame_size-1) so * that we don't go back again and again to the same header. (not very important) */