+ // We work with 200ms (1/5 sec) steps to avoid rounding errors
+ time_start = real_start * 5 / snd_renderbuffer->format.speed;
+ ogg_start = time_start * (per_sfx->format.speed / 5);
+ err = qov_pcm_seek (&per_ch->vf, ogg_start);
+ if (err != 0)
+ {
+ Con_Printf ("OGG_FetchSound: qov_pcm_seek(..., %d) returned %d\n",
+ real_start, err);
+ return NULL;
+ }
+ sb->nbframes = 0;
+
+ real_start = (unsigned int) ((float)ogg_start / per_sfx->format.speed * snd_renderbuffer->format.speed);
+ if (*start - real_start + nbsampleframes > sb->maxframes)
+ {
+ Con_Printf ("OGG_FetchSound: stream buffer too small after seek (%u sample frames required)\n",
+ *start - real_start + nbsampleframes);
+ per_ch->sb_offset = real_start;
+ return NULL;
+ }
+ }
+ // Else, move forward the samples we need to keep in the sound buffer
+ else
+ {
+ memmove (sb->samples, sb->samples + (real_start - per_ch->sb_offset) * factor, newlength * factor);
+ sb->nbframes = newlength;
+ }
+
+ per_ch->sb_offset = real_start;
+
+ // We add more than one frame of sound to the buffer:
+ // 1- to ensure we won't lose many samples during the resampling process
+ // 2- to reduce calls to OGG_FetchSound to regulate workload
+ newlength = (int)(per_sfx->format.speed*STREAM_BUFFER_FILL);
+ // this is how much we FETCH...
+ if ((size_t) ((double) newlength * (double)sb->format.speed / (double)per_sfx->format.speed) + sb->nbframes > sb->maxframes)
+ {
+ Con_Printf ("OGG_FetchSound: stream buffer overflow (%u + %u = %u sample frames / %u)\n",
+ (unsigned int) ((double) newlength * (double)sb->format.speed / (double)per_sfx->format.speed), sb->nbframes, (unsigned int) ((double) newlength * (double)sb->format.speed / (double)per_sfx->format.speed) + sb->nbframes, sb->maxframes);
+ return NULL;
+ }
+ newlength *= factor; // convert from sample frames to bytes
+ if(newlength > (int)sizeof(resampling_buffer))
+ newlength = sizeof(resampling_buffer);
+
+ // Decompress in the resampling_buffer
+ done = 0;
+ while ((ret = qov_read (&per_ch->vf, (char *)&resampling_buffer[done], (int)(newlength - done), mem_bigendian, 2, 1, &per_ch->bs)) > 0)
+ done += ret;
+
+ Snd_AppendToSndBuffer (sb, resampling_buffer, (size_t)done / (size_t)factor, &per_sfx->format);
+
+ *start = per_ch->sb_offset;
+ return sb;