summarylogtreecommitdiffstats
path: root/overread.patch
blob: 0dad2dc82e7982247569f3f8c2f3c30ac4af440c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
diff -aur cdparanoia-III-10.2.pristine/cdparanoia.1 cdparanoia-III-10.2.new/cdparanoia.1
--- cdparanoia-III-10.2.pristine/cdparanoia.1	2013-09-13 03:17:17.992370058 -0400
+++ cdparanoia-III-10.2.new/cdparanoia.1	2013-09-13 03:17:45.698886625 -0400
@@ -197,6 +197,11 @@
 known user data area of the disc, probably causing read errors on most
 drives and possibly even hard lockups on some buggy hardware.
 
+.TP
+.BI "\-x --force-overread
+Force overreading into the lead-out portion of the disc. This option is only applicable when using the
+.B -O
+option with a positive sample offset value. Many drives are not capable of reading into this portion of the disc and attempting to do so on those drives will produce read errors and possibly hard lockups.
 
 .TP
 .B \-Z --disable-paranoia
diff -aur cdparanoia-III-10.2.pristine/main.c cdparanoia-III-10.2.new/main.c
--- cdparanoia-III-10.2.pristine/main.c	2013-09-13 03:17:17.995703373 -0400
+++ cdparanoia-III-10.2.new/main.c	2013-09-13 03:17:49.542199138 -0400
@@ -260,6 +260,7 @@
 "                                    correct\n"
 "  -O --sample-offset <n>          : Add <n> samples to the offset when\n"
 "                                    reading data.  May be negative.\n"
+"  -x --force-overread             : Enable overreading into the lead-out.\n"
 "  -z --never-skip[=n]             : never accept any less than perfect\n"
 "                                    data reconstruction (don't allow 'V's)\n"
 "                                    but if [n] is given, skip after [n]\n"
@@ -604,7 +605,7 @@
     memset(dispcache,' ',graph);
 }
 
-const char *optstring = "escCn:o:O:d:g:k:S:prRwafvqVQhZz::YXWBi:Tt:l::L::A";
+const char *optstring = "escCn:o:O:xd:g:k:S:prRwafvqVQhZz::YXWBi:Tt:l::L::A";
 
 struct option options [] = {
 	{"stderr-progress",no_argument,NULL,'e'},
@@ -618,6 +619,7 @@
 	{"force-generic-device",required_argument,NULL,'g'},
 	{"force-read-speed",required_argument,NULL,'S'},
 	{"sample-offset",required_argument,NULL,'O'},
+	{"force-overread",no_argument,NULL,'x'},
 	{"toc-offset",required_argument,NULL,'t'},
 	{"toc-bias",no_argument,NULL,'T'},
 	{"output-raw",no_argument,NULL,'p'},
@@ -679,6 +681,7 @@
   char *force_generic_device=NULL;
   char *force_cooked_device=NULL;
   int force_cdrom_speed=0;
+  int force_overread=0;
   int max_retries=20;
   char *span=NULL;
   int output_type=1; /* 0=raw, 1=wav, 2=aifc */
@@ -686,6 +689,7 @@
   int query_only=0;
   int batch=0,i;
   int run_cache_test=0;
+  int last_audio_track;
 
   char *logfile_name=NULL;
   char *reportfile_name=NULL;
@@ -853,6 +857,9 @@
     case 'O':
       sample_offset=atoi(optarg);
       break;
+    case 'x':
+      force_overread=1;
+      break;
     default:
       usage(stderr);
       exit(1);
@@ -1176,11 +1183,28 @@
       
     }
 
+	last_audio_track = d->tracks;
+	if (toc_offset && !force_overread) {
+		int lt;
+
+		for (lt = d->tracks ; lt > 0 ; lt--)
+			if (cdda_track_audiop(d, lt))
+				break;
+
+		if (lt > 0)
+			last_audio_track = lt;
+
+		d->disc_toc[last_audio_track].dwStartSector -= toc_offset;
+		if (last_sector > cdda_track_lastsector(d, last_audio_track))
+			last_sector -= toc_offset;
+    }
+
     {
       long cursor;
       int16_t offset_buffer[1176];
       int offset_buffer_used=0;
       int offset_skip=sample_offset*4;
+      off_t sectorlen;
 
       p=paranoia_init(d);
       paranoia_modeset(p,paranoia_mode);
@@ -1202,7 +1226,7 @@
 	 need to set the disc length forward here so that the libs are
 	 willing to read past, assuming that works on the hardware, of
 	 course */
-      if(sample_offset)
+      if(sample_offset && force_overread)
 	d->disc_toc[d->tracks].dwStartSector++;
 
       while(cursor<=last_sector){
@@ -1319,18 +1343,25 @@
 	    fflush(logfile);
 	  }
 	}
-	
+
+	sectorlen = batch_last - batch_first + 1;
+	if (cdda_sector_gettrack(d, cursor) == last_audio_track &&
+		toc_offset > 0 && !force_overread)
+	{
+		sectorlen += toc_offset;
+	}
+
 	switch(output_type){
 	case 0: /* raw */
 	  break;
 	case 1: /* wav */
-	  WriteWav(out,(batch_last-batch_first+1)*CD_FRAMESIZE_RAW);
+	  WriteWav(out, sectorlen * CD_FRAMESIZE_RAW);
 	  break;
 	case 2: /* aifc */
-	  WriteAifc(out,(batch_last-batch_first+1)*CD_FRAMESIZE_RAW);
+	  WriteAifc(out, sectorlen * CD_FRAMESIZE_RAW);
 	  break;
 	case 3: /* aiff */
-	  WriteAiff(out,(batch_last-batch_first+1)*CD_FRAMESIZE_RAW);
+	  WriteAiff(out, sectorlen * CD_FRAMESIZE_RAW);
 	  break;
 	}
 	
@@ -1399,44 +1430,70 @@
 
 	  /* One last bit of silliness to deal with sample offsets */
 	  if(sample_offset && cursor>batch_last){
-	    int i;
-	    /* read a sector and output the partial offset.  Save the
-               rest for the next batch iteration */
-	    readbuf=paranoia_read_limited(p,callback,max_retries);
-	    err=cdda_errors(d);mes=cdda_messages(d);
-
-	    if(mes || err)
-	      fprintf(stderr,"\r                               "
-		      "                                           \r%s%s\n",
-		      mes?mes:"",err?err:"");
-	  
-	    if(err)free(err);if(mes)free(mes);
-	    if(readbuf==NULL){
-	      skipped_flag=1;
-	      report("\nparanoia_read: Unrecoverable error reading through "
-		     "sample_offset shift\n\tat end of track, bailing.\n");
-	      break;
-	    }
-	    if(skipped_flag && abort_on_skip)break;
-	    skipped_flag=0;
-	    /* do not move the cursor */
-	  
-	    if(output_endian!=bigendianp())
-	      for(i=0;i<CD_FRAMESIZE_RAW/2;i++)
-		offset_buffer[i]=swap16(readbuf[i]);
-	    else
-	      memcpy(offset_buffer,readbuf,CD_FRAMESIZE_RAW);
-	    offset_buffer_used=sample_offset*4;
-	  
-	    callback(cursor*(CD_FRAMEWORDS),-2);
+		if (cdda_sector_gettrack(d, batch_last) < last_audio_track || force_overread) {
+		    int i;
 
-	    if(buffering_write(out,(char *)offset_buffer,
+			/* Need to flush the buffer when overreading into the leadout */
+			if (cdda_sector_gettrack(d, batch_last) == last_audio_track)
+				paranoia_seek(p, cursor, SEEK_SET);
+
+		    /* read a sector and output the partial offset.  Save the
+	               rest for the next batch iteration */
+		    readbuf=paranoia_read_limited(p,callback,max_retries);
+		    err=cdda_errors(d);mes=cdda_messages(d);
+	
+		    if(mes || err)
+		      fprintf(stderr,"\r                               "
+			      "                                           \r%s%s\n",
+			      mes?mes:"",err?err:"");
+		  
+		    if(err)free(err);if(mes)free(mes);
+		    if(readbuf==NULL){
+		      skipped_flag=1;
+		      report("\nparanoia_read: Unrecoverable error reading through "
+			     "sample_offset shift\n\tat end of track, bailing.\n");
+		      break;
+		    }
+		    if(skipped_flag && abort_on_skip)break;
+		    skipped_flag=0;
+		    /* do not move the cursor */
+		  
+		    if(output_endian!=bigendianp())
+		      for(i=0;i<CD_FRAMESIZE_RAW/2;i++)
+			offset_buffer[i]=swap16(readbuf[i]);
+		    else
+		      memcpy(offset_buffer,readbuf,CD_FRAMESIZE_RAW);
+		    offset_buffer_used=sample_offset*4;
+		    callback(cursor*(CD_FRAMEWORDS),-2);
+		  } else {
+			memset(offset_buffer, 0, sizeof(offset_buffer));
+			offset_buffer_used = sample_offset * 4;
+		  }
+
+		  if(buffering_write(out,(char *)offset_buffer,
 			       offset_buffer_used)){
-	      report("Error writing output: %s",strerror(errno));
-	      exit(1);
-	    }
-	  }
+		      report("Error writing output: %s",strerror(errno));
+		      exit(1);
+		  }
+		}
 	}
+
+	/* Write sectors of silent audio to compensate for
+       missing samples that would be in the leadout */
+	if (cdda_sector_gettrack(d, batch_last) == last_audio_track &&
+		toc_offset > 0 && !force_overread)
+	{
+		char *silence;
+		size_t missing_sector_bytes = CD_FRAMESIZE_RAW * toc_offset;
+
+		silence = calloc(toc_offset, CD_FRAMESIZE_RAW);
+		if (!silence || buffering_write(out, silence, missing_sector_bytes)) {
+		      report("Error writing output: %s", strerror(errno));
+		      exit(1);
+		}
+		free(silence);
+	}
+
 	callback(cursor*(CD_FRAMESIZE_RAW/2)-1,-1);
 	buffering_close(out);
 	if(skipped_flag){