static int plugin_run(struct playerHandles *ph, char *key, int *totaltime){ size_t size; long ret; const ssize_t len=1600; char buf[len]; /* input buffer */ unsigned int total=0; int channels, enc, retval=DEC_RET_SUCCESS; unsigned int rate; vorbis_info *vi; OggVorbis_File *vf; struct outputdetail *details=ph->outdetail; int sizemod; char tail[OUTPUT_TAIL_SIZE]; if(!(vf=malloc(sizeof(OggVorbis_File)))){ fprintf(stderr,"Malloc failed (vf)."); return DEC_RET_ERROR; } if(ov_open_callbacks(ph->ffd,vf,NULL,0,OV_CALLBACKS_NOCLOSE)<0){ fprintf(stderr,"ov open failed\n"); free(vf); return DEC_RET_ERROR; } details->totaltime=*totaltime; details->percent=-1; vi=ov_info(vf,-1); rate=(unsigned int)vi->rate; channels=(unsigned int)vi->channels; enc=16; sizemod=2*channels; snprintf(tail,OUTPUT_TAIL_SIZE,"New format: %dHz %dch %dbps",rate, channels, (int)vi->bitrate_nominal); addStatusTail(tail,ph->outdetail); snd_param_init(ph,&enc,&channels,&rate); h.vf=vf; h.total=&total; h.rate=rate; h.sizemod=sizemod; ph->dechandle=&h; details->percent=-1; do{ /* Read and write until everything is through. */ if((ret=ov_read(vf,buf,len,0,2,1,&vf->current_link))<1){ if((retval=vorbStatus(ret))==VORB_CONTINUE) continue; break; } size=ret; details->curtime=total/(rate*sizemod); if(details->totaltime>0) details->percent=(details->curtime*100)/details->totaltime; crOutput(ph->pflag,details); #if WITH_ALSA==1 if(writei_snd(ph,buf,size/sizemod)<0)break; #else if(writei_snd(ph,buf,size)<0)break; #endif total+=size; if(ph->pflag->exit!=DEC_RET_SUCCESS){ retval=ph->pflag->exit; break; } }while(1); writei_snd(ph,NULL,0); // drain sound buffer /* Done decoding, now just clean up and leave. */ ov_clear(vf); *totaltime=details->curtime; return retval; }
bool OGG::Decode (Resource *resource, AudioBuffer *audioBuffer) { OggVorbis_File oggFile; if (resource->path) { FILE_HANDLE *file = lime::fopen (resource->path, "rb"); if (!file) { return false; } if (file->isFile ()) { if (ov_open (file->getFile (), &oggFile, NULL, file->getLength ()) != 0) { lime::fclose (file); return false; } } else { lime::fclose (file); Bytes data = Bytes (resource->path); OAL_OggMemoryFile fakeFile = { data.Data (), data.Length (), 0 }; if (ov_open_callbacks (&fakeFile, &oggFile, NULL, 0, OAL_CALLBACKS_BUFFER) != 0) { return false; } } } else { OAL_OggMemoryFile fakeFile = { resource->data->Data (), resource->data->Length (), 0 }; if (ov_open_callbacks (&fakeFile, &oggFile, NULL, 0, OAL_CALLBACKS_BUFFER) != 0) { return false; } } // 0 for Little-Endian, 1 for Big-Endian #ifdef HXCPP_BIG_ENDIAN #define BUFFER_READ_TYPE 1 #else #define BUFFER_READ_TYPE 0 #endif int bitStream; long bytes = 1; int totalBytes = 0; #define BUFFER_SIZE 4096 vorbis_info *pInfo = ov_info (&oggFile, -1); if (pInfo == NULL) { //LOG_SOUND("FAILED TO READ OGG SOUND INFO, IS THIS EVEN AN OGG FILE?\n"); ov_clear (&oggFile); return false; } audioBuffer->channels = pInfo->channels; audioBuffer->sampleRate = pInfo->rate; audioBuffer->bitsPerSample = 16; int dataLength = ov_pcm_total (&oggFile, -1) * audioBuffer->channels * audioBuffer->bitsPerSample / 8; audioBuffer->data->Resize (dataLength); while (bytes > 0) { bytes = ov_read (&oggFile, (char *)audioBuffer->data->Data () + totalBytes, BUFFER_SIZE, BUFFER_READ_TYPE, 2, 1, &bitStream); totalBytes += bytes; } if (dataLength != totalBytes) { audioBuffer->data->Resize (totalBytes); } ov_clear (&oggFile); #undef BUFFER_READ_TYPE return true; }
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; }
/* public */ static void vorbis_stream_decode(struct decoder *decoder, struct input_stream *input_stream) { GError *error = NULL; if (ogg_codec_detect(decoder, input_stream) != OGG_CODEC_VORBIS) return; /* rewind the stream, because ogg_codec_detect() has moved it */ input_stream_lock_seek(input_stream, 0, SEEK_SET, NULL); struct vorbis_input_stream vis; OggVorbis_File vf; if (!vorbis_is_open(&vis, &vf, decoder, input_stream)) return; const vorbis_info *vi = ov_info(&vf, -1); if (vi == NULL) { g_warning("ov_info() has failed"); return; } struct audio_format audio_format; if (!audio_format_init_checked(&audio_format, vi->rate, #ifdef HAVE_TREMOR SAMPLE_FORMAT_S16, #else SAMPLE_FORMAT_FLOAT, #endif vi->channels, &error)) { g_warning("%s", error->message); g_error_free(error); return; } float total_time = ov_time_total(&vf, -1); if (total_time < 0) total_time = 0; decoder_initialized(decoder, &audio_format, vis.seekable, total_time); enum decoder_command cmd = decoder_get_command(decoder); #ifdef HAVE_TREMOR char buffer[4096]; #else float buffer[2048]; const int frames_per_buffer = G_N_ELEMENTS(buffer) / audio_format.channels; const unsigned frame_size = sizeof(buffer[0]) * audio_format.channels; #endif int prev_section = -1; unsigned kbit_rate = 0; do { if (cmd == DECODE_COMMAND_SEEK) { double seek_where = decoder_seek_where(decoder); if (0 == ov_time_seek_page(&vf, seek_where)) { decoder_command_finished(decoder); } else decoder_seek_error(decoder); } int current_section; #ifdef HAVE_TREMOR long nbytes = ov_read(&vf, buffer, sizeof(buffer), VORBIS_BIG_ENDIAN, 2, 1, ¤t_section); #else float **per_channel; long nframes = ov_read_float(&vf, &per_channel, frames_per_buffer, ¤t_section); long nbytes = nframes; if (nframes > 0) { vorbis_interleave(buffer, (const float*const*)per_channel, nframes, audio_format.channels); nbytes *= frame_size; } #endif if (nbytes == OV_HOLE) /* bad packet */ nbytes = 0; else if (nbytes <= 0) /* break on EOF or other error */ break; if (current_section != prev_section) { vi = ov_info(&vf, -1); if (vi == NULL) { g_warning("ov_info() has failed"); break; } if (vi->rate != (long)audio_format.sample_rate || vi->channels != (int)audio_format.channels) { /* we don't support audio format change yet */ g_warning("audio format change, stopping here"); break; } char **comments = ov_comment(&vf, -1)->user_comments; vorbis_send_comments(decoder, input_stream, comments); struct replay_gain_info rgi; if (vorbis_comments_to_replay_gain(&rgi, comments)) decoder_replay_gain(decoder, &rgi); prev_section = current_section; } long test = ov_bitrate_instant(&vf); if (test > 0) kbit_rate = test / 1000; cmd = decoder_data(decoder, input_stream, buffer, nbytes, kbit_rate); } while (cmd != DECODE_COMMAND_STOP); ov_clear(&vf); }
/** * @brief S_OGG_CodecOpenStream * @param[in] filename * @return */ snd_stream_t *S_OGG_CodecOpenStream(const char *filename) { snd_stream_t *stream; // OGG codec control structure OggVorbis_File *vf; // some variables used to get informations about the OGG vorbis_info *OGGInfo; ogg_int64_t numSamples; // check if input is valid if (!filename) { return NULL; } // Open the stream stream = S_CodecUtilOpen(filename, &ogg_codec); if (!stream) { return NULL; } // alloctate the OggVorbis_File vf = Z_Malloc(sizeof(OggVorbis_File)); if (!vf) { S_CodecUtilClose(&stream); return NULL; } // open the codec with our callbacks and stream as the generic pointer if (ov_open_callbacks(stream, vf, NULL, 0, S_OGG_Callbacks) != 0) { Z_Free(vf); S_CodecUtilClose(&stream); return NULL; } // the stream must be seekable if (!ov_seekable(vf)) { ov_clear(vf); Z_Free(vf); S_CodecUtilClose(&stream); return NULL; } // we only support OGGs with one substream if (ov_streams(vf) != 1) { ov_clear(vf); Z_Free(vf); S_CodecUtilClose(&stream); return NULL; } // get the info about channels and rate OGGInfo = ov_info(vf, 0); if (!OGGInfo) { ov_clear(vf); Z_Free(vf); S_CodecUtilClose(&stream); return NULL; } // get the number of sample-frames in the OGG numSamples = ov_pcm_total(vf, 0); // fill in the info-structure in the stream stream->info.rate = OGGInfo->rate; stream->info.width = OGG_SAMPLEWIDTH; stream->info.channels = OGGInfo->channels; stream->info.samples = numSamples; stream->info.size = stream->info.samples * stream->info.channels * stream->info.width; stream->info.dataofs = 0; // We use stream->pos for the file pointer in the compressed ogg file stream->pos = 0; // We use the generic pointer in stream for the OGG codec control structure stream->ptr = vf; return stream; }
bool LoadOggVorbisFromFileInMemory(const u8 *fileData, size_t numBytes, std::vector<u8> &dst, bool *isStereo, bool *is16Bit, int *frequency) { if (!fileData || numBytes == 0) { LogError("Null input data passed in"); return false; } if (!isStereo || !is16Bit || !frequency) { LogError("Outputs not set"); return false; } #ifndef TUNDRA_NO_AUDIO OggVorbis_File vf; OggMemDataSource src(fileData, numBytes); ov_callbacks cb; cb.read_func = &OggReadCallback; cb.seek_func = &OggSeekCallback; cb.tell_func = &OggTellCallback; cb.close_func = 0; int ret = ov_open_callbacks(&src, &vf, 0, 0, cb); if (ret < 0) { LogError("Not ogg vorbis format"); ov_clear(&vf); return false; } vorbis_info* vi = ov_info(&vf, -1); if (!vi) { LogError("No ogg vorbis stream info"); ov_clear(&vf); return false; } std::ostringstream msg; msg << "Decoding ogg vorbis stream with " << vi->channels << " channels, frequency " << vi->rate; // LogDebug(msg.str()); *frequency = vi->rate; *isStereo = (vi->channels > 1); if (vi->channels != 1 && vi->channels != 2) LogWarning("Warning: Loaded Ogg Vorbis data contains an unsupported number of channels: " + QString::number(vi->channels)); uint decoded_bytes = 0; dst.clear(); for(;;) { static const int MAX_DECODE_SIZE = 16384; dst.resize(decoded_bytes + MAX_DECODE_SIZE); int bitstream; long ret = ov_read(&vf, (char*)&dst[decoded_bytes], MAX_DECODE_SIZE, 0, 2, 1, &bitstream); if (ret <= 0) break; decoded_bytes += ret; } dst.resize(decoded_bytes); { std::ostringstream msg; msg << "Decoded " << decoded_bytes << " bytes of ogg vorbis sound data"; // LogDebug(msg.str()); } ov_clear(&vf); return true; #else return false; #endif }
bool OggPlayer::OpenOgg( const char *filename ) { if (!bInitialized) return false; if (bFileOpened) Close(); FILE *f; f = fopen(filename, "rb"); if (!f) return false; ov_open(f, &vf, NULL, 0); // ok now the tricky part // the vorbis_info struct keeps the most of the interesting format info vorbis_info *vi = ov_info(&vf,-1); vorbis_comment *vc = ov_comment(&vf, 0); nLoopStart = 0; nLoopEnd = 0; if (vc != NULL) { for (int i = 0; i < ARRAYLEN(loop_start_tags); i++) { char *value = vorbis_comment_query(vc, loop_start_tags[i], 0); if (value != NULL) { nLoopStart = atoi(value); } } for (int i = 0; i < ARRAYLEN(loop_end_tags); i++) { char *value = vorbis_comment_query(vc, loop_end_tags[i], 0); if (value != NULL) { nLoopEnd = atoi(value); } } } if (nLoopEnd <= nLoopStart) { nLoopEnd = ov_pcm_total(&vf, -1); } // set the wave format WAVEFORMATEX wfm; memset(&wfm, 0, sizeof(wfm)); wfm.cbSize = sizeof(wfm); wfm.nChannels = vi->channels; wfm.wBitsPerSample = 16; // ogg vorbis is always 16 bit wfm.nSamplesPerSec = vi->rate; wfm.nAvgBytesPerSec = wfm.nSamplesPerSec*wfm.nChannels*2; wfm.nBlockAlign = 2*wfm.nChannels; wfm.wFormatTag = 1; // set up the buffer DSBUFFERDESC desc; desc.dwSize = sizeof(desc); desc.dwFlags = DSBCAPS_CTRLVOLUME; desc.lpwfxFormat = &wfm; desc.dwReserved = 0; desc.dwBufferBytes = BUFSIZE*2; pDS->CreateSoundBuffer(&desc, &pDSB, NULL ); // fill the buffer DWORD pos = 0; int sec = 0; int ret = 1; DWORD size = BUFSIZE*2; char *buf; pDSB->Lock(0, size, (LPVOID*)&buf, &size, NULL, NULL, DSBLOCK_ENTIREBUFFER); // now read in the bits while(ret && pos<size) { ret = ov_read(&vf, buf+pos, size-pos, 0, 2, 1, &sec); pos += ret; } pDSB->Unlock( buf, size, NULL, NULL ); nCurSection = nLastSection = 0; return bFileOpened = true; }
int quh_vorbis_in_open (st_quh_nfo_t * file) { ogg_int64_t length = 0; int bits = 16; vorbis_comment *c = NULL; char buf[MAXBUFSIZE]; vorbis_info *nfo = NULL; if (!(fp = fopen (file->fname, "rb"))) return -1; if (ov_open (fp, &vf, NULL, 0) < 0) { fclose (fp); return -1; } opened = 1; // comments *buf = 0; c = vf.vc; if (c) { int x = 0; for (; x < c->comments && strlen (buf) < MAXBUFSIZE - 128; x++) { char *p = strchr (buf, 0); if (x) strcpy (p, "\n"); p = strchr (buf, 0); quh_fix_vorbis_comment (p, c->user_comments[x]); } quh_set_object_s (quh.filter_chain, QUH_OUTPUT, buf); } if (ov_seekable (&vf)) { length = ov_pcm_total (&vf, 0); file->seekable = QUH_SEEKABLE; } if ((nfo = ov_info (&vf, 0))) { file->rate = nfo->rate; file->channels = nfo->channels; file->min_bitrate = nfo->bitrate_lower ? nfo->bitrate_lower : nfo->bitrate_nominal; file->max_bitrate = nfo->bitrate_upper ? nfo->bitrate_upper : nfo->bitrate_nominal; } else { file->rate = 44100; file->channels = 2; file->min_bitrate = file->max_bitrate = 0; } file->is_signed = 1; file->size = bits / 8; if (length > 0) file->raw_size = length * bits / 8 * file->channels; file->raw_size = MIN (file->raw_size, 0x7fffffff); return 0; }
static playbackstatus MV_GetNextVorbisBlock ( VoiceNode *voice ) { vorbis_data * vd = (vorbis_data *) voice->extra; int32_t bytes, bytesread; int32_t bitstream, err; voice->Playing = TRUE; bytesread = 0; do { bytes = ov_read(&vd->vf, vd->block + bytesread, BLOCKSIZE - bytesread, 0, 2, 1, &bitstream); //fprintf(stderr, "ov_read = %d\n", bytes); if (bytes > 0) { bytesread += bytes; continue; } else if (bytes == OV_HOLE) continue; else if (bytes == 0) { if (voice->LoopStart) { err = ov_pcm_seek_page(&vd->vf, 0); if (err != 0) { MV_Printf("MV_GetNextVorbisBlock ov_pcm_seek_page_lap: err %d\n", err); } else { continue; } } else { break; } } else if (bytes < 0) { MV_Printf("MV_GetNextVorbisBlock ov_read: err %d\n", bytes); voice->Playing = FALSE; return NoMoreData; } } while (bytesread < BLOCKSIZE); if (bytesread == 0) { voice->Playing = FALSE; return NoMoreData; } if (bitstream != vd->lastbitstream) { vorbis_info * vi = 0; vi = ov_info(&vd->vf, -1); if (!vi || (vi->channels != 1 && vi->channels != 2)) { voice->Playing = FALSE; return NoMoreData; } voice->channels = vi->channels; voice->SamplingRate = vi->rate; voice->RateScale = ( voice->SamplingRate * voice->PitchScale ) / MV_MixRate; voice->FixedPointBufferSize = ( voice->RateScale * MixBufferSize ) - voice->RateScale; MV_SetVoiceMixMode( voice ); vd->lastbitstream = bitstream; } bytesread /= 2 * voice->channels; voice->position = 0; voice->sound = vd->block; voice->BlockLength = 0; voice->length = bytesread << 16; return( KeepPlaying ); }
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; }
void SoundPlayer::play(ArchiveFile& file) { // If we're not initialised yet, do it now if (!_initialised) { initialise(); } // Stop any previous playback operations, that might be still active clearBuffer(); // Retrieve the extension std::string ext = os::getExtension(file.getName()); if (boost::algorithm::to_lower_copy(ext) == "ogg") { // Convert the file into a buffer, self-destructs at end of scope ScopedArchiveBuffer buffer(file); // This is an OGG Vorbis file, decode it vorbis_info* vorbisInfo; OggVorbis_File oggFile; // Initialise the wrapper class OggFileStream stream(buffer); // Setup the callbacks and point them to the helper class ov_callbacks callbacks; callbacks.read_func = OggFileStream::oggReadFunc; callbacks.seek_func = OggFileStream::oggSeekFunc; callbacks.close_func = OggFileStream::oggCloseFunc; callbacks.tell_func = OggFileStream::oggTellFunc; // Open the OGG data stream using the custom callbacks int res = ov_open_callbacks(static_cast<void*>(&stream), &oggFile, NULL, 0, callbacks); if (res == 0) { // Open successful // Get some information about the OGG file vorbisInfo = ov_info(&oggFile, -1); // Check the number of channels ALenum format = (vorbisInfo->channels == 1) ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16; // Get the sample Rate ALsizei freq = (vorbisInfo->rate); //std::cout << "Sample rate is " << freq << "\n"; long bytes; char smallBuffer[4096]; DecodeBufferPtr largeBuffer(new DecodeBuffer()); do { int bitStream; // Read a chunk of decoded data from the vorbis file bytes = ov_read(&oggFile, smallBuffer, sizeof(smallBuffer), 0, 2, 1, &bitStream); if (bytes == OV_HOLE) { rError() << "SoundPlayer: Error decoding OGG: OV_HOLE.\n"; } else if (bytes == OV_EBADLINK) { rError() << "SoundPlayer: Error decoding OGG: OV_EBADLINK.\n"; } else { // Stuff this into the variable-sized buffer largeBuffer->insert(largeBuffer->end(), smallBuffer, smallBuffer + bytes); } } while (bytes > 0); // Allocate a new buffer alGenBuffers(1, &_buffer); DecodeBuffer& bufferRef = *largeBuffer; // Upload sound data to buffer alBufferData(_buffer, format, &bufferRef[0], static_cast<ALsizei>(bufferRef.size()), freq); // Clean up the OGG routines ov_clear(&oggFile); } else { rError() << "SoundPlayer: Error opening OGG file.\n"; } } else { // Must be a wave file try { // Create an AL sound buffer directly from the buffer in memory _buffer = WavFileLoader::LoadFromStream(file.getInputStream()); } catch (std::runtime_error& e) { rError() << "SoundPlayer: Error opening WAV file: " << e.what() << std::endl; _buffer = 0; } } if (_buffer != 0) { alGenSources(1, &_source); // Assign the buffer to the source and play it alSourcei(_source, AL_BUFFER, _buffer); // greebo: Wait 10 msec. to fix a problem with buffers not being played // maybe the AL needs time to push the data? usleep(10000); alSourcePlay(_source); // Enable the periodic buffer check, this destructs the buffer // as soon as the playback has finished _timer.enable(); } }
bool MkSoundBuffer::_CreateBufferFromOggFile(LPDIRECTSOUND directSound, const MkByteArray& srcData) { OggVorbis_File vorbisFile; ::ZeroMemory(&vorbisFile, sizeof(OggVorbis_File)); do { MkInterfaceForDataReading drInterface; if (!drInterface.SetUp(srcData, 0)) break; // vorbis file 오픈 ov_callbacks ogg_callbacks = { _read_func, _seek_func, _close_func, _tell_func }; if (ov_open_callbacks(reinterpret_cast<void*>(&drInterface), &vorbisFile, NULL, 0, ogg_callbacks) != 0) break; // 구조 정보 vorbis_info* vorbisInfo = ov_info(&vorbisFile, -1); if (vorbisInfo == NULL) break; // 버퍼 확보 int dataSize = vorbisInfo->channels * 16 / 8 * static_cast<int>(ov_pcm_total(&vorbisFile, -1)); if (dataSize <= 0) break; MkByteArray dataBuffer; dataBuffer.Fill(static_cast<unsigned int>(dataSize)); // PCM 블록 읽으며 디코딩 int bitstream, readSize = 0, writeSize = 0; while (true) { writeSize = ov_read(&vorbisFile, reinterpret_cast<char*>(dataBuffer.GetPtr()) + readSize, dataSize - readSize, 0, 2, 1, &bitstream); if(writeSize == 0) // EOF break; if ((dataSize - readSize) >= 0) // continue { readSize += writeSize; } else // 디코딩 실패 { writeSize = -1; break; } } if (writeSize < 0) break; // wave 정보 세팅 WAVEFORMATEX waveFormatEx; waveFormatEx.wFormatTag = WAVE_FORMAT_PCM; waveFormatEx.nChannels = vorbisInfo->channels; waveFormatEx.nSamplesPerSec = vorbisInfo->rate; waveFormatEx.nAvgBytesPerSec = vorbisInfo->channels * vorbisInfo->rate * 16 / 8; // 채널 * 주파수 * 진폭 / 8(bit>byte) waveFormatEx.nBlockAlign = vorbisInfo->channels * 16 / 8; waveFormatEx.wBitsPerSample = 16; waveFormatEx.cbSize = 0; // 사운드 버퍼 생성 후 데이터 복사 m_SoundBuffer = _CreateSoundBuffer(directSound, waveFormatEx, dataBuffer); } while (false); ov_clear(&vorbisFile); return (m_SoundBuffer != NULL); }
static void * ogg_player_thread(private_data_ogg * priv) { int first_time = 1; long ret; //init LWP_InitQueue(&oggplayer_queue); priv[0].vi = ov_info(&priv[0].vf, -1); ASND_Pause(0); priv[0].pcm_indx = 0; priv[0].pcmout_pos = 0; priv[0].eof = 0; priv[0].flag = 0; priv[0].current_section = 0; ogg_thread_running = 1; while (!priv[0].eof && ogg_thread_running) { if (priv[0].flag) LWP_ThreadSleep(oggplayer_queue); // wait only when i have samples to send if (priv[0].flag == 0) // wait to all samples are sent { if (ASND_TestPointer(0, priv[0].pcmout[priv[0].pcmout_pos]) && ASND_StatusVoice(0) != SND_UNUSED) { priv[0].flag |= 64; continue; } if (priv[0].pcm_indx < READ_SAMPLES) { priv[0].flag = 3; if (priv[0].seek_time >= 0) { ov_time_seek(&priv[0].vf, priv[0].seek_time); priv[0].seek_time = -1; } ret = ov_read( &priv[0].vf, (void *) &priv[0].pcmout[priv[0].pcmout_pos][priv[0].pcm_indx], MAX_PCMOUT,/*0,2,1,*/&priv[0].current_section); priv[0].flag &= 192; if (ret == 0) { /* EOF */ if (priv[0].mode & 1) ov_time_seek(&priv[0].vf, 0); // repeat else priv[0].eof = 1; // stops } 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. */ if (ret != OV_HOLE) { if (priv[0].mode & 1) ov_time_seek(&priv[0].vf, 0); // repeat else priv[0].eof = 1; // stops } } else { /* we don't bother dealing with sample rate changes, etc, but you'll have to*/ priv[0].pcm_indx += ret >> 1; //get 16 bits samples } } else priv[0].flag = 1; }
bool open(const std::string &path, int startTime) { int result; mPath = std::string(path.c_str()); mIsValid = true; #ifdef ANDROID mInfo = AndroidGetAssetFD(path.c_str()); oggFile = fdopen(mInfo.fd, "rb"); fseek(oggFile, mInfo.offset, 0); ov_callbacks callbacks; callbacks.read_func = &nme::AudioStream_Ogg::read_func; callbacks.seek_func = &nme::AudioStream_Ogg::seek_func; callbacks.close_func = &nme::AudioStream_Ogg::close_func; callbacks.tell_func = &nme::AudioStream_Ogg::tell_func; #else oggFile = fopen(path.c_str(), "rb"); #endif if(!oggFile) { //throw std::string("Could not open Ogg file."); LOG_SOUND("Could not open Ogg file."); mIsValid = false; return false; } oggStream = new OggVorbis_File(); #ifdef ANDROID result = ov_open_callbacks(this, oggStream, NULL, 0, callbacks); #else result = ov_open(oggFile, oggStream, NULL, 0); #endif if(result < 0) { fclose(oggFile); oggFile = 0; //throw std::string("Could not open Ogg stream. ") + errorString(result); LOG_SOUND("Could not open Ogg stream."); //LOG_SOUND(errorString(result).c_str()); mIsValid = false; return false; } vorbisInfo = ov_info(oggStream, -1); vorbisComment = ov_comment(oggStream, -1); mChannels = vorbisInfo->channels; mRate = vorbisInfo->rate; if (startTime != 0) { double seek = startTime * 0.001; ov_time_seek(oggStream, seek); } return true; }
void CreateVorbisStream(MFAudioStream *pStream, const char *pFilename) { MFCALLSTACK; MFVorbisStream *pVS = (MFVorbisStream*)MFHeap_Alloc(sizeof(MFVorbisStream)); pStream->pStreamData = pVS; // open vorbis file MFFile* hFile = MFFileSystem_Open(pFilename); if(!hFile) return; // attempt to cache the vorbis stream MFOpenDataCachedFile cachedOpen; cachedOpen.cbSize = sizeof(MFOpenDataCachedFile); cachedOpen.openFlags = MFOF_Read | MFOF_Binary | MFOF_Cached_CleanupBaseFile; cachedOpen.maxCacheSize = 256*1024; // 256k cache for vorbis stream should be heaps!! cachedOpen.pBaseFile = hFile; MFFile *pCachedFile = MFFile_Open(MFFileSystem_GetInternalFileSystemHandle(MFFSH_CachedFileSystem), &cachedOpen); if(pCachedFile) hFile = pCachedFile; // setup vorbis read callbacks ov_callbacks callbacks; callbacks.read_func = MFFile_StdRead; callbacks.seek_func = MFSound_VorbisSeek; callbacks.close_func = MFFile_StdClose; callbacks.tell_func = MFFile_StdTell; // open vorbis file if(ov_test_callbacks(hFile, &pVS->vorbisFile, NULL, 0, callbacks)) { MFDebug_Assert(false, "Not a vorbis file."); MFHeap_Free(pVS); return; } ov_test_open(&pVS->vorbisFile); // get vorbis file info pVS->pInfo = ov_info(&pVS->vorbisFile, -1); #if defined(VORBIS_TREMOR) // pStream->trackLength = (float)ov_pcm_total(&pVS->vorbisFile, -1) / (float)pVS->pInfo->rate; pStream->trackLength = 1000.0f; #else pStream->trackLength = (float)ov_time_total(&pVS->vorbisFile, -1); #endif // fill out the stream info pStream->streamInfo.sampleRate = pVS->pInfo->rate; pStream->streamInfo.channels = pVS->pInfo->channels; pStream->streamInfo.bitsPerSample = 16; pStream->streamInfo.bufferLength = pVS->pInfo->rate; // read the vorbis comment data pVS->pComment = ov_comment(&pVS->vorbisFile, -1); if(pVS->pComment) { const char *pTitle = vorbis_comment_query(pVS->pComment, "TITLE", 0); const char *pArtist = vorbis_comment_query(pVS->pComment, "ALBUM", 0); const char *pAlbum = vorbis_comment_query(pVS->pComment, "ARTIST", 0); const char *pGenre = vorbis_comment_query(pVS->pComment, "GENRE", 0); if(pTitle) MFString_CopyN(pStream->streamInfo.songName, pTitle, sizeof(pStream->streamInfo.songName)-1); if(pArtist) MFString_CopyN(pStream->streamInfo.artistName, pArtist, sizeof(pStream->streamInfo.artistName)-1); if(pAlbum) MFString_CopyN(pStream->streamInfo.albumName, pAlbum, sizeof(pStream->streamInfo.albumName)-1); if(pGenre) MFString_CopyN(pStream->streamInfo.genre, pGenre, sizeof(pStream->streamInfo.genre)-1); } }
int32_t MV_PlayLoopedVorbis ( char *ptr, uint32_t ptrlength, int32_t loopstart, int32_t loopend, int32_t pitchoffset, int32_t vol, int32_t left, int32_t right, int32_t priority, uint32_t callbackval ) { VoiceNode *voice; int32_t status; vorbis_data * vd = 0; vorbis_info * vi = 0; UNREFERENCED_PARAMETER(loopend); if ( !MV_Installed ) { MV_SetErrorCode( MV_NotInstalled ); return( MV_Error ); } vd = (vorbis_data *) malloc( sizeof(vorbis_data) ); if (!vd) { MV_SetErrorCode( MV_InvalidVorbisFile ); return MV_Error; } memset(vd, 0, sizeof(vorbis_data)); vd->ptr = ptr; vd->pos = 0; vd->length = ptrlength; vd->lastbitstream = -1; status = ov_open_callbacks((void *) vd, &vd->vf, 0, 0, vorbis_callbacks); if (status < 0) { MV_Printf("MV_PlayLoopedVorbis: err %d\n", status); MV_SetErrorCode( MV_InvalidVorbisFile ); return MV_Error; } vi = ov_info(&vd->vf, 0); if (!vi) { ov_clear(&vd->vf); free(vd); MV_SetErrorCode( MV_InvalidVorbisFile ); return MV_Error; } if (vi->channels != 1 && vi->channels != 2) { ov_clear(&vd->vf); free(vd); MV_SetErrorCode( MV_InvalidVorbisFile ); return MV_Error; } // Request a voice from the voice pool voice = MV_AllocVoice( priority ); if ( voice == NULL ) { ov_clear(&vd->vf); free(vd); MV_SetErrorCode( MV_NoVoices ); return( MV_Error ); } voice->wavetype = Vorbis; voice->bits = 16; voice->channels = vi->channels; voice->extra = (void *) vd; voice->GetSound = MV_GetNextVorbisBlock; voice->NextBlock = vd->block; voice->DemandFeed = NULL; voice->LoopCount = 0; voice->BlockLength = 0; voice->PitchScale = PITCH_GetScale( pitchoffset ); voice->length = 0; voice->next = NULL; voice->prev = NULL; voice->priority = priority; voice->callbackval = callbackval; voice->LoopStart = (char *) (loopstart >= 0 ? TRUE : FALSE); voice->LoopEnd = 0; voice->LoopSize = 0; voice->Playing = TRUE; voice->Paused = FALSE; voice->SamplingRate = vi->rate; voice->RateScale = ( voice->SamplingRate * voice->PitchScale ) / MV_MixRate; voice->FixedPointBufferSize = ( voice->RateScale * MixBufferSize ) - voice->RateScale; MV_SetVoiceMixMode( voice ); MV_SetVoiceVolume( voice, vol, left, right ); MV_PlayVoice( voice ); return( voice->handle ); }
/* 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 */ #ifdef WIN32 if((x->x_file = fopen(filename->s_name, "rb")) < 0) #else if((x->x_file = fopen(filename->s_name, "r")) < 0) #endif { 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)); } } }
ALOGG_OGGSTREAM *alogg_create_oggstream(void *first_data_buffer, int data_buffer_len, int last_block) { ALOGG_OGGSTREAM *ogg; vorbis_info *vi; int ret; void *databuf1, *databuf2, *full_databuf; /* create a new ogg struct */ ogg = (ALOGG_OGGSTREAM *)malloc(sizeof(ALOGG_OGGSTREAM)); if (ogg == NULL) return NULL; /* allocate the buffers */ databuf1 = malloc(data_buffer_len); if (databuf1 == NULL) { free((void *)ogg); return NULL; } databuf2 = malloc(data_buffer_len); if (databuf2 == NULL) { free((void *)ogg); free(databuf1); return NULL; } full_databuf = malloc(data_buffer_len * 2); if (full_databuf == NULL) { free((void *)ogg); free(databuf1); free(databuf2); return NULL; } /* copy the first data */ memcpy(databuf1, first_data_buffer, data_buffer_len); /* fill in the ogg struct */ ogg->databuf1 = databuf1; ogg->databuf2 = databuf2; ogg->full_databuf = (char *)full_databuf; ogg->data_cursor = 0; ogg->databuf_selector = 1; ogg->databuf_len = data_buffer_len; ogg->unsel_databuf_free = TRUE; if (last_block) ogg->bytes_used = data_buffer_len; else ogg->bytes_used = -1; ogg->audiostream = NULL; ogg->auto_polling = FALSE; /* use vorbisfile to open it */ ret = ov_open_callbacks((void *)ogg, &(ogg->vf), NULL, 0, _alogg_oggstream_callbacks); /* if error */ if (ret < 0) { free((void *)ogg); free((void *)databuf1); free((void *)databuf2); free((void *)full_databuf); return NULL; } /* get audio info */ vi = ov_info(&(ogg->vf), -1); if (vi->channels > 1) ogg->stereo = TRUE; else ogg->stereo = FALSE; ogg->freq = vi->rate; return ogg; }
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(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 = static_cast<size_t>(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( const std::exception& ) { ov_clear(&vf); throw; } ov_clear(&vf); }
int main(int argc, char *argv[]) { printf("\nOgg to WAV decoder/converter.\n\n"); if(argc > 2) { printf("No input file.\n\n"); return 1; } OggVorbis_File vf; if(ov_fopen(argv[1], &vf) < 0) { printf("Unable to open file: \"%s\".\n\n"); return 1; } vorbis_info *vi = ov_info(&vf, -1); printf("Vorbis file info:\n\n"); printf("Channels: %d\n", vi->channels); printf("Samples: %ld\n", ov_pcm_total(&vf, -1)); printf("Samplerate: %d.\n", vi->rate); printf("\nLength: ~%ld s.\n", ov_pcm_total(&vf, -1)/vi->rate); uint32_t pcm_size = ov_pcm_total(&vf, -1) * vi->channels * 2; printf("\nPCM size: %ld bytes.\n", pcm_size); printf("\nWAV size: %ld bytes.\n", pcm_size+44); char buffer[4096]; FILE *out = fopen("out.wav", "wb"); if(out == NULL) { printf("Unable to open outfile for writing.\n\n"); return 1; } uint32_t temp32; uint16_t temp16; // Chunk header memcpy(buffer, "RIFF", 4); temp32 = 36+pcm_size; memcpy(&temp32, &buffer[4], 4); memcpy(&buffer[8], "WAVE", 4); // SubChunk1 memcpy(&buffer[12], "fmt ", 4); temp32 = 16; memcpy(&buffer[16], &temp32, 4); temp16 = 1; memcpy(&buffer[20], &temp16, 2); temp16 = vi->channels; memcpy(&buffer[22], &temp16, 2); temp32 = vi->rate; memcpy(&buffer[24], &temp32, 4); temp32 = vi->rate * vi->channels * 2; memcpy(&buffer[28], &temp32, 4); temp16 = vi->channels * 2; memcpy(&buffer[32], &temp16, 2); temp16 = 16; memcpy(&buffer[34], &temp16, 2); // SubChunk2 memcpy(&buffer[36], "data", 4); memcpy(&buffer[40], &pcm_size, 4); // Write WAV header fwrite(buffer, 1, 44, out); printf("\nDecoding:\n\n"); int current_section; while(1) { long ret = ov_read(&vf, buffer,sizeof(buffer), 0, 2, 1, ¤t_section); if(ret == 0) break; if(ret < 0) { printf("Error while reading.\n"); break; } fwrite(buffer, 1, ret, out); } printf("Done.\n"); fclose(out); ov_clear(&vf); return 0; }
//----------------------------------------------------------------------------- bool MusicOggStream::load(const std::string& filename) { if (isPlaying()) stopMusic(); m_error = true; m_fileName = filename; if(m_fileName=="") return false; m_oggFile = fopen(m_fileName.c_str(), "rb"); if(!m_oggFile) { printf("Loading Music: %s failed (fopen returned NULL)\n", m_fileName.c_str()); return false; } #if defined( WIN32 ) || defined( WIN64 ) const int result = ov_open_callbacks((void *)m_oggFile, &m_oggStream, NULL, 0, OV_CALLBACKS_DEFAULT); #else const int result = ov_open(m_oggFile, &m_oggStream, NULL, 0); #endif if (result < 0) { fclose(m_oggFile); const char* errorMessage; switch (result) { case OV_EREAD: errorMessage = "OV_EREAD"; break; case OV_ENOTVORBIS: errorMessage = "OV_ENOTVORBIS"; break; case OV_EVERSION: errorMessage = "OV_EVERSION"; break; case OV_EBADHEADER: errorMessage = "OV_EBADHEADER"; break; case OV_EFAULT: errorMessage = "OV_EFAULT"; break; default: errorMessage = "Unknown Error"; } printf("Loading Music: %s failed : ov_open returned error code %i (%s)\n", m_fileName.c_str(), result, errorMessage); return false; } m_vorbisInfo = ov_info(&m_oggStream, -1); if (m_vorbisInfo->channels == 1) nb_channels = AL_FORMAT_MONO16; else nb_channels = AL_FORMAT_STEREO16; alGenBuffers(2, m_soundBuffers); if (check("alGenBuffers") == false) return false; alGenSources(1, &m_soundSource); if (check("alGenSources") == false) return false; alSource3f(m_soundSource, AL_POSITION, 0.0, 0.0, 0.0); alSource3f(m_soundSource, AL_VELOCITY, 0.0, 0.0, 0.0); alSource3f(m_soundSource, AL_DIRECTION, 0.0, 0.0, 0.0); alSourcef (m_soundSource, AL_ROLLOFF_FACTOR, 0.0 ); alSourcef (m_soundSource, AL_GAIN, 1.0 ); alSourcei (m_soundSource, AL_SOURCE_RELATIVE, AL_TRUE ); m_error=false; return true; } // load
Buffer* LoadOGG(const char* name, const void* data, size_t size) { Buffer* b = new Buffer(name); OggStaticFile fp(data,size); long bytes; std::vector<char> buffer; int bitStream; char arr[OGG_STATIC_BUFFER_SIZE] = {0}; OggVorbis_File oggStream; vorbis_info* vorbisInfo; ALenum format; ALsizei freq; ALint isize; ALint d = 1; if (ov_open_callbacks(&fp,&oggStream,NULL,0,OggStaticGetCallback()) != 0) { freeslw::ErrorPrintf("Failed to load \"%s\"",name); delete b; return 0; } alGenBuffers(1,&b->bufferId[0]); if (b->bufferId[0] == NO_BUFFER) { freeslw::ErrorPrintf("Failed to create buffer for \"%s\"",name); delete b; return 0; } vorbisInfo = ov_info(&oggStream,-1); format = (vorbisInfo->channels == 1)? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16; freq = vorbisInfo->rate; do { bytes = ov_read(&oggStream,arr,OGG_STATIC_BUFFER_SIZE, 0, 2, 1, &bitStream); buffer.insert(buffer.end(),arr,arr + bytes); } while (bytes > 0); ov_clear(&oggStream); alBufferData(b->bufferId[0],format,&buffer[0],(ALsizei)buffer.size(),freq); alGetBufferi(b->bufferId[0],AL_SIZE,&isize); if (format == AL_FORMAT_MONO8) b->format = freeslw::TA_MONO8; else if (format == AL_FORMAT_MONO16) b->format = freeslw::TA_MONO16; else if (format == AL_FORMAT_STEREO8) b->format = freeslw::TA_STEREO8; else if (format == AL_FORMAT_STEREO16) b->format = freeslw::TA_STEREO16; else freeslw::ErrorPrintf("Failed to retrieve a valid sound format (format = %d)",format); if (b->format == freeslw::TA_MONO16 || b->format == freeslw::TA_STEREO8) d = 2; else if (format == freeslw::TA_STEREO16) d = 4; if (freq == 0) { freeslw::ErrorPrintf("\"%s\": Frequency = 0",name); freq = 1; } b->frequency = (int)freq; b->length = (isize * 1000) / (freq * d); b->activeBuffer = 0; b->numBuffers = 1; return b; }
void CSoundRender_Source::LoadWave (LPCSTR pName) { pname = pName; // Load file into memory and parse WAV-format OggVorbis_File ovf; ov_callbacks ovc = {ov_read_func,ov_seek_func,ov_close_func,ov_tell_func}; IReader* wave = FS.r_open (pname.c_str()); R_ASSERT3 (wave&&wave->length(),"Can't open wave file:",pname.c_str()); ov_open_callbacks (wave,&ovf,NULL,0,ovc); vorbis_info* ovi = ov_info(&ovf,-1); // verify R_ASSERT3 (ovi,"Invalid source info:",pName); R_ASSERT3 (ovi->channels==1,"Invalid source num channels:",pName); R_ASSERT3 (ovi->rate==44100,"Invalid source rate:",pName); WAVEFORMATEX wfxdest = SoundRender->wfm; wfxdest.nChannels = u16(ovi->channels); wfxdest.nBlockAlign = wfxdest.nChannels * wfxdest.wBitsPerSample / 8; wfxdest.nAvgBytesPerSec = wfxdest.nSamplesPerSec * wfxdest.nBlockAlign; s64 pcm_total = ov_pcm_total(&ovf,-1); if (psSoundFreq==sf_22K) pcm_total/=2; dwBytesTotal = u32(pcm_total*wfxdest.nBlockAlign); dwBytesPerMS = wfxdest.nAvgBytesPerSec/1000; // dwBytesPerSec = wfxdest.nAvgBytesPerSec; dwTimeTotal = u32 ( sdef_source_footer + u64( (u64(dwBytesTotal)*u64(1000))/u64(wfxdest.nAvgBytesPerSec) ) ); vorbis_comment* ovm = ov_comment(&ovf,-1); if (ovm->comments){ IReader F (ovm->user_comments[0],ovm->comment_lengths[0]); u32 vers = F.r_u32 (); if (vers==0x0001){ m_fMinDist = F.r_float (); m_fMaxDist = F.r_float (); m_fBaseVolume = 1.f; m_uGameType = F.r_u32 (); m_fMaxAIDist = m_fMaxDist; }else if (vers==0x0002){ m_fMinDist = F.r_float (); m_fMaxDist = F.r_float (); m_fBaseVolume = F.r_float (); m_uGameType = F.r_u32 (); m_fMaxAIDist = m_fMaxDist; }else if (vers==OGG_COMMENT_VERSION){ m_fMinDist = F.r_float (); m_fMaxDist = F.r_float (); m_fBaseVolume = F.r_float (); m_uGameType = F.r_u32 (); m_fMaxAIDist = F.r_float (); }else{ Log ("! Invalid ogg-comment version, file: ",pName); } }else{ Log ("! Missing ogg-comment, file: ",pName); } R_ASSERT3((m_fMaxAIDist>=0.1f)&&(m_fMaxDist>=0.1f),"Invalid max distance.",pName); ov_clear (&ovf); FS.r_close (wave); }
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; } else if (strstr(comment->user_comments[i],"COMMENT=loop(")== 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; }
Sound* AudioStreamer::LoadSound(IXAudio2* xaudio2, const std::string& file) { if( !xaudio2 ) { SND_ERROR("AudioStreamer::LoadSound(): NULL == xaudio2"); return false; } FILE* infile = NULL; fopen_s(&infile, file.c_str(), "rb"); if( !infile ) { SND_ERROR("AudioStreamer::LoadSound(): Could not open file"); return NULL; } OggVorbis_File oggfile; int stream; long readbytes = 0; long totalread = 0; ov_open(infile, &oggfile, NULL, 0); vorbis_info* info = ov_info(&oggfile, -1); Sound* s = new Sound(); s->format.nChannels = info->channels; s->format.cbSize = sizeof(WAVEFORMATEX); s->format.wBitsPerSample = 16; s->format.nSamplesPerSec = info->rate; s->format.nAvgBytesPerSec = info->rate * 2 * info->channels; s->format.nBlockAlign = 2 * info->channels; s->format.wFormatTag = 1; s->totalsize = (unsigned int)ov_pcm_total(&oggfile, -1) * 2 * info->channels; s->data[0] = new char[s->totalsize]; do { readbytes = ov_read(&oggfile, s->data[0] + totalread, s->totalsize - totalread, 0, 2, 1, &stream); totalread += readbytes; } while( readbytes > 0 && (unsigned int)totalread < s->totalsize ); ov_clear(&oggfile); // create xaudio voice object if( FAILED(xaudio2->CreateSourceVoice(&s->voice, &s->format, 0, 2.0f, s)) ) { SND_ERROR("AudioStreamer::LoadSound(): Could not create source voice"); delete s; return NULL; } XAUDIO2_BUFFER audbuff; memset(&audbuff, 0, sizeof(XAUDIO2_BUFFER)); audbuff.pAudioData = (const BYTE*)s->data[0]; audbuff.Flags = XAUDIO2_END_OF_STREAM; audbuff.AudioBytes = s->totalsize; audbuff.LoopCount = XAUDIO2_LOOP_INFINITE; if( FAILED(s->voice->SubmitSourceBuffer(&audbuff)) ) { SND_ERROR("AudioStreamer::LoadSound(): Could not submit buffer"); delete s; return NULL; } s->canplay = true; // called from main thread soundguard.Lock(); sound.push_back(s); soundguard.Unlock(); return s; }
int FileVorbis::open_file(int rd, int wr) { int result = 0; //printf("FileVorbis::open_file 1\n"); if(rd) { //printf("FileVorbis::open_file 1\n"); if(!(fd = fopen(asset->path, "rb"))) { eprintf("FileVorbis::open_file %s: %s\n", asset->path, strerror(errno)); result = 1; } else { //printf("FileVorbis::open_file 2 %p %p\n", fd, vf); if(ov_open(fd, &vf, NULL, 0) < 0) { eprintf(_("FileVorbis::open_file %s: invalid bitstream.\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("FileVorbis::open_file %s: %s\n", asset->path, strerror(errno)); 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 OGG::Decode (Resource *resource, AudioBuffer *audioBuffer) { OggVorbis_File oggFile; if (resource->path) { FILE_HANDLE *file = lime::fopen (resource->path, "rb"); if (!file) { return false; } if (file->isFile ()) { ov_open (file->getFile (), &oggFile, NULL, file->getLength ()); } else { ByteArray data = ByteArray (resource->path); OAL_OggMemoryFile fakeFile = { data.Bytes (), data.Size (), 0 }; if (ov_open_callbacks (&fakeFile, &oggFile, NULL, 0, OAL_CALLBACKS_BUFFER) != 0) { return false; } } } else { OAL_OggMemoryFile fakeFile = { resource->data->Bytes (), resource->data->Size (), 0 }; if (ov_open_callbacks (&fakeFile, &oggFile, NULL, 0, OAL_CALLBACKS_BUFFER) != 0) { return false; } } // 0 for Little-Endian, 1 for Big-Endian #ifdef HXCPP_BIG_ENDIAN #define BUFFER_READ_TYPE 1 #else #define BUFFER_READ_TYPE 0 #endif int bitStream; long bytes = 1; int totalBytes = 0; #define BUFFER_SIZE 32768 vorbis_info *pInfo = ov_info (&oggFile, -1); if (pInfo == NULL) { //LOG_SOUND("FAILED TO READ OGG SOUND INFO, IS THIS EVEN AN OGG FILE?\n"); return false; } audioBuffer->channels = pInfo->channels; audioBuffer->sampleRate = pInfo->rate; //default to 16? todo audioBuffer->bitsPerSample = 16; // Seem to need four times the read PCM total audioBuffer->data->Resize (ov_pcm_total (&oggFile, -1) * 4); while (bytes > 0) { if (audioBuffer->data->Size () < totalBytes + BUFFER_SIZE) { audioBuffer->data->Resize (totalBytes + BUFFER_SIZE); } bytes = ov_read (&oggFile, (char *)audioBuffer->data->Bytes () + totalBytes, BUFFER_SIZE, BUFFER_READ_TYPE, 2, 1, &bitStream); totalBytes += bytes; } audioBuffer->data->Resize (totalBytes); ov_clear (&oggFile); #undef BUFFER_SIZE #undef BUFFER_READ_TYPE 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{
SoundBuffer* loadOggFile(const std::string &filepath) { int endian = 0; // 0 for Little-Endian, 1 for Big-Endian int bitStream; long bytes; char array[BUFFER_SIZE]; // Local fixed size array vorbis_info *pInfo; OggVorbis_File oggFile; // Do a dumb-ass static string copy for old versions of ov_fopen // because they expect a non-const char* char nonconst[10000]; snprintf(nonconst, 10000, "%s", filepath.c_str()); // Try opening the given file //if(ov_fopen(filepath.c_str(), &oggFile) != 0) if(ov_fopen(nonconst, &oggFile) != 0) { infostream<<"Audio: Error opening "<<filepath<<" for decoding"<<std::endl; return NULL; } SoundBuffer *snd = new SoundBuffer; // Get some information about the OGG file pInfo = ov_info(&oggFile, -1); // Check the number of channels... always use 16-bit samples if(pInfo->channels == 1) snd->format = AL_FORMAT_MONO16; else snd->format = AL_FORMAT_STEREO16; // The frequency of the sampling rate snd->freq = pInfo->rate; // Keep reading until all is read do { // Read up to a buffer's worth of decoded sound data bytes = ov_read(&oggFile, array, BUFFER_SIZE, endian, 2, 1, &bitStream); if(bytes < 0) { ov_clear(&oggFile); infostream<<"Audio: Error decoding "<<filepath<<std::endl; return NULL; } // Append to end of buffer snd->buffer.insert(snd->buffer.end(), array, array + bytes); } while (bytes > 0); alGenBuffers(1, &snd->buffer_id); alBufferData(snd->buffer_id, snd->format, &(snd->buffer[0]), snd->buffer.size(), snd->freq); ALenum error = alGetError(); #ifdef NOTDEF if(error != AL_NO_ERROR){ infostream<<"Audio: OpenAL error: "<<alErrorString(error) <<"preparing sound buffer"<<std::endl; } infostream<<"Audio file "<<filepath<<" loaded"<<std::endl; #endif // Clean up! ov_clear(&oggFile); return snd; }
static LONG APIENTRY IOProc_Entry2(PVOID pmmioStr, USHORT usMsg, LONG lParam1, LONG lParam2) { PMMIOINFO pmmioinfo = (PMMIOINFO)pmmioStr; switch (usMsg) { case MMIOM_OPEN: { HMMIO hmmioSS; MMIOINFO mmioinfoSS; PSZ pszFileName = (char *)lParam1; if (!pmmioinfo) return MMIO_ERROR; if ((pmmioinfo->ulFlags & MMIO_READWRITE)) { #ifdef DEBUG fprintf(file,"ReadWrite - requested.\n"); #endif return MMIO_ERROR; } if (!(pmmioinfo->ulTranslate & MMIO_TRANSLATEHEADER) && !(pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA)) return MMIO_ERROR; if (!pmmioinfo->fccChildIOProc) { FOURCC fccFileStorageSystem; if (pmmioinfo->ulFlags & MMIO_CREATE) { if (mmioDetermineSSIOProc(pszFileName, pmmioinfo, &fccFileStorageSystem, NULL)) { fccFileStorageSystem = FOURCC_DOS; } } else { if (mmioIdentifyStorageSystem(pszFileName, pmmioinfo, &fccFileStorageSystem)) { return MMIO_ERROR; } } if (!fccFileStorageSystem) { return MMIO_ERROR; } else { pmmioinfo->fccChildIOProc = fccFileStorageSystem; } /* endif */ } memmove(&mmioinfoSS, pmmioinfo, sizeof(MMIOINFO)); mmioinfoSS.pIOProc = NULL; mmioinfoSS.fccIOProc = pmmioinfo->fccChildIOProc; mmioinfoSS.ulFlags |= MMIO_NOIDENTIFY; hmmioSS = mmioOpen (pszFileName, &mmioinfoSS, mmioinfoSS.ulFlags); if (pmmioinfo->ulFlags & MMIO_DELETE) { if (!hmmioSS) { pmmioinfo->ulErrorRet = MMIOERR_DELETE_FAILED; return MMIO_ERROR; } else return MMIO_SUCCESS; } if (!hmmioSS) return MMIO_ERROR; if (pmmioinfo->ulFlags & MMIO_READ) { DecInfo *decInfo = (DecInfo *)malloc(sizeof(DecInfo)); #ifdef DEBUG fprintf(file,"File Read: %s\n",pszFileName); #endif if (!decInfo) { mmioClose(hmmioSS, 0); return MMIO_ERROR; } decInfo->t = READNUM; decInfo->vorbisOptions = pmmioinfo->pExtraInfoStruct; pmmioinfo->pExtraInfoStruct = (PVOID)decInfo; { ov_callbacks cb; cb.read_func = mread; cb.seek_func = mseek; cb.close_func = mclose; cb.tell_func = mtell; if(0 != ov_open_callbacks((void *)hmmioSS, &decInfo->oggfile, 0, 0, cb)) { free(decInfo); mmioClose(hmmioSS, 0); return MMIO_ERROR; } } #ifdef DEBUG fprintf(file,"Open successfull\n"); #endif return MMIO_SUCCESS; } else if (pmmioinfo->ulFlags & MMIO_WRITE) { EncInfo *encInfo = (EncInfo *)malloc(sizeof(EncInfo)); #ifdef DEBUG fprintf(file,"File Write: %s\n",pszFileName); #endif if (!encInfo) { mmioClose(hmmioSS, 0); return MMIO_ERROR; } memset(encInfo, 0, sizeof(EncInfo)); encInfo->t = WRITENUM; encInfo->hmmioSS = hmmioSS; encInfo->vorbisOptions = (PVORBISOPTIONS)pmmioinfo->pExtraInfoStruct; pmmioinfo->pExtraInfoStruct = (PVOID)encInfo; return MMIO_SUCCESS; } #ifdef DEBUG fprintf(file,"File not read nor write: %s\n",pszFileName); #endif return MMIO_ERROR; } break; case MMIOM_READ: { if (!pmmioinfo || !pmmioinfo->pExtraInfoStruct || !lParam1) return MMIO_ERROR; if (!pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA) { return MMIO_ERROR; // return mmioRead (ogginfo->hmmioSS, (PVOID) lParam1, (ULONG) lParam2); } else { OggVorbis_File *oggfile; long rc = 0; int current_section; long total = 0; oggfile = &((DecInfo *)pmmioinfo->pExtraInfoStruct)->oggfile; if (READNUM != ((DecInfo *)pmmioinfo->pExtraInfoStruct)->t) return MMIO_ERROR; while (lParam2 > 0) { rc = ov_read(oggfile, (char *)lParam1, (int)lParam2, 0, 2, 1, ¤t_section); if (rc < 0) { #ifdef DEBUG fprintf(file, "Read failed once\n"); #endif continue; } if (rc <= 0) break; lParam2 -= rc; lParam1 += rc; total += rc; } #ifdef DEBUG fprintf(file,"Read rc:%ld total:%ld\n",rc,total); #endif if (rc < 0) return MMIO_ERROR; return total; } } break; case MMIOM_SEEK: { LONG lPosDesired; OggVorbis_File *oggfile; vorbis_info *vi; if (!pmmioinfo || !pmmioinfo->pExtraInfoStruct) return MMIO_ERROR; if (!pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA) return MMIO_ERROR; oggfile = &((DecInfo *)pmmioinfo->pExtraInfoStruct)->oggfile; if (READNUM != ((DecInfo *)pmmioinfo->pExtraInfoStruct)->t) return MMIO_ERROR; vi = ov_info(oggfile, -1); if (!vi) return MMIO_ERROR; if (SEEK_SET == lParam2) { lPosDesired = lParam1/(2*vi->channels); } else if (SEEK_CUR == lParam2) { if (0 == lParam1) { return ov_pcm_tell(oggfile)*2*vi->channels; } /* endif */ lPosDesired = ov_pcm_tell(oggfile) + lParam1/(2*vi->channels); } else if (SEEK_END == lParam2) { lPosDesired = ov_pcm_total(oggfile,-1) + lParam1/(2*vi->channels); } else { return MMIO_ERROR; } #ifdef DEBUG fprintf(file,"Seek to %ld by %d\n",lPosDesired, lParam2); #endif if (ov_pcm_seek(oggfile, lPosDesired) < 0) return MMIO_ERROR; return lPosDesired*2*vi->channels; } break; case MMIOM_CLOSE: { int rc; #ifdef DEBUG fprintf(file,"start CLOSE\n"); #endif if (!pmmioinfo) return MMIO_ERROR; if (pmmioinfo->pExtraInfoStruct) { DecInfo *decInfo = (DecInfo *)pmmioinfo->pExtraInfoStruct; #ifdef DEBUG fprintf(file,"ready CLOSE\n"); #endif if (READNUM == decInfo->t) { #ifdef DEBUG fprintf(file,"read CLOSE\n"); #endif ov_clear(&decInfo->oggfile); free(decInfo); decInfo = 0; rc=MMIO_SUCCESS; } else if (WRITENUM == decInfo->t) { EncInfo *encInfo = (EncInfo*)pmmioinfo->pExtraInfoStruct; #ifdef DEBUG fprintf(file,"write CLOSE\n"); #endif if (encInfo->headerSet) { vorbis_analysis_wrote(&encInfo->vd,0); rc = oggWrite(encInfo,1); ogg_stream_clear(&encInfo->os); vorbis_block_clear(&encInfo->vb); vorbis_dsp_clear(&encInfo->vd); vorbis_comment_clear(&encInfo->vc); vorbis_info_clear(&encInfo->vi); } mmioClose(encInfo->hmmioSS, 0); free(encInfo); encInfo = 0; rc = MMIO_SUCCESS; } else rc = MMIO_ERROR; pmmioinfo->pExtraInfoStruct = 0; #ifdef DEBUG fprintf(file,"CLOSE\n"); #endif return rc; } return MMIO_ERROR; } break; case MMIOM_IDENTIFYFILE: { unsigned char buf[4]; HMMIO hmmioTemp; ULONG ulTempFlags = MMIO_READ | MMIO_DENYWRITE | MMIO_NOIDENTIFY; LONG rc = MMIO_ERROR; if (!lParam1 && !lParam2) return MMIO_ERROR; hmmioTemp = (HMMIO)lParam2; if (!hmmioTemp) { hmmioTemp = mmioOpen((PSZ)lParam1, NULL, ulTempFlags); } if (hmmioTemp) { rc = mmioRead(hmmioTemp, buf, 4); if (rc == 4 && buf[0] == 'O' && buf[1] == 'g' && buf[2] == 'g' && buf[3] == 'S') { rc = MMIO_SUCCESS; } if (!lParam2) mmioClose(hmmioTemp, 0); } return rc; } break; case MMIOM_GETFORMATINFO: { PMMFORMATINFO pmmformatinfo; pmmformatinfo = (PMMFORMATINFO)lParam1; pmmformatinfo->ulStructLen = sizeof(MMFORMATINFO); pmmformatinfo->fccIOProc = FOURCC_Vorbis; pmmformatinfo->ulIOProcType = MMIO_IOPROC_FILEFORMAT; pmmformatinfo->ulMediaType = MMIO_MEDIATYPE_AUDIO; pmmformatinfo->ulFlags = MMIO_CANREADTRANSLATED | MMIO_CANWRITETRANSLATED | MMIO_CANSEEKTRANSLATED; strcpy(pmmformatinfo->szDefaultFormatExt, "OGG"); pmmformatinfo->ulCodePage = 0; pmmformatinfo->ulLanguage = 0; pmmformatinfo->lNameLength = 21; return MMIO_SUCCESS; } break; case MMIOM_GETFORMATNAME: if (lParam2 > 21) { strcpy((PSZ)lParam1, "Ogg Vorbis"); return MMIO_SUCCESS; } else return MMIO_ERROR; break; case MMIOM_QUERYHEADERLENGTH: return (sizeof (MMAUDIOHEADER)); break; case MMIOM_GETHEADER: { OggVorbis_File *oggfile; DecInfo *decInfo; PMMAUDIOHEADER mmaudioheader; vorbis_info *vi; if (!pmmioinfo || !pmmioinfo->pExtraInfoStruct) return 0; if (!(pmmioinfo->ulFlags & MMIO_READ)) return 0; decInfo = (DecInfo *)pmmioinfo->pExtraInfoStruct; oggfile = &decInfo->oggfile; if (READNUM != decInfo->t){ pmmioinfo->ulErrorRet = MMIOERR_INVALID_STRUCTURE; return 0; } #ifdef DEBUG fprintf(file,"HERE\n"); #endif if (!(pmmioinfo->ulTranslate & MMIO_TRANSLATEHEADER) && !(pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA)) return 0; mmaudioheader = (MMAUDIOHEADER *)lParam1; if (sizeof(MMAUDIOHEADER) > lParam2) { pmmioinfo->ulErrorRet = MMIOERR_INVALID_BUFFER_LENGTH; return 0; } #ifdef DEBUG fprintf(file,"THERE\n"); #endif vi = ov_info(oggfile, -1); if (!vi) { pmmioinfo->ulErrorRet = MMIOERR_INVALID_STRUCTURE; return 0; } mmaudioheader->ulContentType = MMIO_MIDI_UNKNOWN; mmaudioheader->ulMediaType = MMIO_MEDIATYPE_AUDIO; mmaudioheader->mmXWAVHeader.WAVEHeader.usFormatTag=DATATYPE_WAVEFORM; mmaudioheader->mmXWAVHeader.WAVEHeader.usChannels = vi->channels; mmaudioheader->mmXWAVHeader.WAVEHeader.ulSamplesPerSec = vi->rate; mmaudioheader->mmXWAVHeader.WAVEHeader.usBitsPerSample = 16; mmaudioheader->mmXWAVHeader.WAVEHeader.ulAvgBytesPerSec= mmaudioheader->mmXWAVHeader.WAVEHeader.usChannels * mmaudioheader->mmXWAVHeader.WAVEHeader.ulSamplesPerSec * mmaudioheader->mmXWAVHeader.WAVEHeader.usBitsPerSample / 8; mmaudioheader->mmXWAVHeader.WAVEHeader.usBlockAlign= mmaudioheader->mmXWAVHeader.WAVEHeader.usChannels * mmaudioheader->mmXWAVHeader.WAVEHeader.usBitsPerSample / 8; mmaudioheader->mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInMS= (unsigned long)(ov_time_total(oggfile, -1)*1000.0); mmaudioheader->mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes= (unsigned long)ov_pcm_total(oggfile, -1)* mmaudioheader->mmXWAVHeader.WAVEHeader.usBlockAlign; #ifdef DEBUG fprintf(file,"time: %ld size: %ld rate: %ld\n", mmaudioheader->mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInMS, mmaudioheader->mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes, mmaudioheader->mmXWAVHeader.WAVEHeader.ulSamplesPerSec); #endif if (0 != decInfo->vorbisOptions && VORBIS_COOKIE == decInfo->vorbisOptions->cookie) { decInfo->vorbisOptions->nominal_bitrate = ov_bitrate(oggfile, -1); mmaudioheader->mmXWAVHeader.XWAVHeaderInfo.pAdditionalInformation = decInfo->vorbisOptions; } return (sizeof (MMAUDIOHEADER)); } break; case MMIOM_SETHEADER: { EncInfo *encInfo; PMMAUDIOHEADER mmaudioheader; int totalout = 0; int rc; if (!pmmioinfo || !pmmioinfo->pExtraInfoStruct) return 0; encInfo = (EncInfo*)pmmioinfo->pExtraInfoStruct; if (WRITENUM != encInfo->t) return 0; #ifdef DEBUG fprintf(file,"write header: %x, %x, %x\n",!(pmmioinfo->ulFlags & MMIO_WRITE), encInfo->headerSet, (!(pmmioinfo->ulTranslate & MMIO_TRANSLATEHEADER) && !(pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA))); fprintf(file,"flag: %x, trans: %x\n",pmmioinfo->ulFlags,pmmioinfo->ulTranslate); #endif if (/*!(pmmioinfo->ulFlags & MMIO_WRITE) ||*/ encInfo->headerSet || (!(pmmioinfo->ulTranslate & MMIO_TRANSLATEHEADER) && !(pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA))) return 0; if (!lParam1) { pmmioinfo->ulErrorRet = MMIOERR_INVALID_STRUCTURE; return 0; } mmaudioheader = (PMMAUDIOHEADER)lParam1; if (lParam2 != sizeof(MMAUDIOHEADER)) { pmmioinfo->ulErrorRet = MMIOERR_INVALID_BUFFER_LENGTH; return 0; } /********** Encode setup ************/ if (0 != mmaudioheader->mmXWAVHeader.WAVEHeader.usBitsPerSample%8) { /* Bit-rate must be multiple of 8 */ return 0; } encInfo->bitsPerSample=mmaudioheader->mmXWAVHeader.WAVEHeader.usBitsPerSample; #ifdef DEBUG fprintf(file,"ready to write header: "); #endif vorbis_info_init(&encInfo->vi); if (0 == encInfo->vorbisOptions || VORBIS_COOKIE != encInfo->vorbisOptions->cookie) { #ifdef DEBUG fprintf(file,"default quality 0.3\n"); #endif rc = vorbis_encode_init_vbr(&encInfo->vi, mmaudioheader->mmXWAVHeader.WAVEHeader.usChannels, mmaudioheader->mmXWAVHeader.WAVEHeader.ulSamplesPerSec, 0.3); } else { #ifdef DEBUG fprintf(file,"bitsPerSample: %d channels: %d samplesPerSec: %ld min: %ld nominal: %ld max: %ld\n", encInfo->bitsPerSample, mmaudioheader->mmXWAVHeader.WAVEHeader.usChannels, mmaudioheader->mmXWAVHeader.WAVEHeader.ulSamplesPerSec, encInfo->vorbisOptions->max_bitrate, encInfo->vorbisOptions->nominal_bitrate, encInfo->vorbisOptions->min_bitrate); #endif rc = vorbis_encode_init(&encInfo->vi, mmaudioheader->mmXWAVHeader.WAVEHeader.usChannels, mmaudioheader->mmXWAVHeader.WAVEHeader.ulSamplesPerSec, encInfo->vorbisOptions->max_bitrate, encInfo->vorbisOptions->nominal_bitrate, encInfo->vorbisOptions->min_bitrate); } if (rc) { #ifdef DEBUG fprintf(file,"encodeInit failed: %d\n",rc); #endif return 0; } /* endif */ /* add a comment */ vorbis_comment_init(&encInfo->vc); vorbis_comment_add_tag(&encInfo->vc,"ENCODER","mmioVorbis"); /* set up the analysis state and auxiliary encoding storage */ vorbis_analysis_init(&encInfo->vd,&encInfo->vi); vorbis_block_init(&encInfo->vd,&encInfo->vb); /* set up our packet->stream encoder */ /* pick a random serial number; that way we can more likely build chained streams just by concatenation */ srand(time(NULL)); ogg_stream_init(&encInfo->os,rand()); { ogg_packet header; ogg_packet header_comm; ogg_packet header_code; vorbis_analysis_headerout(&encInfo->vd,&encInfo->vc,&header,&header_comm,&header_code); ogg_stream_packetin(&encInfo->os,&header); /* automatically placed in its own page */ ogg_stream_packetin(&encInfo->os,&header_comm); ogg_stream_packetin(&encInfo->os,&header_code); while(1){ int result=ogg_stream_flush(&encInfo->os,&encInfo->og); if(result==0)break; result = mmioWrite(encInfo->hmmioSS, encInfo->og.header,encInfo->og.header_len); totalout += result; if (result!=encInfo->og.header_len) { ogg_stream_clear(&encInfo->os); vorbis_block_clear(&encInfo->vb); vorbis_dsp_clear(&encInfo->vd); vorbis_comment_clear(&encInfo->vc); vorbis_info_clear(&encInfo->vi); return 0; } result = mmioWrite(encInfo->hmmioSS, encInfo->og.body,encInfo->og.body_len); totalout += result; if (result!=encInfo->og.body_len) { ogg_stream_clear(&encInfo->os); vorbis_block_clear(&encInfo->vb); vorbis_dsp_clear(&encInfo->vd); vorbis_comment_clear(&encInfo->vc); vorbis_info_clear(&encInfo->vi); return 0; } } } encInfo->headerSet = 1; return totalout; } break; case MMIOM_WRITE: { EncInfo *encInfo; if (!pmmioinfo || !pmmioinfo->pExtraInfoStruct) return MMIO_ERROR; encInfo = (EncInfo*)pmmioinfo->pExtraInfoStruct; if (WRITENUM != encInfo->t) return MMIO_ERROR; if (!encInfo->headerSet) return MMIO_ERROR; if (!(pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA)) { if (!lParam1) return MMIO_ERROR; return mmioWrite(encInfo->hmmioSS, (PVOID)lParam1, lParam2); } else { if (lParam2 == 0) { vorbis_analysis_wrote(&encInfo->vd,0); } else { long i; int j, k; int num; float denom = 1; signed char *readbuffer = (char *)lParam1; /* data to encode */ /* expose the buffer to submit data */ int sampleSize = encInfo->vi.channels*encInfo->bitsPerSample/8; int samples = lParam2/sampleSize; float **buffer=vorbis_analysis_buffer(&encInfo->vd, samples); #ifdef DEBUG fprintf(file,"write: %ld\n",lParam2); #endif /* :TODO: Work with buffers not a multiple of sampleSize*/ if (lParam2 % sampleSize != 0) { #ifdef DEBUG fprintf(file,"Bad Write Buffer Size\n"); #endif return MMIO_ERROR; } for(i=0;i<samples;i++){ for (j=0;j<encInfo->vi.channels;j++) { num=0; denom=0.5; if (encInfo->bitsPerSample<=8) { buffer[j][i]=(float)((unsigned char)(readbuffer[i*sampleSize])- (1<<(encInfo->bitsPerSample-1)))/ (float)(1<<(encInfo->bitsPerSample-1)); } else { for (k=encInfo->bitsPerSample/8;k>0;k--) { if (k==encInfo->bitsPerSample/8) { num=(readbuffer[i*sampleSize+k-1]); } else { num=(num<<8)|((0xff)&(int)(readbuffer[i*sampleSize+k-1])); } denom *= 256.0; } buffer[j][i]=((float)num)/denom; } } /* endfor */ } vorbis_analysis_wrote(&encInfo->vd,i); } /* endif */ if (oggWrite(encInfo,0)>=0) { return lParam2; } else { return MMIO_ERROR; } /* endif */ } } break; #ifdef DEBUG case MMIOM_TEMPCHANGE: { return MMIO_SUCCESS; } break; #endif } #ifdef DEBUG fprintf(file,"unexpected command: %x\n",usMsg); #endif return MMIOERR_UNSUPPORTED_MESSAGE; }