NVrec patch to improve working with btaudio sound

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]



Hi,

NVrec has a great feature where it slightly resamples the audio to make
sure that exactly the right number of audio bytes are written to the
output file to maintain sync even if the sound card clock is off.

But there is a unpleasant interaction between that code and the btaudio
drivers' fixed 8k fragment size.  The big fragments mean a lot of jitter
in the sampled number of bytes written.  Resulting in NVrec making rather
large adjustments to the resampling.  The result is 4 or 5% "wow" added to
the audio. (remember old tape recorders with a flat pinch wheel?)

This patch changes NVrec to change the resampling rate much more
slowly - so the jitter is proportionatly smaller.  This eliminates the
wow.

This patch also makes a little change in v4l2_core.c to allow NVrec to
work with Gerd's v4l2 implementation in bttv 0.8.  To use NVrec and bttv
0.8 together you'll need these changes in NVrec as well as the
VIDIOC_G_PARM implementation for bttv 0.8 that I posted a day or two ago
as bttv-0.8.31-sld.patch.

I'd appreciate confirmation from any brave person who'll give this a try -
I believe Justin's away till the 20th.

Regards,
Steve
diff -r -U3 NVrec-20011203/nvrec_core.c NVrec-20011203-sld/nvrec_core.c
--- NVrec-20011203/nvrec_core.c	Mon Dec  3 09:31:04 2001
+++ NVrec-20011203-sld/nvrec_core.c	Sat Dec 29 15:39:00 2001
@@ -162,7 +162,7 @@
 			atime = audt->aud_core_tailtime(audt);
 		}
 	}
-	fprintf(stderr, "NVrec: initial sync - audio: %lli video %lli (delta %f)\n", atime, vtime, (atime-vtime)/1e9);
+	fprintf(stderr, "NVrec: initial sync - audio: %lli video %lli (delta %f secs)\n", atime, vtime, (atime-vtime)/1e9);
 
 	/* Now loop until we're done! */
 	while((!nvcore_fin) && (fcount)) {
@@ -197,19 +197,27 @@
 		
 		atime = audt->aud_core_tailtime(audt);
 
-		if ((cseq % 30) == 0) {
-			ftemp = (fatime * 1000000000LL) / audt->aud_core_bps(audt);
-			ftemp -= (double)fvtime;
-			drate = (int)(- ftemp / 1e6);
-			drate -= (int)(lastoff / 1e8);
+		// SLD: Add explanation of how this works before you forget!
+		// Also - the 300 should perhaps be adjusted to be an actual 10 second period
+		// if thats done, perhaps review the <<15 used in oss_core?
+		if ( (cseq = (cseq+1) % 300) == 0) {
+		        ftemp = (fatime * 1000000000LL) / audt->aud_core_bps(audt); // in nsecs
+			ftemp -= (double)fvtime; // nsec, slip between video and audio, since start
+			// Why 1e7?  1e6 to convert from nanosec to millisecs.  another 10 because
+			// our measurement interval is 300 frames - of the order of 10 seconds
+			// old code had this code running every 30 frames, and 1e6 and 1e8 below.
+			drate = (int)(- ftemp / 1e7); // millisecs per second(-ish) to be recovered
+			// don't know what this is for.  Some sort of damping attempt I presume
+			drate -= (int)(lastoff / 1e9);
 			lastoff = lastoff + ftemp;
 			if(drate >= 1000) drate = 999;
 			if(drate <= -1000) drate = -999;
 		}
-		fprintf(stderr, "VQ:% 8.03f Offset: % 8.03f Slipage: % 8.03f Warp: %d Drop: %lld              \r", capstat, (atime-vtime)/1e9, ftemp / 1e9, drate, fdrop);
+		fprintf(stderr, "VQ:% 8.03f Offset: % 8.03f Slippage: % 8.03f Warp: %d Drop: %lld             \r",
+			capstat, (atime-vtime)/1e9, ftemp / 1e9, drate, fdrop);
 		if(fcount > 0) fcount--;
-		cseq ++;
 	}
+	fprintf(stderr, "\nTotal audio bytes: %lli\n", fatime);
 	nvcore_die = 1;
 	sigaction(SIGINT, &oldaction, NULL);
 	return 0;
diff -r -U3 NVrec-20011203/oss_core.c NVrec-20011203-sld/oss_core.c
--- NVrec-20011203/oss_core.c	Mon Dec  3 09:31:04 2001
+++ NVrec-20011203-sld/oss_core.c	Fri Dec 28 22:40:36 2001
@@ -169,11 +169,11 @@
 	osst->tail = i;
 }
 
+//FIXME: will work for little-endian only... (SLD)
 struct s2 {
 	unsigned short lo;
 	unsigned short hi;
 };
-
 typedef union {
 	unsigned int ui;
 	struct s2 us;
@@ -202,6 +202,7 @@
 	} else {
 		dt = 65536;
 	}
+	j.ui = 0;
 	while(1) {
 		i = osst->tail;
 		if((osst->frag + i)->full == 0) {
@@ -220,14 +221,18 @@
 			unsigned int * in = (unsigned int *) ((osst->frag + i)->buf);
 			unsigned int * out = (unsigned int *) (buf + c);
 			k = 0;
-			for(j.ui = 0; j.us.hi < (osst->fragsize >> 2); j.ui += dt)
+			//SLD: Slight tweak here: retain fractional part of j between
+			//fragments.  Should help even out resampling and get closer
+			//to the desired number of output samples
+			for(j.us.hi = 0; j.us.hi < (osst->fragsize >> 2); j.ui += dt)
 				out[k++] = in[j.us.hi];
 			c += k << 2;
 		} else {
 			unsigned short * in = (unsigned short *) ((osst->frag + i)->buf);
 			unsigned short * out = (unsigned short *) (buf + c);
 			k = 0;
-			for(j.ui = 0; j.us.hi < (osst->fragsize >> 1); j.ui += dt)
+			//SLD: Comment as above
+			for(j.us.hi = 0; j.us.hi < (osst->fragsize >> 1); j.ui += dt)
 				out[k++] = in[j.us.hi];
 			c += k << 1;
 		}
@@ -365,12 +370,12 @@
 
 	act = malloc(sizeof(struct aud_core_t));
 	if(!act) {
-		perror("oss core init - could no malloc new audio core");
+		perror("oss core init - could not malloc new audio core");
 		return NULL;
 	}
 	osst = malloc(sizeof(struct oss_core_t));
 	if(!osst) {
-		perror("oss core init - could no malloc new oss core");
+		perror("oss core init - could not malloc new oss core");
 		free(act);
 		return NULL;
 	}
@@ -460,6 +465,7 @@
 	}
  	osst->bps = osst->rate * osst->chans * ((osst->bits==16)?2:1);
  	osst->realbps = j * osst->chans * ((osst->bits==16)?2:1);
+	fprintf(stderr, "oss core init - bps=%d, realbps=%d\n", osst->bps, osst->realbps);
 
 	if (ioctl(osst->fd, SNDCTL_DSP_GETBLKSIZE, &j) < 0) {
 		perror("oss core init - WARNING could not get block size");
diff -r -U3 NVrec-20011203/v4l2_core.c NVrec-20011203-sld/v4l2_core.c
--- NVrec-20011203/v4l2_core.c	Mon Dec  3 09:31:04 2001
+++ NVrec-20011203-sld/v4l2_core.c	Wed Dec 26 12:39:21 2001
@@ -273,7 +273,7 @@
 	}
 	fprintf(stderr, "v4l2 core init - Size: %dx%d from %s\n", vct->width, vct->height, fdev);
 
-	vct->fd = open(fdev, O_RDONLY);
+	vct->fd = open(fdev, O_RDWR);
 	if(vct->fd<=0) {
 		perror("v4l2 core init - open capture device");
 		goto error0;
@@ -413,7 +413,7 @@
 			perror("v4l2 core init - querybuf failed");
 			goto error2;
 		}
-		vct->bufs[i * vct->planes] = (unsigned char *)mmap(NULL, vct->cbuf.length, PROT_READ, MAP_SHARED, vct->fd, vct->cbuf.offset);
+		vct->bufs[i * vct->planes] = (unsigned char *)mmap(NULL, vct->cbuf.length, PROT_READ|PROT_WRITE, MAP_SHARED, vct->fd, vct->cbuf.offset);
 		if((int)(vct->bufs[i * vct->planes])==-1) {
 			perror("v4l2 core init - mmap failed");
 			goto error2;;

[Index of Archives]     [Linux DVB]     [Video Disk Recorder]     [Asterisk]     [Photo]     [DCCP]     [Netdev]     [Xorg]     [Util Linux NG]     [Xfree86]     [Free Photo Albums]     [Fedora Users]     [Fedora Women]     [ALSA Users]     [ALSA Devel]     [Linux USB]

Powered by Linux