Supermodel/Src/Sound/MPEG/position.cpp

132 lines
3.8 KiB
C++

/**
** 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 <http://www.gnu.org/licenses/>.
**/
/*
* 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 <stdlib.h>
#include <string.h>
#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)
*/