f_cnt_t SampleBuffer::decodeSampleOGGVorbis( const char * _f, int_sample_t * & _buf, ch_cnt_t & _channels, sample_rate_t & _samplerate ) { static ov_callbacks callbacks = { qfileReadCallback, qfileSeekCallback, qfileCloseCallback, qfileTellCallback } ; OggVorbis_File vf; f_cnt_t frames = 0; QFile * f = new QFile( _f ); if( f->open( QFile::ReadOnly ) == false ) { delete f; return 0; } int err = ov_open_callbacks( f, &vf, NULL, 0, callbacks ); if( err < 0 ) { switch( err ) { case OV_EREAD: printf( "SampleBuffer::decodeSampleOGGVorbis():" " media read error\n" ); break; case OV_ENOTVORBIS: /* printf( "SampleBuffer::decodeSampleOGGVorbis():" " not an Ogg Vorbis file\n" );*/ break; case OV_EVERSION: printf( "SampleBuffer::decodeSampleOGGVorbis():" " vorbis version mismatch\n" ); break; case OV_EBADHEADER: printf( "SampleBuffer::decodeSampleOGGVorbis():" " invalid Vorbis bitstream header\n" ); break; case OV_EFAULT: printf( "SampleBuffer::decodeSampleOgg(): " "internal logic fault\n" ); break; } delete f; return 0; } ov_pcm_seek( &vf, 0 ); _channels = ov_info( &vf, -1 )->channels; _samplerate = ov_info( &vf, -1 )->rate; ogg_int64_t total = ov_pcm_total( &vf, -1 ); _buf = new int_sample_t[total * _channels]; int bitstream = 0; long bytes_read = 0; do { bytes_read = ov_read( &vf, (char *) &_buf[frames * _channels], ( total - frames ) * _channels * BYTES_PER_INT_SAMPLE, isLittleEndian() ? 0 : 1, BYTES_PER_INT_SAMPLE, 1, &bitstream ); if( bytes_read < 0 ) { break; } frames += bytes_read / ( _channels * BYTES_PER_INT_SAMPLE ); } while( bytes_read != 0 && bitstream == 0 ); ov_clear( &vf ); // if buffer isn't empty, convert it to float and write it down if ( frames > 0 && _buf != NULL ) { convertIntToFloat ( _buf, frames, _channels); } return frames; }
bool SoundBuffer::LoadOGG(const std::string & filename, const SoundInfo & sound_device_info, std::ostream & error_output) { if (loaded) Unload(); name = filename; FILE *fp; unsigned int samples; fp = fopen(filename.c_str(), "rb"); if (fp) { vorbis_info *pInfo; OggVorbis_File oggFile; ov_open_callbacks(fp, &oggFile, NULL, 0, OV_CALLBACKS_DEFAULT); pInfo = ov_info(&oggFile, -1); //I assume ogg is always 16-bit (2 bytes per sample) -Venzon samples = ov_pcm_total(&oggFile,-1); info = SoundInfo(samples*pInfo->channels, pInfo->rate, pInfo->channels, 2); SoundInfo desired_info(info.samples, sound_device_info.frequency, info.channels, sound_device_info.bytespersample); if (!(desired_info == info)) { error_output << "SOUND FORMAT:" << std::endl; info.DebugPrint(error_output); error_output << "DESIRED FORMAT:" << std::endl; desired_info.DebugPrint(error_output); error_output << "Sound file isn't in desired format: "+filename << std::endl; ov_clear(&oggFile); return false; } //allocate space unsigned int size = info.samples*info.channels*info.bytespersample; sound_buffer = new char[size]; int bitstream; int endian = 0; //0 for Little-Endian, 1 for Big-Endian int wordsize = 2; //again, assuming ogg is always 16-bits int issigned = 1; //use signed data int bytes = 1; unsigned int bufpos = 0; while (bytes > 0) { bytes = ov_read(&oggFile, sound_buffer+bufpos, size-bufpos, endian, wordsize, issigned, &bitstream); bufpos += bytes; //cout << bytes << "..."; } loaded = true; //note: no need to call fclose(); ov_clear does it for us ov_clear(&oggFile); return true; } else { error_output << "Can't open sound file: "+filename << std::endl; return false; } }
/* Function: al_load_ogg_vorbis_audio_stream_f */ ALLEGRO_AUDIO_STREAM *al_load_ogg_vorbis_audio_stream_f(ALLEGRO_FILE* file, size_t buffer_count, unsigned int samples) { const int word_size = 2; /* 1 = 8bit, 2 = 16-bit. nothing else */ OggVorbis_File* vf; vorbis_info* vi; int channels; long rate; long total_samples; long total_size; AL_OV_DATA* extra; ALLEGRO_AUDIO_STREAM* stream; extra = _AL_MALLOC(sizeof(AL_OV_DATA)); if (extra == NULL) { ALLEGRO_ERROR("Failed to allocate AL_OV_DATA struct.\n"); return NULL; } if (file == NULL) { ALLEGRO_WARN("File failed to open\n"); fprintf(stderr, "File failed to open\n"); return NULL; } extra->file = file; vf = _AL_MALLOC(sizeof(OggVorbis_File)); if (ov_open_callbacks(extra, vf, NULL, 0, callbacks) < 0) { ALLEGRO_WARN("ogg: Input does not appear to be an Ogg bitstream.\n"); al_fclose(file); return NULL; } extra->vf = vf; vi = ov_info(vf, -1); channels = vi->channels; rate = vi->rate; total_samples = ov_pcm_total(vf,-1); total_size = total_samples * channels * word_size; extra->vi = vi; extra->bitstream = -1; ALLEGRO_DEBUG("channels %d\n", channels); ALLEGRO_DEBUG("word_size %d\n", word_size); ALLEGRO_DEBUG("rate %ld\n", rate); ALLEGRO_DEBUG("total_samples %ld\n", total_samples); ALLEGRO_DEBUG("total_size %ld\n", total_size); stream = al_create_audio_stream(buffer_count, samples, rate, _al_word_size_to_depth_conf(word_size), _al_count_to_channel_conf(channels)); if (!stream) { free(vf); return NULL; } stream->extra = extra; extra->loop_start = 0.0; extra->loop_end = ogg_stream_get_length(stream); stream->feed_thread = al_create_thread(_al_kcm_feed_stream, stream); stream->quit_feed_thread = false; stream->feeder = ogg_stream_update; stream->rewind_feeder = ogg_stream_rewind; stream->seek_feeder = ogg_stream_seek; stream->get_feeder_position = ogg_stream_get_position; stream->get_feeder_length = ogg_stream_get_length; stream->set_feeder_loop = ogg_stream_set_loop; stream->unload_feeder = ogg_stream_close; al_start_thread(stream->feed_thread); return stream; }
void Sound::PlaySound(const boost::filesystem::path& path, bool is_ui_sound/* = false*/) { if (!GetOptionsDB().Get<bool>("UI.sound.enabled") || (is_ui_sound && UISoundsTemporarilyDisabled())) return; std::string filename = path.string(); ALuint current_buffer; ALenum source_state; ALsizei ogg_freq; FILE *file = 0; int m_i; bool found_buffer = true; bool found_source = false; #ifdef FREEORION_WIN32 ov_callbacks callbacks = { (size_t (*)(void *, size_t, size_t, void *)) fread, (int (*)(void *, ogg_int64_t, int)) _fseek64_wrap, (int (*)(void *)) fclose, (long (*)(void *)) ftell }; #endif if (alcGetCurrentContext() != 0) { /* First check if the sound data of the file we want to play is already buffered somewhere */ std::map<std::string, ALuint>::iterator it = m_buffers.find(filename); if (it != m_buffers.end()) current_buffer = it->second; else { if ((file = fopen(filename.c_str(), "rb")) != 0) // make sure we CAN open it { OggVorbis_File ogg_file; vorbis_info *vorbis_info; ALenum ogg_format; #ifdef FREEORION_WIN32 if (!(ov_test_callbacks(file, &ogg_file, 0, 0, callbacks))) // check if it's a proper ogg #else if (!(ov_test(file, &ogg_file, 0, 0))) // check if it's a proper ogg #endif { ov_test_open(&ogg_file); // it is, now fully open the file /* now we need to take some info we will need later */ vorbis_info = ov_info(&ogg_file, -1); if (vorbis_info->channels == 1) ogg_format = AL_FORMAT_MONO16; else ogg_format = AL_FORMAT_STEREO16; ogg_freq = vorbis_info->rate; ogg_int64_t byte_size = ov_pcm_total(&ogg_file, -1) * vorbis_info->channels * 2; if (byte_size <= 1024 * 1024 * 1024) { /* fill up the buffers and queue them up for the first time */ ALuint sound_handle; alGenBuffers(1, &sound_handle); int loop = 0; RefillBuffer(&ogg_file, ogg_format, ogg_freq, sound_handle, byte_size, loop); current_buffer = sound_handle; m_buffers.insert(std::make_pair(filename, sound_handle)); } else { ErrorLogger() << "PlaySound: unable to open file " << filename.c_str() << " too big to buffer. Aborting\n"; } ov_clear(&ogg_file); } else { ErrorLogger() << "PlaySound: unable to open file " << filename.c_str() << " possibly not a .ogg vorbis file. Aborting\n"; } } } if (found_buffer) { /* Now that we have the buffer, we need to find a source to send it to */ for (m_i = 1; m_i < NUM_SOURCES; ++m_i) { // as we're playing sounds we start at 1. 0 is reserved for music alGetSourcei(m_sources[m_i],AL_SOURCE_STATE,&source_state); if ((source_state != AL_PLAYING) && (source_state != AL_PAUSED)) { found_source = true; alSourcei(m_sources[m_i], AL_BUFFER, current_buffer); alSourcePlay(m_sources[m_i]); break; // so that the sound won't block all the sources } } if (!found_source) ErrorLogger() << "PlaySound: Could not find aviable source - playback aborted\n"; } source_state = alGetError(); if (source_state != AL_NONE) ErrorLogger() << "PlaySound: OpenAL ERROR: " << alGetString(source_state); /* it's important to check for errors, as some functions won't work properly if * they're called when there is a unchecked previous error. */ } }
int64 OggVorbisReader::FrameCount(void) { return(ov_pcm_total(&ovfile, -1)); }
int getSourceLength(){ if(isplaying_ogg) return ov_pcm_total(&oggvorbisfile,-1); return N; }
// Just create the Quicktime objects since this routine is also called // for reopening. int FileVorbis::open_file(int rd, int wr) { int result = 0; this->rd = rd; this->wr = wr; //printf("FileVorbis::open_file 1\n"); if(rd) { //printf("FileVorbis::open_file 1\n"); if(!(fd = fopen(asset->path, "rb"))) { eprintf("Error while opening \"%s\" for reading. \n%m\n", asset->path); result = 1; } else { //printf("FileVorbis::open_file 2 %p %p\n", fd, vf); if(ov_open(fd, &vf, NULL, 0) < 0) { eprintf("Invalid bitstream in %s\n", asset->path); result = 1; } else { //printf("FileVorbis::open_file 1\n"); vorbis_info *vi = ov_info(&vf, -1); asset->channels = vi->channels; if(!asset->sample_rate) asset->sample_rate = vi->rate; //printf("FileVorbis::open_file 1\n"); asset->audio_length = ov_pcm_total(&vf,-1); //printf("FileVorbis::open_file 1\n"); asset->audio_data = 1; // printf("FileVorbis::open_file 1 %d %d %d\n", // asset->channels, // asset->sample_rate, // asset->audio_length); } } } if(wr) { if(!(fd = fopen(asset->path, "wb"))) { eprintf("Error while opening \"%s\" for writing. \n%m\n", asset->path); result = 1; } else { vorbis_info_init(&vi); if(!asset->vorbis_vbr) result = vorbis_encode_init(&vi, asset->channels, asset->sample_rate, asset->vorbis_max_bitrate, asset->vorbis_bitrate, asset->vorbis_min_bitrate); else { result = vorbis_encode_setup_managed(&vi, asset->channels, asset->sample_rate, asset->vorbis_max_bitrate, asset->vorbis_bitrate, asset->vorbis_min_bitrate); result |= vorbis_encode_ctl(&vi, OV_ECTL_RATEMANAGE_AVG, NULL); result |= vorbis_encode_setup_init(&vi); } if(!result) { vorbis_analysis_init(&vd, &vi); vorbis_block_init(&vd, &vb); vorbis_comment_init(&vc); srand(time(NULL)); ogg_stream_init(&os, rand()); ogg_packet header; ogg_packet header_comm; ogg_packet header_code; vorbis_analysis_headerout(&vd, &vc, &header, &header_comm, &header_code); ogg_stream_packetin(&os, &header); ogg_stream_packetin(&os, &header_comm); ogg_stream_packetin(&os, &header_code); while(1) { int result = ogg_stream_flush(&os, &og); if(result == 0) break; fwrite(og.header, 1, og.header_len, fd); fwrite(og.body, 1, og.body_len, fd); } } } } //printf("FileVorbis::open_file 2\n"); return result; }
bool OggResourceLoader::ParseOgg(char* oggStream, size_t bufferLength, shared_ptr<ResHandle> handle) { shared_ptr<SoundResourceExtraData> extra = static_pointer_cast<SoundResourceExtraData>(handle->GetExtra()); OggVorbis_File vf; ov_callbacks oggCallbacks; // create the vorbis memory object OggMemoryFile* vorbisMemoryFile = CB_NEW OggMemoryFile; vorbisMemoryFile->dataSize = bufferLength; vorbisMemoryFile->dataPtr = (unsigned char*)oggStream; vorbisMemoryFile->dataRead = 0; // set up ogg callbacks oggCallbacks.read_func = VorbisRead; oggCallbacks.close_func = VorbisClose; oggCallbacks.seek_func = VorbisSeek; oggCallbacks.tell_func = VorbisTell; int ov_ret = ov_open_callbacks(vorbisMemoryFile, &vf, nullptr, 0, oggCallbacks); CB_ASSERT(ov_ret >= 0); vorbis_info* vi = ov_info(&vf, -1); ZeroMemory(&(extra->m_WavFormatEx), sizeof(extra->m_WavFormatEx)); // set up the extra info extra->m_WavFormatEx.cbSize = sizeof(extra->m_WavFormatEx); extra->m_WavFormatEx.nChannels = vi->channels; extra->m_WavFormatEx.wBitsPerSample = 16; extra->m_WavFormatEx.nSamplesPerSec = vi->rate; extra->m_WavFormatEx.nAvgBytesPerSec = extra->m_WavFormatEx.nSamplesPerSec * extra->m_WavFormatEx.nChannels * 2; extra->m_WavFormatEx.nBlockAlign = extra->m_WavFormatEx.nChannels * 2; extra->m_WavFormatEx.wFormatTag = 1; DWORD size = 4096 * 16; DWORD pos = 0; int sec = 0; int ret = 1; DWORD bytes = (DWORD)ov_pcm_total(&vf, -1); bytes *= 2 * vi->channels; if (handle->Size() != bytes) { CB_ASSERT(0 && L"The Ogg size does not match the memory buffer size"); ov_clear(&vf); CB_SAFE_DELETE(vorbisMemoryFile); return false; } // read in the bytes while (ret && pos < bytes) { ret = ov_read(&vf, handle->WritableBuffer() + pos, size, 0, 2, 1, &sec); pos += ret; if (bytes - pos < size) { size = bytes - pos; } } extra->m_LengthMilliseconds = (int)(1000.0f * ov_time_total(&vf, -1)); ov_clear(&vf); CB_SAFE_DELETE(vorbisMemoryFile); return true; }
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{
/* ================= 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; }
int ogg_decoder(const char *ogg_file, const char *pcm_file) { OggVorbis_File vf; int eof = 0; int current_section; int tm1, tm2; FILE *fin, *fout; //open the ogg file fin = fopen(ogg_file, "rb"); if (fin == NULL) { libc_printf("open the ogg file: %s failed!\n", ogg_file); return -1; } //create the pcm file #if 0 fout = fopen(pcm_file, "wb"); if (fout == NULL) { libc_printf("open the ogg file: %s failed!\n", pcm_file); return -1; } #endif if (ov_open(fin, &vf, NULL, 0) < 0) { libc_printf("Input does not appear to be an Ogg bitstream.\n"); return -1; } /* Throw the comments plus a few lines about the bitstream we're decoding */ { char **ptr = ov_comment(&vf, -1)->user_comments; vorbis_info *vi = ov_info(&vf, -1); while (*ptr) { libc_printf("%s\n", *ptr); ++ptr; } libc_printf("\nBitstream is %d channel, %ldHz\n", vi->channels, vi->rate); libc_printf("\nDecoded length: %ld samples\n", (long)ov_pcm_total(&vf, -1)); libc_printf("Encoded by: %s\n\n", ov_comment(&vf, -1)->vendor); } tm1 = osal_get_tick(); while (!eof) { long ret = ov_read(&vf, pcmout, sizeof(pcmout), ¤t_section); if (ret == 0) { libc_printf("file end!\n"); /* EOF */ eof = 1; } else if (ret < 0) { libc_printf("error!!!\n"); /* error in the stream. Not a problem, just reporting it in case we (the app) cares. In this case, we don't. */ } else { /* we don't bother dealing with sample rate changes, etc, but you'll have to*/ //fwrite(pcmout, ret, 1, fout); } } /* cleanup */ ov_clear(&vf); tm2 = osal_get_tick(); libc_printf("decoding time: %dms [%d ~ %d]\n", tm2 - tm1, tm1, tm2); //fclose(fout); libc_printf("Done.\n"); 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; }
bool SoundManager::loadOgg(FILE* file, ALuint buffer) { OggVorbis_File ogg_file; vorbis_info* info; ALenum format; int result; int section; unsigned int size = 0; rewind(file); if ((result = ov_open(file, &ogg_file, NULL, 0)) < 0) { fclose(file); qDebug() << "Failed to open ogg file."; return false; } info = ov_info(&ogg_file, -1); if (info->channels == 1) format = AL_FORMAT_MONO16; else format = AL_FORMAT_STEREO16; // size = #samples * #channels * 2 (for 16 bit). unsigned int data_size = ov_pcm_total(&ogg_file, -1) * info->channels * 2; char* data = new char[data_size]; while (size < data_size) { result = ov_read(&ogg_file, data + size, data_size - size, 0, 2, 1, §ion); if (result > 0) { size += result; } else if (result < 0) { delete data; qDebug() << "Failed to read ogg file; file is missing data."; return false; } else { break; } } if (size == 0) { delete data; qDebug() << "Filed to read ogg file; unable to read any data."; return false; } alBufferData(buffer, format, data, data_size, info->rate); ALenum error = alGetError(); if (error != AL_NO_ERROR) { reportOpenALError(error); } delete data; ov_clear(&ogg_file); // ov_clear actually closes the file pointer as well. file = 0; return true; }
std::pair<ALuint, float> Sound_Buffer::load_ogg_vorbis(const String & #ifndef DISABLE_AL filename #endif ) { #ifndef DISABLE_AL /*** Open VorbisFile ***/ OggVorbis_File oggFile; if(ov_fopen(const_cast<char *>((filename + ".ogg").c_str()), &oggFile)) return std::make_pair(AL_NONE, 0.0f); /*** Get Information About the Audio File ***/ vorbis_info *pInfo = ov_info(&oggFile, -1); const ALenum format = pInfo->channels == 2 ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16; const ALsizei freq = ALsizei(pInfo->rate); const ALsizei bytes_per_sample = format == AL_FORMAT_STEREO16 ? 4 : 2; const ogg_int64_t num_samples = ov_pcm_total(&oggFile, -1); const ogg_int64_t pcm_size = num_samples * bytes_per_sample; const float duration = float(num_samples) / freq; #ifndef NDEBUG if(format == AL_FORMAT_STEREO16) std::cerr << "WARNING: '" << filename << "' is stereo and will be unaffected by the OpenAL positional audio system." << std::endl; #endif /*** Load the Audio File ***/ long bytes = 0; ogg_int64_t remaining = pcm_size; if(pcm_size > std::numeric_limits<size_t>::max()) throw Sound_Buffer_Init_Failure(); std::vector<char> buffer(static_cast<size_t>(pcm_size)); for(char *begin = &buffer[0], *end = begin + pcm_size; begin != end; begin += bytes, remaining -= bytes) { int read_size = remaining > std::numeric_limits<int>::max() ? std::numeric_limits<int>::max() : int(remaining); bytes = ov_read(&oggFile, begin, read_size, 0, 2, 1, 0); if(bytes < 0) { ov_clear(&oggFile); throw Sound_Buffer_Init_Failure(); } } /*** Generate Audio Buffer ***/ ALuint bufferID = AL_NONE; Sound_Renderer_AL::alGenBuffers()(1, &bufferID); Sound_Renderer_AL::alBufferData()(bufferID, format, &buffer[0], static_cast<ALsizei>(buffer.size()), freq); return std::make_pair(bufferID, duration); #else return std::make_pair(AL_NONE, 0.0f); #endif }
VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, const char * filename, ov_callbacks *callbacks_p, off_t other_header_bytes, const vgm_vorbis_info_t *vgm_inf) { VGMSTREAM * vgmstream = NULL; OggVorbis_File temp_ovf; ogg_vorbis_streamfile temp_streamfile; ogg_vorbis_codec_data * data = NULL; OggVorbis_File *ovf; int inited_ovf = 0; vorbis_info *info; int loop_flag = vgm_inf->loop_flag; int32_t loop_start = vgm_inf->loop_start; int loop_length_found = vgm_inf->loop_length_found; int32_t loop_length = vgm_inf->loop_length; int loop_end_found = vgm_inf->loop_end_found; int32_t loop_end = vgm_inf->loop_end; ov_callbacks default_callbacks; if (!callbacks_p) { default_callbacks.read_func = read_func; default_callbacks.seek_func = seek_func; default_callbacks.close_func = close_func; default_callbacks.tell_func = tell_func; if (vgm_inf->scd_xor != 0) { default_callbacks.read_func = read_func_scd; } callbacks_p = &default_callbacks; } temp_streamfile.streamfile = streamFile; temp_streamfile.offset = 0; temp_streamfile.size = get_streamfile_size(temp_streamfile.streamfile); temp_streamfile.other_header_bytes = other_header_bytes; temp_streamfile.scd_xor = vgm_inf->scd_xor; temp_streamfile.scd_xor_len = vgm_inf->scd_xor_len; /* can we open this as a proper ogg vorbis file? */ memset(&temp_ovf, 0, sizeof(temp_ovf)); if (ov_test_callbacks(&temp_streamfile, &temp_ovf, NULL, 0, *callbacks_p)) goto fail; /* we have to close this as it has the init_vgmstream meta-reading STREAMFILE */ ov_clear(&temp_ovf); /* proceed to open a STREAMFILE just for this stream */ data = calloc(1,sizeof(ogg_vorbis_codec_data)); if (!data) goto fail; data->ov_streamfile.streamfile = streamFile->open(streamFile,filename, STREAMFILE_DEFAULT_BUFFER_SIZE); if (!data->ov_streamfile.streamfile) goto fail; data->ov_streamfile.offset = 0; data->ov_streamfile.size = get_streamfile_size(data->ov_streamfile.streamfile); data->ov_streamfile.other_header_bytes = other_header_bytes; data->ov_streamfile.scd_xor = vgm_inf->scd_xor; data->ov_streamfile.scd_xor_len = vgm_inf->scd_xor_len; /* open the ogg vorbis file for real */ if (ov_open_callbacks(&data->ov_streamfile, &data->ogg_vorbis_file, NULL, 0, *callbacks_p)) goto fail; ovf = &data->ogg_vorbis_file; inited_ovf = 1; data->bitstream = DEFAULT_BITSTREAM; info = ov_info(ovf,DEFAULT_BITSTREAM); /* grab the comments */ { int i; vorbis_comment *comment; comment = ov_comment(ovf,DEFAULT_BITSTREAM); /* search for a "loop_start" comment */ for (i=0;i<comment->comments;i++) { if (strstr(comment->user_comments[i],"loop_start=")== comment->user_comments[i] || strstr(comment->user_comments[i],"LOOP_START=")== comment->user_comments[i] || strstr(comment->user_comments[i],"COMMENT=LOOPPOINT=")== comment->user_comments[i] || strstr(comment->user_comments[i],"LOOPSTART=")== comment->user_comments[i] || strstr(comment->user_comments[i],"um3.stream.looppoint.start=")== comment->user_comments[i] || strstr(comment->user_comments[i],"LOOP_BEGIN=")== comment->user_comments[i] || strstr(comment->user_comments[i],"LoopStart=")== comment->user_comments[i] ) { loop_start=atol(strrchr(comment->user_comments[i],'=')+1); if (loop_start >= 0) loop_flag=1; } else if (strstr(comment->user_comments[i],"LOOPLENGTH=")== comment->user_comments[i]) { loop_length=atol(strrchr(comment->user_comments[i],'=')+1); loop_length_found=1; } else if (strstr(comment->user_comments[i],"title=-lps")== comment->user_comments[i]) { loop_start=atol(comment->user_comments[i]+10); if (loop_start >= 0) loop_flag=1; } else if (strstr(comment->user_comments[i],"album=-lpe")== comment->user_comments[i]) { loop_end=atol(comment->user_comments[i]+10); loop_flag=1; loop_end_found=1; } else if (strstr(comment->user_comments[i],"LoopEnd=")== comment->user_comments[i]) { if(loop_flag) { loop_length=atol(strrchr(comment->user_comments[i],'=')+1)-loop_start; loop_length_found=1; } } else if (strstr(comment->user_comments[i],"LOOP_END=")== comment->user_comments[i]) { if(loop_flag) { loop_length=atol(strrchr(comment->user_comments[i],'=')+1)-loop_start; loop_length_found=1; } } else if (strstr(comment->user_comments[i],"lp=")== comment->user_comments[i]) { sscanf(strrchr(comment->user_comments[i],'=')+1,"%d,%d", &loop_start,&loop_end); loop_flag=1; loop_end_found=1; } } } /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(info->channels,loop_flag); if (!vgmstream) goto fail; /* store our fun extra datas */ vgmstream->codec_data = data; /* fill in the vital statistics */ vgmstream->channels = info->channels; vgmstream->sample_rate = info->rate; /* let's play the whole file */ vgmstream->num_samples = ov_pcm_total(ovf,-1); if (loop_flag) { vgmstream->loop_start_sample = loop_start; if (loop_length_found) vgmstream->loop_end_sample = loop_start+loop_length; else if (loop_end_found) vgmstream->loop_end_sample = loop_end; else vgmstream->loop_end_sample = vgmstream->num_samples; vgmstream->loop_flag = loop_flag; if (vgmstream->loop_end_sample > vgmstream->num_samples) vgmstream->loop_end_sample = vgmstream->num_samples; } vgmstream->coding_type = coding_ogg_vorbis; vgmstream->layout_type = vgm_inf->layout_type; vgmstream->meta_type = vgm_inf->meta_type; return vgmstream; /* clean up anything we may have opened */ fail: if (data) { if (inited_ovf) ov_clear(&data->ogg_vorbis_file); if (data->ov_streamfile.streamfile) close_streamfile(data->ov_streamfile.streamfile); free(data); } if (vgmstream) { vgmstream->codec_data = NULL; close_vgmstream(vgmstream); } return NULL; }
int ov_raw_seek(OggVorbis_File *vf,long pos){ ogg_stream_state work_os; if(vf->ready_state<OPENED)return(OV_EINVAL); if(!vf->seekable) return(OV_ENOSEEK); /* don't dump machine if we can't seek */ if(pos<0 || pos>vf->offsets[vf->links])return(OV_EINVAL); /* clear out decoding machine state */ vf->pcm_offset=-1; _decode_clear(vf); _seek_helper(vf,pos); /* we need to make sure the pcm_offset is set, but we don't want to advance the raw cursor past good packets just to get to the first with a granulepos. That's not equivalent behavior to beginning decoding as immediately after the seek position as possible. So, a hack. We use two stream states; a local scratch state and a the shared vf->os stream state. We use the local state to scan, and the shared state as a buffer for later decode. Unfortuantely, on the last page we still advance to last packet because the granulepos on the last page is not necessarily on a packet boundary, and we need to make sure the granpos is correct. */ { ogg_page og; ogg_packet op; int lastblock=0; int accblock=0; int thisblock=-1; int eosflag=0; memset(&work_os,0,sizeof(work_os));/* so that it's safe to clear it later even if we don't init it */ while(1){ if(vf->ready_state==STREAMSET){ /* snarf/scan a packet if we can */ int result=ogg_stream_packetout(&work_os,&op); if(result>0){ if(vf->vi[vf->current_link].codec_setup) thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op); if(eosflag) ogg_stream_packetout(&vf->os,NULL); else if(lastblock)accblock+=(lastblock+thisblock)>>2; if(op.granulepos!=-1){ int i,link=vf->current_link; ogg_int64_t granulepos=op.granulepos; for(i=0;i<link;i++) granulepos+=vf->pcmlengths[i]; vf->pcm_offset=granulepos-accblock; break; } lastblock=thisblock; continue; } } if(!lastblock){ if(_get_next_page(vf,&og,-1)<0){ vf->pcm_offset=ov_pcm_total(vf,-1); break; } }else{ /* huh? Bogus stream with packets but no granulepos */ vf->pcm_offset=-1; break; } /* has our decoding just traversed a bitstream boundary? */ if(vf->ready_state==STREAMSET) if(vf->current_serialno!=ogg_page_serialno(&og)){ _decode_clear(vf); /* clear out stream state */ ogg_stream_clear(&work_os); } if(vf->ready_state<STREAMSET){ int link; vf->current_serialno=ogg_page_serialno(&og); for(link=0;link<vf->links;link++) if(vf->serialnos[link]==vf->current_serialno)break; if(link==vf->links)goto seek_error; /* sign of a bogus stream. error out, leave machine uninitialized */ vf->current_link=link; ogg_stream_init(&vf->os,vf->current_serialno); ogg_stream_reset(&vf->os); ogg_stream_init(&work_os,vf->current_serialno); ogg_stream_reset(&work_os); vf->ready_state=STREAMSET; } ogg_stream_pagein(&vf->os,&og); ogg_stream_pagein(&work_os,&og); eosflag=ogg_page_eos(&og); } }
static void ogg_load_vorbis(const char *filename, WAVEFORMATEX *pwf, std::vector<char> *data) { SafePtr<FS::Stream> s = g_fs->Open(filename)->QueryStream(); ov_callbacks cb; cb.read_func = read_func; cb.seek_func = seek_func; cb.close_func = NULL; cb.tell_func = tell_func; OggVorbis_File vf; if( int result = ov_open_callbacks(GetRawPtr(s), &vf, NULL, 0, cb) ) { switch( result ) { case OV_EREAD: throw std::runtime_error("A read from media returned an error"); case OV_ENOTVORBIS: throw std::runtime_error("Bitstream does not contain any Vorbis data"); case OV_EVERSION: throw std::runtime_error("Vorbis version mismatch"); case OV_EBADHEADER: throw std::runtime_error("Invalid Vorbis bitstream header"); case OV_EFAULT: throw std::runtime_error("Internal logic fault; indicates a bug or heap/stack corruption"); } throw std::runtime_error("unknown error opening ov stream"); } try { vorbis_info *pinfo = ov_info(&vf, -1); if( NULL == pinfo ) { throw std::runtime_error("could not get info from ov stream"); } pwf->wFormatTag = WAVE_FORMAT_PCM; pwf->nChannels = pinfo->channels; pwf->nSamplesPerSec = pinfo->rate; pwf->nAvgBytesPerSec = pinfo->rate * pinfo->channels * 2; pwf->nBlockAlign = pinfo->channels * 2; pwf->wBitsPerSample = 16; pwf->cbSize = 0; size_t size = ov_pcm_total(&vf, -1) * pwf->nBlockAlign; data->resize(size); int bitstream = 0; size_t total = 0; while( total < size ) { long ret = ov_read(&vf, &data->at(total), size - total, 0, 2, 1, &bitstream); if( 0 == ret ) { break; // eof } if( ret < 0 ) { // error in stream switch( ret ) { case OV_HOLE: throw std::runtime_error("garbage between pages, loss of sync followed by recapture, or a corrupt page"); case OV_EBADLINK: throw std::runtime_error("invalid stream section or the requested link is corrupt"); case OV_EINVAL: throw std::runtime_error("initial file headers couldn't be read or are corrupt"); } throw std::runtime_error("unknown error in ov stream"); } else { total += ret; } } } catch(...) { ov_clear(&vf); throw; } ov_clear(&vf); }
uint64 CDAFReader_Vorbis::FrameCount(void) { return(ov_pcm_total(&ovfile, -1)); }
bool AudioBuffer::loadOgg(Stream* stream, ALuint buffer) { GP_ASSERT(stream); OggVorbis_File ogg_file; vorbis_info* info; ALenum format; long result; int section; long size = 0; stream->rewind(); ov_callbacks callbacks; callbacks.read_func = readStream; callbacks.seek_func = seekStream; callbacks.close_func = closeStream; callbacks.tell_func = tellStream; if ((result = ov_open_callbacks(stream, &ogg_file, NULL, 0, callbacks)) < 0) { GP_ERROR("Failed to open ogg file."); return false; } info = ov_info(&ogg_file, -1); GP_ASSERT(info); if (info->channels == 1) format = AL_FORMAT_MONO16; else format = AL_FORMAT_STEREO16; // size = #samples * #channels * 2 (for 16 bit). long data_size = ov_pcm_total(&ogg_file, -1) * info->channels * 2; char* data = new char[data_size]; while (size < data_size) { result = ov_read(&ogg_file, data + size, data_size - size, 0, 2, 1, §ion); if (result > 0) { size += result; } else if (result < 0) { SAFE_DELETE_ARRAY(data); GP_ERROR("Failed to read ogg file; file is missing data."); return false; } else { break; } } if (size == 0) { SAFE_DELETE_ARRAY(data); GP_ERROR("Filed to read ogg file; unable to read any data."); return false; } AL_CHECK( alBufferData(buffer, format, data, data_size, info->rate) ); SAFE_DELETE_ARRAY(data); ov_clear(&ogg_file); return true; }
/* Load an OGG stream from an SDL_RWops object */ OGG_music *OGG_new_RW(SDL_RWops *src, int freesrc) { OGG_music *music; ov_callbacks callbacks; if(!Mix_Init(MIX_INIT_OGG)) return(NULL); SDL_memset(&callbacks, 0, sizeof(callbacks)); callbacks.read_func = sdl_read_func; callbacks.seek_func = sdl_seek_func; callbacks.tell_func = sdl_tell_func; music = (OGG_music *)SDL_malloc(sizeof * music); if(music) { vorbis_info *vi; vorbis_comment *ptr; int isLength = 0; int i; ogg_int64_t total; /* Initialize the music structure */ SDL_memset(music, 0, (sizeof * music)); music->src = src; music->freesrc = freesrc; OGG_stop(music); OGG_setvolume(music, MIX_MAX_VOLUME); music->section = -1; music->channels = 0; music->mus_title = NULL; music->mus_artist = NULL; music->mus_album = NULL; music->mus_copyright = NULL; MyResample_zero(&music->resample); music->loop = -1; music->loop_start = -1; music->loop_end = 0; music->loop_len = 0; if(vorbis.ov_open_callbacks(src, &music->vf, NULL, 0, callbacks) < 0) { SDL_SetError("Not an Ogg Vorbis audio stream"); SDL_free(music); return(NULL); } vi = vorbis.ov_info(&music->vf, -1); music->channels = vi->channels; /* Parse comments and extract title and loop points */ ptr = ov_comment(&music->vf, -1); for(i = 0; i < ptr->comments; i++) { int paramLen = ptr->comment_lengths[i] + 1; char *param = (char *)SDL_malloc(paramLen); char *argument = param; char *value = param; memset(param, 0, paramLen); memcpy(param, ptr->user_comments[i], ptr->comment_lengths[i]); value = strchr(param, '='); if(value == NULL) { value = param + paramLen - 1; /* set null */ } else { *(value++) = '\0'; } #ifdef __USE_ISOC99 #define A_TO_OGG64(x) (ogg_int64_t)atoll(x) #else #define A_TO_OGG64(x) (ogg_int64_t)atol(x) #endif if(strcasecmp(argument, "LOOPSTART") == 0) music->loop_start = A_TO_OGG64(value); else if(strcasecmp(argument, "LOOPLENGTH") == 0) { music->loop_len = A_TO_OGG64(value); isLength = 1; } else if(strcasecmp(argument, "LOOPEND") == 0) { isLength = 0; music->loop_end = A_TO_OGG64(value); } else if(strcasecmp(argument, "TITLE") == 0) { music->mus_title = (char *)SDL_malloc(sizeof(char) * strlen(value) + 1); strcpy(music->mus_title, value); } else if(strcasecmp(argument, "ARTIST") == 0) { music->mus_artist = (char *)SDL_malloc(sizeof(char) * strlen(value) + 1); strcpy(music->mus_artist, value); } else if(strcasecmp(argument, "ALBUM") == 0) { music->mus_album = (char *)SDL_malloc(sizeof(char) * strlen(value) + 1); strcpy(music->mus_album, value); } else if(strcasecmp(argument, "COPYRIGHT") == 0) { music->mus_copyright = (char *)SDL_malloc(sizeof(char) * strlen(value) + 1); strcpy(music->mus_copyright, value); } SDL_free(param); } #undef A_TO_OGG64 if(isLength == 1) music->loop_end = music->loop_start + music->loop_len; else music->loop_len = music->loop_end - music->loop_start; total = ov_pcm_total(&music->vf, -1); if(((music->loop_start >= 0) || (music->loop_end > 0)) && ((music->loop_start < music->loop_end) || (music->loop_end == 0)) && (music->loop_start < total) && (music->loop_end <= total)) { if(music->loop_start < 0) music->loop_start = 0; if(music->loop_end == 0) music->loop_end = total; music->loop = 1; music->loop_len_ch = music->channels; } } else { SDL_OutOfMemory(); return(NULL); } return (music); }
void OggVorbisFileReader::Read(Stream::IStream& stream) { OggVorbis_File vf; // open file OggVorbisStreamCallbacks callbacks(false, stream.CanSeek()); int iRet = ov_open_callbacks(&stream, &vf, NULL, 0, callbacks); if (iRet == -1) { ov_clear(&vf); throw Exception(_T("Ogg Vorbis: couldn't open file"), __FILE__, __LINE__); } // get metadata { vorbis_info* vi = ov_info(&vf, -1); // vi doesn't need to be freed if (vi == NULL) { ov_clear(&vf); throw Exception(_T("Ogg Vorbis: couldn't get info"), __FILE__, __LINE__); } m_uiChannels = vi->channels; m_uiSamplerate = vi->rate; } // prepare buffer ogg_int64_t ilLength = ov_pcm_total(&vf, -1); // double number of samples when stereo if (m_uiChannels == 2) ilLength <<= 1; ATLASSERT(ilLength >= 0 && ilLength <= std::numeric_limits<size_t>::max()); size_t uiLength = static_cast<size_t>(ilLength); m_vecSamples.resize(uiLength); // read in samples int iCurrentBitstream = 0; bool bEof = false; size_t ulAlreadyRead = 0; while(!bEof) { // read 64k samples at once int iLengthToRead = std::min(int(uiLength - ulAlreadyRead), 65536); if (iLengthToRead == 0) { bEof = true; break; } long lRet = ov_read(&vf, reinterpret_cast<char*>(&m_vecSamples[ulAlreadyRead]), iLengthToRead * 2, // in bytes 0, // big endian: no 2, // size of word 1, // signed: yes &iCurrentBitstream); if (lRet == 0) bEof = true; else if (lRet < 0) { // error in the stream break; } else { // ov_read returns number of bytes written, so divide by size of word ulAlreadyRead += lRet / 2; } } // finished ov_clear(&vf); // when not at EOF, we had an error if (!bEof) throw Exception(_T("Ogg Vorbis: couldn't read samples"), __FILE__, __LINE__); }
int64 FrameCount(void) { return(ov_pcm_total(&ovfile, -1)); }
prMALError SDKGetInfo8( imStdParms *stdParms, imFileAccessRec8 *fileAccessInfo8, imFileInfoRec8 *SDKFileInfo8) { prMALError result = malNoError; SDKFileInfo8->hasDataRate = kPrFalse; // private data assert(SDKFileInfo8->privatedata); ImporterLocalRec8H ldataH = reinterpret_cast<ImporterLocalRec8H>(SDKFileInfo8->privatedata); stdParms->piSuites->memFuncs->lockHandle(reinterpret_cast<char**>(ldataH)); ImporterLocalRec8Ptr localRecP = reinterpret_cast<ImporterLocalRec8Ptr>( *ldataH ); SDKFileInfo8->hasVideo = kPrFalse; SDKFileInfo8->hasAudio = kPrFalse; if(localRecP) { if(localRecP->fileType == Ogg_filetype && localRecP->vf != NULL) { OggVorbis_File &vf = *localRecP->vf; vorbis_info *info = ov_info(&vf, 0); // Audio information SDKFileInfo8->hasAudio = kPrTrue; SDKFileInfo8->audInfo.numChannels = info->channels; SDKFileInfo8->audInfo.sampleRate = info->rate; SDKFileInfo8->audInfo.sampleType = kPrAudioSampleType_Compressed; SDKFileInfo8->audDuration = ov_pcm_total(&vf, 0); } else if(localRecP->fileType == Opus_filetype && localRecP->opus != NULL) { SDKFileInfo8->hasAudio = kPrTrue; SDKFileInfo8->audInfo.numChannels = op_channel_count(localRecP->opus, -1); SDKFileInfo8->audInfo.sampleRate = 48000; // Ogg Opus always uses 48 kHz SDKFileInfo8->audInfo.sampleType = kPrAudioSampleType_Compressed; SDKFileInfo8->audDuration = op_pcm_total(localRecP->opus, -1); } else if(localRecP->fileType == FLAC_filetype && localRecP->flac != NULL) { try { SDKFileInfo8->hasAudio = kPrTrue; SDKFileInfo8->audInfo.numChannels = localRecP->flac->get_channels(); SDKFileInfo8->audInfo.sampleRate = localRecP->flac->get_sample_rate(); int bitDepth = localRecP->flac->get_bits_per_sample(); SDKFileInfo8->audInfo.sampleType = bitDepth == 8 ? kPrAudioSampleType_8BitInt : bitDepth == 16 ? kPrAudioSampleType_16BitInt : bitDepth == 24 ? kPrAudioSampleType_24BitInt : bitDepth == 32 ? kPrAudioSampleType_32BitInt : bitDepth == 64 ? kPrAudioSampleType_64BitFloat : kPrAudioSampleType_Compressed; SDKFileInfo8->audDuration = localRecP->flac->get_total_samples(); } catch(...) { result = imBadFile; } } localRecP->audioSampleRate = SDKFileInfo8->audInfo.sampleRate; localRecP->numChannels = SDKFileInfo8->audInfo.numChannels; if(SDKFileInfo8->audInfo.numChannels > 2 && SDKFileInfo8->audInfo.numChannels != 6) { // Premiere can't handle anything but Mono, Stereo, and 5.1 result = imUnsupportedAudioFormat; } } stdParms->piSuites->memFuncs->unlockHandle(reinterpret_cast<char**>(ldataH)); return result; }
ALboolean loadOgg( const char *fname, void **wave, ALsizei *format, ALsizei *size, ALsizei *bits, ALsizei *freq ) { *format = 0; OggVorbis_File vf; memset(&vf, 0, sizeof(vf)); int eof = 0; int current_section; long ret; FILE * file = fopen(fname,"rb+"); //ov_open could take long and should be called in a thread //INFO: If the program crashes here and you are compiling under windows, make sure your // debugging option equals "Multithreaded DLL" if(ov_open(file, &vf, NULL, 0) < 0) { fprintf(stderr,"\n"); fclose(file); throw Exception(std::string("Input ") + fname + " does not appear to be an Ogg bitstream."); } { vorbis_info *vi=ov_info(&vf,-1); *freq = (ALsizei) vi->rate; /************* HACK? ************/ *size = (ALsizei) ov_pcm_total(&vf, -1)*2; *bits = (ALsizei) 16; //ov_read returns PCM 16-bit little-endian samples int channels = vi->channels; if (channels == 1) { *format = AL_FORMAT_MONO16; } else if (channels == 2) { *format = AL_FORMAT_STEREO16; } else { return AL_FALSE; } } char * pcm_data = new char[*size]; char * pcm_data_p = pcm_data; while(!eof) { ret=ov_read(&vf,(char *)pcm_data_p,4096,0,2,1,¤t_section); if (ret == 0) { /* EOF */ eof=1; } else if (ret < 0) { /* error in the stream. Not a problem, just reporting it in case we (the app) cares. In this case, we don't. */ return AL_FALSE; } else { /* we don't bother dealing with sample rate changes, etc, but you'll have to*/ pcm_data_p += ret; } } /* cleanup */ ov_clear(&vf); *wave = pcm_data; return AL_TRUE; }
uint64_t OGGDecoder::getLength() { return ov_pcm_total(&vf,-1); }
int main(int argc, char *argv[]){ OggVorbis_File vf; int eof=0; int current_section; FILE *fp; int dev=0; char **ptr; vorbis_info *vi; #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 if(argc < 2) { printf("Usage : ivorbisfile_example <ogg filename>\n"); exit(0); } fp = fopen(argv[1],"rb"); if(fp == NULL) printf("File open error\n"); //if(ov_open(stdin, &vf, NULL, 0) < 0) { if(ov_open(fp, &vf, NULL, 0) < 0) { fprintf(stderr,"Input does not appear to be an Ogg bitstream.\n"); exit(1); } /* Throw the comments plus a few lines about the bitstream we're decoding */ // { ptr=ov_comment(&vf,-1)->user_comments; vi=ov_info(&vf,-1); while(*ptr){ fprintf(stderr,"%s\n",*ptr); ++ptr; //printf(". \n"); } fprintf(stderr,"\nBitstream is %d channel, %ldHz\n",vi->channels,vi->rate); fprintf(stderr,"\nDecoded length: %ld samples\n", (long)ov_pcm_total(&vf,-1)); fprintf(stderr,"Encoded by: %s\n\n",ov_comment(&vf,-1)->vendor); // } if ((dev = open(DEV, O_RDWR)) < 1) { printf("Device open failed"); } #if 1 { int i, v; v = vi->rate/2;//22050; i = ioctl(dev, SNDCTL_DSP_SPEED, &v); fprintf(stderr, "%s(%d): ioctl(SNDCTL_DSP_SPEED)=%d, set=%d\n", __FILE__, __LINE__, i, v); v = 1; i = ioctl(dev, SNDCTL_DSP_STEREO, &v); fprintf(stderr, "%s(%d): ioctl(SNDCTL_DSP_STEREO)=%d, set=%d\n", __FILE__, __LINE__, i, v); v = AFMT_S16_BE; i = ioctl(dev, SNDCTL_DSP_SAMPLESIZE, &v); fprintf(stderr, "%s(%d): ioctl(SNDCTL_DSP_SAMPLESIZE)=%d, set=%d\n", __FILE__, __LINE__, i, v); } #endif #if 0 { int i, v; v = 44100; i = ioctl(fileno(stdout), SNDCTL_DSP_SPEED, &v); fprintf(stderr, "%s(%d): ioctl(SNDCTL_DSP_SPEED)=%d, set=%d\n", __FILE__, __LINE__, i, v); v = 1; i = ioctl(fileno(stdout), SNDCTL_DSP_STEREO, &v); fprintf(stderr, "%s(%d): ioctl(SNDCTL_DSP_STEREO)=%d, set=%d\n", __FILE__, __LINE__, i, v); v = AFMT_S16_BE; i = ioctl(fileno(stdout), SNDCTL_DSP_SAMPLESIZE, &v); fprintf(stderr, "%s(%d): ioctl(SNDCTL_DSP_SAMPLESIZE)=%d, set=%d\n", __FILE__, __LINE__, i, v); } #endif while(!eof){ long ret=ov_read(&vf,pcmout,sizeof(pcmout),¤t_section); // printf("\nRet = %d\n",ret); if (ret == 0) { /* EOF */ eof=1; } else if (ret < 0) { /* error in the stream. Not a problem, just reporting it in case we (the app) cares. In this case, we don't. */ } else { /* we don't bother dealing with sample rate changes, etc, but you'll have to*/ //fwrite(pcmout,1,ret,stdout); write(dev,pcmout,ret); } } /* cleanup */ ov_clear(&vf); fprintf(stderr,"Done.\n"); return(0); }
/* Function: al_load_ogg_vorbis_f */ ALLEGRO_SAMPLE *al_load_ogg_vorbis_f(ALLEGRO_FILE* file) { /* Note: decoding library returns floats. I always return 16-bit (most * commonly supported). */ #ifdef ALLEGRO_LITTLE_ENDIAN const int endian = 0; /* 0 for Little-Endian, 1 for Big-Endian */ #else const int endian = 1; /* 0 for Little-Endian, 1 for Big-Endian */ #endif int word_size = 2; /* 1 = 8bit, 2 = 16-bit. nothing else */ int signedness = 1; /* 0 for unsigned, 1 for signed */ const int packet_size = 4096; /* suggestion for size to read at a time */ OggVorbis_File vf; vorbis_info* vi; char *buffer; long pos; ALLEGRO_SAMPLE *sample; int channels; long rate; long total_samples; int bitstream; long total_size; AL_OV_DATA ov; if (file == NULL) { ALLEGRO_WARN("Audio file failed to open.\n"); return NULL; } ov.file = file; if (ov_open_callbacks(&ov, &vf, NULL, 0, callbacks) < 0) { ALLEGRO_WARN("Audio file does not appear to be an Ogg bitstream.\n"); al_fclose(file); return NULL; } vi = ov_info(&vf, -1); channels = vi->channels; rate = vi->rate; total_samples = ov_pcm_total(&vf, -1); bitstream = -1; total_size = total_samples * channels * word_size; ALLEGRO_DEBUG("channels %d\n", channels); ALLEGRO_DEBUG("word_size %d\n", word_size); ALLEGRO_DEBUG("rate %ld\n", rate); ALLEGRO_DEBUG("total_samples %ld\n", total_samples); ALLEGRO_DEBUG("total_size %ld\n", total_size); buffer = _AL_MALLOC_ATOMIC(total_size); if (!buffer) { al_fclose(file); return NULL; } pos = 0; while (pos < total_size) { /* XXX error handling */ #if !defined(ALLEGRO_GP2XWIZ) && !defined(ALLEGRO_IPHONE) long read = ov_read(&vf, buffer + pos, packet_size, endian, word_size, signedness, &bitstream); #else (void)endian; (void)signedness; long read = ov_read(&vf, buffer + pos, packet_size, &bitstream); #endif pos += read; if (read == 0) break; } ov_clear(&vf); sample = al_create_sample(buffer, total_samples, rate, _al_word_size_to_depth_conf(word_size), _al_count_to_channel_conf(channels), true); if (!sample) { _AL_FREE(buffer); } return sample; }
int cOggDecoder::getTotalSize() { return ov_pcm_total(&oggStream, -1) * vorbisInfo->channels; }
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; }
SoundID Audio::addSound(const char *fileName, unsigned int flags){ Sound sound; // Clear error flag alGetError(); const char *ext = strrchr(fileName, '.') + 1; char str[256]; if (stricmp(ext, "ogg") == 0){ FILE *file = fopen(fileName, "rb"); if (file == NULL){ sprintf(str, "Couldn't open \"%s\"", fileName); ErrorMsg(str); return SOUND_NONE; } OggVorbis_File vf; memset(&vf, 0, sizeof(vf)); if (ov_open(file, &vf, NULL, 0) < 0){ fclose(file); sprintf(str, "\"%s\" is not an ogg file", fileName); ErrorMsg(str); return SOUND_NONE; } vorbis_info *vi = ov_info(&vf, -1); int nSamples = (uint) ov_pcm_total(&vf, -1); int nChannels = vi->channels; sound.format = nChannels == 1? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16; sound.sampleRate = vi->rate; sound.size = nSamples * nChannels; sound.samples = new short[sound.size]; sound.size *= sizeof(short); int samplePos = 0; while (samplePos < sound.size){ char *dest = ((char *) sound.samples) + samplePos; int bitStream, readBytes = ov_read(&vf, dest, sound.size - samplePos, 0, 2, 1, &bitStream); if (readBytes <= 0) break; samplePos += readBytes; } ov_clear(&vf); } else { ALboolean al_bool; ALvoid *data; alutLoadWAVFile(fileName, &sound.format, &data, &sound.size, &sound.sampleRate, &al_bool); sound.samples = (short *) data; } alGenBuffers(1, &sound.buffer); alBufferData(sound.buffer, sound.format, sound.samples, sound.size, sound.sampleRate); if (alGetError() != AL_NO_ERROR){ alDeleteBuffers(1, &sound.buffer); sprintf(str, "Couldn't open \"%s\"", fileName); ErrorMsg(str); return SOUND_NONE; } return insertSound(sound); }