void getOggData(float **dst,int num_frames){ float **sound; long read=ov_read_float(&oggvorbisfile,&sound,num_frames,¤t_oggsection); if(read==0){ ov_pcm_seek(&oggvorbisfile,0); read=ov_read_float(&oggvorbisfile,&sound,num_frames,¤t_oggsection); } memcpy(dst[0],sound[0],read*sizeof(float)); memcpy(dst[1],sound[1],read*sizeof(float)); if(read<num_frames){ float *newdst[2]={dst[0]+read,dst[1]+read}; getOggData(newdst,num_frames-read); } }
size_t SourceFileOggVorbis::performRead( Buffer *buffer, size_t bufferFrameOffset, size_t numFramesNeeded ) { CI_ASSERT( buffer->getNumFrames() >= bufferFrameOffset + numFramesNeeded ); size_t readCount = 0; while( readCount < numFramesNeeded ) { float **outChannels; int section; long outNumFrames = ov_read_float( &mOggVorbisFile, &outChannels, int( numFramesNeeded - readCount ), §ion ); if( outNumFrames <= 0 ) { if( outNumFrames < 0 ) throw AudioFileExc( "ov_read_float error", (int32_t)outNumFrames ); break; } size_t offset = bufferFrameOffset + readCount; for( size_t ch = 0; ch < mNumChannels; ch++ ) memcpy( buffer->getChannel( ch ) + offset, outChannels[ch], outNumFrames * sizeof( float ) ); readCount += outNumFrames; } return static_cast<size_t>( readCount ); }
void OGGDecoder::reader() { float **pcm; long ret=1; int bit; size_t j,done=0; while (ATOMIC_CAS(&owner->work,true,true) && ret > 0 ){ j=0; ret=1; done=0; while (done<VPBUFFER_FRAMES && ret > 0){ ret = ov_read_float( &vf, &pcm, VPBUFFER_FRAMES - done,&bit ); for (long i=0;i<ret;i++){ for (size_t ch=0;ch<bout->chans;ch++){ buffer[j]=pcm[ch][i]; j++; } } done+=ret; } memcpy(bout->buffer[*bout->cursor], buffer, VPBUFFER_FRAMES*bout->chans*sizeof(float) ); owner->postProcess(bout->buffer[*bout->cursor]); owner->mutex[0].lock(); VP_SWAP_BUFFERS(bout); owner->mutex[1].unlock(); } }
Int64 OggAudioSource::decodeData(float* buffer, UInt32 numFrames) { RScopedLock l(&mDecodeLock); int bitStream; float** data = 0; long framesRead = ov_read_float(&mOggFile, &data, numFrames, &bitStream); if(framesRead > 0) { for(int i = 0; i < getNumChannels(); ++i) { int channels = getNumChannels(); float *pTemp = &buffer[i]; for(int j = 0; j < framesRead; ++j) { *pTemp = data[i][j]; pTemp += channels; } } } else mEOF = true; return framesRead; }
void OggVorbisMusic::processAudio(void *outputBuffer, unsigned int nBufferFrames, double, RtAudioStreamStatus) { int requestSize = nBufferFrames; int startOffset = 0; float* out = (float*)outputBuffer; while (requestSize > 0) { float** ov_buffers; int currentBitstream; int readed = ov_read_float(&vorbisFile, &ov_buffers, requestSize, ¤tBitstream); if (readed < 0) { handleOVError(readed); break; } jassert(readed <= requestSize); // wrongly understand the documentation vorbis_info *vi = ov_info(&vorbisFile, -1); for (int c = 0; c < vi->channels; ++c) { for (int s = 0; s < readed; ++s) { out[startOffset + s * vi->channels + c] = ov_buffers[c][s] * 0.5f; } } startOffset += readed * vi->channels; requestSize -= readed; } }
SINT SoundSourceOggVorbis::readSampleFrames( SINT numberOfFrames, CSAMPLE* sampleBuffer, SINT sampleBufferSize, bool readStereoSamples) { DEBUG_ASSERT(isValidFrameIndex(m_curFrameIndex)); DEBUG_ASSERT(getSampleBufferSize(numberOfFrames, readStereoSamples) <= sampleBufferSize); const SINT numberOfFramesTotal = math_min( numberOfFrames, getMaxFrameIndex() - m_curFrameIndex); CSAMPLE* pSampleBuffer = sampleBuffer; SINT numberOfFramesRemaining = numberOfFramesTotal; while (0 < numberOfFramesRemaining) { float** pcmChannels; int currentSection; // Use 'long' here, because ov_read_float() returns this type. // This is an exception from the rule not to any types with // differing sizes on different platforms. // https://bugs.launchpad.net/mixxx/+bug/1094143 const long readResult = ov_read_float(&m_vf, &pcmChannels, numberOfFramesRemaining, ¤tSection); if (0 < readResult) { m_curFrameIndex += readResult; if (kChannelCountMono == getChannelCount()) { if (readStereoSamples) { for (long i = 0; i < readResult; ++i) { *pSampleBuffer++ = pcmChannels[0][i]; *pSampleBuffer++ = pcmChannels[0][i]; } } else { for (long i = 0; i < readResult; ++i) { *pSampleBuffer++ = pcmChannels[0][i]; } } } else if (readStereoSamples || (kChannelCountStereo == getChannelCount())) { for (long i = 0; i < readResult; ++i) { *pSampleBuffer++ = pcmChannels[0][i]; *pSampleBuffer++ = pcmChannels[1][i]; } } else { for (long i = 0; i < readResult; ++i) { for (SINT j = 0; j < getChannelCount(); ++j) { *pSampleBuffer++ = pcmChannels[j][i]; } } } numberOfFramesRemaining -= readResult; } else { qWarning() << "Failed to read from OggVorbis file:" << readResult; break; // abort } } DEBUG_ASSERT(isValidFrameIndex(m_curFrameIndex)); DEBUG_ASSERT(numberOfFramesTotal >= numberOfFramesRemaining); return numberOfFramesTotal - numberOfFramesRemaining; }
unsigned int oggDecoder::decode( float*** data, int count ) { int ret = -1; while( ret < 0) { ret = ov_read_float( decoder, data, count, ¤t_section); if(ret == OV_HOLE) qWarning("Hole in ogg datastream detected.. skipping..."); } return ret; }
int FileVorbis::read_samples(double *buffer, int64_t len) { if(!fd) return 0; // printf("FileVorbis::read_samples 1 %d %d %d %d\n", // history_start, // history_size, // file->current_sample, // len); float **vorbis_output; int bitstream; int accumulation = 0; update_pcm_history(len); // Fill history buffer if(decode_start != decode_end) { ov_pcm_seek(&vf, decode_start); decode_end = decode_start; } while(accumulation < decode_len) { int result = ov_read_float(&vf, &vorbis_output, decode_len - accumulation, &bitstream); //printf("FileVorbis::read_samples 1 %d %d %d\n", result, len, accumulation); if(!result) break; append_history(vorbis_output, result); accumulation += result; } read_history(buffer, file->current_sample, file->current_channel, len); // printf("FileVorbis::read_samples 2 %d %d %d %d\n", // history_start, // history_size, // file->current_sample, // len); return 0; }
static int oggread_decode_input(t_oggread *x) { long ret; /* bytes per channel returned by decoder */ int i; float **pcm; x->x_vi = ov_info(&x->x_ov, x->x_current_section); while(!x->x_eos) { ret = ov_read_float(&x->x_ov, &pcm, READ, &x->x_current_section); if (ret == 0) { /* EOF */ x->x_eos = 1; x->x_stream = 0; clock_unset(x->x_clock); // post("oggread~: end of file detected, stopping"); outlet_bang(x->x_out_end); } else if (ret < 0) { /* error in the stream. Not a problem, just reporting it in case we (the app) cares. In this case, we don't. */ } else { /* we don't bother dealing with sample rate changes, etc, but you'll have to */ long j; for(j = 0; j < ret; j++) { for(i = 0; i < x->x_vi->channels; i++) { x->x_outbuffer[x->x_outwriteposition] = pcm[i][j]; x->x_outwriteposition = (x->x_outwriteposition + 1)%x->x_outbuffersize; } } x->x_outunread += (t_int)ret * x->x_vi->channels; } break; } x->x_decoded = (t_int)ret * x->x_vi->channels; /* num. of samples we got from decoder */ x->x_position = (t_float)ov_time_tell(&x->x_ov); /* exit decoding 'loop' here, we'll get called again by perform() */ return 1; }
static void read_packet (VorbisHandle *vhandle) { gfloat **pcm = NULL; gint stream_id, i; vhandle->pcm_pos = ov_pcm_tell (&vhandle->ofile) - vhandle->soffset; vhandle->pcm_length = ov_read_float (&vhandle->ofile, &pcm, G_MAXINT, &stream_id); if (vhandle->pcm_pos < 0 || vhandle->pcm_length < 0 || stream_id != vhandle->bitstream) { /* urg, this is bad! */ dh_vorbis_coarse_seek (&vhandle->dhandle, 0); } else for (i = 0; i < vhandle->dhandle.setup.n_channels; i++) vhandle->pcm[i] = pcm[i]; }
void WaveView::setAudio(Audio* audio) { waves.clear(); OggVorbis_File vf; vorbisData.pos = 0; vorbisData.data = audio->data(); int rv = ov_open_callbacks(&vorbisData, &vf, 0, 0, ovCallbacks); if (rv < 0) { qDebug("ogg open failed: %d", rv); return; } int rn = 0; const int n = 10000 / WSCALE; uchar dst[n]; float* r = 0; float* l = 0; for (;;) { for (int i = 0; i < n; ++i) { float val = 0; for (int k = 0; k < WSCALE; ++k) { if (rn == 0) { float** pcm; int section; rn = ov_read_float(&vf, &pcm, 1000, §ion); if (rn == 0) { for (; i < n; ++i) dst[i] = 0; waves.append((char*)dst, n); ov_clear(&vf); return; } r = pcm[0]; l = pcm[1]; } val += fabsf(*r++) + fabsf(*l++); --rn; } unsigned int v = lrint(val * 128); if (v > 255) v = 255; dst[i] = v; } waves.append((char*)dst, n); } }
// Returns samples (1 sample contains data from all channels) long OggStream::read(float* buffer, int bytes) { float **pcm; long samples_read = ov_read_float(&mStream, &pcm, bytes, &mSection); switch(samples_read) { case OV_HOLE: LOG4CXX_WARN(narratorOsLog, "Interruption in data while playing " << mStreamInfo); break; case OV_EBADLINK: LOG4CXX_WARN(narratorOsLog, "Invalid stream section was supplied while playing " << mStreamInfo); break; } //Convert the samples to a linear vector float *bufptr = buffer; for (long i = 0; i < samples_read; i++) for(int c = 0; c < mChannels; c++) *bufptr++ = pcm[c][i]; return (samples_read)/mChannels; }
gc_int32 gauX_sample_source_ogg_read(void* in_context, void* in_dst, gc_int32 in_numSamples, tOnSeekFunc in_onSeekFunc, void* in_seekContext) { gau_SampleSourceOggContext* ctx = &((gau_SampleSourceOgg*)in_context)->context; gc_int32 samplesLeft = in_numSamples; gc_int32 samplesRead; gc_int32 channels = ctx->oggInfo->channels; gc_int32 totalSamples = 0; size_t dataSizeOff = 0; do{ gc_int32 bitStream; gc_float32** samples; gc_int32 i; gc_int16* dst; gc_int32 channel; gc_mutex_lock(ctx->oggMutex); samplesRead = ov_read_float(&ctx->oggFile, &samples, samplesLeft, &bitStream); if(samplesRead == 0) ctx->endOfSamples = 1; gc_mutex_unlock(ctx->oggMutex); if(samplesRead > 0) { samplesLeft -= samplesRead; dst = (gc_int16*)(in_dst) + totalSamples * channels; totalSamples += samplesRead; for(i = 0; i < samplesRead; ++i) { for(channel = 0; channel < channels; ++channel, ++dst) { gc_float32 sample = samples[channel][i] * 32768.0f; gc_int32 int32Sample = (gc_int32)sample; gc_int16 int16Sample; int32Sample = int32Sample > 32767 ? 32767 : int32Sample < -32768 ? -32768 : int32Sample; int16Sample = (gc_int16)int32Sample; *dst = int16Sample; } } } } while (samplesRead > 0 && samplesLeft); return totalSamples; }
void OGGDecoder::reader() { float **pcm; long ret=1; int bit; size_t j,done=0; while (ATOMIC_CAS(&owner->work,true,true) && ret > 0 ){ j=0; ret=1; done=0; if (ATOMIC_CAS(&seek_to,SEEK_MAX,SEEK_MAX) != SEEK_MAX ){ if (ov_seekable(&vf)) ov_pcm_seek(&vf,(ogg_int64_t) seek_to); seek_to = SEEK_MAX; } while (done<VPBUFFER_FRAMES && ret > 0){ ret = ov_read_float( &vf, &pcm, VPBUFFER_FRAMES - done,&bit ); for (long i=0;i<ret;i++){ for (size_t ch=0;ch<bout->chans;ch++){ buffer[j]=(float)pcm[ch][i]; j++; } } done+=ret; } int samples= done*bout->chans; memcpy(bout->currentBuffer(), buffer,samples*sizeof(float) ); for (int i=samples;i<VPBUFFER_FRAMES*bout->chans;i++){ bout->currentBuffer()[i]=0.0f; } owner->postProcess(); owner->mutex[0].lock(); VP_SWAP_BUFFERS(bout); owner->mutex[1].unlock(); } }
void VorbisFileReader::fillBuffer() { buffer_start_time = ov_time_tell(&vf); if (buffer_start_time < 0) { state = sError; throwVorbisError((int)buffer_start_time, L"fillBuffer (1)"); } int ret = ov_read_float(&vf, &buffer, buffer_size_request, ¤t_section); if (ret < 0) { state = sError; throwVorbisError(ret, L"fillBuffer (2)"); } else if (ret >= 0) { cursor_position_in_buffer = 0; buffer_actual_size = ret; } }
int RageSoundReader_Vorbisfile::Read( float *buf, int iFrames ) { int frames_read = 0; while( iFrames && !eof ) { const int bytes_per_frame = sizeof(float)*channels; int iFramesRead = 0; { int curofs = (int) ov_pcm_tell(vf); if( curofs < read_offset ) { /* The timestamps moved backwards. Ignore it. This file probably * won't sync correctly. */ LOG->Trace( "p ahead %p %i < %i, we're ahead by %i", this, curofs, read_offset, read_offset-curofs ); read_offset = curofs; } else if( curofs > read_offset ) { /* Our offset doesn't match. We have a hole in the data, or corruption. * If we're reading with accurate syncing, insert silence to line it up. * That way, corruptions in the file won't casue desyncs. */ /* In bytes: */ int iSilentFrames = curofs - read_offset; iSilentFrames = min( iSilentFrames, (int) iFrames ); int silence = iSilentFrames * bytes_per_frame; CHECKPOINT_M( ssprintf("p %i,%i: %i frames of silence needed", curofs, read_offset, silence) ); memset( buf, 0, silence ); iFramesRead = iSilentFrames; } } if( iFramesRead == 0 ) { int bstream; #if defined(INTEGER_VORBIS) int ret = ov_read( vf, (char *) buf, iFrames * channels * sizeof(int16_t), &bstream ); #else // float vorbis decoder float **pcm; int ret = ov_read_float( vf, &pcm, iFrames, &bstream ); #endif { vorbis_info *vi = ov_info( vf, -1 ); ASSERT( vi != NULL ); if( (unsigned) vi->channels != channels ) RageException::Throw( "File \"%s\" changes channel count from %i to %i; not supported.", filename.c_str(), channels, (int)vi->channels ); } if( ret == OV_HOLE ) continue; if( ret == OV_EBADLINK ) { SetError( ssprintf("Read: OV_EBADLINK") ); return ERROR; } if( ret == 0 ) { eof = true; continue; } #if defined(INTEGER_VORBIS) if( ret > 0 ) { int iSamplesRead = ret / sizeof(int16_t); iFramesRead = iSamplesRead / channels; /* Convert in reverse, so we can do it in-place. */ const int16_t *pIn = (int16_t *) buf; float *pOut = (float *) buf; for( int i = iSamplesRead-1; i >= 0; --i ) pOut[i] = pIn[i] / 32768.0f; } #else if( ret > 0 ) { iFramesRead = ret; int iNumChannels = channels; for( int iChannel = 0; iChannel < iNumChannels; ++iChannel ) { const float *pChannelIn = pcm[iChannel]; float *pChannelOut = &buf[iChannel]; for( int i = 0; i < iFramesRead; ++i ) { *pChannelOut = *pChannelIn; ++pChannelIn; pChannelOut += iNumChannels; } } } #endif } read_offset += iFramesRead; buf += iFramesRead * channels; frames_read += iFramesRead; iFrames -= iFramesRead; } if( !frames_read ) return END_OF_FILE; return frames_read; }
static prMALError SDKImportAudio7( imStdParms *stdParms, imFileRef SDKfileRef, imImportAudioRec7 *audioRec7) { prMALError result = malNoError; // privateData ImporterLocalRec8H ldataH = reinterpret_cast<ImporterLocalRec8H>(audioRec7->privateData); stdParms->piSuites->memFuncs->lockHandle(reinterpret_cast<char**>(ldataH)); ImporterLocalRec8Ptr localRecP = reinterpret_cast<ImporterLocalRec8Ptr>( *ldataH ); if(localRecP) { assert(audioRec7->position >= 0); // Do they really want contiguous samples? // for surround channels // Premiere uses Left, Right, Left Rear, Right Rear, Center, LFE // Ogg (and Opus) uses Left, Center, Right, Left Read, Right Rear, LFE // http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-800004.3.9 static const int surround_swizzle[] = {0, 2, 3, 4, 1, 5}; static const int stereo_swizzle[] = {0, 1, 2, 3, 4, 5}; // no swizzle, actually const int *swizzle = localRecP->numChannels > 2 ? surround_swizzle : stereo_swizzle; if(localRecP->fileType == Ogg_filetype && localRecP->vf != NULL) { OggVorbis_File &vf = *localRecP->vf; int seek_err = OV_OK; if(audioRec7->position >= 0) // otherwise contiguous, but we should be good at the current position seek_err = ov_pcm_seek(&vf, audioRec7->position); if(seek_err == OV_OK) { int num = 0; float **pcm_channels; long samples_needed = audioRec7->size; long pos = 0; while(samples_needed > 0 && result == malNoError) { int samples = samples_needed; if(samples > 1024) samples = 1024; // maximum size this call can read at once long samples_read = ov_read_float(&vf, &pcm_channels, samples, &num); if(samples_read >= 0) { if(samples_read == 0) { // EOF // Premiere will keep asking me for more and more samples, // even beyond what I told it I had in SDKFileInfo8->audDuration. // Just stop and everything will be fine. break; } for(int i=0; i < localRecP->numChannels; i++) { memcpy(&audioRec7->buffer[swizzle[i]][pos], pcm_channels[i], samples_read * sizeof(float)); } samples_needed -= samples_read; pos += samples_read; } else result = imDecompressionError; } } } else if(localRecP->fileType == Opus_filetype && localRecP->opus != NULL) { const int num_channels = op_channel_count(localRecP->opus, -1); assert(localRecP->numChannels == num_channels); int seek_err = OV_OK; if(audioRec7->position >= 0) // otherwise contiguous, but we should be good at the current position seek_err = op_pcm_seek(localRecP->opus, audioRec7->position); if(seek_err == OV_OK) { float *pcm_buf = (float *)malloc(sizeof(float) * audioRec7->size * num_channels); if(pcm_buf != NULL) { long samples_needed = audioRec7->size; long pos = 0; while(samples_needed > 0 && result == malNoError) { float *_pcm = &pcm_buf[pos * num_channels]; int samples_read = op_read_float(localRecP->opus, _pcm, samples_needed * num_channels, NULL); if(samples_read == 0) { // guess we're at the end of the stream break; } else if(samples_read < 0) { result = imDecompressionError; } else { for(int c=0; c < localRecP->numChannels; c++) { for(int i=0; i < samples_read; i++) { audioRec7->buffer[swizzle[c]][pos + i] = _pcm[(i * num_channels) + c]; } } samples_needed -= samples_read; pos += samples_read; } } free(pcm_buf); } } } else if(localRecP->fileType == FLAC_filetype && localRecP->flac != NULL) { try { //localRecP->flac->reset(); assert(audioRec7->position >= 0); // not handling Premiere's continuous reads assert(localRecP->flac->get_channels() == localRecP->numChannels); long samples_needed = audioRec7->size; localRecP->flac->set_buffers(audioRec7->buffer, samples_needed, audioRec7->position); // Calling seek will cause flac to "write" some audio, of course! bool sought = localRecP->flac->seek_absolute(audioRec7->position); bool eof = false; size_t buffer_position = 0; if(sought) { do{ size_t new_buffer_position = localRecP->flac->get_pos(); int samples_read = (new_buffer_position - buffer_position); if(samples_read > 0) { samples_needed -= samples_read; } else eof = true; buffer_position = new_buffer_position; if(samples_needed > 0 && !eof) { bool processed = localRecP->flac->process_single(); if(!processed) samples_needed = 0; } }while(samples_needed > 0 && !eof); } localRecP->flac->set_buffers(NULL, 0, 0); // don't trust libflac not to write at inopportune times } catch(...) { result = imDecompressionError; } } } stdParms->piSuites->memFuncs->unlockHandle(reinterpret_cast<char**>(ldataH)); assert(result == malNoError); return result; }
static PyObject* VorbisDecoder_read(decoders_VorbisDecoder *self, PyObject *args) { int current_bitstream; long samples_read; float **pcm_channels; if (self->closed) { PyErr_SetString(PyExc_ValueError, "stream is closed"); return NULL; } samples_read = ov_read_float(&(self->vorbisfile), &pcm_channels, 4096, ¤t_bitstream); if (samples_read >= 0) { /*convert floating point samples to integer-based ones*/ pcm_FrameList *framelist; int *samples; int c; if (samples_read == 0) { if (self->vorbisfile.os.e_o_s == 0) { /*EOF encountered without EOF being marked in stream*/ PyErr_SetString(PyExc_IOError, "I/O error reading from Ogg stream"); return NULL; } else { return empty_FrameList(self->audiotools_pcm, self->channel_count, BITS_PER_SAMPLE); } } framelist = new_FrameList(self->audiotools_pcm, self->channel_count, BITS_PER_SAMPLE, (unsigned)samples_read); samples = framelist->samples; for (c = 0; c < self->channel_count; c++) { int channel[samples_read]; float_to_int_converter(BITS_PER_SAMPLE)( (unsigned)samples_read, pcm_channels[c], channel); put_channel_data(samples, c, self->channel_count, (unsigned)samples_read, channel); } /*reorder channels to .wav order if necessary*/ switch (self->channel_count) { case 1: case 2: default: /*no change*/ break; case 3: /*fL fC fR -> fL fR fC*/ swap_channel_data(samples, 1, 2, self->channel_count, (unsigned)samples_read); break; case 4: /*fL fR bL bR -> fL fR bL bR*/ /*no change*/ break; case 5: /*fL fC fR bL bR -> fL fR fC bL bR*/ swap_channel_data(samples, 1, 2, self->channel_count, (unsigned)samples_read); break; case 6: /*fL fC fR bL bR LFE -> fL fR fC bL bR LFE*/ swap_channel_data(samples, 1, 2, self->channel_count, (unsigned)samples_read); /*fL fR fC bL bR LFE -> fL fR fC LFE bR bL*/ swap_channel_data(samples, 3, 5, self->channel_count, (unsigned)samples_read); /*fL fR fC LFE bR bL -> fL fR fC LFE bL bR*/ swap_channel_data(samples, 4, 5, self->channel_count, (unsigned)samples_read); break; case 7: /*fL fC fR sL sR bC LFE -> fL fR fC sL sR bC LFE*/ swap_channel_data(samples, 1, 2, self->channel_count, (unsigned)samples_read); /*fL fR fC sL sR bC LFE -> fL fR fC LFE sR bC sL*/ swap_channel_data(samples, 3, 6, self->channel_count, (unsigned)samples_read); /*fL fR fC LFE sR bC sL -> fL fR fC LFE bC sR sL*/ swap_channel_data(samples, 4, 5, self->channel_count, (unsigned)samples_read); /*fL fR fC LFE bC sR sL -> fL fR fC LFE bC sL sR*/ swap_channel_data(samples, 5, 6, self->channel_count, (unsigned)samples_read); break; case 8: /*fL fC fR sL sR bL bR LFE -> fL fR fC sL sR bL bR LFE*/ swap_channel_data(samples, 1, 2, self->channel_count, (unsigned)samples_read); /*fL fR fC sL sR bL bR LFE -> fL fR fC LFE sR bL bR sL*/ swap_channel_data(samples, 3, 6, self->channel_count, (unsigned)samples_read); /*fL fR fC LFE sR bL bR sL -> fL fR fC LFE bL sR bR sL*/ swap_channel_data(samples, 4, 5, self->channel_count, (unsigned)samples_read); /*fL fR fC LFE bL sR bR sL -> fL fR fC LFE bL bR sR sL*/ swap_channel_data(samples, 5, 6, self->channel_count, (unsigned)samples_read); /*fL fR fC LFE bL bR sR sL -> fL fR fC LFE bL bR sL sR*/ swap_channel_data(samples, 6, 7, self->channel_count, (unsigned)samples_read); break; } return (PyObject*)framelist; } else { switch (samples_read) { case OV_HOLE: PyErr_SetString(PyExc_ValueError, "data interruption detected"); return NULL; case OV_EBADLINK: PyErr_SetString(PyExc_ValueError, "invalid stream section"); return NULL; case OV_EINVAL: PyErr_SetString(PyExc_ValueError, "initial file headers corrupt"); return NULL; default: PyErr_SetString(PyExc_ValueError, "unspecified error"); return NULL; } } }
int FileVorbis::read_samples_float(float *buffer, int64_t len) { if(!fd) return 0; // printf("FileVorbis::read_samples 1 %d %d %d %d\n", // history_start, // history_size, // file->current_sample, // len); float **vorbis_output; int bitstream; int accumulation = 0; //printf("FileVorbis::read_samples 1\n"); int decode_start = 0; int decode_len = 0; if(len > 0x100000) { eprintf("FileVorbis::read_samples max samples=%d\n", HISTORY_MAX); return 1; } if(!pcm_history_float) { pcm_history_float = new float*[asset->channels]; for(int i = 0; i < asset->channels; i++) pcm_history_float[i] = new float[HISTORY_MAX]; history_start = 0; history_size = 0; } // Restart history. Don't bother shifting history back. if(file->current_sample < history_start || file->current_sample > history_start + history_size) { history_size = 0; history_start = file->current_sample; decode_start = file->current_sample; decode_len = len; } else // Shift history forward to make room for new samples if(file->current_sample + len > history_start + history_size) { if(file->current_sample + len > history_start + HISTORY_MAX) { int diff = file->current_sample + len - (history_start + HISTORY_MAX); for(int i = 0; i < asset->channels; i++) { float *temp = pcm_history_float[i]; // for(int j = 0; j < HISTORY_MAX - diff; j++) // { // temp[j] = temp[j + diff]; // } bcopy(temp, temp + diff, (HISTORY_MAX - diff) * sizeof(float)); } history_start += diff; history_size -= diff; } // Decode more data decode_start = history_start + history_size; decode_len = file->current_sample + len - (history_start + history_size); } // Fill history buffer if(history_start + history_size != ov_pcm_tell(&vf)) { //printf("FileVorbis::read_samples %d %d\n", history_start + history_size, ov_pcm_tell(&vf)); ov_pcm_seek(&vf, history_start + history_size); } while(accumulation < decode_len) { int result = ov_read_float(&vf, &vorbis_output, decode_len - accumulation, &bitstream); //printf("FileVorbis::read_samples 1 %d %d %d\n", result, len, accumulation); if(!result) break; for(int i = 0; i < asset->channels; i++) { float *output = pcm_history_float[i] + history_size; float *input = vorbis_output[i]; // for(int j = 0; j < result; j++) // output[j] = input[j]; bcopy(input, output, result * sizeof(float)); } history_size += result; accumulation += result; } // printf("FileVorbis::read_samples 1 %d %d\n", // file->current_sample, // history_start); float *input = pcm_history_float[file->current_channel] + file->current_sample - history_start; // for(int i = 0; i < len; i++) // buffer[i] = input[i]; bcopy(input, buffer, len * sizeof(float)); // printf("FileVorbis::read_samples 2 %d %d %d %d\n", // history_start, // history_size, // file->current_sample, // len); return 0; }
static gboolean vorbis_play (const gchar * filename, VFSFile * file) { if (file == NULL) return FALSE; vorbis_info *vi; OggVorbis_File vf; gint last_section = -1; ReplayGainInfo rg_info; gfloat pcmout[PCM_BUFSIZE*sizeof(float)], **pcm; gint bytes, channels, samplerate, br; gchar * title = NULL; memset(&vf, 0, sizeof(vf)); gboolean error = FALSE; if (ov_open_callbacks (file, & vf, NULL, 0, vfs_is_streaming (file) ? vorbis_callbacks_stream : vorbis_callbacks) < 0) { error = TRUE; goto play_cleanup; } vi = ov_info(&vf, -1); if (vi->channels > 2) goto play_cleanup; br = vi->bitrate_nominal; channels = vi->channels; samplerate = vi->rate; aud_input_set_bitrate (br); if (!aud_input_open_audio(FMT_FLOAT, samplerate, channels)) { error = TRUE; goto play_cleanup; } vorbis_update_replaygain(&vf, &rg_info); aud_input_set_gain (& rg_info); /* * Note that chaining changes things here; A vorbis file may * be a mix of different channels, bitrates and sample rates. * You can fetch the information for any section of the file * using the ov_ interface. */ while (! aud_input_check_stop ()) { int seek_value = aud_input_check_seek(); if (seek_value >= 0 && ov_time_seek (& vf, (double) seek_value / 1000) < 0) { fprintf (stderr, "vorbis: seek failed\n"); error = TRUE; break; } gint current_section = last_section; bytes = ov_read_float(&vf, &pcm, PCM_FRAMES, ¤t_section); if (bytes == OV_HOLE) continue; if (bytes <= 0) break; bytes = vorbis_interleave_buffer (pcm, bytes, channels, pcmout); { /* try to detect when metadata has changed */ vorbis_comment * comment = ov_comment (& vf, -1); const gchar * new_title = (comment == NULL) ? NULL : vorbis_comment_query (comment, "title", 0); if (new_title != NULL && (title == NULL || strcmp (title, new_title))) { g_free (title); title = g_strdup (new_title); aud_input_set_tuple (get_tuple_for_vorbisfile (& vf, filename)); } } if (current_section != last_section) { /* * The info struct is different in each section. vf * holds them all for the given bitstream. This * requests the current one */ vi = ov_info(&vf, -1); if (vi->channels > 2) goto stop_processing; if (vi->rate != samplerate || vi->channels != channels) { samplerate = vi->rate; channels = vi->channels; if (!aud_input_open_audio(FMT_FLOAT, vi->rate, vi->channels)) { error = TRUE; goto stop_processing; } vorbis_update_replaygain(&vf, &rg_info); aud_input_set_gain (& rg_info); /* audio reopened */ } } aud_input_write_audio (pcmout, bytes); stop_processing: if (current_section != last_section) { aud_input_set_bitrate (br); last_section = current_section; } } /* main loop */ play_cleanup: ov_clear(&vf); g_free (title); return ! error; }
/* 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); }
/* ==================== idSampleDecoderLocal::DecodeOGG ==================== */ int idSampleDecoderLocal::DecodeOGG( idSoundSample *sample, int sampleOffset44k, int sampleCount44k, float *dest ) { int readSamples, totalSamples; int shift = 22050 / sample->objectInfo.nSamplesPerSec; int sampleOffset = sampleOffset44k >> shift; int sampleCount = sampleCount44k >> shift; // open OGG file if not yet opened if ( lastSample == NULL ) { // make sure there is enough space for another decoder if ( decoderMemoryAllocator.GetFreeBlockMemory() < MIN_OGGVORBIS_MEMORY ) { return 0; } if ( sample->nonCacheData == NULL ) { assert( false ); // this should never happen failed = true; return 0; } file.SetData( (const char *)sample->nonCacheData, sample->objectMemSize ); if ( ov_openFile( &file, &ogg ) < 0 ) { failed = true; return 0; } lastFormat = WAVE_FORMAT_TAG_OGG; lastSample = sample; } // seek to the right offset if necessary if ( sampleOffset != lastSampleOffset ) { if ( ov_pcm_seek( &ogg, sampleOffset / sample->objectInfo.nChannels ) != 0 ) { failed = true; return 0; } } lastSampleOffset = sampleOffset; // decode OGG samples totalSamples = sampleCount; readSamples = 0; do { float **samples; int ret = ov_read_float( &ogg, &samples, totalSamples / sample->objectInfo.nChannels, &ogg.stream ); if ( ret == 0 ) { failed = true; break; } if ( ret < 0 ) { failed = true; return 0; } ret *= sample->objectInfo.nChannels; SIMDProcessor->UpSampleOGGTo44kHz( dest + ( readSamples << shift ), samples, ret, sample->objectInfo.nSamplesPerSec, sample->objectInfo.nChannels ); readSamples += ret; totalSamples -= ret; } while( totalSamples > 0 ); lastSampleOffset += readSamples; return ( readSamples << shift ); }
static int audiosourceogg_Read(struct audiosource* source, char* buffer, unsigned int bytes) { struct audiosourceogg_internaldata* idata = source->internaldata; if (idata->eof) { return -1; } // open up ogg file if we don't have one yet if (!idata->vorbisopened) { if (!audiosourceogg_InitOgg(source)) { idata->eof = 1; idata->returnerroroneof = 1; source->samplerate = -1; source->channels = -1; return -1; } vorbis_info* vi = ov_info(&idata->vorbisfile, -1); source->samplerate = vi->rate; source->channels = vi->channels; if (source->channels < 1 || source->channels > 2) { // incompatible channel count idata->eof = 1; idata->returnerroroneof = 1; source->samplerate = -1; source->channels = -1; ov_clear(&idata->vorbisfile); return -1; } idata->vorbisopened = 1; } // if no bytes were requested, don't do anything if (bytes == 0) { return 0; } // read bytes audiosourceogg_ReadUndecoded(idata); unsigned int byteswritten = 0; while (bytes > 0) { // see how much we want to decode now unsigned int decodeamount = bytes; if (decodeamount > sizeof(idata->decodedbuf) - idata->decodedbytes) { decodeamount = sizeof(idata->decodedbuf) - idata->decodedbytes; } // decode from encoded fetched bytes if (source->channels == 0) { // this is invalid idata->returnerroroneof = 1; idata->eof = 1; return -1; } unsigned int decodesamples = decodeamount/(source->channels * sizeof(float)); if (decodesamples > 0) { // because of possible divison rounding issues, // try one less sample. we will add more in the next check // if not all bytes requested are covered decodesamples--; } while ( decodesamples * (source->channels * sizeof(float)) < decodeamount && (decodesamples+1) * (source->channels * sizeof(float)) <= (sizeof(idata->decodedbuf) - idata->decodedbytes) ) { // make sure we cover all desired bytes even for half-sample requests or something decodesamples++; } while (!idata->vorbiseof && decodesamples > 0) { float **pcm; long ret = ov_read_float(&idata->vorbisfile, &pcm, decodesamples, &idata->vbitstream); if (ret < 0) { if (ret == OV_HOLE) { // a "jump" or temporary decoding problem - ignore this continue; } // some vorbis error we want to report idata->returnerroroneof = 1; idata->vorbiseof = 1; } else { if (ret > 0) { // success // We will walk through all bytes now: // (unavoidable since we need to interleave them) unsigned int i = 0; while (i < (unsigned int)ret) { unsigned int j = 0; while (j < source->channels) { memcpy(idata->decodedbuf + idata->decodedbytes, &pcm[j][i], sizeof(float)); idata->decodedbytes += sizeof(float); j++; } i++; } } else { // regular eof idata->vorbiseof = 1; } } break; } // check how much we want and can copy unsigned int amount = idata->decodedbytes; if (amount > bytes) { // never copy more than we want amount = bytes; } // vorbis end of file if (amount == 0) { if (byteswritten == 0) { idata->eof = 1; if (idata->returnerroroneof) { return -1; } return 0; } else { return byteswritten; } } // output bytes memcpy(buffer, idata->decodedbuf, amount); byteswritten += amount; buffer += amount; idata->decodedbytes -= amount; bytes -= amount; // move remaining contents in our decode buffer if (amount > 0 && idata->decodedbytes > 0) { memmove(idata->decodedbuf, idata->decodedbuf + amount, sizeof(idata->decodedbuf) - amount); } } return byteswritten; }
static gboolean vorbis_play (InputPlayback * playback, const gchar * filename, VFSFile * file, gint start_time, gint stop_time, gboolean pause) { if (file == NULL) return FALSE; vorbis_info *vi; OggVorbis_File vf; gint last_section = -1; ReplayGainInfo rg_info; gfloat pcmout[PCM_BUFSIZE*sizeof(float)], **pcm; gint bytes, channels, samplerate, br; gchar * title = NULL; seek_value = (start_time > 0) ? start_time : -1; stop_flag = FALSE; memset(&vf, 0, sizeof(vf)); gboolean error = FALSE; if (ov_open_callbacks (file, & vf, NULL, 0, vfs_is_streaming (file) ? vorbis_callbacks_stream : vorbis_callbacks) < 0) { error = TRUE; goto play_cleanup; } vi = ov_info(&vf, -1); if (vi->channels > 2) goto play_cleanup; br = vi->bitrate_nominal; channels = vi->channels; samplerate = vi->rate; playback->set_params (playback, br, samplerate, channels); if (!playback->output->open_audio(FMT_FLOAT, samplerate, channels)) { error = TRUE; goto play_cleanup; } playback->output->flush (start_time); if (pause) playback->output->pause (TRUE); vorbis_update_replaygain(&vf, &rg_info); playback->output->set_replaygain_info (& rg_info); playback->set_pb_ready(playback); /* * Note that chaining changes things here; A vorbis file may * be a mix of different channels, bitrates and sample rates. * You can fetch the information for any section of the file * using the ov_ interface. */ while (1) { if (stop_time >= 0 && playback->output->written_time () >= stop_time) goto DRAIN; pthread_mutex_lock (& seek_mutex); if (stop_flag) { pthread_mutex_unlock (& seek_mutex); break; } if (seek_value >= 0) { ov_time_seek (& vf, (double) seek_value / 1000); playback->output->flush (seek_value); seek_value = -1; } pthread_mutex_unlock (& seek_mutex); gint current_section = last_section; bytes = ov_read_float(&vf, &pcm, PCM_FRAMES, ¤t_section); if (bytes == OV_HOLE) continue; if (bytes <= 0) { DRAIN: break; } bytes = vorbis_interleave_buffer (pcm, bytes, channels, pcmout); { /* try to detect when metadata has changed */ vorbis_comment * comment = ov_comment (& vf, -1); const gchar * new_title = (comment == NULL) ? NULL : vorbis_comment_query (comment, "title", 0); if (new_title != NULL && (title == NULL || strcmp (title, new_title))) { g_free (title); title = g_strdup (new_title); playback->set_tuple (playback, get_tuple_for_vorbisfile (& vf, filename)); } } if (current_section != last_section) { /* * The info struct is different in each section. vf * holds them all for the given bitstream. This * requests the current one */ vi = ov_info(&vf, -1); if (vi->channels > 2) goto stop_processing; if (vi->rate != samplerate || vi->channels != channels) { samplerate = vi->rate; channels = vi->channels; if (!playback->output->open_audio(FMT_FLOAT, vi->rate, vi->channels)) { error = TRUE; goto stop_processing; } playback->output->flush(ov_time_tell(&vf) * 1000); vorbis_update_replaygain(&vf, &rg_info); playback->output->set_replaygain_info (& rg_info); /* audio reopened */ } } playback->output->write_audio (pcmout, bytes); stop_processing: if (current_section != last_section) { playback->set_params (playback, br, samplerate, channels); last_section = current_section; } } /* main loop */ pthread_mutex_lock (& seek_mutex); stop_flag = TRUE; pthread_mutex_unlock (& seek_mutex); play_cleanup: ov_clear(&vf); g_free (title); return ! error; }
//============================================================================== bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, int64 startSampleInFile, int numSamples) override { while (numSamples > 0) { auto numAvailable = (int) (reservoirStart + samplesInReservoir - startSampleInFile); if (startSampleInFile >= reservoirStart && numAvailable > 0) { // got a few samples overlapping, so use them before seeking.. auto numToUse = jmin (numSamples, numAvailable); for (int i = jmin (numDestChannels, reservoir.getNumChannels()); --i >= 0;) if (destSamples[i] != nullptr) memcpy (destSamples[i] + startOffsetInDestBuffer, reservoir.getReadPointer (i, (int) (startSampleInFile - reservoirStart)), sizeof (float) * (size_t) numToUse); startSampleInFile += numToUse; numSamples -= numToUse; startOffsetInDestBuffer += numToUse; if (numSamples == 0) break; } if (startSampleInFile < reservoirStart || startSampleInFile + numSamples > reservoirStart + samplesInReservoir) { // buffer miss, so refill the reservoir reservoirStart = jmax (0, (int) startSampleInFile); samplesInReservoir = reservoir.getNumSamples(); if (reservoirStart != (int) ov_pcm_tell (&ovFile)) ov_pcm_seek (&ovFile, reservoirStart); int bitStream = 0; int offset = 0; int numToRead = samplesInReservoir; while (numToRead > 0) { float** dataIn = nullptr; auto samps = ov_read_float (&ovFile, &dataIn, numToRead, &bitStream); if (samps <= 0) break; jassert (samps <= numToRead); for (int i = jmin ((int) numChannels, reservoir.getNumChannels()); --i >= 0;) memcpy (reservoir.getWritePointer (i, offset), dataIn[i], sizeof (float) * (size_t) samps); numToRead -= samps; offset += samps; } if (numToRead > 0) reservoir.clear (offset, numToRead); } } if (numSamples > 0) { for (int i = numDestChannels; --i >= 0;) if (destSamples[i] != nullptr) zeromem (destSamples[i] + startOffsetInDestBuffer, sizeof (int) * (size_t) numSamples); } return true; }
ReadableSampleFrames SoundSourceOggVorbis::readSampleFramesClamped( WritableSampleFrames writableSampleFrames) { const SINT firstFrameIndex = writableSampleFrames.frameIndexRange().start(); if (m_curFrameIndex != firstFrameIndex) { const int seekResult = ov_pcm_seek(&m_vf, firstFrameIndex); if (seekResult == 0) { m_curFrameIndex = firstFrameIndex; } else { kLogger.warning() << "Failed to seek file:" << seekResult; const ogg_int64_t pcmOffset = ov_pcm_tell(&m_vf); if (0 <= pcmOffset) { m_curFrameIndex = pcmOffset; } else { // Reset to EOF m_curFrameIndex = frameIndexMax(); } // Abort return ReadableSampleFrames( IndexRange::between( m_curFrameIndex, m_curFrameIndex)); } } DEBUG_ASSERT(m_curFrameIndex == firstFrameIndex); const SINT numberOfFramesTotal = writableSampleFrames.frameLength(); CSAMPLE* pSampleBuffer = writableSampleFrames.writableData(); SINT numberOfFramesRemaining = numberOfFramesTotal; while (0 < numberOfFramesRemaining) { float** pcmChannels; int currentSection; // Use 'long' here, because ov_read_float() returns this type. // This is an exception from the rule not to any types with // differing sizes on different platforms. // https://bugs.launchpad.net/mixxx/+bug/1094143 const long readResult = ov_read_float(&m_vf, &pcmChannels, numberOfFramesRemaining, ¤tSection); if (0 < readResult) { m_curFrameIndex += readResult; if (pSampleBuffer) { switch (channelCount()) { case 1: for (long i = 0; i < readResult; ++i) { *pSampleBuffer++ = pcmChannels[0][i]; } break; case 2: for (long i = 0; i < readResult; ++i) { *pSampleBuffer++ = pcmChannels[0][i]; *pSampleBuffer++ = pcmChannels[1][i]; } break; default: for (long i = 0; i < readResult; ++i) { for (SINT j = 0; j < channelCount(); ++j) { *pSampleBuffer++ = pcmChannels[j][i]; } } } } numberOfFramesRemaining -= readResult; } else { kLogger.warning() << "Failed to read from file:" << readResult; break; // abort } } DEBUG_ASSERT(isValidFrameIndex(m_curFrameIndex)); DEBUG_ASSERT(numberOfFramesTotal >= numberOfFramesRemaining); const SINT numberOfFrames = numberOfFramesTotal - numberOfFramesRemaining; return ReadableSampleFrames( IndexRange::forward(firstFrameIndex, numberOfFrames), SampleBuffer::ReadableSlice( writableSampleFrames.writableData(), std::min(writableSampleFrames.writableLength(), frames2samples(numberOfFrames)))); }
// Read // // Returns number of bytes actually read. // // Returns -1 if there is nothing more to be read. This function can return 0, since // sometimes the amount of bytes requested is too small for the ACM decompression to // locate a suitable block int WaveFile::Read(ubyte *pbDest, uint cbSize, int service) { void *dest_buf=NULL, *uncompressed_wave_data; int rc, uncompressed_bytes_written, section, last_section = -1, byte_order = 0; uint src_bytes_used, convert_len, num_bytes_desired=0, num_bytes_read; // nprintf(("Alan","Reqeusted: %d\n", cbSize)); #if BYTE_ORDER == BIG_ENDIAN byte_order = 1; #endif if ( service ) { uncompressed_wave_data = Wavedata_service_buffer; } else { uncompressed_wave_data = Wavedata_load_buffer; } switch ( m_wave_format ) { case WAVE_FORMAT_PCM: num_bytes_desired = cbSize; dest_buf = pbDest; break; case WAVE_FORMAT_ADPCM: { if ( !m_hStream_open ) { if ( !ACM_stream_open(m_pwfmt_original, &m_wfxDest, (void**)&m_hStream, m_bits_per_sample_uncompressed) ) { m_hStream_open = 1; } else { Int3(); } } num_bytes_desired = cbSize; if ( service ) { dest_buf = Compressed_service_buffer; } else { dest_buf = Compressed_buffer; } if ( num_bytes_desired <= 0 ) { num_bytes_desired = 0; // nprintf(("Alan","No bytes required for ADPCM time interval\n")); } else { num_bytes_desired = ACM_query_source_size((void*)m_hStream, cbSize); // nprintf(("Alan","Num bytes desired: %d\n", num_bytes_desired)); } break; } case OGG_FORMAT_VORBIS: num_bytes_desired = cbSize; dest_buf = pbDest; break; case WAVE_FORMAT_IEEE_FLOAT: { num_bytes_desired = cbSize; if (m_wfmt.wBitsPerSample == 32) { dest_buf = pbDest; } else { if (service) { dest_buf = Compressed_service_buffer; } else { dest_buf = Compressed_buffer; } } break; } default: nprintf(("SOUND", "SOUND => Not supporting %d format for playing wave files\n", m_wave_format)); Int3(); break; } // end switch num_bytes_read = 0; convert_len = 0; src_bytes_used = 0; // read data from disk if ( m_data_bytes_left <= 0 ) { num_bytes_read = 0; uncompressed_bytes_written = 0; return -1; } if ( (m_data_bytes_left > 0) && (num_bytes_desired > 0) ) { int actual_read = 0; if ( num_bytes_desired <= (uint)m_data_bytes_left ) { num_bytes_read = num_bytes_desired; } else { num_bytes_read = m_data_bytes_left; } // OGG reading is special if ( m_wave_format == OGG_FORMAT_VORBIS ) { int sign = (m_wfmt.wBitsPerSample == 8) ? 0 : 1; int sample_size = sizeof(float) * m_wfmt.nChannels; while ( !m_abort_next_read && ((uint)actual_read < num_bytes_read)) { float **pcm = NULL; if (m_wfmt.wBitsPerSample == 32) { rc = ov_read_float(&m_snd_info.vorbis_file, &pcm, (num_bytes_read - actual_read) / sample_size, §ion); } else { rc = ov_read(&m_snd_info.vorbis_file, (char *)dest_buf + actual_read, num_bytes_read - actual_read, byte_order, m_wfmt.wBitsPerSample / 8, sign, §ion); } // fail if the bitstream changes, shouldn't get this far if that's the case though if ((last_section != -1) && (last_section != section)) { mprintf(("AUDIOSTR => OGG reading error: We don't handle bitstream changes!\n")); goto READ_ERROR; } if ( rc > 0 ) { if (m_wfmt.wBitsPerSample == 32) { float *out_p = (float*)((ubyte*)dest_buf + actual_read); for (int i = 0; i < rc; i++) { for (int j = 0; j < m_wfmt.nChannels; j++) { *out_p++ = pcm[j][i]; } } actual_read += (rc * m_wfmt.nBlockAlign); } else { actual_read += rc; } last_section = section; } else if ( rc == 0 ) { break; } else if ( rc < 0 ) { if ( dbg_print_ogg_error(m_wFilename, rc) ) { // must be a fatal error goto READ_ERROR; } else { // not fatal, just continue on break; } } } } // IEEE FLOAT is special too, downsampling can give short buffers else if (m_wave_format == WAVE_FORMAT_IEEE_FLOAT) { while ( !m_abort_next_read && ((uint)actual_read < num_bytes_read) ) { rc = mmioRead(m_snd_info.cfp, (char *)dest_buf, num_bytes_read); if (rc <= 0) { break; } #if BYTE_ORDER == BIG_ENDIAN // need to byte-swap before any later conversions float *swap_tmp; for (int i = 0; i < rc; i += sizeof(float)) { swap_tmp = (float *)((ubyte*)dest_buf + i); *swap_tmp = INTEL_FLOAT(swap_tmp); } #endif if (m_wfmt.wBitsPerSample == 32) { actual_read = rc; } else if (m_wfmt.wBitsPerSample == 16) { float *in_p = (float*)dest_buf; short *out_p = (short*)((ubyte*)uncompressed_wave_data + actual_read); int end = rc / sizeof(float); for (int i = 0; i < end; i++) { int i_val = (int)(in_p[i] * 32767.0f + 0.5f); CLAMP(i_val, -32768, 32767); *out_p++ = (short)i_val; } actual_read += (rc >> 1); } else { Assert( m_wfmt.wBitsPerSample == 8 ); float *in_p = (float*)dest_buf; ubyte *out_p = (ubyte*)((ubyte*)uncompressed_wave_data + actual_read); int end = num_bytes_read / sizeof(float); for (int i = 0; i < end; i++) { int i_val = (int)(in_p[i] * 127.0f + 0.5f) + 128; CLAMP(i_val, 0, 255); *out_p++ = (ubyte)i_val; } actual_read += (rc >> 2); } }