Exemple #1
0
SINT SoundSourceOpus::readSampleFrames(
        SINT numberOfFrames, CSAMPLE* sampleBuffer) {
    DEBUG_ASSERT(isValidFrameIndex(m_curFrameIndex));

    const SINT numberOfFramesTotal = math_min(
            numberOfFrames, getMaxFrameIndex() - m_curFrameIndex);

    CSAMPLE* pSampleBuffer = sampleBuffer;
    SINT numberOfFramesRemaining = numberOfFramesTotal;
    while (0 < numberOfFramesRemaining) {
        int readResult = op_read_float(m_pOggOpusFile,
                pSampleBuffer,
                frames2samples(numberOfFramesRemaining), NULL);
        if (0 < readResult) {
            m_curFrameIndex += readResult;
            pSampleBuffer += frames2samples(readResult);
            numberOfFramesRemaining -= readResult;
        } else {
            qWarning() << "Failed to read sample data from OggOpus file:"
                    << readResult;
            break; // abort
        }
    }

    DEBUG_ASSERT(isValidFrameIndex(m_curFrameIndex));
    DEBUG_ASSERT(numberOfFramesTotal >= numberOfFramesRemaining);
    return numberOfFramesTotal - numberOfFramesRemaining;
}
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;
}
Exemple #3
0
static int
opusdec_read (DB_fileinfo_t *_info, char *bytes, int size) {
    opusdec_info_t *info = (opusdec_info_t *)_info;

    // Work round some streamer limitations and infobar issue #22
    if (info->new_track && is_playing_track(info->new_track)) {
        info->new_track = NULL;
        send_event(info->it, DB_EV_TRACKINFOCHANGED);
        info->next_update = -2;
    }

    // Don't read past the end of a sub-track
    int samples_to_read = size / sizeof(float) / _info->fmt.channels;
    int64_t endsample = deadbeef->pl_item_get_endsample (info->it);
    if (endsample > 0) {
        opus_int64 samples_left = endsample - op_pcm_tell (info->opusfile);
        if (samples_left < samples_to_read) {
            samples_to_read = (int)samples_left;
            size = samples_to_read * sizeof(float) * _info->fmt.channels;
        }
    }

    // Read until we have enough bytes to satisfy streamer, or there are none left
    int bytes_read = 0;
    int ret = OP_HOLE;

    int samples_read = 0;
    while (samples_read < samples_to_read && (ret > 0 || ret == OP_HOLE))
    {
        int nframes = samples_to_read-samples_read;
        float pcm[nframes * _info->fmt.channels];
        int new_link = -1;
        ret = op_read_float(info->opusfile, pcm, nframes * _info->fmt.channels, &new_link);

        if (ret < 0) {
        }
        else if (new_link != info->cur_bit_stream && !op_seekable (info->opusfile) && new_streaming_link(info, new_link)) {
            samples_read = samples_to_read;
            break;
        }
        else if (ret > 0) {
            for (int channel = 0; channel < _info->fmt.channels; channel++) {
                const float *pcm_channel = &pcm[info->channelmap ? info->channelmap[channel] : channel];
                float *ptr = ((float *)bytes + samples_read*_info->fmt.channels) + channel;
                for (int sample = 0; sample < ret; sample ++, pcm_channel += _info->fmt.channels) {
                    *ptr = *pcm_channel;
                    ptr += _info->fmt.channels;
                }
            }
            samples_read += ret;
        }
    }
    bytes_read = samples_read * sizeof(float) * _info->fmt.channels;
    info->currentsample += bytes_read / (sizeof (float) * _info->fmt.channels);


    int64_t startsample = deadbeef->pl_item_get_startsample (info->it);
    _info->readpos = (float)(op_pcm_tell(info->opusfile) - startsample) / _info->fmt.samplerate;
    if (info->set_bitrate && _info->readpos > info->next_update) {
        const int rate = (int)op_bitrate_instant(info->opusfile) / 1000;
        if (rate > 0) {
            deadbeef->streamer_set_bitrate(rate);
            info->next_update = info->next_update <= 0 ? info->next_update + 1 : _info->readpos + 5;
        }
    }

    return bytes_read;
}