Example #1
0
 void getOggData(float **dst,int num_frames){
   float **sound;
   long read=ov_read_float(&oggvorbisfile,&sound,num_frames,&current_oggsection);
   if(read==0){
     ov_pcm_seek(&oggvorbisfile,0);
     read=ov_read_float(&oggvorbisfile,&sound,num_frames,&current_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);
   }
 }
Example #2
0
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 ), &section );
		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 );
}
Example #3
0
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();
    }
}
Example #4
0
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;
}
Example #5
0
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, &currentBitstream);
    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;
  }
}
Example #6
0
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, &currentSection);
        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;
}
Example #7
0
unsigned int oggDecoder::decode( float*** data, int count )
{
    int ret = -1;
    while( ret < 0)
    {
        ret = ov_read_float( decoder, data, count, &current_section);
        if(ret == OV_HOLE)
            qWarning("Hole in ogg datastream detected.. skipping...");
    }
    return ret;
}
Example #8
0
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;
}
Example #9
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;
}
Example #10
0
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];
}
Example #11
0
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, &section);
                              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);
            }
      }
Example #12
0
// 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;
}
Example #13
0
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;
}
Example #14
0
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();
    }
}
Example #15
0
	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, &current_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;
}
Example #17
0
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,
                                 &current_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;
        }
    }
}
Example #19
0
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;
}
Example #20
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, &current_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;
}
Example #21
0
/* 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,
				      &current_section);
#else
		float **per_channel;
		long nframes = ov_read_float(&vf, &per_channel,
					     frames_per_buffer,
					     &current_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);
}
Example #22
0
/*
====================
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 );
}
Example #23
0
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;
}
Example #24
0
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, &current_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;
    }
Example #26
0
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, &currentSection);
        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, &section);
				} 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, &section);
				}

				// 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);
				}
			}