static sf_count_t vorbis_length (SF_PRIVATE *psf) { sf_count_t length ; int error ; if (psf->sf.seekable == 0) return SF_COUNT_MAX ; psf_fseek (psf, 0, SEEK_SET) ; length = vorbis_length_aux (psf) ; psf_fseek (psf, 12, SEEK_SET) ; if ((error = vorbis_read_header (psf, 0)) != 0) psf->error = error ; return length ; } /* vorbis_length */
static sf_count_t vorbis_seek (SF_PRIVATE *psf, int UNUSED (mode), sf_count_t offset) { OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ; VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ; if (odata == NULL || vdata == NULL) return 0 ; if (offset < 0) { psf->error = SFE_BAD_SEEK ; return ((sf_count_t) -1) ; } ; if (psf->file.mode == SFM_READ) { sf_count_t target = offset - vdata->loc ; if (target < 0) { /* 12 to allow for OggS bit */ psf_fseek (psf, 12, SEEK_SET) ; vorbis_read_header (psf, 0) ; /* Reset state */ target = offset ; } ; while (target > 0) { sf_count_t m = target > 4096 ? 4096 : target ; /* ** Need to multiply by channels here because the seek is done in ** terms of frames and the read function is done in terms of ** samples. */ vorbis_read_sample (psf, (void *) NULL, m * psf->sf.channels, vorbis_rnull) ; target -= m ; } ; return vdata->loc ; } ; return 0 ; } /* vorbis_seek */
int ogg_vorbis_open (SF_PRIVATE *psf) { OGG_PRIVATE* odata = psf->container_data ; VORBIS_PRIVATE* vdata = calloc (1, sizeof (VORBIS_PRIVATE)) ; int error = 0 ; if (odata == NULL) { psf_log_printf (psf, "%s : odata is NULL???\n", __func__) ; return SFE_INTERNAL ; } ; psf->codec_data = vdata ; if (psf->file.mode == SFM_RDWR) return SFE_BAD_MODE_RW ; psf_log_printf (psf, "Vorbis library version : %s\n", vorbis_version_string ()) ; if (psf->file.mode == SFM_READ) { /* Call this here so it only gets called once, so no memory is leaked. */ ogg_sync_init (&odata->osync) ; if ((error = vorbis_read_header (psf, 1))) return error ; psf->read_short = vorbis_read_s ; psf->read_int = vorbis_read_i ; psf->read_float = vorbis_read_f ; psf->read_double = vorbis_read_d ; psf->sf.frames = vorbis_length (psf) ; } ; psf->codec_close = vorbis_close ; if (psf->file.mode == SFM_WRITE) { /* Set the default vorbis quality here. */ vdata->quality = 0.4 ; psf->write_header = vorbis_write_header ; psf->write_short = vorbis_write_s ; psf->write_int = vorbis_write_i ; psf->write_float = vorbis_write_f ; psf->write_double = vorbis_write_d ; psf->sf.frames = SF_COUNT_MAX ; /* Unknown really */ psf->strings.flags = SF_STR_ALLOW_START ; } ; psf->seek = vorbis_seek ; psf->command = vorbis_command ; psf->byterate = vorbis_byterate ; /* FIXME, FIXME, FIXME : Hack these here for now and correct later. */ psf->sf.format = SF_FORMAT_OGG | SF_FORMAT_VORBIS ; psf->sf.sections = 1 ; psf->datalength = 1 ; psf->dataoffset = 0 ; /* End FIXME. */ return error ; } /* ogg_vorbis_open */