int TrackCount(const char* strFile) { VorbisContext* ctx = new VorbisContext; ctx->file = XBMC->OpenFile(strFile, 4); if (!ctx->file) { delete ctx; return 1; } ctx->callbacks = GetCallbacks(strFile); if (ov_open_callbacks(ctx->file, &ctx->vorbisfile, NULL, 0, ctx->callbacks) != 0) { delete ctx; return 1; } long iStreams=ov_streams(&ctx->vorbisfile); ov_clear(&ctx->vorbisfile); delete ctx; return iStreams; }
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; }
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; }
AudioData LoadOggCodec(std::string filename) { std::string audioFile; try { audioFile = FS::PakPath::ReadFile(filename); } catch (std::system_error& err) { audioLogs.Warn("Failed to open %s: %s", filename, err.what()); return AudioData(); } OggDataSource dataSource = {&audioFile, 0}; std::unique_ptr<OggVorbis_File> vorbisFile(new OggVorbis_File); if (ov_open_callbacks(&dataSource, vorbisFile.get(), nullptr, 0, Ogg_Callbacks) != 0) { audioLogs.Warn("Error while reading %s", filename); ov_clear(vorbisFile.get()); return AudioData(); } if (ov_streams(vorbisFile.get()) != 1) { audioLogs.Warn("Unsupported number of streams in %s.", filename); ov_clear(vorbisFile.get()); return AudioData(); } vorbis_info* oggInfo = ov_info(vorbisFile.get(), 0); if (!oggInfo) { audioLogs.Warn("Could not read vorbis_info in %s.", filename); ov_clear(vorbisFile.get()); return AudioData(); } const int sampleWidth = 2; int sampleRate = oggInfo->rate; int numberOfChannels = oggInfo->channels; char buffer[4096]; int bytesRead = 0; int bitStream = 0; std::vector<char> samples; while ((bytesRead = ov_read(vorbisFile.get(), buffer, 4096, 0, sampleWidth, 1, &bitStream)) > 0) { std::copy_n(buffer, bytesRead, std::back_inserter(samples)); } ov_clear(vorbisFile.get()); char* rawSamples = new char[samples.size()]; std::copy_n(samples.data(), samples.size(), rawSamples); return AudioData(sampleRate, sampleWidth, numberOfChannels, samples.size(), rawSamples); }
void setup() { static const ov_callbacks cbs = { readCallback, 0, 0, 0 }; ov_open_callbacks(this, &file_, 0, 0, cbs); vorbis_info* info = ov_info(&file_, -1); // -1 is current bitstream if (ov_streams(&file_) != 1) throw std::runtime_error("multi-stream vorbis files not supported"); format_ = info->channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16; sampleRate_ = info->rate; }
bool OggFilter::Attach(IFS* src) { if(!ov_open_callbacks((void*)src, &Vorbis, NULL, 0, Callbacks) && (ov_streams(&Vorbis) == 1)) { Source = src; vorbis_info* info = ov_info(&Vorbis, -1); Wave.Format.Channels = info->channels; Wave.Format.SamplesPerSec = info->rate; Wave.Format.BlockAlign = Wave.Format.Channels * Wave.Format.BitsPerSample / 8; Wave.Format.AvgBytesPerSec = Wave.Format.SamplesPerSec * Wave.Format.BlockAlign; Wave.dataChunk.ChunkSize = (uInt)ov_pcm_total(&Vorbis, -1) * Wave.Format.BlockAlign; Wave.Header.RiffSize = Wave.dataChunk.ChunkSize + sizeof(WaveFile) - 8; Offset = 0; return true; } Close(); return false; }
int vorbis_decoder_finish_open(decoder_t * dec) { vorbis_pdata_t * pd = (vorbis_pdata_t *)dec->pdata; file_decoder_t * fdec = dec->fdec; pd->vi = ov_info(&(pd->vf), -1); if ((pd->vi->channels != 1) && (pd->vi->channels != 2)) { fprintf(stderr, "vorbis_decoder_open: Ogg Vorbis file with %d channels " "is unsupported\n", pd->vi->channels); return DECODER_OPEN_FERROR; } if (ov_streams(&(pd->vf)) != 1) { fprintf(stderr, "vorbis_decoder_open: This Ogg Vorbis file contains " "multiple logical streams.\n" "Currently such a file is not supported.\n"); return DECODER_OPEN_FERROR; } pd->is_eos = 0; pd->rb = rb_create(pd->vi->channels * sample_size * RB_VORBIS_SIZE); fdec->fileinfo.channels = pd->vi->channels; fdec->fileinfo.sample_rate = pd->vi->rate; if (fdec->is_stream && pd->session->type != HTTPC_SESSION_NORMAL) { fdec->fileinfo.total_samples = 0; } else { fdec->fileinfo.total_samples = ov_pcm_total(&(pd->vf), -1); } fdec->fileinfo.bps = ov_bitrate(&(pd->vf), -1); fdec->file_lib = VORBIS_LIB; strcpy(dec->format_str, "Ogg Vorbis"); vorbis_send_metadata(fdec, pd); vorbis_decoder_send_metadata(dec); return DECODER_OPEN_SUCCESS; }
/* 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)); } } }
void* Init(const char* strFile, unsigned int filecache, int* channels, int* samplerate, int* bitspersample, int64_t* totaltime, int* bitrate, AEDataFormat* format, const AEChannel** channelinfo) { VorbisContext* result = new VorbisContext; result->track=0; std::string toLoad(strFile); if (toLoad.find(".oggstream") != std::string::npos) { size_t iStart=toLoad.rfind('-') + 1; result->track = atoi(toLoad.substr(iStart, toLoad.size()-iStart-10).c_str()); // The directory we are in, is the file // that contains the bitstream to play, // so extract it size_t slash = toLoad.rfind('\\'); if (slash == std::string::npos) slash = toLoad.rfind('/'); toLoad = toLoad.substr(0, slash); } result->file = XBMC->OpenFile(toLoad.c_str(), 0); if (!result->file) { delete result; return NULL; } result->callbacks = GetCallbacks(strFile); if (ov_open_callbacks(result->file, &result->vorbisfile, NULL, 0, result->callbacks) != 0) { delete result; return NULL; } long iStreams=ov_streams(&result->vorbisfile); if (iStreams>1) { if (result->track > iStreams) { DeInit(result); return NULL; } } // Calculate the offset in secs where the bitstream starts result->timeoffset = 0; for (int i=0; i<result->track; ++i) result->timeoffset += ov_time_total(&result->vorbisfile, i); vorbis_info* pInfo=ov_info(&result->vorbisfile, result->track); if (!pInfo) { XBMC->Log(ADDON::LOG_ERROR, "OGGCodec: Can't get stream info from %s", toLoad.c_str()); DeInit(result); return NULL; } *channels = pInfo->channels; *samplerate = pInfo->rate; *bitspersample = 16; *totaltime = (int64_t)ov_time_total(&result->vorbisfile, result->track)*1000; *format = AE_FMT_S16NE; static enum AEChannel map[8][9] = { {AE_CH_FC, AE_CH_NULL}, {AE_CH_FL, AE_CH_FR, AE_CH_NULL}, {AE_CH_FL, AE_CH_FC, AE_CH_FR, AE_CH_NULL}, {AE_CH_FL, AE_CH_FR, AE_CH_BL, AE_CH_BR, AE_CH_NULL}, {AE_CH_FL, AE_CH_FC, AE_CH_FR, AE_CH_BL, AE_CH_BR, AE_CH_NULL}, {AE_CH_FL, AE_CH_FC, AE_CH_FR, AE_CH_BL, AE_CH_BR, AE_CH_LFE, AE_CH_NULL}, {AE_CH_FL, AE_CH_FC, AE_CH_FR, AE_CH_SL, AE_CH_SR, AE_CH_BL, AE_CH_BR, AE_CH_NULL}, {AE_CH_FL, AE_CH_FC, AE_CH_FR, AE_CH_SL, AE_CH_SR, AE_CH_BL, AE_CH_BR, AE_CH_LFE, AE_CH_NULL} }; *channelinfo = NULL; if (*channels <= 8) *channelinfo = map[*channels - 1]; *bitrate = pInfo->bitrate_nominal; if (*samplerate == 0 || *channels == 0 || *bitspersample == 0 || *totaltime == 0) { XBMC->Log(ADDON::LOG_ERROR, "OGGCodec: Can't get stream info, SampleRate=%i, Channels=%i, BitsPerSample=%i, TotalTime=%" PRIu64, *samplerate, *channels, *bitspersample, *totaltime); delete result; return NULL; } if (result->timeoffset > 0.0) { if (ov_time_seek(&result->vorbisfile, result->timeoffset)!=0) { XBMC->Log(ADDON::LOG_ERROR, "OGGCodec: Can't seek to the bitstream start time (%s)", toLoad.c_str()); DeInit(result); return NULL; } } return result; }
// Open BOOL WaveFile::Open(LPSTR pszFilename) { int done = FALSE, rc = 0; WORD cbExtra = 0; BOOL fRtn = SUCCESS; // assume success PCMWAVEFORMAT pcmwf; char fullpath[_MAX_PATH]; m_total_uncompressed_bytes_read = 0; m_max_uncompressed_bytes_to_read = AS_HIGHEST_MAX; int FileSize, FileOffset; if (!cf_find_file_location(pszFilename, CF_TYPE_ANY, sizeof(fullpath) - 1, fullpath, &FileSize, &FileOffset)) { goto OPEN_ERROR; } m_snd_info.cfp = mmioOpen(fullpath, NULL, MMIO_ALLOCBUF | MMIO_READ); if (m_snd_info.cfp == NULL) { goto OPEN_ERROR; } m_snd_info.true_offset = FileOffset; m_snd_info.size = FileSize; // if in a VP then position the stream at the start of the file if (FileOffset > 0) { mmioSeek(m_snd_info.cfp, FileOffset, SEEK_SET); } // first check for an OGG if ((rc = ov_open_callbacks(&m_snd_info, &m_snd_info.vorbis_file, NULL, 0, mmio_callbacks)) == 0) { // got an OGG so lets read the info in ov_info(&m_snd_info.vorbis_file, -1); // we only support one logical bitstream if (ov_streams(&m_snd_info.vorbis_file) != 1) { mprintf(("AUDIOSTR => OGG reading error: We don't handle bitstream changes!\n")); goto OPEN_ERROR; } m_wave_format = OGG_FORMAT_VORBIS; m_wfmt.wFormatTag = WAVE_FORMAT_PCM; m_wfmt.nChannels = (WORD)m_snd_info.vorbis_file.vi->channels; m_wfmt.nSamplesPerSec = m_snd_info.vorbis_file.vi->rate; m_wfmt.cbSize = 0; if (UserSampleBits == 16 || UserSampleBits == 8) m_wfmt.wBitsPerSample = UserSampleBits; //Decode at whatever the user specifies; only 16 and 8 are supported. else if (UserSampleBits > 16) m_wfmt.wBitsPerSample = 16; else m_wfmt.wBitsPerSample = 8; m_wfmt.nBlockAlign = (ushort)((m_wfmt.nChannels * m_wfmt.wBitsPerSample) / 8); m_wfmt.nAvgBytesPerSec = m_wfmt.nSamplesPerSec * m_wfmt.nBlockAlign; m_nBlockAlign = m_wfmt.nBlockAlign; m_nUncompressedAvgDataRate = m_wfmt.nAvgBytesPerSec; // location of start of file in VP m_data_offset = 0; m_nDataSize = m_data_bytes_left = ((int)ov_pcm_total(&m_snd_info.vorbis_file, -1) * m_wfmt.nBlockAlign); // Cue for streaming Cue(); // successful open goto OPEN_DONE; } // not an OGG so assume that it's WAVE else { // extra check, if it's not ogg then but if the error was a bad ogg then bail if (rc && (rc != OV_ENOTVORBIS)) goto OPEN_ERROR; // Skip the "RIFF" tag and file size (8 bytes) // Skip the "WAVE" tag (4 bytes) mmioSeek(m_snd_info.cfp, 12 + FileOffset, SEEK_SET); /*char buf[4]; mmioRead(m_snd_info.cfp, buf, sizeof(char)*4); if(strnicmp("RIFF", buf, 4)) goto OPEN_ERROR; //Skip file length mmioSeek( m_snd_info.cfp, 4, SEEK_CUR); mmioRead(m_snd_info.cfp, buf, sizeof(char)*4); if(strnicmp("WAVE", buf, 4)) goto OPEN_ERROR;*/ // Now read RIFF tags until the end of file uint tag, size, next_chunk; while (done == FALSE) { if (mmioRead(m_snd_info.cfp, (char*)&tag, sizeof(uint)) != sizeof(uint)) break; if (mmioRead(m_snd_info.cfp, (char*)&size, sizeof(uint)) != sizeof(uint)) break; next_chunk = mmioSeek(m_snd_info.cfp, 0, SEEK_CUR); next_chunk += size; switch (tag) { case 0x20746d66: // The 'fmt ' tag mmioRead(m_snd_info.cfp, (char*)&pcmwf, sizeof(PCMWAVEFORMAT)); if (pcmwf.wf.wFormatTag != WAVE_FORMAT_PCM) { mmioRead(m_snd_info.cfp, (char*)&cbExtra, sizeof(short)); } // Allocate memory for WAVEFORMATEX structure + extra bytes if ((m_pwfmt_original = (WAVEFORMATEX*)vm_malloc(sizeof(WAVEFORMATEX) + cbExtra)) != NULL) { Assert(m_pwfmt_original != NULL); // Copy bytes from temporary format structure memcpy(m_pwfmt_original, &pcmwf, sizeof(pcmwf)); m_pwfmt_original->cbSize = cbExtra; // Read those extra bytes, append to WAVEFORMATEX structure if (cbExtra != 0) { mmioRead(m_snd_info.cfp, (char*)((ubyte*)(m_pwfmt_original)+ sizeof(WAVEFORMATEX)), cbExtra); } } else { Int3(); // malloc failed goto OPEN_ERROR; } break; case 0x61746164: // the 'data' tag m_nDataSize = size; // This is size of data chunk. Compressed if ADPCM. m_data_bytes_left = size; m_data_offset = mmioSeek(m_snd_info.cfp, 0, SEEK_CUR); done = TRUE; break; default: // unknown, skip it break; } // end switch mmioSeek(m_snd_info.cfp, next_chunk, SEEK_SET); } // At this stage, examine source format, and set up WAVEFORATEX structure for DirectSound. // Since DirectSound only supports PCM, force this structure to be PCM compliant. We will // need to convert data on the fly later if our souce is not PCM switch (m_pwfmt_original->wFormatTag) { case WAVE_FORMAT_PCM: m_wave_format = WAVE_FORMAT_PCM; m_wfmt.wBitsPerSample = m_pwfmt_original->wBitsPerSample; break; case WAVE_FORMAT_ADPCM: m_wave_format = WAVE_FORMAT_ADPCM; if (UserSampleBits == 16 || UserSampleBits == 8) m_wfmt.wBitsPerSample = UserSampleBits; //Decode at whatever the user specified, if it's 16 or 8 else if (UserSampleBits > 16) m_wfmt.wBitsPerSample = 16; else m_wfmt.wBitsPerSample = 8; break; default: nprintf(("SOUND", "SOUND => Not supporting %d format for playing wave files\n", m_pwfmt_original->wFormatTag)); //Int3(); goto OPEN_ERROR; break; } // end switch // Set up the WAVEFORMATEX structure to have the right PCM characteristics m_wfmt.wFormatTag = WAVE_FORMAT_PCM; m_wfmt.nChannels = m_pwfmt_original->nChannels; m_wfmt.nSamplesPerSec = m_pwfmt_original->nSamplesPerSec; m_wfmt.cbSize = 0; m_wfmt.nBlockAlign = (unsigned short)((m_wfmt.nChannels * m_wfmt.wBitsPerSample) / 8); m_wfmt.nAvgBytesPerSec = m_wfmt.nBlockAlign * m_wfmt.nSamplesPerSec; // Init some member data from format chunk m_nBlockAlign = m_pwfmt_original->nBlockAlign; m_nUncompressedAvgDataRate = m_wfmt.nAvgBytesPerSec; // Cue for streaming Cue(); // Successful open goto OPEN_DONE; } OPEN_ERROR: // Handle all errors here nprintf(("SOUND", "SOUND ==> Could not open wave file %s for streaming\n", pszFilename)); fRtn = FAILURE; if (m_snd_info.cfp != NULL) { // Close file mmioClose(m_snd_info.cfp, 0); m_snd_info.cfp = NULL; m_snd_info.true_offset = 0; m_snd_info.size = 0; } if (m_pwfmt_original) { vm_free(m_pwfmt_original); m_pwfmt_original = NULL; } OPEN_DONE: return (fRtn); }
/* ================= 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; }
static BseErrorType dh_vorbis_open (GslDataHandle *dhandle, GslDataHandleSetup *setup) { VorbisHandle *vhandle = (VorbisHandle*) dhandle; VFile *vfile; vorbis_info *vi; GslLong n, i; gint err; vfile = g_new0 (VFile, 1); vfile->rfile = gsl_rfile_open (vhandle->dhandle.name); if (!vfile->rfile) { g_free (vfile); return gsl_error_from_errno (errno, BSE_ERROR_FILE_OPEN_FAILED); } vfile->byte_length = gsl_rfile_length (vfile->rfile); if (vhandle->rfile_add_zoffset) { vfile->byte_offset = gsl_hfile_zoffset (vfile->rfile->hfile) + 1; vfile->byte_offset += vhandle->rfile_byte_offset; vfile->byte_offset = MIN (vfile->byte_offset, vfile->byte_length); vfile->byte_length -= vfile->byte_offset; } else { vfile->byte_offset = MIN (vhandle->rfile_byte_offset, vfile->byte_length); vfile->byte_length -= vfile->byte_offset; } if (vhandle->rfile_byte_length > 0) vfile->byte_length = MIN (vfile->byte_length, vhandle->rfile_byte_length); err = ov_open_callbacks (vfile, &vhandle->ofile, NULL, 0, vfile_ov_callbacks); if (err < 0) { if (0) g_printerr ("failed to open ogg at offset %d (real offset=%lld) (add-zoffset=%d): %s\n", vhandle->rfile_byte_offset, vfile->byte_offset, vhandle->rfile_add_zoffset, bse_error_blurb (ov_errno_to_error (err, BSE_ERROR_FILE_OPEN_FAILED))); vfile_close (vfile); return ov_errno_to_error (err, BSE_ERROR_FILE_OPEN_FAILED); } n = ov_streams (&vhandle->ofile); if (n > vhandle->bitstream) { vhandle->bitstream_serialno = ov_serialnumber (&vhandle->ofile, vhandle->bitstream); vhandle->n_bitstreams = n; if (0) g_printerr ("Ogg/Vorbis: opening ogg: bitstream=%d/%d serialno=%d\n", vhandle->bitstream, vhandle->n_bitstreams, vhandle->bitstream_serialno); } else { ov_clear (&vhandle->ofile); /* closes file */ return BSE_ERROR_NO_DATA; /* requested bitstream not available */ } vhandle->soffset = 0; for (i = 0; i < vhandle->bitstream; i++) vhandle->soffset += ov_pcm_total (&vhandle->ofile, i); n = ov_pcm_total (&vhandle->ofile, vhandle->bitstream); vi = ov_info (&vhandle->ofile, vhandle->bitstream); if (n > 0 && vi && vi->channels && ov_pcm_seek (&vhandle->ofile, vhandle->soffset) >= 0) { setup->n_channels = vi->channels; setup->n_values = n * setup->n_channels; } else { ov_clear (&vhandle->ofile); /* closes file */ return BSE_ERROR_NO_DATA; } vhandle->max_block_size = vorbis_info_blocksize (vi, 0); n = vorbis_info_blocksize (vi, 1); vhandle->max_block_size = MAX (vhandle->max_block_size, n); vhandle->pcm_pos = 0; vhandle->pcm_length = 0; setup->bit_depth = 24; setup->mix_freq = vi->rate; setup->needs_cache = TRUE; setup->xinfos = bse_xinfos_add_float (setup->xinfos, "osc-freq", vhandle->osc_freq); return BSE_ERROR_NONE; }
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 snd_stream_t *S_VORBIS_CodecOpenStream (const char *filename) { snd_stream_t *stream; OggVorbis_File *ovFile; vorbis_info *ovf_info; long numstreams; int res; stream = S_CodecUtilOpen(filename, &vorbis_codec); if (!stream) return NULL; ovFile = (OggVorbis_File *) Z_Malloc(sizeof(OggVorbis_File)); 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", filename, res); goto _fail; } stream->priv = ovFile; if (!ov_seekable(ovFile)) { Con_Printf("Stream %s not seekable.\n", filename); goto _fail; } ovf_info = ov_info(ovFile, 0); if (!ovf_info) { Con_Printf("Unable to get stream info for %s.\n", filename); goto _fail; } /* FIXME: handle section changes */ numstreams = ov_streams(ovFile); if (numstreams != 1) { Con_Printf("More than one (%ld) stream in %s.\n", numstreams, filename); goto _fail; } if (ovf_info->channels != 1 && ovf_info->channels != 2) { Con_Printf("Unsupported number of channels %d in %s\n", ovf_info->channels, filename); goto _fail; } stream->info.rate = ovf_info->rate; stream->info.channels = ovf_info->channels; stream->info.width = VORBIS_SAMPLEWIDTH; return stream; _fail: if (res == 0) ov_clear(ovFile); Z_Free(ovFile); S_CodecUtilClose(&stream); return NULL; }
int WOggDecoder::_OpenFile(unsigned int fLite) { bit_stream.start = c_pchStreamStart; bit_stream.end = c_pchStreamStart + c_nStreamSize - 1; bit_stream.pos = c_pchStreamStart; bit_stream.size = c_nStreamSize; if(c_fManagedStream) { if(ov_open_callbacks(this, &vf, NULL, 0, cb) < 0) { err(DECODER_NOT_VALID_OGG_STREAM); return 0; } } else { if(ov_open_callbacks(&bit_stream, &vf, NULL, 0, cb) < 0) { err(DECODER_NOT_VALID_OGG_STREAM); return 0; } } if(fLite) return 1; // get number of logical streams c_nNumberOfLogicalBitstreams = ov_streams(&vf); if(c_nNumberOfLogicalBitstreams == 0) { err(DECODER_NOT_VALID_OGG_STREAM); return 0; } c_nLogicalBitstreamIndex = 0; vi = ov_info(&vf, c_nLogicalBitstreamIndex); if(vi == NULL) { err(DECODER_NOT_VALID_OGG_STREAM); return 0; } c_isInfo.nSampleRate = vi->rate; c_isInfo.nChannel = vi->channels; c_isInfo.fVbr = 1; if(vi->bitrate_upper == vi->bitrate_lower) c_isInfo.fVbr = 0; c_isInfo.nFileBitrate = ov_bitrate(&vf, c_nLogicalBitstreamIndex); ogg_int64_t len = ov_pcm_total(&vf, c_nLogicalBitstreamIndex); if(len == OV_EINVAL) c_isInfo.nLength = 0; else c_isInfo.nLength = len; if(c_isInfo.nChannel > 2) c_isInfo.pchStreamDescription = "VORBIS OGG MULTI CHANNEL"; else if(c_isInfo.nChannel == 2) c_isInfo.pchStreamDescription = "VORBIS OGG STEREO"; else c_isInfo.pchStreamDescription = "VORBIS OGG MONO"; // get informations of input stream // WE ALWAYS USE 16 bit per sample // save original bit per sample if(c_isInfo.nChannel >= 2) c_nBlockAlign = 4; else c_nBlockAlign = 2; c_isInfo.nBlockAlign = 4; c_isInfo.nBitPerSample = 16; c_nReversePos = 0; c_nCurrentPosition = 0; c_fReady = 1; return 1; }
static int OGG_open(Sound_Sample *sample, const char *ext) { int rc; double total_time; OggVorbis_File *vf; vorbis_info *info; Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; vf = (OggVorbis_File *) malloc(sizeof (OggVorbis_File)); BAIL_IF_MACRO(vf == NULL, ERR_OUT_OF_MEMORY, 0); rc = ov_open_callbacks(internal->rw, vf, NULL, 0, RWops_ogg_callbacks); if (rc != 0) { #if (defined DEBUG_CHATTER) SNDDBG(("OGG: can't grok data. reason: [%s].\n", ogg_error(rc))); #endif free(vf); BAIL_MACRO("OGG: Not valid Ogg Vorbis data.", 0); } /* if */ info = ov_info(vf, -1); if (info == NULL) { ov_clear(vf); free(vf); BAIL_MACRO("OGG: failed to retrieve bitstream info", 0); } /* if */ output_ogg_comments(vf); SNDDBG(("OGG: bitstream version == (%d).\n", info->version)); SNDDBG(("OGG: bitstream channels == (%d).\n", info->channels)); SNDDBG(("OGG: bitstream sampling rate == (%ld).\n", info->rate)); SNDDBG(("OGG: seekable == {%s}.\n", ov_seekable(vf) ? "TRUE" : "FALSE")); SNDDBG(("OGG: number of logical bitstreams == (%ld).\n", ov_streams(vf))); SNDDBG(("OGG: serial number == (%ld).\n", ov_serialnumber(vf, -1))); SNDDBG(("OGG: total seconds of sample == (%f).\n", ov_time_total(vf, -1))); internal->decoder_private = vf; sample->flags = SOUND_SAMPLEFLAG_CANSEEK; sample->actual.rate = (uint32_t) info->rate; sample->actual.channels = (uint8_t) info->channels; total_time = ov_time_total(vf, -1); if (OV_EINVAL == total_time) internal->total_time = -1; else internal->total_time = (int32_t)(total_time); /* * Since we might have more than one logical bitstream in the OGG file, * and these bitstreams may be in different formats, we might be * converting two or three times: once in vorbisfile, once again in * SDL_sound, and perhaps a third time to get it to the sound device's * format. That's wickedly inefficient. * * To combat this a little, if the user specified a desired format, we * claim that to be the "actual" format of the collection of logical * bitstreams. This means that VorbisFile will do a conversion as * necessary, and SDL_sound will not. If the user didn't specify a * desired format, then we pretend the "actual" format is something that * OGG files are apparently commonly encoded in. */ sample->actual.format = (sample->desired.format == 0) ? AUDIO_S16SYS : sample->desired.format; return(1); } /* OGG_open */
// Open bool WaveFile::Open(char *pszFilename, bool keep_ext) { int rc = -1; WORD cbExtra = 0; bool fRtn = true; // assume success PCMWAVEFORMAT pcmwf; int FileSize, FileOffset; char fullpath[MAX_PATH]; char filename[MAX_FILENAME_LEN]; const int NUM_EXT = 2; const char *audio_ext[NUM_EXT] = { ".ogg", ".wav" }; m_total_uncompressed_bytes_read = 0; m_max_uncompressed_bytes_to_read = AS_HIGHEST_MAX; // NOTE: we assume that the extension has already been stripped off if it was supposed to be!! strcpy_s( filename, pszFilename ); // if we are supposed to load the file as passed... if (keep_ext) { for (int i = 0; i < NUM_EXT; i++) { if ( stristr(pszFilename, audio_ext[i]) ) { rc = i; break; } } // not a supported extension format ... somebody screwed up their tbls :) if (rc < 0) goto OPEN_ERROR; cf_find_file_location(pszFilename, CF_TYPE_ANY, sizeof(fullpath) - 1, fullpath, &FileSize, &FileOffset); } // ... otherwise we just find the best match else { rc = cf_find_file_location_ext(filename, NUM_EXT, audio_ext, CF_TYPE_ANY, sizeof(fullpath) - 1, fullpath, &FileSize, &FileOffset); } if (rc < 0) { goto OPEN_ERROR; } else { // set proper filename for later use (assumes that it doesn't already have an extension) strcat_s( filename, audio_ext[rc] ); } m_snd_info.cfp = mmioOpen( fullpath, NULL, MMIO_ALLOCBUF | MMIO_READ ); if (m_snd_info.cfp == NULL) goto OPEN_ERROR; m_snd_info.true_offset = FileOffset; m_snd_info.size = FileSize; // if in a VP then position the stream at the start of the file if (FileOffset > 0) mmioSeek( m_snd_info.cfp, FileOffset, SEEK_SET ); // if Ogg Vorbis... if (rc == 0) { if ( ov_open_callbacks(&m_snd_info, &m_snd_info.vorbis_file, NULL, 0, mmio_callbacks) == 0 ) { // got an Ogg Vorbis, so lets read the info in ov_info(&m_snd_info.vorbis_file, -1); // we only support one logical bitstream if ( ov_streams(&m_snd_info.vorbis_file) != 1 ) { mprintf(("AUDIOSTR => OGG reading error: We don't handle bitstream changes!\n")); goto OPEN_ERROR; } m_wave_format = OGG_FORMAT_VORBIS; m_wfmt.wFormatTag = WAVE_FORMAT_PCM; m_wfmt.nChannels = (WORD) m_snd_info.vorbis_file.vi->channels; m_wfmt.nSamplesPerSec = m_snd_info.vorbis_file.vi->rate; switch (Ds_sound_quality) { case DS_SQ_HIGH: m_wfmt.wBitsPerSample = Ds_float_supported ? 32 : 16; break; case DS_SQ_MEDIUM: m_wfmt.wBitsPerSample = 16; break; default: m_wfmt.wBitsPerSample = 8; break; } m_wfmt.cbSize = 0; m_wfmt.nBlockAlign = (ushort)(( m_wfmt.nChannels * m_wfmt.wBitsPerSample ) / 8); m_wfmt.nAvgBytesPerSec = m_wfmt.nSamplesPerSec * m_wfmt.nBlockAlign; m_nBlockAlign = m_wfmt.nBlockAlign; m_nUncompressedAvgDataRate = m_wfmt.nAvgBytesPerSec; // location of start of file in VP m_data_offset = 0; m_nDataSize = m_data_bytes_left = ((int)ov_pcm_total(&m_snd_info.vorbis_file, -1) * m_wfmt.nBlockAlign); } else { mprintf(("AUDIOSTR => OGG reading error: Not a valid Vorbis file!\n")); } } // if Wave... else if (rc == 1) { bool done = false; // Skip the "RIFF" tag and file size (8 bytes) // Skip the "WAVE" tag (4 bytes) mmioSeek( m_snd_info.cfp, 12+FileOffset, SEEK_SET ); // Now read RIFF tags until the end of file uint tag, size, next_chunk; while ( !done ) { if ( !audiostr_read_uint(m_snd_info.cfp, &tag) ) break; if ( !audiostr_read_uint(m_snd_info.cfp, &size) ) break; next_chunk = mmioSeek(m_snd_info.cfp, 0, SEEK_CUR ); next_chunk += size; switch (tag) { case 0x20746d66: // The 'fmt ' tag { audiostr_read_word(m_snd_info.cfp, &pcmwf.wf.wFormatTag); audiostr_read_word(m_snd_info.cfp, &pcmwf.wf.nChannels); audiostr_read_dword(m_snd_info.cfp, &pcmwf.wf.nSamplesPerSec); audiostr_read_dword(m_snd_info.cfp, &pcmwf.wf.nAvgBytesPerSec); audiostr_read_word(m_snd_info.cfp, &pcmwf.wf.nBlockAlign); audiostr_read_word(m_snd_info.cfp, &pcmwf.wBitsPerSample); if (pcmwf.wf.wFormatTag == WAVE_FORMAT_ADPCM) audiostr_read_word(m_snd_info.cfp, &cbExtra); // Allocate memory for WAVEFORMATEX structure + extra bytes if ( (m_pwfmt_original = (WAVEFORMATEX *) vm_malloc(sizeof(WAVEFORMATEX)+cbExtra)) != NULL ) { Assert(m_pwfmt_original != NULL); // Copy bytes from temporary format structure memcpy (m_pwfmt_original, &pcmwf, sizeof(pcmwf)); m_pwfmt_original->cbSize = cbExtra; // Read those extra bytes, append to WAVEFORMATEX structure if (cbExtra != 0) mmioRead( m_snd_info.cfp, ((char *)(m_pwfmt_original) + sizeof(WAVEFORMATEX)), cbExtra ); } else { Int3(); // malloc failed goto OPEN_ERROR; } break; } case 0x61746164: // the 'data' tag { m_nDataSize = size; // This is size of data chunk. Compressed if ADPCM. m_data_bytes_left = size; m_data_offset = mmioSeek( m_snd_info.cfp, 0, SEEK_CUR ); done = true; break; } default: // unknown, skip it break; } // end switch mmioSeek( m_snd_info.cfp, next_chunk, SEEK_SET ); } // make sure that we did good if ( !done || (m_pwfmt_original == NULL) ) goto OPEN_ERROR; // At this stage, examine source format, and set up WAVEFORATEX structure for DirectSound. // Since DirectSound only supports PCM, force this structure to be PCM compliant. We will // need to convert data on the fly later if our souce is not PCM switch (m_pwfmt_original->wFormatTag) { case WAVE_FORMAT_PCM: m_wave_format = WAVE_FORMAT_PCM; m_wfmt.wBitsPerSample = m_pwfmt_original->wBitsPerSample; break; case WAVE_FORMAT_ADPCM: m_wave_format = WAVE_FORMAT_ADPCM; m_wfmt.wBitsPerSample = (Ds_sound_quality) ? 16: 8; m_bits_per_sample_uncompressed = m_wfmt.wBitsPerSample; break; case WAVE_FORMAT_IEEE_FLOAT: { m_wave_format = WAVE_FORMAT_IEEE_FLOAT; switch (Ds_sound_quality) { case DS_SQ_HIGH: m_wfmt.wBitsPerSample = (Ds_float_supported) ? 32 : 16; break; case DS_SQ_MEDIUM: m_wfmt.wBitsPerSample = 16; break; default: m_wfmt.wBitsPerSample = 8; break; } break; } default: nprintf(("SOUND", "SOUND => Not supporting %d format for playing wave files\n", m_pwfmt_original->wFormatTag)); goto OPEN_ERROR; break; } // end switch // Set up the WAVEFORMATEX structure to have the right PCM characteristics m_wfmt.wFormatTag = WAVE_FORMAT_PCM; m_wfmt.nChannels = m_pwfmt_original->nChannels; m_wfmt.nSamplesPerSec = m_pwfmt_original->nSamplesPerSec; m_wfmt.cbSize = 0; m_wfmt.nBlockAlign = (ushort)(( m_wfmt.nChannels * m_wfmt.wBitsPerSample ) / 8); m_wfmt.nAvgBytesPerSec = m_wfmt.nBlockAlign * m_wfmt.nSamplesPerSec; // Init some member data from format chunk m_nBlockAlign = m_pwfmt_original->nBlockAlign; m_nUncompressedAvgDataRate = m_wfmt.nAvgBytesPerSec; Assert( (m_wfmt.nChannels == 1) || (m_wfmt.nChannels == 2) ); } // something unkown??? else { Int3(); } m_al_format = openal_get_format(m_wfmt.wBitsPerSample, m_wfmt.nChannels); if (m_al_format != AL_INVALID_VALUE) { // Cue for streaming Cue(); goto OPEN_DONE; } OPEN_ERROR: // Handle all errors here nprintf(("SOUND","SOUND ==> Could not open wave file %s for streaming\n", filename)); fRtn = false; if (m_snd_info.cfp != NULL) { // Close file mmioClose( m_snd_info.cfp, 0 ); m_snd_info.cfp = NULL; m_snd_info.true_offset = 0; m_snd_info.size = 0; } if (m_pwfmt_original) { vm_free(m_pwfmt_original); m_pwfmt_original = NULL; } OPEN_DONE: strncpy(m_wFilename, filename, MAX_FILENAME_LEN-1); if (fRtn) nprintf(("SOUND", "AUDIOSTR => Successfully opened: %s\n", filename)); return (fRtn); }
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; }
/* 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; }