long SoundSourceOpus::seek(long filepos) {
    // In our speak, filepos is a sample in the file abstraction (i.e. it's
    // stereo no matter what). filepos/2 is the frame we want to seek to.
    if (filepos % 2 != 0) {
        qDebug() << "SoundSourceOpus got non-even seek target.";
        filepos--;
    }

    if (op_seekable(m_ptrOpusFile)) {
        // I can't say why filepos have to divide by two
        // Have no idea.. probably seek point is mono..
        if (op_pcm_seek(m_ptrOpusFile, filepos / 2) != 0) {
            // This is totally common (i.e. you're at EOF). Let's not leave this
            // qDebug on.

            qDebug() << "opus: Seek ERR on seekable.";
        }

        // qDebug() << "Wanted:" << filepos << "GOT:" << op_pcm_tell(m_ptrOpusFile);


        //return op_pcm_tell(m_ptrOpusFile);
        // We are here allways!
        return filepos;
    } else {
        qDebug() << "opus: Seek ERR at file " << m_qFilename;
        return 0;
    }
    return filepos;
}
Beispiel #2
0
void AudioStreamPlaybackOpus::seek_pos(float p_time) {
	if(!playing) return;
	ogg_int64_t pcm_offset = (ogg_int64_t)(p_time * osrate);
	bool ok = op_pcm_seek(opus_file,pcm_offset)==0;
	if(!ok) {
		ERR_PRINT("Seek time over stream size.");
		return;
	}
	frames_mixed=osrate*p_time;
}
Beispiel #3
0
static off_t
sample_offset(OggOpusFile *opusfile, const opus_int64 sample)
{
    if (sample <= 0 || sample == op_pcm_total(opusfile, -1))
        return 0;

    if (op_pcm_seek(opusfile, sample)) {
        return -1;
    }

    return op_raw_tell(opusfile);
}
Beispiel #4
0
int AudioStreamPlaybackOpus::mix(int16_t* p_bufer,int p_frames) {
	if (!playing)
		return 0;

	int total=p_frames;

	while (true) {

		int todo = p_frames;

		if (todo==0 || todo<MIN_MIX) {
			break;
		}

		int ret=op_read(opus_file,(opus_int16*)p_bufer,todo*stream_channels,&current_section);
		if (ret<0) {
			playing = false;
			ERR_EXPLAIN("Error reading Opus File: "+file);
			ERR_BREAK(ret<0);
		} else if (ret==0) { // end of song, reload?
			op_free(opus_file);

			_close_file();

			f=FileAccess::open(file,FileAccess::READ);

			int errv = 0;
			opus_file = op_open_callbacks(f,&_op_callbacks,NULL,0,&errv);
			if (errv!=0) {
				playing=false;
				break; // :(
			}

			if (!has_loop()) {
				playing=false;
				repeats=1;
				break;
			}

			if (loop_restart_time) {
				bool ok = op_pcm_seek(opus_file, (loop_restart_time*osrate)+pre_skip)==0;
				if (!ok) {
					playing=false;
					ERR_PRINT("loop restart time rejected")
				}

				frames_mixed=(loop_restart_time*osrate)+pre_skip;
			} else {
Beispiel #5
0
static int
opusdec_seek_sample (DB_fileinfo_t *_info, int sample) {
    opusdec_info_t *info = (opusdec_info_t *)_info;
    if (sample < 0) {
        return -1;
    }
    if (!info->info.file) {
        return -1;
    }
    int64_t startsample = deadbeef->pl_item_get_startsample (info->it);

    int res = op_pcm_seek (info->opusfile, sample + startsample);
    if (res != 0 && res != OP_ENOSEEK) {
        return -1;
    }
    info->currentsample = sample;
    _info->readpos = (float)sample/_info->fmt.samplerate;
    info->next_update = -2;
    return 0;
}
Beispiel #6
0
static gint64
xmms_opus_seek (xmms_xform_t *xform, gint64 samples,
                  xmms_xform_seek_mode_t whence, xmms_error_t *err)
{
	xmms_opus_data_t *data;

	g_return_val_if_fail (whence == XMMS_XFORM_SEEK_SET, -1);
	g_return_val_if_fail (xform, -1);

	data = xmms_xform_private_data_get (xform);
	g_return_val_if_fail (data, FALSE);

	if (samples > op_pcm_total (data->opusfile, -1)) {
		xmms_log_error ("Trying to seek past end of stream");
		return -1;
	}

	op_pcm_seek (data->opusfile, samples);

	return samples;
}
Beispiel #7
0
SINT SoundSourceOpus::seekSampleFrame(SINT frameIndex) {
    DEBUG_ASSERT(isValidFrameIndex(m_curFrameIndex));
    DEBUG_ASSERT(isValidFrameIndex(frameIndex));

    int seekResult = op_pcm_seek(m_pOggOpusFile, frameIndex);
    if (0 == seekResult) {
        m_curFrameIndex = frameIndex;
    } else {
        qWarning() << "Failed to seek OggOpus file:" << seekResult;
        const ogg_int64_t pcmOffset = op_pcm_tell(m_pOggOpusFile);
        if (0 <= pcmOffset) {
            m_curFrameIndex = pcmOffset;
        } else {
            // Reset to EOF
            m_curFrameIndex = getMaxFrameIndex();
        }
    }

    DEBUG_ASSERT(isValidFrameIndex(m_curFrameIndex));
    return m_curFrameIndex;
}
Beispiel #8
0
pcm_chunk_t OpusDynamicLoader::load_chunk(uint32_t offset, uint32_t chunk_size) {
	// if the requested offset is greater than the resource's length, there is
	// no chunk left to load
	if (offset > length) {
		return {};
	}

	// open opus file
	auto op_file = open_opus_file();

	// allocate the chunk's buffer
	pcm_chunk_t chunk;
	chunk.reserve(chunk_size);
	// initialize chunks with zeroes
	std::memset(&chunk.front(), 0, chunk_size*sizeof(int16_t));

	// seek to the requested offset, the seek offset is given in samples
	// while the requested offset is given in int16_t values, so the division
	// by 2 is necessary
	int64_t pcm_offset = static_cast<int64_t>(offset / 2);
	int op_ret = op_pcm_seek(op_file.get(), pcm_offset);
	if (op_ret < 0) {
		throw util::Error{"Could not seek in %s: %d", path.c_str(), op_ret};
	}

	// read a chunk from the requested offset
	// if the opus file is a mono source, we read chunk_size / 2 values and
	// convert it to stereo directly
	// if the opus file is a stereo source, we read chunk_size directly
	int read_num_values = chunk_size / 2 * channels;
	int read_count = 0;
	int samples_read;
	// loop as long as there are samples left to read
	while (read_count <= read_num_values) {
		samples_read = op_read(
			op_file.get(), &chunk.front() + read_count,
			read_num_values - read_count, nullptr
		);

		// an error occured
		if (samples_read < 0) {
			throw util::Error{"Could not read from %s: %d", path.c_str(), samples_read};
		}
		// end of the resource
		else if (samples_read == 0) {
			break;
		}

		// increase read_count by the number of int16_t values that have been
		// read
		read_count += samples_read * channels;
	}

	// convert to stereo
	if (channels == 1) {
		for(int i = read_count-1; i >= 0; i--) {
			auto value = chunk[i];
			chunk[i*2+1] = value;
			chunk[i*2] = value;
		}
	}

	log::msg("DYNLOAD: file=%d all=%d", read_count, read_count * 2 / channels);
	return std::move(chunk);
}
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;
}
Beispiel #10
0
bool OggOpusReader::Seek_(int64 frame_offset)
{
 op_pcm_seek(opfile, frame_offset);
 return(true);
}
Beispiel #11
0
static int S_OPUS_CodecRewindStream (snd_stream_t *stream)
{
	return op_pcm_seek ((OggOpusFile *)stream->priv, 0);
}