⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 resample.c

📁 刻录光盘的程序
💻 C
📖 第 1 页 / 共 2 页
字号:
		memcpy( newp+(di*4), p+(si*4), 4 );		idx += (double)(global.playback_rate/100.0);		si = (long)idx;		di++;	}	return di;}#endifstatic int guess_endianess(p, p2, SamplesToDo)	UINT4 *p;	short *p2;	unsigned SamplesToDo;{    /* analyse samples */    int vote_for_little = 0;    int vote_for_big = 0;    int total_votes;    while (((UINT4 *)p2 - p) + (unsigned) 1 < SamplesToDo) {      unsigned char *p3 = (unsigned char *)p2;#if MY_LITTLE_ENDIAN == 1      int diff_lowl = *(p2+0) - *(p2+2);      int diff_lowr = *(p2+1) - *(p2+3);      int diff_bigl = ((*(p3  ) << 8) + *(p3+1)) - ((*(p3+4) << 8) + *(p3+5));      int diff_bigr = ((*(p3+2) << 8) + *(p3+3)) - ((*(p3+6) << 8) + *(p3+7));#else      int diff_lowl = ((*(p3+1) << 8) + *(p3  )) - ((*(p3+5) << 8) + *(p3+4));      int diff_lowr = ((*(p3+3) << 8) + *(p3+2)) - ((*(p3+7) << 8) + *(p3+6));      int diff_bigl = *(p2+0) - *(p2+2);      int diff_bigr = *(p2+1) - *(p2+3);#endif      if ((abs(diff_lowl) + abs(diff_lowr)) <	  (abs(diff_bigl) + abs(diff_bigr))) {	vote_for_little++;      } else {	if ((abs(diff_lowl) + abs(diff_lowr)) >	    (abs(diff_bigl) + abs(diff_bigr))) {	  vote_for_big++;	}      }      p2 += 2;   }#ifdef DEBUG_VOTE_ENDIANESS   if (global.quiet != 1)     fprintf(stderr, "votes for little: %4d,  votes for big: %4d\n", 		vote_for_little, vote_for_big);#endif   total_votes = vote_for_big + vote_for_little;   if (total_votes < 3       || abs(vote_for_big - vote_for_little) < total_votes/3) {     return -1;   } else {	if (vote_for_big > vote_for_little)		return 1;	else		return 0;   }}int jitterShift = 0; unsigned char *synchronize(p, SamplesToDo, TotSamplesDone)	UINT4 *p;	unsigned SamplesToDo;	unsigned TotSamplesDone;{  static int jitter = 0;  char *pSrc;                   /* start of cdrom buffer */  /* if endianess is unknown, guess endianess based on      differences between succesive samples. If endianess     is correct, the differences are smaller than with the     opposite byte order.   */  if ((*in_lendian) < 0) {    short *p2 = (short *)p;    /* skip constant samples */    while ((((UINT4 *)p2 - p) + (unsigned) 1 < SamplesToDo)           && *p2 == *(p2+2)) p2++;    if (((UINT4 *)p2 - p) + (unsigned) 1 < SamplesToDo) {      switch (guess_endianess(p, p2, SamplesToDo)) {        case -1: break;        case  1: (*in_lendian) = 0;#if 0	         if (global.quiet != 1)		   fprintf(stderr, "big endian detected\n");#endif	break;        case  0: (*in_lendian) = 1;#if 0	         if (global.quiet != 1)		   fprintf(stderr, "little endian detected\n");#endif	break;      }    }  }  /* ENDIAN ISSUES:   * the individual endianess of cdrom/cd-writer, cpu,    * sound card and audio output format need a careful treatment.   *   * For possible sample processing (rate conversion) we need   * the samples in cpu byte order. This is the first conversion.   *   * After processing it depends on the endianness of the output   * format, whether a second conversion is needed.   *   */  if (global.need_hostorder && (*in_lendian) != MY_LITTLE_ENDIAN) {    /* change endianess of delivered samples to native cpu order */    change_endianness(p, SamplesToDo);  }  /* synchronisation code */  if (TotSamplesDone != 0 && global.overlap != 0 && SamplesToDo > CD_FRAMESAMPLES) {    pSrc = (char *) sync_buffers((unsigned char *)p);    if (!pSrc ) {      return NULL;    }    if (pSrc) {      jitter = ((unsigned char *)pSrc - (((unsigned char *)p) + global.overlap*CD_FRAMESIZE_RAW))/4;      jitterShift += jitter;      SamplesToDo -= jitter + global.overlap*CD_FRAMESAMPLES;#if 0      fprintf(stderr,	    "Length: pre %d, diff1 %ld, diff2 %ld, min %ld\n", SamplesToDo,	   (TotSamplesWanted - TotSamplesDone),	   SamplesNeeded((TotSamplesWanted - TotSamplesDone), undersampling),	   min(SamplesToDo, SamplesNeeded((TotSamplesWanted - TotSamplesDone), undersampling)));#endif    }  } else {    pSrc = ( char * ) p;  }  return (unsigned char *) pSrc;}/* convert cdda data to required output format * sync code for unreliable cdroms included *  */long SaveBuffer (p, SamplesToDo, TotSamplesDone)	UINT4 *p;	unsigned long SamplesToDo;	unsigned long *TotSamplesDone;{  UINT4 *pSrc;                   /* start of cdrom buffer */  UINT4 *pSrcStop;               /* end of cdrom buffer */  /* in case of different endianness between host and output format,     copy in a seperate buffer and modify the local copy */  if ( ((!global.need_hostorder && global.need_big_endian == (*in_lendian)) ||	 (global.need_hostorder && global.need_big_endian != MY_BIG_ENDIAN))      && global.OutSampleSize > 1) {     static UINT4 *localoutputbuffer;     if (localoutputbuffer == NULL) {       localoutputbuffer = (UINT4 *) malloc(global.nsectors*CD_FRAMESIZE_RAW);       if (localoutputbuffer == NULL) {         perror("cannot allocate local buffer");         return 1;       }     }     memcpy(localoutputbuffer, p, SamplesToDo*4);     p = localoutputbuffer;  }  pSrc = p;  pDst = (unsigned char *) p;  pStart = ( unsigned char * ) pSrc;  pSrcStop = pSrc + SamplesToDo;  /* code for subsampling and output stage */  if (global.ismono && global.findmono) {    short *pmm;    for (pmm = (short *)pStart; (UINT4 *) pmm < pSrcStop; pmm += 2) {      if (*pmm != *(pmm+1)) {        global.ismono = 0;        break;      }    }  }  /* optimize the case of no conversion */  if (1 && undersampling == 1 && samples_to_do == 1 &&       global.channels == 2 && global.OutSampleSize == 2 && Halved == 0) {    /* output format is the original cdda format ->     * just forward the buffer      */          if ( waitforsignal != 0 && any_signal == 0) {      int *myptr = (int *)pStart;      while ((UINT4 *)myptr < pSrcStop && *myptr == 0) myptr++;      pStart = (unsigned char *) myptr;      /* scan for first signal */      if ( (UINT4 *)pStart != pSrcStop ) {	/* first non null amplitude is found in buffer */	any_signal = 1;      }    }    pDst = (unsigned char *) pSrcStop;		/* set pDst to end */    if (global.deemphasize) {      /* this implements an attenuation treble shelving filter          to undo the effect of pre-emphasis. The filter is of         a recursive first order */      static short lastin[2] = { 0, 0 };      static double lastout[2] = { 0.0, 0.0 };      short *pmm;      /* Here is the gnuplot file for the frequency response         of the deemphasis. The error is below +-0.1dB# first define the ideal filter. We use the tenfold sampling frequency.T=1./441000.OmegaU=1./15E-6OmegaL=15./50.*OmegaUV0=OmegaL/OmegaUH0=V0-1.B=V0*tan(OmegaU*T/2.)# the coefficients followa1=(B - 1.)/(B + 1.)b0=(1.0 + (1.0 - a1) * H0/2.)b1=(a1 + (a1 - 1.0) * H0/2.)# helper variablesD=b1/b0o=2*pi*TH2(f)=b0*sqrt((1+2*cos(f*o)*D+D*D)/(1+2*cos(f*o)*a1+a1*a1))# now approximate the ideal curve with a fitted one for sampling frequency# of 44100 Hz.T2=1./44100.V02=0.3365OmegaU2=1./19E-6B2=V02*tan(OmegaU2*T2/2.)# the coefficients followa12=(B2 - 1.)/(B2 + 1.)b02=(1.0 + (1.0 - a12) * (V02-1.)/2.)b12=(a12 + (a12 - 1.0) * (V02-1.)/2.)# helper variablesD2=b12/b02o2=2*pi*T2H(f)=b02*sqrt((1+2*cos(f*o2)*D2+D2*D2)/(1+2*cos(f*o2)*a12+a12*a12))# plot best, real, ideal, level with halved attenuation,#      level at full attentuation, 10fold magnified errorset logscale xset grid xtics ytics mxtics myticsplot [f=1000:20000] [-12:2] 20*log10(H(f)),20*log10(H2(f)),  20*log10(OmegaL/(2*pi*f)), 0.5*20*log10(V0), 20*log10(V0), 200*log10(H(f)/H2(f))pause -1 "Hit return to continue"       */#ifdef TEST#define V0	0.3365#define OMEGAG	(1./19e-6)#define T	(1./44100.)#define H0	(V0-1.)#define B	(V0*tan((OMEGAG * T)/2.0))#define a1	((B - 1.)/(B + 1.))#define b0 	(1.0 + (1.0 - a1) * H0/2.0)#define b1 	(a1 + (a1 - 1.0) * H0/2.0)#else#define a1	-0.62786881719628784282#define b0 	0.45995451989513153057#define b1 	-0.08782333709141937339#endif      for (pmm = (short *)pStart; pmm < (short *)pDst;) {        lastout[0] = *pmm * b0 + lastin[0] * b1 - lastout[0] * a1;        lastin[0] = *pmm;        *pmm++ = lastout[0] > 0.0 ? lastout[0] + 0.5 : lastout[0] - 0.5;        lastout[1] = *pmm * b0 + lastin[1] * b1 - lastout[1] * a1;        lastin[1] = *pmm;        *pmm++ = lastout[1] > 0.0 ? lastout[1] + 0.5 : lastout[1] - 0.5;      }    }    if (global.swapchannels == 1) {	swap_channels((UINT4 *)pStart, SamplesToDo);    }    if (global.findminmax) {      short *pmm;      for (pmm = (short *)pStart; pmm < (short *)pDst; pmm++) {        if (*pmm < global.minamp[1]) global.minamp[1] = *pmm;        if (*pmm > global.maxamp[1]) global.maxamp[1] = *pmm;        pmm++;        if (*pmm < global.minamp[0]) global.minamp[0] = *pmm;        if (*pmm > global.maxamp[0]) global.maxamp[0] = *pmm;      }    }  } else {#define none_missing	0#define one_missing	1#define two_missing	2#define collecting	3    static int sample_state = collecting;    static int Toggle_on = 0;    if (global.channels == 2 && global.swapchannels == 1) {	swap_channels((UINT4 *)pStart, SamplesToDo);    }    /* conversion required */    while ( pSrc < pSrcStop ) {	  	long l,r;	long iSamples_left = (pSrcStop - pSrc) / sizeof(short) / 2;	short *myptr = (short *) pSrc;	/* LSB l, MSB l */	l = *myptr++;	/* left channel */	r = *myptr++;	/* right channel */	pSrc = (UINT4 *) myptr;	switch (sample_state) {	case two_missing:two__missing:	    ls2 += l; rs2 += r;	    if (undersampling > 1) {		ls3 += l; rs3 += r;	    }	    sample_state = one_missing;	    break;	case one_missing:	    auxl = l; auxr = r;	    ls3 += l; rs3 += r;	    sample_state = none_missing;	    /* FALLTHROUGH */none__missing:	case none_missing:	    /* Filtered samples are complete. Now interpolate and scale. */	    if (Halved != 0 && Toggle_on == 0) {                lsum = interpolate(lsum, ls2, ls3)/(int) undersampling;	        rsum = interpolate(rsum, rs2, rs3)/(int) undersampling;            } else {		lsum /= (int) undersampling;		rsum /= (int) undersampling;            }	    emit_sample(lsum, rsum, global.channels);	    /* reload counter */	    samples_to_do = undersampling - 1;	    lsum = auxl;	    rsum = auxr;	    /* reset sample register */	    auxl = ls2 = ls3 = 0;	    auxr = rs2 = rs3 = 0;	    Toggle_on ^= 1;	    sample_state = collecting;	    break;	case collecting:	    if ( samples_to_do > 0) {		samples_to_do--;		if (Halved != 0 && Toggle_on == 0) {		    /* Divider x.5 : we need data for quadratic interpolation */		    iSamples_left--;		    lsum += l; rsum += r;		    if ( samples_to_do < undersampling - 1) {			ls2 += l; rs2 += r;		    }		    if ( samples_to_do < undersampling - 2) {			ls3 += l; rs3 += r;		    }		} else {		    /* integral divider */		    lsum += l;		    rsum += r;		    iSamples_left--;		}	    } else {	        if (Halved != 0 && Toggle_on == 0) {		    sample_state = two_missing;		    goto two__missing;		} else {		    auxl = l;		    auxr = r;		    sample_state = none_missing;		    goto none__missing;		}	    }	    break;	} /* switch state */    } /* while */    /* flush_buffer */    if ((samples_to_do == 0 && Halved == 0))    {	if (Halved != 0 && Toggle_on == 0) {	    lsum = interpolate(lsum, ls2, ls3)/(int) undersampling;	    rsum = interpolate(rsum, rs2, rs3)/(int) undersampling;	} else {	    lsum /= (int) undersampling;	    rsum /= (int) undersampling;	}	emit_sample(lsum, rsum, global.channels);		/* reload counter */	samples_to_do = undersampling;		/* reset sample register */	lsum = auxl = ls2 = ls3 = 0;	rsum = auxr = rs2 = rs3 = 0;	Toggle_on ^= 1;	sample_state = collecting;    }  } /* if optimize else */  if ( waitforsignal == 0 ) pStart = (unsigned char *)p;  else if (any_signal != 0) global.SkippedSamples += ((UINT4 *)pStart - p);  else global.SkippedSamples += (pSrcStop - p);  if ( waitforsignal == 0 || any_signal != 0) {    int retval = 0;    unsigned outlen;    assert(pDst >= pStart);    outlen = (size_t) (pDst - pStart);    if (outlen <= 0) return 0;#ifdef	ECHO_TO_SOUNDCARD    /* this assumes the soundcard needs samples in native cpu byte order */    if (global.echo != 0) {               static unsigned char *newp;               unsigned    newlen;               newlen = (100*(outlen/4))/global.playback_rate;               newlen = (newlen*4);               if ( (newp != NULL) || (newp = (unsigned char *) malloc( 2*global.nsectors*CD_FRAMESIZE_RAW+32 )) ) {			newlen = 4*ReSampleBuffer( pStart, newp, outlen/4 );			write_snd_device((char *)newp, newlen);               }    }#endif    if ( global.no_file != 0 ) {        *TotSamplesDone += SamplesToDo;        return 0;    }    if ( (!global.need_hostorder && global.need_big_endian == (*in_lendian)) ||	 (global.need_hostorder && global.need_big_endian != MY_BIG_ENDIAN)) {      if ( global.OutSampleSize > 1) {        /* change endianness from input sample or native cpu order            to required output endianness */        change_endianness((UINT4 *)pStart, outlen/4);      }    }    if ((unsigned)(retval = write ( global.audio, pStart, outlen )) == outlen) {        *TotSamplesDone += SamplesToDo;	return 0;    } else {        fprintf(stderr, "write(audio, 0x%p, %u) = %d\n",pStart,outlen,retval);        perror("Probably disk space exhausted");        return 1;    }  } else return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -