Add jitter simulation and jitter-correction testing.

This commit is contained in:
rocky
2005-01-22 18:11:32 +00:00
parent 4e8d4c1373
commit 567e6e7775
4 changed files with 153 additions and 36 deletions

View File

@@ -1,5 +1,5 @@
/*
$Id: cdda.h,v 1.8 2005/01/22 03:43:03 rocky Exp $
$Id: cdda.h,v 1.9 2005/01/22 18:11:32 rocky Exp $
Copyright (C) 2004, 2005 Rocky Bernstein <rocky@panix.com>
Copyright (C) 2001 Xiph.org
@@ -111,26 +111,35 @@ struct cdrom_drive_s {
};
/**< under-run testing. The below bit is set for testing. */
#define CDDA_TEST_UNDERRUN 16
#if TESTING_IS_FINISHED
/** jitter testing. The first two bits are set to determine
how much jitter to simulate.
/**< jitter testing. The first two bits are set to determine
the byte-distance we will jitter the data; 0 is no shifting.
*/
#define CDDA_TEST_JITTER_SMALL 1
#define CDDA_TEST_JITTER_LARGE 2
#define CDDA_TEST_JITTER_MASSIVE 3
/**< jitter testing. Set the below bit to always cause jittering on reads.
The below bit only has any effect if the first two (above) bits are
nonzero. If the above bits are set, but the below bit isn't we'll
jitter 90% of the time.
*/
#define CDDA_TEST_ALWAYS_JITTER 4
/** fragment testing */
#define CDDA_TEST_FRAG_SMALL (1<<2)
#define CDDA_TEST_FRAG_LARGE (2<<2)
#define CDDA_TEST_FRAG_MASSIVE (3<<2)
#define CDDA_TEST_FRAG_SMALL (1<<3)
#define CDDA_TEST_FRAG_LARGE (2<<3)
#define CDDA_TEST_FRAG_MASSIVE (3<<3)
/**< under-run testing. The below bit is set for testing. */
#define CDDA_TEST_UNDERRUN 64
#if TESTING_IS_FINISHED
/** scratch testing */
#define CDDA_TEST_SCRATCH 32
#undef CDDA_TEST_BOGUS_BYTES 64
#undef CDDA_TEST_DROPDUPE_BYTES 128
#define CDDA_TEST_SCRATCH 128
#undef CDDA_TEST_BOGUS_BYTES 256
#undef CDDA_TEST_DROPDUPE_BYTES 512
#endif /* TESTING_IS_FINISHED */
/** autosense functions */

View File

@@ -1,5 +1,5 @@
/*
$Id: cooked_interface.c,v 1.12 2005/01/18 00:57:20 rocky Exp $
$Id: cooked_interface.c,v 1.13 2005/01/22 18:11:32 rocky Exp $
Copyright (C) 2004, 2005 Rocky Bernstein <rocky@panix.com>
Original interface.c Copyright (C) 1994-1997
@@ -69,33 +69,24 @@ cooked_setspeed(cdrom_drive_t *d, int i_speed)
return cdio_set_speed(d->p_cdio, i_speed);
}
/* read 'SectorBurst' adjacent sectors of audio sectors
* to Buffer '*p' beginning at sector 'lSector'
/* read 'i_sector' adjacent audio sectors
* into buffer '*p' beginning at sector 'begin'
*/
static long int
cooked_read (cdrom_drive_t *d, void *p, lsn_t begin, long sectors)
read_blocks (cdrom_drive_t *d, void *p, lsn_t begin, long i_sectors)
{
int retry_count,err;
int retry_count = 0;
int err;
char *buffer=(char *)p;
/* read d->nsectors at a time, max. */
sectors=( sectors > d->nsectors && d->nsectors > 0 ? d->nsectors : sectors);
/* If we are testing under-run correction, we will deliberately set
what we read a frame short. */
if (d->i_test_flags & CDDA_TEST_UNDERRUN )
sectors--;
retry_count=0;
do {
err = cdio_read_audio_sectors( d->p_cdio, buffer, begin, sectors);
err = cdio_read_audio_sectors( d->p_cdio, buffer, begin, i_sectors);
if ( 0 != err ) {
if (!d->error_retry) return -7;
if (sectors==1) {
if (i_sectors==1) {
/* *Could* be I/O or media error. I think. If we're at
30 retries, we better skip this unhappy little
sector. */
@@ -111,8 +102,8 @@ cooked_read (cdrom_drive_t *d, void *p, lsn_t begin, long sectors)
}
if(retry_count>4)
if(sectors>1)
sectors=sectors*3/4;
if(i_sectors>1)
i_sectors=i_sectors*3/4;
retry_count++;
if (retry_count>MAX_RETRIES) {
cderror(d,"007: Unknown, unrecoverable error reading data\n");
@@ -122,7 +113,115 @@ cooked_read (cdrom_drive_t *d, void *p, lsn_t begin, long sectors)
break;
} while (err);
return(sectors);
return(i_sectors);
}
typedef enum {
JITTER_NONE = 0,
JITTER_SMALL= 1,
JITTER_LARGE= 2,
JITTER_MASSIVE=3
} jitter_baddness_t;
/* read 'i_sector' adjacent audio sectors
* into buffer '*p' beginning at sector 'begin'
*/
static long int
jitter_read (cdrom_drive_t *d, void *p, lsn_t begin, long i_sectors,
jitter_baddness_t jitter_badness)
{
static int i_jitter=0;
int jitter_flag;
long i_sectors_orig = i_sectors;
long i_jitter_offset = 0;
char *p_buf=malloc(CDIO_CD_FRAMESIZE_RAW*(i_sectors+1));
if (d->i_test_flags & CDDA_TEST_ALWAYS_JITTER)
jitter_flag = 1;
else
jitter_flag = (drand48() > .9) ? 1 : 0;
if (jitter_flag) {
int i_coeff = 0;
int i_jitter_sectors = 0;
switch(jitter_badness) {
case JITTER_SMALL : i_coeff = 4; break;
case JITTER_LARGE : i_coeff = 32; break;
case JITTER_MASSIVE: i_coeff = 128; break;
case JITTER_NONE :
default : ;
}
i_jitter = i_coeff * (int)((drand48()-.5)*CDIO_CD_FRAMESIZE_RAW/8);
/* We may need to add another sector to compensate for the bytes that
will be dropped off when jittering, and the begin location may
be a little different.
*/
i_jitter_sectors = i_jitter / CDIO_CD_FRAMESIZE_RAW;
if (i_jitter >= 0)
i_jitter_offset = i_jitter % CDIO_CD_FRAMESIZE_RAW;
else {
i_jitter_offset = CDIO_CD_FRAMESIZE_RAW -
(-i_jitter % CDIO_CD_FRAMESIZE_RAW);
i_jitter_sectors--;
}
if (begin + i_jitter_sectors > 0) {
char buffer[256];
sprintf(buffer, "jittering by %d, offset %ld\n", i_jitter,
i_jitter_offset);
cdmessage(d,buffer);
begin += i_jitter_sectors;
i_sectors ++;
} else
i_jitter_offset = 0;
}
i_sectors = read_blocks(d, p_buf, begin, i_sectors);
if (i_sectors < 0) return i_sectors;
if (i_sectors < i_sectors_orig)
/* Had to reduce # of sectors due to read errors. So give full amount,
with no jittering. */
memcpy(p, p_buf, i_sectors*CDIO_CD_FRAMESIZE_RAW);
else
/* Got full amount, but now adjust size for jittering. */
memcpy(p, p_buf+i_jitter_offset, i_sectors_orig*CDIO_CD_FRAMESIZE_RAW);
free(p_buf);
return(i_sectors);
}
/* read 'i_sector' adjacent audio sectors
* into buffer '*p' beginning at sector 'begin'
*/
static long int
cooked_read (cdrom_drive_t *d, void *p, lsn_t begin, long i_sectors)
{
jitter_baddness_t jitter_badness = d->i_test_flags & 0x3;
/* read d->nsectors at a time, max. */
i_sectors = ( i_sectors > d->nsectors && d->nsectors > 0 )
? d->nsectors : i_sectors;
/* If we are testing under-run correction, we will deliberately set
what we read a frame short. */
if (d->i_test_flags & CDDA_TEST_UNDERRUN )
i_sectors--;
if (jitter_badness) {
return jitter_read(d, p, begin, i_sectors, jitter_badness);
} else
return read_blocks(d, p, begin, i_sectors);
}
/* hook */

View File

@@ -847,7 +847,6 @@ main(int argc,char *argv[])
}
}
d->i_test_flags = test_flags;
switch( cdda_open(d) ) {
case -2:case -3:case -4:case -5:
report("\nUnable to open disc. Is there an audio CD in the drive?");
@@ -862,6 +861,8 @@ main(int argc,char *argv[])
exit(1);
}
d->i_test_flags = test_flags;
/* Dump the TOC */
if (query_only || verbose ) display_toc(d);

View File

@@ -1,5 +1,5 @@
#!/bin/sh
# $Id: check_paranoia.sh.in,v 1.3 2005/01/15 16:05:44 rocky Exp $
# $Id: check_paranoia.sh.in,v 1.4 2005/01/22 18:11:32 rocky Exp $
# Compare our cd-paranoia with an installed cdparanoia
if test "@CMP@" != no -a "@BUILD_CD_PARANOIA_TRUE@"X = X ; then
@@ -12,15 +12,23 @@ if test "@CMP@" != no -a "@BUILD_CD_PARANOIA_TRUE@"X = X ; then
echo "** Raw cdda.bin extraction differ"
exit 3
fi
../src/cd-paranoia/cd-paranoia -d ./cdda.cue -x 1 -v -r -- "1-"
mv cdda.raw cdda-good.raw
../src/cd-paranoia/cd-paranoia -d ./cdda.cue -x 64 -v -r -- "1-"
mv cdda.raw cdda-underrun.raw
../src/cd-paranoia/cd-paranoia -d ./cdda.cue -r -- "1-"
if @CMP@ ./cdda-underrun.raw ./cdda.raw ; then
if @CMP@ ./cdda-underrun.raw ./cdda-good.raw ; then
echo "** Under-run correction okay"
else
echo "** Under-run correction problem"
exit 3
fi
../src/cd-paranoia/cd-paranoia -d ./cdda.cue -x 5 -v -r -- "1-"
if @CMP@ ./cdda-jitter.raw ./cdda-good.raw ; then
echo "** Jitter correction okay"
else
echo "** Jitter correction problem"
exit 3
fi
exit 0
else
echo "Don't see libcdio cd-paranoia program. Test skipped."