OggAudio* OggAudio::CreateFromMemory(const FileIdRef& fileId, MemoryData data) { ov_callbacks callbacks; callbacks.read_func = ogg_read_func; callbacks.seek_func = ogg_seek_func; callbacks.close_func = ogg_close_func; callbacks.tell_func = ogg_tell_func; OggVorbis_File vf; MemoryStream oggStream = MemoryStream::OpenRead(data); if (ov_open_callbacks(&oggStream, &vf, nullptr, 0, callbacks)) { Log::FormatError("{} does not appear to be an Ogg bitstream.", fileId.Name); return nullptr; } vorbis_info* vi = ov_info(&vf, -1); uintp sampleCount = (uintp)ov_pcm_total(&vf, -1); bool seekable = ov_seekable(&vf)!=0; uint bigEndian = !BitConverter::IsLittle(); int currentSection = 0; uintp pcmSize = sampleCount*vi->channels*sizeof(short); MemoryStream pcmSteam(pcmSize); while (true) { long readSize = ov_read(&vf, (char*)pcmSteam.MutablePtr(), (int)pcmSteam.LeftLength(), bigEndian, 2, 1, ¤tSection); if (readSize == 0) { //end of file break; } else if (readSize > 0) { pcmSteam.Seek(readSize, SeekOrigin::Current); } else { if (readSize == OV_EBADLINK) { Log::FormatError("{} Corrupt bitstream section!", fileId.Name); return nullptr; } } } auto audioData = pcmSteam.CurrentBuffer(); OggAudio* audio = new OggAudio(audioData, fileId); audio->SetSampleCount(sampleCount); audio->SetChannelCount(vi->channels); audio->SetSampleRate(vi->rate); audio->SetBitsPerSample(16); audio->SetSeekable(seekable); return audio; }
long SoundSourceOggVorbis::seek(long filepos) { // In our speak, filepos is a sample in the file abstraction (i.e. it's // stereo no matter what). filepos/2 is the frame we want to seek to. if (filepos % 2 != 0) { qDebug() << "SoundSourceOggVorbis got non-even seek target."; filepos--; } if (ov_seekable(&vf)) { if (ov_pcm_seek(&vf, filepos/2) != 0) { // This is totally common (i.e. you're at EOF). Let's not leave this // qDebug on. // qDebug() << "ogg vorbis: Seek ERR on seekable."; } // Even if an error occured, return them the current position because // that's what we promised. (Double it because ov_pcm_tell returns // frames and we pretend to the world that everything is stereo) return ov_pcm_tell(&vf) * 2; } else { qDebug() << "ogg vorbis: Seek ERR at file " << getFilename(); return 0; } }
void OggWrapper::LoadFromMemory(char * data, int dataSize, SoundInfo * soundinfo) { oggFile_.curPtr = oggFile_.filePtr = data; oggFile_.fileSize = dataSize; ovFile_ = new OggVorbis_File; memset(ovFile_, 0, sizeof OggVorbis_File); ov_open_callbacks((void*)&oggFile_, ovFile_, nullptr, -1, callbacks_ogg); vorbis_info * vorbisinfo = ov_info(ovFile_, -1); memset(soundinfo, 0, sizeof SoundInfo); soundinfo->channels = vorbisinfo->channels; soundinfo->bitrateLower = vorbisinfo->bitrate_lower; soundinfo->bitrateUpper = vorbisinfo->bitrate_upper; soundinfo->bitrateNominal = vorbisinfo->bitrate_nominal; soundinfo->bitrateWindow = vorbisinfo->bitrate_window; soundinfo->frequency = vorbisinfo->rate; soundinfo->bpc = 16; if (ov_seekable(ovFile_) == 0) { soundinfo->seekable = false; seekable_ = false; } else { soundinfo->seekable = true; seekable_ = true; } }
void OggWrapper::LoadFromFile(FILE * file, SoundInfo * soundinfo) { ovFile_ = new OggVorbis_File; memset(ovFile_, 0, sizeof OggVorbis_File); ov_open_callbacks(file, ovFile_, nullptr, -1, OV_CALLBACKS_DEFAULT); vorbis_info * vorbisinfo = ov_info(ovFile_, -1); memset(soundinfo, 0, sizeof SoundInfo); soundinfo->channels = vorbisinfo->channels; soundinfo->bitrateLower = vorbisinfo->bitrate_lower; soundinfo->bitrateUpper = vorbisinfo->bitrate_upper; soundinfo->bitrateNominal = vorbisinfo->bitrate_nominal; soundinfo->bitrateWindow = vorbisinfo->bitrate_window; soundinfo->frequency = vorbisinfo->rate; soundinfo->bpc = 16; if (ov_seekable(ovFile_) == 0) { soundinfo->seekable = false; seekable_ = false; } else { soundinfo->seekable = true; seekable_ = true; } }
// int WINAPI e_seek( onu_deck_cable_s *cable, long pos ) static bool oggSeek( OggDecoder *dd, long pos ) { dd->seekOffset = pos; if (!ov_seekable(&(OGGDATA(dd)->vf))) return false; return true; }
bool cOggDecoder::isSeekingSupported() { if(Valid) { return (ov_seekable(&oggStream)!=0); } return false; }
static qboolean S_VORBIS_CodecOpenStream (snd_stream_t *stream) { OggVorbis_File *ovFile; vorbis_info *ovf_info; long numstreams; int res; ovFile = (OggVorbis_File *) Z_Malloc(sizeof(OggVorbis_File), Z_MAINZONE); stream->priv = ovFile; res = ov_open_callbacks(&stream->fh, ovFile, NULL, 0, ovc_qfs); if (res != 0) { Con_Printf("%s is not a valid Ogg Vorbis file (error %i).\n", stream->name, res); goto _fail; } if (!ov_seekable(ovFile)) { Con_Printf("Stream %s not seekable.\n", stream->name); goto _fail; } ovf_info = ov_info(ovFile, 0); if (!ovf_info) { Con_Printf("Unable to get stream info for %s.\n", stream->name); goto _fail; } /* FIXME: handle section changes */ numstreams = ov_streams(ovFile); if (numstreams != 1) { Con_Printf("More than one (%ld) stream in %s.\n", numstreams, stream->name); goto _fail; } if (ovf_info->channels != 1 && ovf_info->channels != 2) { Con_Printf("Unsupported number of channels %d in %s\n", ovf_info->channels, stream->name); goto _fail; } stream->info.rate = ovf_info->rate; stream->info.channels = ovf_info->channels; stream->info.bits = VORBIS_SAMPLEBITS; stream->info.width = VORBIS_SAMPLEWIDTH; return true; _fail: if (res == 0) ov_clear(ovFile); Z_Free(ovFile); return false; }
bool cOggDecoder::setPosition(int position, bool relative) { if(Valid) { if(ov_seekable(&oggStream)) { return (ov_raw_seek(&oggStream,position)==0); } } return false; }
JNIEXPORT void JNICALL Java_com_jme3_audio_plugins_NativeVorbisFile_open (JNIEnv *env, jobject nvf, jint fd, jlong off, jlong len) { LOGI("open: fd = %d, off = %lld, len = %lld", fd, off, len); OggVorbis_File* ovf = (OggVorbis_File*) malloc(sizeof(OggVorbis_File)); FileDescWrapper* wrapper = (FileDescWrapper*) malloc(sizeof(FileDescWrapper)); wrapper->fd = fd; wrapper->env = env; // NOTE: every java call has to update this wrapper->start = off; wrapper->current = off; wrapper->end = off + len; int result = ov_open_callbacks((void*)wrapper, ovf, NULL, 0, FileDescCallbacks); if (result != 0) { LOGI("ov_open fail"); free(ovf); free(wrapper); char err[512]; sprintf(err, "ov_open failed: %d", result); throwIOException(env, err); return; } LOGI("ov_open OK"); jobject ovfBuf = (*env)->NewDirectByteBuffer(env, ovf, sizeof(OggVorbis_File)); vorbis_info* info = ov_info(ovf, -1); // total # of bytes = total samples * bytes per sample * channels int total_samples = ov_pcm_total(ovf, -1); jint total_bytes = total_samples * 2 * info->channels; jboolean seekable = ov_seekable(ovf) != 0; // duration = millis / 1000 long timeMillis = ov_time_total(ovf, -1); double timeSeconds = ((double)timeMillis) / 1000.0; jfloat duration = (jfloat) timeSeconds; (*env)->SetObjectField(env, nvf, nvf_field_ovf, ovfBuf); (*env)->SetBooleanField(env, nvf, nvf_field_seekable, seekable); (*env)->SetIntField(env, nvf, nvf_field_channels, info->channels); (*env)->SetIntField(env, nvf, nvf_field_sampleRate, info->rate); (*env)->SetIntField(env, nvf, nvf_field_bitRate, info->bitrate_nominal); (*env)->SetIntField(env, nvf, nvf_field_totalBytes, total_bytes); (*env)->SetFloatField(env, nvf, nvf_field_duration, duration); }
void OggFile::Seek(uint32_t cursor) { if(ov_seekable(&_vorbis_file) == 0) { IF_PRINT_WARNING(AUDIO_DEBUG) << "failed because Ogg file was not seekable: " << _filename << std::endl; return; } ov_pcm_seek(&_vorbis_file, cursor); // Reset the temporary buffer by setting the position to 0 _read_buffer_position = 0; _read_buffer_size = 0; }
bool libname::COggStreamSample::Rewind() { if ( ov_seekable(&m_OggFile) ) { ov_raw_seek( &m_OggFile, 0 ); m_bHasEnded = false; return true; } else { cerr << "file is not seekable" << endl; return false; } }
bool COggDec::Open(FILE* in, OggVorbis_File* vf) { int rval; ov_callbacks cb; /* we need to use our own functions, because we have */ /* the netfile layer hooked in here. If we would not */ /* provide callbacks, the tremor lib and the netfile */ /* layer would clash and steal each other the data */ /* from the stream ! */ cb.read_func = ogg_read; cb.seek_func = ogg_seek; cb.close_func = ogg_close; cb.tell_func = ogg_tell; /* test the dope ... */ //rval = ov_test_callbacks((void*)in, vf, NULL, 0, cb); rval = ov_open_callbacks(in, vf, NULL, 0, cb); /* and tell our friends about the quality of the stuff */ // initialize the sound device here if(rval<0) { switch(rval) { /* err_txt from netfile.cpp */ case OV_EREAD: sprintf(err_txt, "media read error"); break; case OV_ENOTVORBIS: sprintf(err_txt, "no vorbis stream"); break; case OV_EVERSION: sprintf(err_txt, "incompatible vorbis version"); break; case OV_EBADHEADER: sprintf(err_txt, "invalid bvorbis bitstream header"); break; case OV_EFAULT: sprintf(err_txt, "internal logic fault (tremor)"); break; default: sprintf(err_txt, "unknown error, code: %d", rval); } fprintf(stderr,"%s: %s\n", ProgName, err_txt); return false; } /* finish the opening and ignite the joint */ //ov_test_open(vf); if(ov_seekable(vf)) mSeekable = true; else mSeekable = false; return true; }
bool cOggDecoder::seek(float seconds, bool relative) { if(Valid) { if(ov_seekable(&oggStream)) { if(relative) { float curtime = ov_time_tell(&oggStream); return (ov_time_seek(&oggStream,curtime+seconds)==0); } else return (ov_time_seek(&oggStream,seconds)==0); } } return false; }
int main(){ OggVorbis_File ov; int i; #ifdef _WIN32 /* We need to set stdin/stdout to binary mode. Damn windows. */ /* Beware the evil ifdef. We avoid these where we can, but this one we cannot. Don't add any more, you'll probably go to hell if you do. */ _setmode( _fileno( stdin ), _O_BINARY ); _setmode( _fileno( stdout ), _O_BINARY ); #endif /* open the file/pipe on stdin */ if(ov_open(stdin,&ov,NULL,-1)<0){ printf("Could not open input as an OggVorbis file.\n\n"); exit(1); } /* print details about each logical bitstream in the input */ if(ov_seekable(&ov)){ printf("Input bitstream contained %ld logical bitstream section(s).\n", ov_streams(&ov)); printf("Total bitstream samples: %ld\n\n", (long)ov_pcm_total(&ov,-1)); printf("Total bitstream playing time: %ld seconds\n\n", (long)ov_time_total(&ov,-1)); }else{ printf("Standard input was not seekable.\n" "First logical bitstream information:\n\n"); } for(i=0;i<ov_streams(&ov);i++){ vorbis_info *vi=ov_info(&ov,i); printf("\tlogical bitstream section %d information:\n",i+1); printf("\t\t%ldHz %d channels bitrate %ldkbps serial number=%ld\n", vi->rate,vi->channels,ov_bitrate(&ov,i)/1000, ov_serialnumber(&ov,i)); printf("\t\theader length: %ld bytes\n",(long) (ov.dataoffsets[i]-ov.offsets[i])); printf("\t\tcompressed length: %ld bytes\n",(long)(ov_raw_total(&ov,i))); printf("\t\tplay time: %lds\n",(long)ov_time_total(&ov,i)); } ov_clear(&ov); return 0; }
Result SoundSourceOggVorbis::tryOpen(const AudioSourceConfig& /*audioSrcCfg*/) { m_pFile = new QFile(getLocalFileName()); if(!m_pFile->open(QFile::ReadOnly)) { qWarning() << "Failed to open OggVorbis file:" << getUrlString(); return ERR; } if (ov_open_callbacks(m_pFile, &m_vf, NULL, 0, s_callbacks) < 0) { qDebug() << "oggvorbis: Input does not appear to be an Ogg bitstream."; return ERR; } if (!ov_seekable(&m_vf)) { qWarning() << "OggVorbis file is not seekable:" << getUrlString(); return ERR; } // lookup the ogg's channels and sample rate const vorbis_info* vi = ov_info(&m_vf, kCurrentBitstreamLink); if (!vi) { qWarning() << "Failed to read OggVorbis file:" << getUrlString(); return ERR; } setChannelCount(vi->channels); setSamplingRate(vi->rate); if (0 < vi->bitrate_nominal) { setBitrate(vi->bitrate_nominal / 1000); } else { if ((0 < vi->bitrate_lower) && (vi->bitrate_lower == vi->bitrate_upper)) { setBitrate(vi->bitrate_lower / 1000); } } ogg_int64_t pcmTotal = ov_pcm_total(&m_vf, kEntireBitstreamLink); if (0 <= pcmTotal) { setFrameCount(pcmTotal); } else { qWarning() << "Failed to read total length of OggVorbis file:" << getUrlString(); return ERR; } return OK; }
void OGGDecoder::reader() { float **pcm; long ret=1; int bit; size_t j,done=0; while (ATOMIC_CAS(&owner->work,true,true) && ret > 0 ){ j=0; ret=1; done=0; if (ATOMIC_CAS(&seek_to,SEEK_MAX,SEEK_MAX) != SEEK_MAX ){ if (ov_seekable(&vf)) ov_pcm_seek(&vf,(ogg_int64_t) seek_to); seek_to = SEEK_MAX; } while (done<VPBUFFER_FRAMES && ret > 0){ ret = ov_read_float( &vf, &pcm, VPBUFFER_FRAMES - done,&bit ); for (long i=0;i<ret;i++){ for (size_t ch=0;ch<bout->chans;ch++){ buffer[j]=(float)pcm[ch][i]; j++; } } done+=ret; } int samples= done*bout->chans; memcpy(bout->currentBuffer(), buffer,samples*sizeof(float) ); for (int i=samples;i<VPBUFFER_FRAMES*bout->chans;i++){ bout->currentBuffer()[i]=0.0f; } owner->postProcess(); owner->mutex[0].lock(); VP_SWAP_BUFFERS(bout); owner->mutex[1].unlock(); } }
int WOggDecoder::Seek(unsigned int nSamples) { ASSERT_W(c_fReady); err(DECODER_NO_ERROR); c_nBufferSize = 0; if(c_fManagedStream) { err(DECODER_SEEK_NOT_SUPPORTED_MANAGED); return 0; } if(nSamples >= c_isInfo.nLength) { err(DECODER_SEEK_POSITION_OUT_OF_BOUNDS); return 0; } if(ov_seekable(&vf) == 0) { err(DECODER_UNKNOWN_ERROR); return 0; } if(ov_pcm_seek(&vf, nSamples) != 0) { err(DECODER_UNKNOWN_ERROR); return 0; } c_nCurrentPosition = nSamples; c_nReversePos = nSamples; return 1; }
Result SoundSourceOggVorbis::tryOpen(const AudioSourceConfig& /*audioSrcCfg*/) { const QByteArray qbaFilename(getLocalFileNameBytes()); if (0 != ov_fopen(qbaFilename.constData(), &m_vf)) { qWarning() << "Failed to open OggVorbis file:" << getUrlString(); return ERR; } if (!ov_seekable(&m_vf)) { qWarning() << "OggVorbis file is not seekable:" << getUrlString(); return ERR; } // lookup the ogg's channels and sample rate const vorbis_info* vi = ov_info(&m_vf, kCurrentBitstreamLink); if (!vi) { qWarning() << "Failed to read OggVorbis file:" << getUrlString(); return ERR; } setChannelCount(vi->channels); setFrameRate(vi->rate); if (0 < vi->bitrate_nominal) { setBitrate(vi->bitrate_nominal / 1000); } else { if ((0 < vi->bitrate_lower) && (vi->bitrate_lower == vi->bitrate_upper)) { setBitrate(vi->bitrate_lower / 1000); } } ogg_int64_t pcmTotal = ov_pcm_total(&m_vf, kEntireBitstreamLink); if (0 <= pcmTotal) { setFrameCount(pcmTotal); } else { qWarning() << "Failed to read total length of OggVorbis file:" << getUrlString(); return ERR; } return OK; }
/* ========== OGG_Seek Change position in the file. ========== */ void OGG_Seek(ogg_seek_t type, double offset) { double pos; /* Position in file (in seconds). */ double total; /* Length of file (in seconds). */ /* Check if the file is seekable. */ if (ov_seekable(&ovFile) == 0) { Com_Printf("OGG_Seek: file is not seekable.\n"); return; } /* Get file information. */ pos = ov_time_tell(&ovFile); total = ov_time_total(&ovFile, -1); switch (type) { case ABS: if (offset >= 0 && offset <= total) { if (ov_time_seek(&ovFile, offset) != 0) Com_Printf("OGG_Seek: could not seek.\n"); else Com_Printf("%0.2f -> %0.2f of %0.2f.\n", pos, offset, total); } else Com_Printf("OGG_Seek: invalid offset.\n"); break; case REL: if (pos + offset >= 0 && pos + offset <= total) { if (ov_time_seek(&ovFile, pos + offset) != 0) Com_Printf("OGG_Seek: could not seek.\n"); else Com_Printf("%0.2f -> %0.2f of %0.2f.\n", pos, pos + offset, total); } else Com_Printf("OGG_Seek: invalid offset.\n"); break; } }
static int decode_file(FILE *in, FILE *out, char *infile, char *outfile) { OggVorbis_File vf; int bs = 0; char buf[8192], outbuf[8192]; char *p_outbuf; int buflen = 8192; unsigned int written = 0; int ret; ogg_int64_t length = 0; ogg_int64_t done = 0; int size = 0; int seekable = 0; int percent = 0; int channels; int samplerate; if (ov_open_callbacks(in, &vf, NULL, 0, OV_CALLBACKS_DEFAULT) < 0) { fprintf(stderr, _("ERROR: Failed to open input as Vorbis\n")); fclose(in); return 1; } channels = ov_info(&vf,0)->channels; samplerate = ov_info(&vf,0)->rate; if(ov_seekable(&vf)) { int link; int chainsallowed = 0; for(link = 0; link < ov_streams(&vf); link++) { if(ov_info(&vf, link)->channels == channels && ov_info(&vf, link)->rate == samplerate) { chainsallowed = 1; } } seekable = 1; if(chainsallowed) length = ov_pcm_total(&vf, -1); else length = ov_pcm_total(&vf, 0); size = bits/8 * channels; if(!quiet) fprintf(stderr, _("Decoding \"%s\" to \"%s\"\n"), infile?infile:_("standard input"), outfile?outfile:_("standard output")); } if(!raw) { if(write_prelim_header(&vf, out, length)) { ov_clear(&vf); return 1; } } while((ret = ov_read(&vf, buf, buflen, endian, bits/8, sign, &bs)) != 0) { if(bs != 0) { vorbis_info *vi = ov_info(&vf, -1); if(channels != vi->channels || samplerate != vi->rate) { fprintf(stderr, _("Logical bitstreams with changing parameters are not supported\n")); break; } } if(ret < 0 ) { if( !quiet ) { fprintf(stderr, _("WARNING: hole in data (%d)\n"), ret); } continue; } if(channels > 2 && !raw) { /* Then permute! */ permute_channels(buf, outbuf, ret, channels, bits/8); p_outbuf = outbuf; } else { p_outbuf = buf; } if(fwrite(p_outbuf, 1, ret, out) != ret) { fprintf(stderr, _("Error writing to file: %s\n"), strerror(errno)); ov_clear(&vf); return 1; } written += ret; if(!quiet && seekable) { done += ret/size; if((double)done/(double)length * 200. > (double)percent) { percent = (int)((double)done/(double)length *200); fprintf(stderr, "\r\t[%5.1f%%]", (double)percent/2.); } } } if(seekable && !quiet) fprintf(stderr, "\n"); if(!raw) rewrite_header(out, written); /* We don't care if it fails, too late */ ov_clear(&vf); return 0; }
prMALError SDKOpenFile8( imStdParms *stdParms, imFileRef *SDKfileRef, imFileOpenRec8 *SDKfileOpenRec8) { prMALError result = malNoError; ImporterLocalRec8H localRecH = NULL; ImporterLocalRec8Ptr localRecP = NULL; if(SDKfileOpenRec8->privatedata) { localRecH = (ImporterLocalRec8H)SDKfileOpenRec8->privatedata; stdParms->piSuites->memFuncs->lockHandle(reinterpret_cast<char**>(localRecH)); localRecP = reinterpret_cast<ImporterLocalRec8Ptr>( *localRecH ); } else { localRecH = (ImporterLocalRec8H)stdParms->piSuites->memFuncs->newHandle(sizeof(ImporterLocalRec8)); SDKfileOpenRec8->privatedata = (PrivateDataPtr)localRecH; stdParms->piSuites->memFuncs->lockHandle(reinterpret_cast<char**>(localRecH)); localRecP = reinterpret_cast<ImporterLocalRec8Ptr>( *localRecH ); localRecP->vf = NULL; localRecP->opus = NULL; localRecP->flac = NULL; localRecP->importerID = SDKfileOpenRec8->inImporterID; localRecP->fileType = SDKfileOpenRec8->fileinfo.filetype; } SDKfileOpenRec8->fileinfo.fileref = *SDKfileRef = reinterpret_cast<imFileRef>(imInvalidHandleValue); if(localRecP) { const prUTF16Char *path = SDKfileOpenRec8->fileinfo.filepath; #ifdef PRWIN_ENV HANDLE fileH = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(fileH != imInvalidHandleValue) { SDKfileOpenRec8->fileinfo.fileref = *SDKfileRef = fileH; } else result = imFileOpenFailed; #else FSIORefNum refNum = CAST_REFNUM(imInvalidHandleValue); CFStringRef filePathCFSR = CFStringCreateWithCharacters(NULL, path, prUTF16CharLength(path)); CFURLRef filePathURL = CFURLCreateWithFileSystemPath(NULL, filePathCFSR, kCFURLPOSIXPathStyle, false); if(filePathURL != NULL) { FSRef fileRef; Boolean success = CFURLGetFSRef(filePathURL, &fileRef); if(success) { HFSUniStr255 dataForkName; FSGetDataForkName(&dataForkName); OSErr err = FSOpenFork( &fileRef, dataForkName.length, dataForkName.unicode, fsRdWrPerm, &refNum); } CFRelease(filePathURL); } CFRelease(filePathCFSR); if(CAST_FILEREF(refNum) != imInvalidHandleValue) { SDKfileOpenRec8->fileinfo.fileref = *SDKfileRef = CAST_FILEREF(refNum); } else result = imFileOpenFailed; #endif } if(result == malNoError) { localRecP->fileType = SDKfileOpenRec8->fileinfo.filetype; assert(0 == ogg_tell_func(static_cast<void *>(*SDKfileRef))); if(localRecP->fileType == Ogg_filetype) { localRecP->vf = new OggVorbis_File; OggVorbis_File &vf = *localRecP->vf; int ogg_err = ov_open_callbacks(static_cast<void *>(*SDKfileRef), &vf, NULL, 0, g_ov_callbacks); if(ogg_err == OV_OK) { if( ov_streams(&vf) == 0 ) { result = imFileHasNoImportableStreams; ov_clear(&vf); } else if( !ov_seekable(&vf) ) { result = imBadFile; } } else result = imBadHeader; } else if(localRecP->fileType == Opus_filetype) { int _error = 0; localRecP->opus = op_open_callbacks(static_cast<void *>(*SDKfileRef), &g_opusfile_callbacks, NULL, 0, &_error); if(localRecP->opus != NULL && _error == 0) { assert(op_link_count(localRecP->opus) == 1); // we're not really handling multi-link scenarios } else result = imBadHeader; } else if(localRecP->fileType == FLAC_filetype) { try { localRecP->flac = new OurDecoder(*SDKfileRef); localRecP->flac->set_md5_checking(true); FLAC__StreamDecoderInitStatus init_status = localRecP->flac->init(); assert(init_status == FLAC__STREAM_DECODER_INIT_STATUS_OK && localRecP->flac->is_valid()); bool ok = localRecP->flac->process_until_end_of_metadata(); assert(ok); } catch(...) { result = imBadHeader; } } } // close file and delete private data if we got a bad file if(result != malNoError) { if(SDKfileOpenRec8->privatedata) { stdParms->piSuites->memFuncs->disposeHandle(reinterpret_cast<PrMemoryHandle>(SDKfileOpenRec8->privatedata)); SDKfileOpenRec8->privatedata = NULL; } } else { stdParms->piSuites->memFuncs->unlockHandle(reinterpret_cast<char**>(SDKfileOpenRec8->privatedata)); } return result; }
static int decode_file(char *infile, char *outfile) { FILE *in, *out=NULL; OggVorbis_File vf; int bs = 0; char buf[8192]; int buflen = 8192; unsigned int written = 0; int ret; ogg_int64_t length = 0; ogg_int64_t done = 0; int size; int seekable = 0; int percent = 0; if(!infile) { #ifdef __BORLANDC__ setmode(fileno(stdin), O_BINARY); #elif _WIN32 _setmode(_fileno(stdin), _O_BINARY); #endif in = stdin; } else { in = fopen(infile, "rb"); if(!in) { fprintf(stderr, "ERROR: Failed to open input file: %s\n", strerror(errno)); return 1; } } if(ov_open(in, &vf, NULL, 0) < 0) { fprintf(stderr, "ERROR: Failed to open input as vorbis\n"); fclose(in); return 1; } if(!outfile) { #ifdef __BORLANDC__ setmode(fileno(stdout), O_BINARY); #elif _WIN32 _setmode(_fileno(stdout), _O_BINARY); #endif out = stdout; } else { out = fopen(outfile, "wb"); if(!out) { fprintf(stderr, "ERROR: Failed to open output file: %s\n", strerror(errno)); return 1; } } if(ov_seekable(&vf)) { seekable = 1; length = ov_pcm_total(&vf, 0); size = bits/8 * ov_info(&vf, 0)->channels; if(!quiet) fprintf(stderr, "Decoding \"%s\" to \"%s\"\n", infile?infile:"standard input", outfile?outfile:"standard output"); } if(!raw) { if(write_prelim_header(&vf, out, length)) { ov_clear(&vf); fclose(out); return 1; } } while((ret = ov_read(&vf, buf, buflen, endian, bits/8, sign, &bs)) != 0) { if(bs != 0) { fprintf(stderr, "Only one logical bitstream currently supported\n"); break; } if(ret < 0 ) { if( !quiet ) { fprintf(stderr, "Warning: hole in data\n"); } continue; } if(fwrite(buf, 1, ret, out) != ret) { fprintf(stderr, "Error writing to file: %s\n", strerror(errno)); ov_clear(&vf); fclose(out); return 1; } written += ret; if(!quiet && seekable) { done += ret/size; if((double)done/(double)length * 200. > (double)percent) { percent = (double)done/(double)length *200; fprintf(stderr, "\r\t[%5.1f%%]", (double)percent/2.); } } } if(seekable && !quiet) fprintf(stderr, "\n"); if(!raw) rewrite_header(out, written); /* We don't care if it fails, too late */ ov_clear(&vf); fclose(out); return 0; }
int main(){ OggVorbis_File ov; int i,ret; ogg_int64_t pcmlength; double timelength; char *bigassbuffer; int dummy; int hs=0; #ifdef _WIN32 /* We need to set stdin/stdout to binary mode. Damn windows. */ _setmode( _fileno( stdin ), _O_BINARY ); #endif /* open the file/pipe on stdin */ if(ov_open_callbacks(stdin,&ov,NULL,-1,OV_CALLBACKS_NOCLOSE)<0){ fprintf(stderr,"Could not open input as an OggVorbis file.\n\n"); exit(1); } #if 0 /*enable this code to test seeking with halfrate decode */ if(ov_halfrate(&ov,1)){ fprintf(stderr,"Sorry; unable to set half-rate decode.\n\n"); exit(1); }else hs=1; #endif if(ov_seekable(&ov)){ /* to simplify our own lives, we want to assume the whole file is stereo. Verify this to avoid potentially mystifying users (pissing them off is OK, just don't confuse them) */ for(i=0;i<ov.links;i++){ vorbis_info *vi=ov_info(&ov,i); if(vi->channels!=2){ fprintf(stderr,"Sorry; right now seeking_test can only use Vorbis files\n" "that are entirely stereo.\n\n"); exit(1); } } /* because we want to do sample-level verification that the seek does what it claimed, decode the entire file into memory */ pcmlength=ov_pcm_total(&ov,-1); timelength=ov_time_total(&ov,-1); bigassbuffer=malloc((pcmlength>>hs)*2); /* w00t */ i=0; while(i<(pcmlength>>hs)*2){ int ret=ov_read(&ov,bigassbuffer+i,((pcmlength>>hs)*2)-i,1,1,1,&dummy); if(ret<0){ fprintf(stderr,"Error reading file.\n"); exit(1); } if(ret){ i+=ret; }else{ pcmlength=(i/2)<<hs; } fprintf(stderr,"\rloading.... [%ld left] ", (long)((pcmlength>>hs)*2-i)); } { ogg_int64_t length=ov.end; fprintf(stderr,"\rtesting raw seeking to random places in %ld bytes....\n", (long)length); for(i=0;i<1000;i++){ ogg_int64_t val=(double)rand()/RAND_MAX*length; fprintf(stderr,"\r\t%d [raw position %ld]... ",i,(long)val); ret=ov_raw_seek(&ov,val); if(ret<0){ fprintf(stderr,"seek failed: %d\n",ret); exit(1); } _verify(&ov,val,-1,-1.,pcmlength,bigassbuffer); } } fprintf(stderr,"\r"); { fprintf(stderr,"testing pcm page seeking to random places in %ld samples....\n", (long)pcmlength); for(i=0;i<1000;i++){ ogg_int64_t val= i==0?(ogg_int64_t)0:(double)rand()/RAND_MAX*pcmlength; fprintf(stderr,"\r\t%d [pcm position %ld]... ",i,(long)val); ret=ov_pcm_seek_page(&ov,val); if(ret<0){ fprintf(stderr,"seek failed: %d\n",ret); exit(1); } _verify(&ov,-1,val,-1.,pcmlength,bigassbuffer); } } fprintf(stderr,"\r"); { fprintf(stderr,"testing pcm exact seeking to random places in %f seconds....\n", timelength); for(i=0;i<1000;i++){ ogg_int64_t val= i==0?(ogg_int64_t)0:(double)rand()/RAND_MAX*pcmlength; fprintf(stderr,"\r\t%d [pcm position %ld]... ",i,(long)val); ret=ov_pcm_seek(&ov,val); if(ret<0){ fprintf(stderr,"seek failed: %d\n",ret); exit(1); } if(ov_pcm_tell(&ov)!=((val>>hs)<<hs)){ fprintf(stderr,"Declared position didn't perfectly match request: %ld != %ld\n", (long)val,(long)ov_pcm_tell(&ov)); exit(1); } _verify(&ov,-1,val,-1.,pcmlength,bigassbuffer); } } fprintf(stderr,"\r"); { fprintf(stderr,"testing time page seeking to random places in %f seconds....\n", timelength); for(i=0;i<1000;i++){ double val=(double)rand()/RAND_MAX*timelength; fprintf(stderr,"\r\t%d [time position %f]... ",i,val); ret=ov_time_seek_page(&ov,val); if(ret<0){ fprintf(stderr,"seek failed: %d\n",ret); exit(1); } _verify(&ov,-1,-1,val,pcmlength,bigassbuffer); } } fprintf(stderr,"\r"); { fprintf(stderr,"testing time exact seeking to random places in %f seconds....\n", timelength); for(i=0;i<1000;i++){ double val=(double)rand()/RAND_MAX*timelength; fprintf(stderr,"\r\t%d [time position %f]... ",i,val); ret=ov_time_seek(&ov,val); if(ret<0){ fprintf(stderr,"seek failed: %d\n",ret); exit(1); } if(ov_time_tell(&ov)<val-1 || ov_time_tell(&ov)>val+1){ fprintf(stderr,"Declared position didn't perfectly match request: %f != %f\n", val,ov_time_tell(&ov)); exit(1); } _verify(&ov,-1,-1,val,pcmlength,bigassbuffer); } } fprintf(stderr,"\r \nOK.\n\n"); }else{
/* open ogg/vorbis file */ static void oggread_open(t_oggread *x, t_symbol *filename) { int i; x->x_stream = 0; /* first close previous file */ if(x->x_fd > 0) { ov_clear(&x->x_ov); post("oggread~: previous file closed"); } /* open file for reading */ if((x->x_file = sys_fopen(filename->s_name, "rb")) <= 0) { post("oggread~: could not open file \"%s\"", filename->s_name); x->x_eos = 1; x->x_fd = -1; } else { x->x_stream = 0; x->x_eos = 0; x->x_fd = 1; x->x_outreadposition = 0; x->x_outwriteposition = 0; x->x_outunread = 0; post("oggread~: file \"%s\" opened", filename->s_name); outlet_float( x->x_out_position, 0); /* try to open as ogg vorbis file */ if(ov_open(x->x_file, &x->x_ov, NULL, -1) < 0) { /* an error occured (no ogg vorbis file ?) */ post("oggread~: error: could not open \"%s\" as an OggVorbis file", filename->s_name); ov_clear(&x->x_ov); post("oggread~: file closed due to error"); x->x_fd=-1; x->x_eos=1; return; } /* print details about each logical bitstream in the input */ if(ov_seekable(&x->x_ov)) { post("oggread~: input bitstream contained %ld logical bitstream section(s)", ov_streams(&x->x_ov)); post("oggread~: total bitstream playing time: %ld seconds", (long)ov_time_total(&x->x_ov,-1)); post("oggread~: encoded by: %s\n",ov_comment(&x->x_ov,-1)->vendor); } else { post("oggread~: file \"%s\" was not seekable\n" "oggread~: first logical bitstream information:", filename->s_name); } for(i = 0; i < ov_streams(&x->x_ov); i++) { x->x_vi = ov_info(&x->x_ov,i); post("\tlogical bitstream section %d information:",i+1); post("\t\t%ldHz %d channels bitrate %ldkbps serial number=%ld", x->x_vi->rate,x->x_vi->channels,ov_bitrate(&x->x_ov,i)/1000, ov_serialnumber(&x->x_ov,i)); post("\t\theader length: %ld bytes",(long) (x->x_ov.dataoffsets[i] - x->x_ov.offsets[i])); post("\t\tcompressed length: %ld bytes",(long)(ov_raw_total(&x->x_ov,i))); post("\t\tplay time: %ld seconds\n",(long)ov_time_total(&x->x_ov,i)); } } }
/* Reads an ogg vorbis file, infile, and dumps the data into a big buffer, *pcmbuffer (which it allocates via malloc) and returns the number of samples in *nsamples, and the samplesize in *samplesize. and etc. */ int ogg_to_pcm(char *infile, int16_t **pcmbuffer, int *samplesize, int *sample_rate, int *nchannels, uint64_t *nsamples) { OggVorbis_File vf; char buf[8192]; unsigned char *bufferptr; int link, ret, chainsallowed = 0, bs = 0; /* how to do this portably at compile time? */ const uint32_t dummy = 0x01020304; const unsigned char *endian = (unsigned char *) &dummy; /* use ov_fopen to avoid runtime conflicts on win32 */ if (ov_fopen(infile, &vf) < 0) { fprintf(stderr, "%s:%d: ERROR: Failed to open '%s' as vorbis\n", __FILE__, __LINE__, infile); ov_clear(&vf); return -1; } if (!ov_seekable(&vf)) { fprintf(stderr, "%s:%d: %s is not seekable.\n", __FILE__, __LINE__, infile); ov_clear(&vf); return -1; } *nchannels = ov_info(&vf,0)->channels; *sample_rate = ov_info(&vf,0)->rate; for (link = 0; link < ov_streams(&vf); link++) { if (ov_info(&vf, link)->channels == *nchannels && ov_info(&vf, link)->rate == *sample_rate) { chainsallowed = 1; } } if (chainsallowed) *nsamples = ov_pcm_total(&vf, -1); else *nsamples = ov_pcm_total(&vf, 0); *pcmbuffer = (void *) malloc(sizeof(int16_t) * *nsamples * *nchannels); memset(*pcmbuffer, 0, sizeof(int16_t) * *nsamples * *nchannels); if (*pcmbuffer == NULL) { fprintf(stderr, "%s:%d: Failed to allocate memory for '%s'\n", __FILE__, __LINE__, infile); ov_clear(&vf); return -1; } bufferptr = (unsigned char *) *pcmbuffer; while ((ret = ov_read(&vf, buf, sizeof(buf), endian[0] == 0x01, bits/8, 1, &bs)) != 0) { if (bs != 0) { vorbis_info *vi = ov_info(&vf, -1); if (*nchannels != vi->channels || *sample_rate != vi->rate) { fprintf(stderr, "%s:%d: Logical bitstreams with changing " "parameters are not supported\n", __FILE__, __LINE__); break; } } if(ret < 0 ) { fprintf(stderr, "%s:%d: Warning: hole in data (%d)\n", __FILE__, __LINE__, ret); continue; } /* copy the data to the pcmbuffer. */ memcpy(bufferptr, buf, ret); bufferptr += ret; } /* ov_clear closes the file, so don't fclose here, even though we fopen()ed. * libvorbis is weird that way. */ ov_clear(&vf); return 0; }
SoundSource::OpenResult SoundSourceOggVorbis::tryOpen( OpenMode /*mode*/, const OpenParams& /*config*/) { m_pFile = std::make_unique<QFile>(getLocalFileName()); if (!m_pFile->open(QFile::ReadOnly)) { kLogger.warning() << "Failed to open file for" << getUrlString(); return OpenResult::Failed; } const int initDecoderResult = ov_open_callbacks(m_pFile.get(), &m_vf, nullptr, 0, s_callbacks); switch (initDecoderResult) { case 0: // success -> continue break; case OV_ENOTVORBIS: case OV_EVERSION: kLogger.warning() << "Unsupported format in" << getUrlString(); return OpenResult::Aborted; default: kLogger.warning() << "Failed to initialize decoder for" << getUrlString(); return OpenResult::Failed; } if (!ov_seekable(&m_vf)) { kLogger.warning() << "Stream in" << getUrlString() << "is not seekable"; return OpenResult::Aborted; } // lookup the ogg's channels and sample rate const vorbis_info* vi = ov_info(&m_vf, kCurrentBitstreamLink); if (!vi) { kLogger.warning() << "Failed to read stream info from" << getUrlString(); return OpenResult::Failed; } setChannelCount(vi->channels); setSampleRate(vi->rate); if (0 < vi->bitrate_nominal) { initBitrateOnce(vi->bitrate_nominal / 1000); } else { if ((0 < vi->bitrate_lower) && (vi->bitrate_lower == vi->bitrate_upper)) { initBitrateOnce(vi->bitrate_lower / 1000); } } ogg_int64_t pcmTotal = ov_pcm_total(&m_vf, kEntireBitstreamLink); if (0 <= pcmTotal) { initFrameIndexRangeOnce(IndexRange::forward(0, pcmTotal)); } else { kLogger.warning() << "Failed to read read total length of" << getUrlString(); return OpenResult::Failed; } return OpenResult::Succeeded; }
int main(){ OggVorbis_File ov; int i,ret; ogg_int64_t pcmlength; char *bigassbuffer; int dummy; #ifdef _WIN32 /* We need to set stdin/stdout to binary mode. Damn windows. */ _setmode( _fileno( stdin ), _O_BINARY ); _setmode( _fileno( stdout ), _O_BINARY ); #endif /* open the file/pipe on stdin */ if(ov_open(stdin,&ov,NULL,-1)<0){ printf("Could not open input as an OggVorbis file.\n\n"); exit(1); } if(ov_seekable(&ov)){ /* to simplify our own lives, we want to assume the whole file is stereo. Verify this to avoid potentially mystifying users (pissing them off is OK, just don't confuse them) */ for(i=0;i<ov.links;i++){ vorbis_info *vi=ov_info(&ov,i); if(vi->channels!=2){ printf("Sorry; right now seeking_test can only use Vorbis files\n" "that are entirely stereo.\n\n"); exit(1); } } /* because we want to do sample-level verification that the seek does what it claimed, decode the entire file into memory */ fflush(stdout); pcmlength=ov_pcm_total(&ov,-1); bigassbuffer=malloc(pcmlength*2); /* w00t */ i=0; while(i<pcmlength*2){ int ret=ov_read(&ov,bigassbuffer+i,pcmlength*2-i,1,1,1,&dummy); if(ret<0)continue; if(ret){ i+=ret; }else{ pcmlength=i/2; } fprintf(stderr,"\rloading.... [%ld left] ", (long)(pcmlength*2-i)); } /* Exercise all the real seeking cases; ov_raw_seek, ov_pcm_seek_page and ov_pcm_seek. time seek is just a wrapper on pcm_seek */ { ogg_int64_t length=ov.end; printf("\rtesting raw seeking to random places in %ld bytes....\n", (long)length); for(i=0;i<1000;i++){ ogg_int64_t val=(double)rand()/RAND_MAX*length; ogg_int64_t pos; printf("\r\t%d [raw position %ld]... ",i,(long)val); fflush(stdout); ret=ov_raw_seek(&ov,val); if(ret<0){ printf("seek failed: %d\n",ret); exit(1); } _verify(&ov,pos,val,-1,pcmlength,bigassbuffer); } } printf("\r"); { printf("testing pcm page seeking to random places in %ld samples....\n", (long)pcmlength); for(i=0;i<1000;i++){ ogg_int64_t val=(double)rand()/RAND_MAX*pcmlength; ogg_int64_t pos; printf("\r\t%d [pcm position %ld]... ",i,(long)val); fflush(stdout); ret=ov_pcm_seek_page(&ov,val); if(ret<0){ printf("seek failed: %d\n",ret); exit(1); } _verify(&ov,pos,-1,val,pcmlength,bigassbuffer); } } printf("\r"); { ogg_int64_t length=ov.end; printf("testing pcm exact seeking to random places in %ld samples....\n", (long)pcmlength); for(i=0;i<1000;i++){ ogg_int64_t val=(double)rand()/RAND_MAX*pcmlength; ogg_int64_t pos; printf("\r\t%d [pcm position %ld]... ",i,(long)val); fflush(stdout); ret=ov_pcm_seek(&ov,val); if(ret<0){ printf("seek failed: %d\n",ret); exit(1); } if(ov_pcm_tell(&ov)!=val){ printf("Declared position didn't perfectly match request: %ld != %ld\n", (long)val,(long)ov_pcm_tell(&ov)); exit(1); } _verify(&ov,pos,-1,val,pcmlength,bigassbuffer); } } printf("\r \nOK.\n\n"); }else{ printf("Standard input was not seekable.\n"); } ov_clear(&ov); return 0; }
/* ================= S_OGG_CodecOpenStream ================= */ snd_stream_t* S_OGG_CodecOpenStream(const char* filename) { snd_stream_t* stream; // OGG codec control structure OggVorbis_File* vf; // some variables used to get informations about the OGG vorbis_info* OGGInfo; ogg_int64_t numSamples; // check if input is valid if (!filename) { return NULL; } // Open the stream stream = S_CodecUtilOpen(filename, &ogg_codec); if (!stream) { return NULL; } // alloctate the OggVorbis_File vf = Z_Malloc(sizeof(OggVorbis_File)); if (!vf) { S_CodecUtilClose(&stream); return NULL; } // open the codec with our callbacks and stream as the generic pointer if (ov_open_callbacks(stream, vf, NULL, 0, S_OGG_Callbacks) != 0) { Z_Free(vf); S_CodecUtilClose(&stream); return NULL; } // the stream must be seekable if (!ov_seekable(vf)) { ov_clear(vf); Z_Free(vf); S_CodecUtilClose(&stream); return NULL; } // we only support OGGs with one substream if (ov_streams(vf) != 1) { ov_clear(vf); Z_Free(vf); S_CodecUtilClose(&stream); return NULL; } // get the info about channels and rate OGGInfo = ov_info(vf, 0); if (!OGGInfo) { ov_clear(vf); Z_Free(vf); S_CodecUtilClose(&stream); return NULL; } // get the number of sample-frames in the OGG numSamples = ov_pcm_total(vf, 0); // fill in the info-structure in the stream stream->info.rate = OGGInfo->rate; stream->info.width = OGG_SAMPLEWIDTH; stream->info.channels = OGGInfo->channels; stream->info.samples = numSamples; stream->info.size = stream->info.samples * stream->info.channels * stream->info.width; stream->info.dataofs = 0; // We use stream->pos for the file pointer in the compressed ogg file stream->pos = 0; // We use the generic pointer in stream for the OGG codec control structure stream->ptr = vf; return stream; }
bool VorbisDecoder::IsSeekable() { if (!m_opened) { return false; } return ov_seekable(&m_file)!=0; }